Create a single charge when using Stripe Payment Intents#45
Merged
spaghetticode merged 13 commits intoApr 10, 2020
Merged
Conversation
This allows the controller to be aware of the data included in the payment form.
When the customer pays with Payment Intents we need to explicitly require manual capture, or the Payment Intents charge will be marked as authorized as soon as the customer authorizes the use of their card. Also, in order to allow the reusability of the payment method that is created when the customer adds a new card, we need to explicitly mark the payment intents valid for off-session usage.
We need to make sure that when the customer is checking out by adding a new Payment Intents card, we don't create a second payment by following the standard Solidus payment flow. Also, when the customer does completes the payment by changing the payment method after having added a new Payment Intents card, we need to make sure that the pending charge for that intent is voided.
This change is required in order to allow customers to successfully checkout by reusing an existing card that was added via the Payment Intents API.
The card ending with 3184 requires always 3D Secure authentication, whether the payment method was created with the option to be used off-session. It is replaced by the one ending with 3155, which represents a more realistic scenario, requiring authentication only when actually necessary.
This will allow to edit the Payment Intent description on Stripe dashboard.
Spree::Payment#gateway_order_id is defined as private in Solidus, so the public method `gateway_order_identifier` is introduced in order to make it accessible outside the context of the Payment model. app/decorators/models/spree/payment_decorator.rb decoerator
This service encapsulates all the logic for creating a Solidus payment starting from a Stripe Payment Intent object. It also updates the Payment Intent description with Solidus payment number, so it's much easier to match them on Stripe dashboard.
When reusing a 3D-Secure card it's important to verify that the payment stored in Solidus can be properly captured. If the original payment method or subsequent payments made with it are not properly configured, Stripe will create charges that cannot be actually be captured, without showing any error.
By extracting the method `#authenticate_3d_secure_card` we can avoid much code repetition among specs using the 3D Secure card.
We need to ensure that, when the customer pays first with a Payment Intents and then changes the payment to something else (ie. check) the first payment gets voided.
We need to invalidate existing pending Payment Intents payments when we're adding a new credit card with Payment Intents.
spaghetticode
force-pushed
the
payment-intents-single-payment
branch
from
April 9, 2020 15:50
3336912 to
891e31a
Compare
kennyadsl
approved these changes
Apr 10, 2020
kennyadsl
left a comment
Member
There was a problem hiding this comment.
Thanks @spaghetticode, commits are super-readable and they made it easier to review.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #44, plus other minor issues found while working on that main problem.
When using the Payment Intents API, we need to create a single charge. In order to achieve the goal, we now create a Solidus payment as soon as the Payment Intent is authorized from Stripe (while the customer is still on the payment page). Later, we skip the creation of the second payment during Solidus default flow after the order has been confirmed.
The first payment will be created
uncapturedinstead ofauthorized(already captured) as the customer may decide to not complete their purchase.When the customer enters multiple credit cards during the same checkout process or changes the payment method from a freshly entered credit card to something else (ie. check) we also need to properly invalidate (void) stale Payment Intents charges and their payment records in Solidus.
This PR also fixes an issue with 3D-Secure card reusability. before this fix, orders finalized by reusing an already authorized 3DS card would end up in creating payments that cannot be properly captured.
Some integration tests were added in order to improve edge cases coverage, including checks on the backend that verify payments are created with the proper state and their capturability, when appropriate.