#holykent

1 messages · Page 1 of 1 (latest)

coarse boneBOT
gloomy dagger
#

Hi there

cobalt herald
#

Hello!

gloomy dagger
#

That event will be emitted any time a payment attempt fails. So yes, it can be async for async payment methods

cobalt herald
#

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"?

gloomy dagger
#

Yeah there is no payment attempt until a PaymentIntent is confirmed

cobalt herald
#

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?

gloomy dagger
#

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.

cobalt herald
#

alright, in what circumstances do i need to cancel payment intents or setup intents?

#

it's not entirely clear to me

gloomy dagger
#

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

cobalt herald
#

Alright, that's good to know. It has essentially no impact on my application then, right?

#

the cancellation of payment/setup intents

gloomy dagger
#

Correct.

#

Only a bit of Dashboard clutter if you care about that

#

But otherwise, no real impact.

cobalt herald
#

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?

gloomy dagger
#

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?

cobalt herald
#

My flow is like this:

Book Now button

  1. 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)
  2. Return reservationId upon success to client
  3. reservationId is passed into one of three endpoints (ProcessKlarnaPayment, ProcessCardPayment, ProcessOfflinePayment (setup intent for this one))
  4. 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.
  5. 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)

gloomy dagger
#

Both Klarna and Cards are synchronous payment methods.

#

You will get a success/failure immediately.

cobalt herald
#

That's great to know. Then there is no issue I assume. Same goes for charging a setup intent?

gloomy dagger
#

Yep

#

Only things like bank debits will have a processing status

cobalt herald
#

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?

gloomy dagger
#

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.

cobalt herald
#

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.

gloomy dagger
#

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

cobalt herald
#

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?

gloomy dagger
#

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

cobalt herald
#

and absolutely not failure?

gloomy dagger
#

Let me double check on Async capture

#

I haven't played with that myself yet as it is pretty new

cobalt herald
#

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?

gloomy dagger
#

Yeah that is true.

#

Same can happen for 3DS

cobalt herald
#

yes

gloomy dagger
#

So you will want a time frame overall

#

In terms of handling your inventory

#

At that point you do want to cancel the PaymentIntent

cobalt herald
#

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

gloomy dagger
#

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

cobalt herald
#

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

gloomy dagger
#

Well there won't be an exception for requires_action

cobalt herald
#

ofc not

gloomy dagger
#

But yeah it will either be an exception, move to requires_action or succeeded.

cobalt herald
#

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

gloomy dagger
cobalt herald
#

i dont see the point of doing that.

gloomy dagger
#

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

cobalt herald
#

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

gloomy dagger
#

Yep

#

That would be my recommendation

cobalt herald
#

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

gloomy dagger
#

Happy to help!