Active
Project:
Pay
Version:
6.x-1.1
Component:
Code
Priority:
Normal
Category:
Feature request
Assigned:
Unassigned
Reporter:
Created:
29 Dec 2010 at 02:29 UTC
Updated:
3 Sep 2011 at 18:46 UTC
Jump to comment: Most recent file
We're having a problem with Pay module in that it allows orders to go through and submit handlers to execute before it knows that the credit card number was invalid or denied. In pay_form.inc's form_validate() method, Pay module should load each payment method and query the payment gateway to ensure the credit card is valid.
I tried putting this code together myself but I couldn't figure out how to have the payment method query the gateway without creating a pay transaction and a pay activity, which seems completely unnecessary for merely validating the number.
| Comment | File | Size | Author |
|---|---|---|---|
| #5 | pay_validate_gateway2.patch | 2.61 KB | quicksketch |
| #3 | pay_validate_gateway.patch | 2.63 KB | quicksketch |
| #2 | pay_validate_authorizenet.patch | 1.03 KB | quicksketch |
| #1 | pay_validate_gateway.patch | 2.63 KB | quicksketch |
Comments
Comment #1
quicksketchI figured this out with a little bit of research. Reviews on this patch would be greatly appreciated. It does seem to properly validate, note that payment gateways such as authorize.net will also need to be updated to set $this->error_message when validation fails.
Comment #2
quicksketchHere is an example change needed for Authorize.net. Other gateways would need a similar minor change. Considering this error is shown to end users, I made it a slightly more friendly message.
Comment #3
quicksketchMy patch in #1 wasn't properly using the fallback error if the payment gateway did not set one in $this->error_message.
Comment #4
charlie-s commentedThanks for bringing this up. Using Pay/Webform Pay/Authnet modules and having this problem. Credit card fails but "success" page is shown. I've applied both patches but see identical results. Does this need similar patching with Webform Pay?
Comment #5
quicksketchAfter applying this patch we're having issues with double-charging of users. Even though the first charge should be for zero dollars, it seems like our payment gateway (Authorize.net) combines the first request (AUTH_ONLY) with the second request (AUTH_CAPTURE) and charges twice. To prevent this behavior I've amended the current patch to put the gateway into test mode first before it sends the authorization request. This ensures that the first transaction is never charged or even recorded, but it still does the basic validation testing.
No, it should throw the validation error regardless of which module is showing the form. We're using this same patch on Webform Pay also.
Comment #6
beetlecat commentedThat seems a little awkward from a software point of view, but if it gets the job done...
Does putting the gateway into test mode still result in properly validated cards? It's easy to test for malformed numbers, but expired or canceled (or overdrawn) cards are a different issue.
Could a multi-page form perform some of this validation on page one, then processing on page two?
I really want to keep to a simple one-form, cart-less checkout, but pay+webform pay are coming up short so far.
Comment #7
quicksketchYeah I agree. Well as it turns out it doesn't even validate the card properly anyway when it's in TESTMODE, so I guess I'll have to look at other options. Now that I've researched a bit, I think the issue isn't that the card is getting charged twice, I think it's because the administrator receives an e-mail for both the authorization and the actual charge, which makes it look like it got double charged (but it didn't really). I'll need to research further.
Not currently. Right now the entire pay component must be on the last page of the form. Of course if your form is only one page then you don't have to worry about that and just put everything on one page.
Comment #8
quicksketchSo after further research it looks like it's pretty much impossible to just ask a payment gateway, "Could you validate this number for me?" You MUST specify some value amount (even just $0.01) to actually get a reliable response back. Further more, there's no way to just request a check without charging or at least authorizing the card.
It would appear that the only reliable way of doing validation against a payment gateway would be to "authorize" the transaction during validation, and then send a followup "capture" (or charge) request to finalize the previously authorized request. Unfortunately this means that we need to store the transaction ID temporarily between the form validation and submit handling, not to mention that Pay (as far as I know) doesn't yet support separate authorize and capture requests at all. I'm setting this request back to active because the current patches certainly aren't going work correctly.
Comment #9
beetlecat commentedIt's curious that this problem hasn't been noticed before. :) Perhaps it is only an issue with a module like "webform pay" since completing the transaction and submitting the form are the same activity -- and both happen no matter what the response is from the processor.
Comment #10
allie mickaquicksketch, It seems reasonable to do the authorize + capture in two steps. After all, who cares if the credit card number is valid if there's not enough credit to handle the transaction? The auth / capture two-step is much easier to finish now, but not quite there yet. The authorization will be stored as its own activity, which will obviously persist through form handling transaction.
When we've got that working, this patch should be revisited.
Thanks a lot!
Comment #11
krisrobinson commentedSubscribing
Comment #12
univate commentedThis issues is a bit of design flaw in the pay process.
Ideally the credit card payment really should be happening in the validation step (after all the other form elements are validated). That way if the payment fails it can use form_set_error like any other form validation method and redirect back to the form to get the user to attempt again.
Currently I am trying to use pay to purchase nodes and the way I managed to hack around this is in a hook_nodeapi [$op == 'presave'] and to do a drupal_goto back to the form page if the payment failed. Which then stops the node being created if the payment fails for any reason.
Comment #13
skoledin commentedJust adding my support for fix on this issue. Not being able to stop the flow for failed payments basically prevents the use of Pay and associated modules for any type of real-time authorization flow. If an admin still has to cross check between submits and actual successful payments via their gateway then the usefulness is really limited.
Is there any general way to catch an error message from the gateway and at least ask the user to re-submit before going to a success page? I don't mind doing it manually in the Confirmation page, but just not sure how to even catch the error (using webform_pay in this case).
Comment #16
stella commentedI don't think we can rely on pay's validate routines capturing every scenario - e.g. communication errors, and really this has to be handled within webform_pay itself. I've got a patch working for this, see #1038436: Handling of failed transactions for more deets.