#mesudev-webhook

1 messages ยท Page 1 of 1 (latest)

bold garden
#

Hi there ๐Ÿ‘‹ what's your question?

normal juniper
#

Hi Toby, great, thanks, so, I had a quick chat about the rough implementation of the webhook with one of your admin devs, and wanted to check upon a last question

#

happy easter by the way

bold garden
#

Thanks and same to you! ๐Ÿ˜„

normal juniper
#

Cheers! So:

#

I'm currently integrating your solution into my platform. Consider the following (I try to be as short as possible):

  • My platform stores CCs upon account creations
  • My platform only allows CC (incl Google Pay and Apple Pay) payments, because all payments pass through authorize (at the moment the service is booked) and capture (after the service has been provided)

The principle of a service booking is setup like this:

A) Client clicks on "book service"

B) payload about the service is sent to the platform server, and a new payment intent is created on the server - side with the according pricing information, without confirming

C) the obtained client secret of the intent is sent back to the frontend as a response to A)

D) The client secret is used to do Stripe.confirmCardPayment on the frontend to confirm the payment intent, and to eventually trigger and use the authentication popup modal (3D secure)

E) If everything's alright and the payment could be confirmed / confirmed and authenticated, another request is made to the platform server. THIS IS WHERE THE CONNECTION MAY FAIL, AND THE WEBHOOK SHOULD KICK IN, as a fallback recommended by your admin dev

F) In the second server call of the flow, internal platform DB adaptations are made to register the paid service on the side of the platform. This includes multiple DB updates, hence taking place in the form of a transaction.

The issue now is: The server-side script that would respons to a positive answer from E) executes the same internal DB tasks as the script called via the webhook. Like this, I can always be sure that the integrity of my reservations is intact, even if the client loses connection at the moment described in E).

My question is: How can I properly treat the race in between the non-webhook and the webhook script, which listens to https://stripe.com/docs/api/events/types#event_types-payment_intent.amount_capturable_updated ?

#

My current logic is:

A) storing a DB record before authorization, for example INSERT INTO status_list (ID,payload) VALUES (1,$data)

B) I pass the ID of that DB record to the metadata of the created payment intent, as your metadata best pracs recommend it (https://stripe.com/docs/videos/developer-foundations?video=metadata&lang=php); such that the payload is available to the webhook script too.

C) Upon start of the transaction used in both the webhook / non-webhook script, I use "SELECT ... FOR UPDATE" to check for the existence of such a record A), using "SELECT ... FOR UPDATE" to assure that the snapshot used for the transaction is not taken from one of the two scripts while the other one is in execution (and hence, the state of the record A) is the same and both will fully execute).

D) At the end of a fully executed webhook / non-webhook script, I delete the record A) and commit the transaction.

bold garden
#

Ah gotcha, yeah race conditions can be challenging. Looking at your first message, if you have webhooks notifying you of successful auth, then do you need to make a synchronous request to your sever to trigger that flow as well?

normal juniper
#

That would be ideal yes, to immediately take care of it; so basically do exactly the same, except from providing any output to the client, as that would happen off-session

#

Or do you see a better approach? It's just cause a week ago your colleague said this for my scenario:

"Generally when you're doing client-side confirmation you want to have both the client-side code and the webhooks both trigger server-side confirmation of the payment success (or capture success), with the one that happens first being the "winner"."

And well I wanna make sure that I use the perfect approach for the "winner" thing ๐Ÿ˜„

bold garden
#

Gotcha, if your goal is to be able to show something to your customers if they don't immediately leave the flow, then making that synchronous request makes sense. If the results of the flow from Step E or the webhook won't be returned to the client in any way, then I would just use the webhook events to trigger that flow.

The flow you described for preventing the race condition in your DB sounds reasonable, but it's been a while since I've had to do anything like that so I'm not terribly knowledgable on the topic.

normal juniper
#

Well yes I'd need to provide an immediate feedback to the client, as the payment of my platform is associated with many other functions like a chat, a calendar etc., so immediate frontend updates + an according feedback according to the use-case are a must if the transaction is not being triggered via the webhook ๐Ÿ™‚

#

Hmmm okay, and (no offense of course) you probably don't have any colleagues that are experienced with such stuff which are currently online; that you could pull into the chat?

bold garden
#

None taken! No I don't, and most of them would decline providing guidance on topics that far outside of the Stripe ecosystem.

normal juniper
#

Ok cheers then! And just to double-check, the payment_intent.amount_capturable_updated event is the right one to track in that context right? It's not triggered when you for example cancel an authorized payment or refund one that was authorized and captured etc., right?

#

exclusively when a payment gets authorized OR you update the payment intent with another amount (which I never do in my entire stack)

#

I'm particularly asking this because the script executed via the webhook / non-webhook eventually cancels a previously authorized / refunds a previously captured payment. So if that would also trigger payment_intent.amount_capturable_updated I would end up in an endless loop, making my and your servers fume ^^

bold garden
#

Double checking on that.

normal juniper
#

Cheers! And just to say it again, your support is awesome! Given the crazy interesting scope of custom stripe integrations, I'm really thinking of joining stripe as my work ๐Ÿ˜„

bold garden
#

I just tested creating and confirming a separate auth/capture intent, and it did generate payment_intent.amount_capturable_updated when confirming the intent, but did not trigger the event again when I canceled it.

normal juniper
#

ok cool ๐Ÿ™‚

bold garden
normal juniper
#

I mean if you have a suggestion for a better event to listen for the successful authorization of a payment, lemme know. I found that one to be the best choice for my case.

bold garden
#

No better suggestion here, that's the perfect event for the scenario you're handling.

normal juniper
#

Okidoki, then I'll implement that in the discussed way!

#

Thank you! Can I maybe ask you a few other questions before closing our thread? They're probably much easier for you to answer

bold garden
#

Sure

normal juniper
#

Cheers! So the thing is that I've integrated everything in my platform to be handled automatically except the authorizations; captures, refunds etc. are all automated. In that sense, I noticed that connected account users can, in their own dashboard, manually refund a payment. I actually want to avoid that, as the refunds should be handled by the automation I've integrated on my platform. My question here is thus, how can I disable that connected account users can manually refund payments in their dashboard?

bold garden
#

What type of connected accounts are you going to be using?

normal juniper
#

ah yeah sorry, I'm using stripe connect express accounts with destination charges to split the payments incoming from my customers to the platform + connected accounts.

#

They've actually told me that that's the best setup they recommend for my business model when using stripe

bold garden
#

Gotcha, so Express accounts don't have access to the main (for lack of a better term) Stripe dashboard. I know that when you're logged into the dashboard, it gives you the option to view the dashboard as a connected account but that's most representative of what a Standard connected account would see.

normal juniper
#

aaaaaaaaahhhhhhh

normal juniper
#

Because your docs say that the platform is responsible for refunds etc. when using stripe connect non-standard, but then in the preview you can basically do everything as a connected account user, that scared me somewhat ^^

bold garden
#

Yup, that bit of dashboard functionality is definitely confusing. For Express accounts a separate, and very limited, dashboard was built where they can see activity and make changes to the one or two settings that they have control over:
https://stripe.com/docs/connect/express-dashboard

Learn about the features of the Express Dashboard.

normal juniper
#

So my connected account users don't even have a dashboard then? That's perfect, because that's what I was looking for. Oh ok, checking your link now, one sec.

#

I guess I'll just setup an express account for my own on my prod environment to see what it looks like then ๐Ÿ˜„

#

Thanks a lot for that, what a relief!! Because my second question concerned the payout thing; because in the dashboard preview as a connected account, I could trigger manual payouts. As I've preset payouts via the connected account API when creating the accounts, I'd also like to prevent that. Particularly due to the refund flows:

My platform allows the customers to receive a full refund within 6 days after the capture of the payment. The reason is because the payouts are set to occur on a weekly basis, so within 7 days, the payments stay within the stripe balance of the connected account; with the payout fees of connect express not being applied yet. So the principle is to not lose more money than the basic stripe transaction fees, even in case of refunds; makes sense?

#

I was also confused what the payouts_enabled parameter does in that case (https://stripe.com/docs/api/accounts/object#account_object-payouts_enabled); I guess it's for no use in my context; as I must enable payouts to all of my service providers anyway? Or is it better to explicitly set the payouts_enabled => true flag when creating my connected accounts, to be on the safe side?

bold garden
#

So payouts_enabled isn't a parameter that you can drive (you'll notice it's not listed in the API ref under the create or update account functions). Instead it's a field that you can consume to check whether Stripe is allowing payouts on an account.

normal juniper
#

aaah ok, so useless anyway in my scenario

bold garden
#

Possibly, if it goes to false then that indicates that something is wrong with the account, likely it's missing necessary KYC/KYB info.

normal juniper
bold garden
normal juniper
#

OK yes, sorry for the non-dev question actually.

#

Great thanks for your help, it's gonna be a hell of a productive easter monday now!

bold garden
#

Heck yes, that's what we like to hear!