#ghidinelli

1 messages ยท Page 1 of 1 (latest)

limpid flareBOT
sly sinew
#

FWIW, one of the things causing us to look at this is we'll be introducing US ACH which has async settlement so we'll require some async processing for payments. We're exploring whether or not we can go all-async, all-the-time or not. We just don't want to be the first/only using this approach. ๐Ÿ™‚

proper swift
#

to asynchronously sending requests to stripe for storing, charging, and refunding accounts; catching webhooks; and pushing results out to the pages/clients with a websocket
No the recommendation only to be part-async or async when you need to. You still do sync transactions, but handle any extra operations on listening to webhook. I would say it's hybrid.

Just follow https://stripe.com/docs/payments/ach-debit/accept-a-payment for ACH on Checkout

Build a custom payment form or use Stripe Checkout to accept payments with ACH Direct Debit.

#

What is a "typical" time we should expect to wait to receive a webhook from Stripe for a successful Checkout Session, Charge, or Refund?
Should be immediate. Test it on Test mode!

sly sinew
#

If it's good enough for a Stripe Checkout Session, why not do it for charges and refunds too?

#

It's not clear what are the reasons to be part sync and part async (vs. say a more consistent processing pipeline if one were to be all async)? This post from stigg.io got me thinking we could use a similar architecture and drop every webhook from stipe into a queue and process them FIFO (knowing we have to deal with idemopotency and out of order events).

In this article we will describe what are the best practices to create the webhook integration with Stripe. We will be focusing only on one side of our two-way integration. The side that is listening to webhooks and acting on them.

proper swift
#

For fulfilling orders yes it's recommended for async. ie if you customer is on a train getting into the tunnel, they will lost their internet access and won't reach the redirect. So you are correct! I meant all other things than fulfilling orders, ie if you create a Customer, or create a Subscription, or create a PaymentIntent, you can look at the response instead of listen to customer.created in example.

#

So if you are asking about fulfilling orders, yes async all the way!

sly sinew
#

Ok, copy. And what about taking a SetupIntent and then firing off a PaymentIntent? Or performing a refund at a later date? There isn't a redirect at play, but I'm trying to foresee any negatives to pushing those webhooks into the same queue and letting workers update the database (and then signal to the user via websocket or polling). There is additional complexity in the last part, but there's also consistency in that everything would traverse that pipeline.

#

(finally, it may let us replatform those webhook workers bit-by-bit as we change our tech stack)

#

I'm willing to trade a bit of upfront architectural complexity for fewer ways of doing things. I am just afraid of what I don't know here.

proper swift
#

Can you elaborate a bit about taking SetupIntent and firing off PaymentIntent? What does it have to do with webhook?

sly sinew
#

So our flow is generally during checkouit:

  • Put a card on file (using Elements today, but Checkout in the future we hope)
  • Charge it right away if it's a "charge now" checkout
  • Inform the user it'll be charged later on fulfillment

I'm evaluating an architecture like:

  • Using Checkout to capture SetupIntent; listen for webhook checkout.session.completed (IIRC) to know it succeeded, convert that into a customer with a payment method and store that value in our database
  • If we have a "charge now" checkout, then create a PaymentIntent. What I'm suggesting is that I would put that PaymentIntent into a queue, and a worker would pull it and make the API call to Stripe.
  • Stripe would send back a webhook response as to whether or not the charge succeeded.
  • We'd grab that, put it into a queue again, and a different worker would process the charge completed event, updating the database.
  • The page the user was on with the Stripe Checkout would have a websocket open (or polling JS) and would check to see if their payment status gets updated and their order is done.

Now this is some extra lifting for processing a payment, but for our delayed fulfillment cases, sometimes we have instances where an operator fulfills up to 1000 orders at once. Each of those needs to run a PaymentIntent. I'm thinking with this queue->api call->webhook->webhook processing worker architecture, we can use the same approach whether we're processing a single charge during a user checkout or we have an admin processing 1,000 orders at a go.

Does that make sense?

#

I know we can have a PaymentIntent and simultaneously set up the charge for offline processing. However, we currently put every card on file because there can be additional charges later. For that reason we thought we would mirror our current implementation and put every account on file (e.g. SetupIntent) and then conditionally charge a minority of them on the spot (PaymentIntent).

proper swift
#

I hear you and somewhat get the intention, but these 2 steps

Stripe would send back a webhook response as to whether or not the charge succeeded.
We'd grab that, put it into a queue again, and a different worker would process the charge completed event, updating the database.
What advantage vs just take the response from the API call of creating PaymentIntent earlier? Says you send out 1000 Create PaymentIntent requests (you surely will hit rate limit, it's 100 RPS so probably you would need to split it to 10 batch of 100 requests, but that's a different thing), you can just get 1000 response and continue

#

The async/fullfill order is for eliminating the connection dependency between customer's browser and your server. But here is your server vs Stripe server

sly sinew
#

I say 1,000, but next year maybe it's 10,000. The year after 100,000 (would be an awesome problem to have! ๐Ÿ™‚ ). At the queue level I can throttle RPS across all requests and not just charges (thanks for sharing that, I didn't know).

I'm probably doing a poor job of explaining, but I suppose I'm trying to abstract away who is making the call (is it our server, is it a user browsing our site) and create a consistent mechanism for sending requests to stripe and processing their responses, and, finally, distributing those results to interested listeners (be that, again, via our server ot our dataase or to a user in their web browser).

#

The current tech we're on has server-side timeouts, so processing 1,000 payments server-side might not complete successfully.

It would also get thru the 1,000 much faster if we could fan out even just 10 concurrent workers instead of 1 looping thru them, no?