Payment Intents with card pre-authorization#43
Conversation
At the moment payments done with Payment Intents end up in a double charge for the customer. A first charge is created istantly when the customer authorizes their card, and a second one is created later after order confirmation. This issue is not of easy solution, as the first charge is always required for Payment Intents, and the second one is created automatically by Solidus flow. A possible temporary workaround for this issue is to introduce the concept of card pre-authorization: the first charge, now limited to only 1$ is not captured anymore, and have an appropriate description so, even when customers receive notifications for uncaptured transactions from their bank, they will understand this is not going to be actually captured.
kennyadsl
left a comment
There was a problem hiding this comment.
Left a couple of questions, thanks Andrea!
| # frozen_string_literal: true | ||
|
|
||
| module ActiveMerchant::StripePaymentIntentsGatewayDecorator | ||
| def authorize(money, payment_method, options = {}) |
There was a problem hiding this comment.
can't we pass this option to AM via the authorize method in our StripePaymentMethod?
There was a problem hiding this comment.
I think that makes more sense, thanks!
| if params[:stripe_payment_method_id].present? | ||
| intent = stripe.create_intent( | ||
| (current_order.total * 100).to_i, | ||
| 100, |
There was a problem hiding this comment.
what's wrong with preauthorizing the full amount?
There was a problem hiding this comment.
I think that would block twice the full amount on the customer card.
Also, as a customer, I would not be particularly scared by noticing a $1 pre-authorization charge notice (I've seen something similar done in the past by PayPal and Amazon as well if I recall correctly), but seeing the double amount I would instantly think there's been some double charge error.
There was a problem hiding this comment.
yep, but if you have $1 on your card, it's not guaranteed that you have the full amount to pay the order. Anyway, I'm ok with this strategy, and we can revisit it later. We just need to be clear in the README that this is the behavior of the gem. Also, what about pre-authorizing $0.01 instead?
There was a problem hiding this comment.
Unfortunately, you can't pre-authorize less than 0.50$ (or 0.50€... so why not 0.50? if you're in EU and you're buying in USD, the conversion would be 0.43€ which is not acceptable again).
I'm not sure what happens when you don't have enough funds for the order, but I guess that at that point the second payment would fail (for sure the capture would fail).
Anyway, the second payment is Solidus' default process, for example what happens with Solidus Stripe and Elements. The failed pre-authorization for the whole amount would behave just like in that case.
aldesantis
left a comment
There was a problem hiding this comment.
@spaghetticode this is looking good as a workaround, although it's not an ideal UX. For a long-term solution, would it make sense to implement some kind of API in the core to support this?
|
@aldesantis the long term solution would be, in my opinion, to only save the Payment Intents charge in Solidus (with the full amount, uncaptured) and don't create the second one (which is currently created automatically). So, not sure what changes we would need inside Solidus, if any at all... this is something I still have to look into. |
07dc18d to
3e55d38
Compare
| end | ||
|
|
||
| def authorize(money, creditcard, transaction_options) | ||
| transaction_options.merge!(off_session: true) |
There was a problem hiding this comment.
do we need to add this option only when using intents?
When the customer pays with a 3D-Secure card we need to explicitly set the `off_session` param so the charge for their order will not require to go through the 3D-Secure verification step. Failing this, it will not be possible to capture the payment on Solidus backend or Stripe dashboard. This is legitimated by the fact that when we create a Payment Intent, we explicitly allow this by using `setup_future_usage: 'off_session'`.
The card ending with 3184 is not compatible with real-life scenarions as it will always require customer manual authorization, regardless of the actual settings for the payment and payment method used. So, the new card ending with 3155 simulates more realisticly what happens in real life, being still 3D-Secure, but allowing payment methods to create off-session charges.
3e55d38 to
2108717
Compare
|
Superseded by #45 |
At the moment payments done with Payment Intents end up in a double charge for the customer.
A first charge is created instantly when the customer authorizes their card, and a second one is created later after order confirmation. This issue is not of easy solution, as the first charge is always required for Payment Intents, and the second one is created automatically by Solidus flow.
Also, the first charge happens outside of Solidus' current processes, so there's no record of it in on the DB.
A possible temporary workaround for this issue is to introduce the concept of card pre-authorization: the first charge, now limited to only 1$ is not captured anymore, and have an appropriate description so, even when customers receive notifications for uncaptured transactions from their bank, they will understand this is not going to be actually captured.