Problem:
doing custom operation based on Views Bulk Operation API, executed on Order management view makes uc_credit_cache('load') to return and save wrong payment details on order. In uc_credit.module, line 266 (load option) function uc_credit_cache returns wrong data from static variable.

Example:
- initial state:
Order # | Last 4 digits
00001 | 0027
00002 | 1111
00003 | 8888

- after uc_credit_cache messes up:
Order # | Last 4 digits
00001 | 8888
00002 | 0027
00003 | 1111

As you can see, orders get someone else credit cards thanks to uc_credit_cache. This happens when uc_order calls all hook_uc_order to execute, and uc_credit_uc_order executes. In it, payment details are built through uc_credit_cache which bring incorrect data from static variable.

In order to "fix" this, I created module (in attach). This module makes sure it has a bit higher weight (weight might not be necessary, didn't test without it) and implements hook_uc_order. It checks if payment method is set and if payment method is credit card. If it is, it calls uc_credit_cache('clear') which clears data in static variable and pulls correct payment details data from database. This will essentially fix this problem every time we are manipulating with uc_order_load, though not always this issue happens. After carefully testing, I realized this happens on interfaces such as Views + VBO where custom operation is executed on multiple orders. You need minimum two orders to be handled at once to reproduce this problem.

This should be fixed somewhere in Ubercart core. Not 100% sure where, but I attached my workaround so it might give you additional clue what might cause uc_credit_cache to pull wrong data. I am available if you have any questions, need some kind of help for debugging, or providing more info or simply testing patch you might provide.

Related issue on Ubercart forum:
http://www.ubercart.org/forum/bug_reports/6413/uc_credit_cache_assumes_n...

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

milovan’s picture

Issue summary: View changes
stewart.adam’s picture

Priority: Normal » Major

I just ran into the same issue as well, but not from Views; as far as I can tell, any time two different orders are loaded in a single request we will run into this. If a save operation is called for that second order, then its cached CC details get destroyed.

I am moving this bug to Major priority due to the potential for silent data loss or corruption in customer credit card data.

deja711’s picture

I confirm this as well and I agree this is major fix. I fixed it the same way milovan posted above. Thank you milovan! Subscribed.

TR’s picture

Priority: Major » Normal
Status: Active » Needs work

My understanding is that this is something that only affects you if you create a VBO or some other custom page that allows payment to be applied to multiple orders. That is not part of core Ubercart. If you want a fix to be applied for this issue, we need a real PATCH, not a gzip of some altered module file.

stewart.adam’s picture

Attached patch fixes the issue. Unfortunately, it's not particularly elegant since we cannot simply clear the credit caches at every load like milovan's module does - this breaks compatibility with some checkout gateways as they call uc_order_load() during the same request and (reasonably) expect the payment details to be there.

However, uc_credit_cache() is not keyed by order ID and it has no clue what order it's operating on and therefore cannot attempt to refresh the caches itself. hook_uc_order() of uc_credit sets the cache initially, and so it has to be responsible for clearing it. This patch makes it remember what order was loaded last, and if that order is different than the one being loaded, flushes the credit caches before resetting them based on the loading order. This approach ensures that we don't flush caches too early for modules that call uc_order_load() on the same order multiple times in a request or during checkout.

If the patch is not suitable for upstream, I've also provided a sandbox module that achieves the same functionality here: https://www.drupal.org/sandbox/firewing1/uc_credit_cache_refresher. if this patch cannot be accepted, I'll promote that to a full module for use with modules that perform bulk order editing such as views_bulk_operations.

stewart.adam’s picture

Version: 7.x-3.6 » 7.x-3.x-dev
Status: Needs work » Needs review

Marking as needs review.

I also forgot to mention in my last comment: in the D8 branch, we should introduce a $order_id parameter to uc_credit_cache() to avoid this situation entirely - we can simply key the static array by order ID and never have to worry about these collisions.

TR’s picture

It shouldn't be a problem to put this patch in, but I'm out of town for a few weeks so that will have to wait until I get back.

For D8 we will be using Payment. That's being worked on now.

milovan’s picture

In the latest Ubercart (7.x-3.10) I don't see this patch included. Do you plan to include it in next release? Thanks

TR’s picture

@milovan: This issue is marked as "Needs review", which means that someone in the community needs to try the patch and report back on whether or not it fixes the reported problem. See the issue queue handbook (link below) for more information about what issue statuses mean.

Since you are the one who initially reported the bug, I'm surprised you haven't tried the patch yet - or if you have tried it I'm surprised you haven't posted a comment saying whether it worked for you or not.

milovan’s picture

Status: Needs review » Reviewed & tested by the community

Sorry, I got confused on your post #7, so I thought it ll be accepted. This patch was already on my production sites, so it is tested with the latest Ubercart. In multiple order load, it doesn't pull CC data from cache, but rather getting correct CC data.
As far as I am concerned, patch is fine and ready to be included in next release.

vood002’s picture

Terrific, this patch solved the issue on my site that was actually showing the wrong CC data to customers and on the admin/order/### view screens. Thank you very much.