#50an6xy06r6n

1 messages · Page 1 of 1 (latest)

thick sageBOT
pearl needle
#

Hello 👋
Can you provide a concrete example? I'm not sure I follow the usecase exactly.

fringe obsidian
#

so we're a connect platform where service providers charge customers or recurring services, so we're saving their payment info and creating offline payment intents. After the payment intent is created, we save its ID onto our internal data object for the service provided so that when we receive the webhook indicating that the payment succeeded we can pull up that service object and perform a follow-up action.

The issue we're having is that the webhook is coming through before the payment intent ID is saved onto the service object, which causes the follow-up action to not be taken

#

The reason we don't send the webhook a failure response is that there are other types of payments that we aren't currently handling the payment intent webhooks for

pearl needle
#

When you say offline payment intents, do you mean off-session? When the customer isn't really around to authorize the payment?

fringe obsidian
#

ah yes I mean off-session

pearl needle
#

I'm hesitant to set off_session to false in case that triggers some extra confirmations that we're not equipped to handle.

What's the recommended flow here? It seems like it would be a common scenario
if the off-session payment requires additional authorization (like 3DS), then you'd typically receive an error and payment intent would switch to requires_action status. You'll have to bring your customer back on-session to complete authorization.

The issue we're having is that the webhook is coming through before the payment intent ID is saved onto the service object, which causes the follow-up action to not be taken

The reason we don't send the webhook a failure response is that there are other types of payments that we aren't currently handling the payment intent webhooks for
Not sure I completely follow this. Are you saying when the event is delivered, your database is still processing your service object?

fringe obsidian
#

yes

#

I thought I could solve it by creating and confirming the payment intent separately but then I got the above error

pearl needle
#

Ah I see. So let me summarize so that I'm on the same page (feel free to correct me if I am wrong)

1/ You're creating off-session PaymentIntents
2/ When you receive payment_intent.created you make a call to update your own service object (in your database)
3/ However, payment_intent.succeeded is delivered before your earlier update call finishes.
4/ That causes your code to not trigger additional actions and update the service object with the latest information from the PaymentIntent

Am I understanding the issue correctly?

fringe obsidian
#

for 2) we're actually updating the service object using the response returned from stripe.paymentIntents.create

#

otherwise that's correct

pearl needle
#

Gotcha. Hmm thinking..

fringe obsidian
#

is this not a common use case? I can think of a few ways around it but they all seem slightly hacky

pearl needle
#

Typically folks perform the operations asynchronously by implementing a queue like logic where if the object is busy then they stack the update and wait for it to finish.

fringe obsidian
#

But how do you know how to group the webhooks? or is it just a global queue

pearl needle
#

There's no way to group it, no. The webhooks are delivered asynchronously when they are generated. That's also the reason behind why we don't guarantee order of the events as well as the average time it would take to receive these events.

thick sageBOT
fringe obsidian
#

ok so going back to the original issue, how should we handle it?

sand geyser
#

Hi, stepping in as it's hanzo end of the day. Please give me some time to read through the thread.

fringe obsidian
#

any thoughts here?

sand geyser
#

Still catching up here and trying to understand the root issue before I can share next steps. Thank you for your patience.

#

Ok, I'm caught up. As hanzo stated, there is no guarantee for ordering of events: https://stripe.com/docs/webhooks/best-practices#event-ordering. You'd need to be resilient to this. Your endpoint shouldn’t expect delivery of these events in this order and should handle this accordingly. You could fetch events here.

fringe obsidian
#

what do you mean by fetch events?

#

I guess the slight difference here is that I'm not relying on a webhook event to save the payment intent ID

#

I'm using the response from the API call. Is that also not guaranteed to arrive before the webhooks?

sand geyser
#

The response should happen right away.. earlier, you mentioned webhook so that is why I made the recommendation. In this case, you can look at the response and fetch the Payment Intent by making the 'Retrieve a PaymentIntent
' API call: https://stripe.com/docs/api/payment_intents/retrieve

fringe obsidian
#

well the issue is the sequencing of the webhook and the response

#

The way we know how to respond to a webhook is that we match it to a DB object that contains the Stripe resource ID, which we store on the object when the Stripe resource is created. But since we don't get the Stripe resource ID until after the API call is made, that can create a race condition

#

In the past we just returned a failure response when the object wasn't found, which forced a retry. But that seems sketchy