Hi,
After entering their details some users are skipping the remote gateway (Sagepay form type payment). The order is then being set to checkout complete with outstanding amounts still.
This only occurs on some browsers; works in chrome but fails in safari. Sometimes it works when logged in, sometimes not (dependent on browser). So if user logs into Safari it works.
I believe that the reason it is skipping is related to the code listed below from /commerce_payment.checkout_pane.inc . In the order revisions log, the message 'Customer skipped the Payment page because no payment was required' given for orders that fail to go to gateway.
It seems that the variable $payment_method is empty for the orders that fail to be sent for payment. I just can't figure out why it is empty for some orders/scenarios.
// If the payment method doesn't exist or does not require a redirect...
if (!$payment_method || !$payment_method['offsite']) {
if (!$payment_method) {
$log = t('Customer skipped the Payment page because no payment was required.');
}
else {
$log = t('Customer skipped the Payment page because payment was already submitted.');
}
// Advance the customer to the next step of the checkout process.
commerce_payment_redirect_pane_next_page($order, $log);
drupal_goto(commerce_checkout_order_uri($order));
}
I have explored Sagepay, ssl/multiple sessions and *think* these are not the issue. I have turned of ssl, still happens. Truncated sessions table, cleared cookies at browser level, disabled Sagepay and enabled Paypal, still happens.
This started after I modified the checkout process. I have added extra checkout steps and moved panes around. I have attached the screenshot of checkout panes.
I am now going to try and debugging the payment process starting with code above!
Trying to give as much info. I hope someone can help, I have been battling this now for some time.
Many thanks in advance.
Richard
| Comment | File | Size | Author |
|---|---|---|---|
| #35 | 2219483-35.altered_checkout_form.patch | 2.13 KB | rszrama |
| #29 | commerce-errors_outside_panes-2219483-29.patch | 1.14 KB | smccabe |
Comments
Comment #1
rszrama commentedCan you print a dump of the $order variable right before that if statement? We'll need to figure out why you don't have a value set for payment method - I can't think of a reason in the core checkout form for that to happen.
Comment #2
richard moger commentedThanks for replying Ryan,
Here is the var dump. First one is the failed one (goes straight thru to complete), second is one that passes ok.
first dump
object(stdClass)#241 (21) { ["order_number"]=> string(3) "902" ["revision_id"]=> string(4) "6070" ["revision_uid"]=> string(1) "0" ["mail"]=> string(32) "rxxxx@xxx.co.uk" ["status"]=> string(16) "checkout_payment" ["log"]=> string(65) "Customer continued to the next checkout page via a submit button." ["revision_timestamp"]=> string(10) "1395072598" ["revision_hostname"]=> string(12) "xxx.xxx.xxx.xxx" ["data"]=> array(2) { ["last_cart_refresh"]=> int(1395072577) ["profile_copy"]=> array(1) { ["customer_profile_shipping"]=> array(2) { ["elements"]=> array(1) { ["commerce_customer_address"]=> array(1) { ["und"]=> array(1) { [0]=> bool(true) } } } ["status"]=> bool(true) } } } ["order_id"]=> string(3) "902" ["type"]=> string(14) "commerce_order" ["uid"]=> string(1) "0" ["created"]=> string(10) "1395072559" ["changed"]=> string(10) "1395072598" ["hostname"]=> string(12) "xxx.xxx.xxx.xxx" ["commerce_line_items"]=> array(1) { ["und"]=> array(2) { [0]=> array(1) { ["line_item_id"]=> string(4) "7797" } [1]=> array(1) { ["line_item_id"]=> string(4) "7818" } } } ["commerce_order_total"]=> array(1) { ["und"]=> array(1) { [0]=> array(3) { ["amount"]=> string(4) "1698" ["currency_code"]=> string(3) "GBP" ["data"]=> array(1) { ["components"]=> array(2) { [0]=> array(3) { ["name"]=> string(10) "base_price" ["price"]=> array(3) { ["amount"]=> int(1300) ["currency_code"]=> string(3) "GBP" ["data"]=> array(0) { } } ["included"]=> bool(true) } [1]=> array(3) { ["name"]=> string(20) "flat_rate_uk_postage" ["price"]=> array(3) { ["amount"]=> int(398) ["currency_code"]=> string(3) "GBP" ["data"]=> array(0) { } } ["included"]=> bool(true) } } } } } } ["commerce_customer_billing"]=> array(1) { ["und"]=> array(1) { [0]=> array(1) { ["profile_id"]=> string(3) "942" } } } ["commerce_customer_shipping"]=> array(1) { ["und"]=> array(1) { [0]=> array(1) { ["profile_id"]=> string(3) "943" } } } ["commerce_coupon_order_reference"]=> array(0) { } ["rdf_mapping"]=> array(0) { } }
second dump
object(stdClass)#241 (21) { ["order_number"]=> string(3) "761" ["revision_id"]=> string(4) "6061" ["revision_uid"]=> string(1) "1" ["mail"]=> string(28) "xxxxx@xxxx.co.uk" ["status"]=> string(16) "checkout_payment" ["log"]=> string(65) "Customer continued to the next checkout page via a submit button." ["revision_timestamp"]=> string(10) "1395072075" ["revision_hostname"]=> string(12) "10.227.47.79" ["data"]=> array(4) { ["last_cart_refresh"]=> int(1395072068) ["profile_copy"]=> array(1) { ["customer_profile_shipping"]=> array(2) { ["status"]=> bool(true) ["elements"]=> array(1) { ["commerce_customer_address"]=> array(1) { ["und"]=> array(1) { [0]=> bool(true) } } } } } ["payment_method"]=> string(60) "commerce_sagepay_form|commerce_payment_commerce_sagepay_form" ["VendorTxId"]=> string(13) "761_493600716" } ["order_id"]=> string(3) "761" ["type"]=> string(14) "commerce_order" ["uid"]=> string(1) "1" ["created"]=> string(10) "1393606870" ["changed"]=> string(10) "1395072075" ["hostname"]=> string(12) "10.xxx.47.79" ["commerce_line_items"]=> array(1) { ["und"]=> array(2) { [0]=> array(1) { ["line_item_id"]=> string(4) "7795" } [1]=> array(1) { ["line_item_id"]=> string(4) "7796" } } } ["commerce_order_total"]=> array(1) { ["und"]=> array(1) { [0]=> array(3) { ["amount"]=> string(3) "408" ["currency_code"]=> string(3) "GBP" ["data"]=> array(1) { ["components"]=> array(2) { [0]=> array(3) { ["name"]=> string(10) "base_price" ["price"]=> array(3) { ["amount"]=> int(10) ["currency_code"]=> string(3) "GBP" ["data"]=> array(0) { } } ["included"]=> bool(true) } [1]=> array(3) { ["name"]=> string(20) "flat_rate_uk_postage" ["price"]=> array(3) { ["amount"]=> int(398) ["currency_code"]=> string(3) "GBP" ["data"]=> array(0) { } } ["included"]=> bool(true) } } } } } } ["commerce_customer_billing"]=> array(1) { ["und"]=> array(1) { [0]=> array(1) { ["profile_id"]=> string(3) "807" } } } ["commerce_customer_shipping"]=> array(1) { ["und"]=> array(1) { [0]=> array(1) { ["profile_id"]=> string(3) "808" } } } ["commerce_coupon_order_reference"]=> array(0) { } ["rdf_mapping"]=> array(0) { } }
Comment #3
rszrama commentedYep, you're right about it missing the payment_method key, so I'd just focus on figuring out why some users are progressing past the payment page without a payment method specified. It should be impossible, but one thing you can do to check is toggle on the payment pane's setting to ensure orders can't progress past the pane without selecting a payment method.
Comment #4
richard moger commentedRyan,
Gave that a try but unfortunately didn't fix it.
I will carry on hunting!
Thanks
Rich
Comment #5
rszrama commentedMaybe look to see if the $order->data is being overwritten prior to save such that the pane does set the payment method key but then somehow it's removed in a follow-up save.
Comment #6
richard moger commentedOn first page of checkout, all I see in $order->data for failed orders is.
In ok orders I see more keys.
Worth noting that I have re-arranged checkout as per attached diagram, the early part of process is looking particularly shady.
Comment #7
rszrama commentedI wouldn't expect the payment method key to be set until the Payment checkout pane on page 3 has submitted.
Comment #8
richard moger commentedIt is now working.
Worryingly, I am not sure what fixed it and can't reproduce, all changes I made I reset back and now get a different result :-(
I disabled and re-enabled Commerce Checkout Progress and a feature module. I can now clear caches, sessions and local browser caches and payment method key is there at payment time.
For now I will leave it there. I have one user who has been constantly erroring, I will get that tested in the next day or so.
Thank you very much Ryan for your help, holding my breath though on this one!
If OK with you I will leave it at postponed and close in few days after more testing & time has past if all still OK.
:-)
Comment #9
rszrama commentedWorks for me. If there's some problem with the core payment pane, I'd just as soon have this issue dangling around on the chance we could nail it down and prevent it in the future. Glad it's working in the meantime. : )
Comment #10
richard moger commentedSpoke far too soon!
starting to home it in though I think.
I can consistently reproduce the issue and a fix for a user that was failing on every request since changes were made to cart.
Lots of anonymous user checkout attempts were made using various products, email addresses and billing information combinations.
Between these, I cleared cache, truncated sessions and cleared browser cache between them (user on the phone).
For all attempts where the name and billing address were one specific one used originally, I get a fail.
I get a pass for all combinations as long as a different name and billing address is used.
So it looks like it is related to a specific user name and/or billing address?!
Off to investigate this line off enquiry, any further clues/other experiences that may help would be appreciated.
:-)
Comment #11
richard moger commentedRyan,
I am pretty sure it was cause by an additional phone field number that we added to the billing information profile.
The number accepted both landlines and mobiles but process failed for mobiles, making it such a pain to diagnose!
The field was provided by the phone number module and after I turned off country level validation in the fields settings the issue stopped.
Next I need to investigate why the error caused the form to validate and continue the process even after the order entity was malformed.
Not really a Commerce issue though I don't think so have set to closed works as designed? I will raise another ticket if I find subsequent issues.
Thanks again for help on this, really appreciate it.
Rich
Comment #12
rszrama commentedAye aye, thanks for keeping it up to date. : )
Comment #13
rich.3po commentedHi
I'm also experiencing this issue using Sagepay server (iframe) integration - thanks for posting up your findings. Its a very intermittent problem that i've only managed to reproduce 'by accident'. However our client has had reports of it on production.
Its a particularly dangerous bug because payment is skipped altogether.. meaning customers have been putting orders through for free! Perhaps in the code snippet in commerce_payment.checkout_pane.inc there should be more failsafe / checking to ensure this cant happen? Maybe a master variable for example flagging whether payment can be bypassed (which is useful for dev of course). Or even better, just check to see if order object has been malformed for whatever reason?
@RichieRampage - could you give any more info as to what was causing it in your case? We have made quite a few modifications to the checkout form like you were describing, which could be causing it
Many thanks
Comment #14
brandonratz commentedI just had an issue where Anonymous checkout was working flawlessly. However, an Authenticated user would skip the payment action all together. After 3-4 hours of trial and error, rules investigation, and face palming...
I have found that the checkout panes are to blame in my case. I have 'Billing Info' and 'Payment' (with 'require a payment..' checked) in the PAYMENT pane. Payment is completely skipped in this case. If I move those two items into REVIEW ORDER pane my problem is fixed.
Can we shed any light on the reason for this?
Comment #15
VanD commentedI have been trying to resolve this when related to commerce_stripe since I am not the only one with this issue, maybe it is related to something else. Here is my commerce_stripe issue for more information https://www.drupal.org/node/2530918
#14 suggests that the payment be in review, which is what I have done, but I am still experiencing this issue, and it only seems to happen for certain users. I require payment, but yet the payment still proceeds, just without processing, because no payment_method is attached to these orders. I don't know why this is the case, but since I have checked the box on Payment "Require a payment method at all times, preventing checkout if none is available." It should not go through. Anyone else able to figure this one out?
Comment #16
rich.3po commentedHi,
I managed to fix this issue in the end, but it was stemming from a (rather obscure) conflict between Commerce and a custom module. Its difficult to understand the root cause myself, but maybe it will help @rszrama
Briefly, in my custom module was:
1) A definition of a custom checkout pane
2) Within the pane was a form with single checkbox (for accepting T&C's)
3) A validation function for the form, attached using
'#element_validate' => array('my_validation_function')
Now.. if the user was to alter the 'country' selector on the addressfield when checking out (causing ajax form actions to fire etc), then on submission the payment pages would skip and the order would go through for free..!
When i removed the '#element_validate' property and implemented via the standard FORM_ID_validate() convention, the problem went away.
So in conclusion... it seems like if some kind of validation error / misconfiguraton happens in a checkout pane, then it can cause odd behaviour such as payment pages skipping. This was clearly a convoluted scenario which took me a long time to reproduce and trace through (there were no errors in watchdog etc), but maybe it sheds some light for other people having the same problem
I think, in either case, Commerce should have more robust failsafe mechanisms to prevent this from happening
Comment #17
VanD commentedI've put in a temporary hacked fix until I can diagnose this problem. Please be aware that this may only mask the problem. It stops people from checking out if there is no payment method selected. I have not submitted it in patch format, because it's not a proper fix. Just a stop gap
Original (line 304 of commerce/modules/payment/includes/commerce_payment.checkout_pane.inc):
New (line 304 of commerce/modules/payment/includes/commerce_payment.checkout_pane.inc):
Comment #18
andyg5000I've had 2 sites report a similar issue recently. The log entry says "Customer skipped the Payment page because no payment was required." which means that the site was unable to load any payment methods for the order. Both sites use Auth.net and don't have any conditions on the payment rule.
Just like @rich.3po, both of these sites have a clause to accept before checking out. However in my case, I'm just adding a required checkbox field to the existing checkout pane. There are no additional checkout panes or validation/submit callbacks.
I'm unable to reproduce the issue, but I'll report back as soon as a I find the culprit.
Comment #19
rszrama commentedThe updated title points to the culprit: our error trapping code that allows us to display form errors inline with their checkout panes does not properly accommodate fields that exist outside of checkout panes. We need to ensure any leftover errors from our special handler are still displayed and prevent form submission.
Comment #20
andyg5000Nice detective work Ryan :D
Comment #21
jens peter commentedI also have this problem. Any updates on this?
I find this error very critical as it can result in items being shipped before payment unless we do a manual control every time.
Thank you.
Comment #22
rich.3po commentedIts good to see the root cause of this issue has been identified - nice one Ryan
Agree it should be higher priority so ramping this up...
Comment #23
rszrama commentedI won't change it back down, but I actually wouldn't consider it a major issue since the fix is so easy: put your custom form element inside an existing checkout pane or create a new one. : )
Comment #24
andyg5000I think it's major because it was a major pain in my ass :D ... Using standard FAPI techniques that should work for all of Drupal expose a big problem.
Comment #25
rich.3po commentedI'm still a little unclear (as i suspect others are too..?) as to what exactly triggers this bug.
When you say the issue is triggered by "fields that exist outside of checkout panes", could you give an example of this and how it should be done instead?
In my case, i was in fact defining my own checkout pane, with fields within it defined in
BASE_checkout_form()(ie the standard method AFAIK), but i still got the issue until i removed the'#element_validate'key...Comment #26
andyg5000Hey @rich.3po, I think you should be using the hook to define your checkout pane validator instead of using #element_validate. The pane validator has to return TRUE or FALSE (unlike standard form validators)
See: http://api.drupalcommerce.org/api/Drupal%20Commerce/sites!all!modules!co...
Hopefully the fix for this issue will address your instance as well. Basically if any form element on the page fails validation it will prevent the form from being submitted and advancing to the next order status.
Comment #27
jens peter commentedHave you seen the module Commerce Commonwealth.
They describe the exact same issue as here and have just released a module update.
I cannot say it is the same as I dont use the Commerce Commonwealth module, but it looks to be the same problem.
Read more here https://www.drupal.org/node/2542380
Comment #28
rszrama commentedNah, that's unrelated.
Comment #29
smccabe commentedI believe something like this is the fix? The problem is we only loop over errors by pane_id, so anything outside a pane_id gets displayed, but doesn't trigger the rebuild to keep us on the same page. I just added a basic check in front to set form validation = false if there are ANY form errors, then all the pane specific stuff can continue below as normal.
Comment #30
torgospizzaWe have this issue now and then with PayPal - I even created a Rule that tells people to email us if they make it to the "Checkout Complete" page without paying when they should have - so this is definitely in our wheelhouse. I'll give the patch a try. Thanks, @smccabe!
Comment #31
andyg5000Comment #32
torgospizzaI can't say with 100% certainty but at this point we haven't had anyone skipping checkout since applying this patch. If that changes I will update the status again, but I think this is a good candidate for RTBC.
Comment #33
merauluka commentedWe applied it on our client's site and it fixed the issue.
However, it brought up a separate issue with Commerce Discount. :-(
#2618488: Commerce Discount line items cause errors in Commerce
Comment #34
joelpittetRelating that issue as we'll need to track down what validation is failing.
@merauluka do you know what errors or a stack trace?
Comment #35
rszrama commentedAttaching a minor reroll w/ comments on why it was important to check for global error messages. I'm going to hold off on committing until we're sure we can resolve the issue in Discount.
Comment #36
joelpittethttps://www.drupal.org/node/2661530
Fairly confident if we can resolve this commerce entity_unchanged load from calling refresh we will likely be in a better world;)
Discussed briefly with Ryan at midcamp. Will find andy and others to try and pickup the discussion.
Comment #37
joelpittetOk less confident on my last point. Will test tomorrow at sprint
Comment #38
joelpittetI tried to reproduce the discount problem with the latest patch and was unable to, so I don't see currently that this patch should be held up. I'll wait for someone to provide more details as maybe I missed something in reproducing the discount validation issue.
Comment #39
rszrama commentedI could not reproduce the related issue, and I'm pretty sure it's outdated now given the work we did in Commerce Discount 7.x-1.0-beta1 to fix issues with discount deletion / recreation and compatibility checking. As such, committing this one at long last. Sorry for the delay, everyone.