#holykent
1 messages · Page 1 of 1 (latest)
Hi there
Hello!
That event will be emitted any time a payment attempt fails. So yes, it can be async for async payment methods
Yes, but it has nothing to do with the paymentintent, right? it has to do with the confirmation of the paymentintent? the underlying payment intent could be "ok"?
Yeah there is no payment attempt until a PaymentIntent is confirmed
how can i reasonably respond to this event if payment is processing for 15 minutes until it fails, after which the user has left the site potentially?
just cancel the paymentintent and send a mail to the customer?
if i have a grace period of 15 minutes, it's safe to always cancel any paymentintents that come in as failures in the webhook?
You don't really have to cancel the PaymentIntent -- it will just move back to requires_payment_method and you can confirm it again in the future.
That is up to you though, if you prefer to do clean up by canceling that is fine.
alright, in what circumstances do i need to cancel payment intents or setup intents?
it's not entirely clear to me
But yes, for async failures you likely want to contact your customer
You never have to cancel PaymentIntents or SetupIntents
They can be "incomplete" indefinitely
Alright, that's good to know. It has essentially no impact on my application then, right?
the cancellation of payment/setup intents
Correct.
Only a bit of Dashboard clutter if you care about that
But otherwise, no real impact.
Alright, yeah no that's fine. So, in cases where processing takes an abnormally long time to finish, it might be a good idea to queue a mail to the customer in he webhook upon failed paymentintents? is this a common practice to deal with the problem of payment intents that take too long?
Well let's back up.
This first is dependent on what types of payment methods you are going to support
Like payment_intent.payment_failed will be emitted immediately for synchronous payment methods (like cards)
What are you really trying to do with payment_intent.payment_failed events here?
My flow is like this:
Book Now button
- CreateReservation endpoint (create reservation and schedule an undo reservation job 15 minutes from now that wil run only if payment is not "succeeded" in the grace period)
- Return reservationId upon success to client
- reservationId is passed into one of three endpoints (ProcessKlarnaPayment, ProcessCardPayment, ProcessOfflinePayment (setup intent for this one))
- In processklarnapayment and processofflinepayment we return client secret if nothing else fails, in processcardpayment we both create and confirm intent and that's that (and check for requires_action so the client can do further authorization as per SCA regulations.
- All while this is happening, my webhook listens for setupintent statuses and payment intent statuses, and translates them to my own statuses and assigns them to the correct Reservation.
In 4, this is important for the undo reservation job as it will know whether to undo the reservation or not.
And the client also polls stripe to get payment status for 10 seconds, if it's succeeded, we show a receipt of some kind "Purchase successful", if not, we tell them payment is processing and we'll send a mail.
So that's where we are, mail stage. I should just send a mail to the customer if the payment fails? i dont think there's a way for them to reuse that paymentintent (in the case of card payments).
is this a reasonable flow and am i thinking correctly about it?
will it always be emitted immediately for card payments? that's what Im asking i think
cant card payments also be stuck in processing for a while?
The only other types of payment i have are klarna and offline (so just a setup intent that we intend to charge in the future. We save it in the db along with a customerid)
Both Klarna and Cards are synchronous payment methods.
You will get a success/failure immediately.
That's great to know. Then there is no issue I assume. Same goes for charging a setup intent?
does this mean that I can safely assume that if ConfirmAsync (card paymentintent) doesnt throw an exception, it is guaranteed to be either requires_action or succeeded?
you say they are synchronous but there is aconfirmasync method for payment intents
i guess you mean synchronous on stripes end then?
Yes that's correct. And yes, I wasn't talking about using capture_method: automatic_async if that is what you are referencing with the above.
var confirmedPaymentIntent = await retryPolicy.ExecuteAsync(async () => await _paymentIntentService.ConfirmAsync(paymentIntentId));
should I be using ConfirmASync or Confirm or does it depend on the type of paymentmethod in the paymentintent?
if it's card vs sepa debit?
im guessing async either way and that it's synchronouns on stripes end since it does take a small amount of time to finish the ConfirmAsync operation I've noticed.
Yes that's correct.
It is just a latency thing
So it is really up to you and just depends on how you want your integration to flow
Yes ok, so if ConfirmAsync(PaymentIntentId) does not throw an exception (neither stripe nor httprequestexception), i can assume that it's either requires_action or successful?
The easiest route is to simply use confirm and show a spinner for the 1-2 seconds that it takes for the PaymentIntent to process
and absolutely not failure?
Let me double check on Async capture
I haven't played with that myself yet as it is pretty new
gotcha!
I feel like I will have to undo reservation either way after 15 minutes because once klarna leaves my server and client confirmation is needed, there's no way for me to know if they closed their browser and decided not to pay and now they get a reservation for free.
or is there some better solution for that im missing?
yes
So you will want a time frame overall
In terms of handling your inventory
At that point you do want to cancel the PaymentIntent
so it's good to release inventory and undo reservation like I'm doing? I've never worked with ecommerce payment flow before
if(reservation.Payment is OnlinePayment onlinePayment)
{
if (onlinePayment.PaymentStatus is PaymentStatus.Paid)
{
await _paymentGateway.CancelPaymentIntent(onlinePayment.PaymentIntentId);
return Unit.Value;
}
}
else if(reservation.Payment is OfflinePayment offlinePayment)
{
if (!offlinePayment.SetupIntentIsSuccessful)
{
await _paymentGateway.CancelSetupIntent(offlinePayment.SetupIntentId);
return Unit.Value;
}
}
Yes i have something like this
Okay yeah with async capture you will still get an exception immediately if payment fails
It is just that the balance transaction and other stuff is available later
and this is true for klarna and card?
and if n oexception was thrown during ConfirmAsync, we can safely assume that either it requires further action (3DS) or is successful? just to be sure :p
Well there won't be an exception for requires_action
ofc not
But yeah it will either be an exception, move to requires_action or succeeded.
great, well then I can't see that the webhook is that useful for payment intents?
currently in my webhook i send mails and schedule a payout job to host upon Events.PaymentIntentSucceeded
but if you say it occurs instnatly
You should also make sure that you have the ability to handle connection errors and API errors in case those come into play. See: https://stripe.com/docs/error-handling
i dont see the point of doing that.
Even "instantly" takes time.
So overall you do want webhooks
Though if you are polling the API then that is the other option
And that does solve the issue, though overall Webhooks are recommended over polling
but once confirmasync is done, either an exception is thrown or success, we're stil lserver side. Then I dont see why i cant just queue the mails and schedfule thepayout job immediately there instead of the webhook?
But yes nvm i forgot about 3DS
so i may as well handle all mailing and payout jobs in the webhook for all payments
one central place
Yes, thanks. you're doing the lord's work in this channel. now i dont have to scour the docs another 150 hours to get some reliable answers :p
thanks
Happy to help!