Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem / motivation
When a payment method is selected during checkout, it is not used to make a payment.
Proposed resolution
Perform the payment transaction when the checkout complete event is fired.
Remaining tasks
- Implementation
- Tests
Comment | File | Size | Author |
---|---|---|---|
#16 | Complete___Site-Install.png | 29.26 KB | mglaman |
#12 | 2820931-11.patch | 4.15 KB | steveoliver |
#11 | 2820931-10.patch | 7.57 KB | steveoliver |
#8 | 0001-Completes-payment-from-checkoutflow.patch | 4.08 KB | ChrisGrewe |
Comments
Comment #2
steveoliver CreditAttribution: steveoliver commentedFrom the PR: "This works, but needs some cleanup (see @todos). Also needs test(s) - I tried in https://gist.github.com/steveoliver/3135b75b573d0fb902ebc7cf23426505#fil..., but had issues getting a payment method to be created this way. I'd like someone else to take it from here."
Comment #3
mglamanSo I have concerns about the event listener.
With
'commerce_order.place.post_transition' => 'onOrderPostPlace',
the event will run on admin placed orders and checkout. Checkout and admin have two flows, in my opinion. With checkout an order collects payment information before being placed. An admin workflow probably leads to an order being placed then collecting payment. We cannot always assume we have payment method information on the placed transition, only when in the checkout context.Comment #4
steveoliver CreditAttribution: steveoliver commentedAh, good point. I'll take another look at it.
Comment #5
steveoliver CreditAttribution: steveoliver commentedThe way forward is to use (re-add) the Checkout complete event.
Comment #6
steveoliver CreditAttribution: steveoliver commentedWe also need a way to create a payment transaction with knowledge of whether to capture or not.
Comment #7
ChrisGrewe CreditAttribution: ChrisGrewe commentedSteve, building on what bojanz said here in #2822056, could your code potentially work in CheckoutFlowBase::validateForm (with a similar condition to what's firing the complete event) to create the payment? We could trap any exceptions there and redirect back to the current step with an error message if the payment fails or proceed to complete if it's good.
Comment #8
ChrisGrewe CreditAttribution: ChrisGrewe commentedI'm working on a payment processor implementation right now, so I went ahead and took Steve's code from the event listener and moved it to CheckoutFlowBase::validateForm (with appropriate conditionals and one minor fix, which was to use the $payment_gateway->id() for the payment gateway as opposed to the plugin ID, which only worked if the name of the plugin for the gateway was the same as the gateway plugin's ID). This seemed to work for me and could be used as a starting point at least. We'd needed a dependency on commerce_payment added to commerce_checkout if this is to work though.
Comment #9
steveoliver CreditAttribution: steveoliver commented@ChrisGrewe, we won't be able to make a dependency for commerce_payment in commerce_checkout -- the modules are intended to not be required. We will need to find a way to safely support payments on checkout without the hard dependency.
I'll see what I can come up with.
Comment #10
steveoliver CreditAttribution: steveoliver commentedAttached patch moves payment creation into payment module by setting values on form_state in checkout, signifying that the form is a commerce_checkout_form and when it is complete. No dependency between modules. May need some tweaking and there are follow-up todos, but this seems to work. Needs a test or two.
Comment #11
steveoliver CreditAttribution: steveoliver commentedWhoops, patch attached.
Comment #12
steveoliver CreditAttribution: steveoliver commentedAttaching actual patch, last one was interdiff.
Comment #13
nikathoneTested patch #12 with commerce braintree and dev version of commerce module and it seems to be working.
Comment #14
mglamanGoing to take a stab at wrapping this up. Here's a tl;dr of what I discussed with bojanz that will help support onsite and offsite payment gateways
offsite_payment
steppayment_information
will allow selecting payment gateway and selecting payment method if an onsite gatewaypayment_process
that lives on Payment pageThis then places all payment collection logic in one place. Onsite payments will provide the form redirect based on success or failure.
Comment #15
mglamanNew PR: https://github.com/drupalcommerce/commerce/pull/542
Comment #16
mglamanCame across an issue that I think we should handle in a follow-up. On-site payment gateways will cause the payment page to be skipped (we have a payment method and we run it to create a payment.) This only needs to be present when the user has selected an offsite payment gateway.
I have messed around with
::isVisible
a bit but there isn't a good solution. I tried to return FALSE if the gateway was OnSite, but then it caused the page to be skipped. But this was also an issue in 1.x with the checkout progress module.Comment #17
bojanz CreditAttribution: bojanz commentedOpened followup for #16: #2831945: The payment step is always present in the checkout progress block.
Comment #19
bojanz CreditAttribution: bojanz commentedBOOM!