#яσчαℓтℓя

1 messages · Page 1 of 1 (latest)

golden pythonBOT
marble bolt
#

Hi there!

#

What is your questions?

rustic tundra
#

Hi Soma

#

Well, our client takes one-off payments from customers for various digital products such as classifieds and auctions.

#

I did initially go down the route of using the checkout API to create invoices until I realised that you cannot use this API for one-off invoices

#

As explained here in the second sentence

#

So, I have built a custom invoicing flow for customers who need to check out some of our client's products. In most, if not all cases, the flow is very similar to the checkout flow (except we don't have payment intent, session or anything like that)

#

Essentially the flow is this:

  1. User signs up and Stripe customer is created. They enter their payment method details (this is required to sign up to the platform)
#
  1. User bids on auctions or sells an auctions - both buyer and seller are charged a commission. This is triggered by cronjobs and invoices are sent accordingly
#
  1. User decides they want to buy a classified ad. During classified creation, they must confirm their order. When they click "Confirm Order" - we do a few things - generate an invoice (create), generate the invoice items (create invoice items), finalize the invoice and make the payment of the invoice.
#

We do this so it acts like a checkout flow.

#

However. We've run in to some weird 'race-condition-esque' issues. For example. Let's say an auction ends and triggers invoice create, finalise and pay flow for both buyer and seller.

But at the same time, the same user is ordering a classified ad. This ultimately causes some issues where the invoice items are wrong. The code assumes that the auction invoice item is supposed to be the classified order invoice item or vice versa

#

How do you suggest we tackle this problem?

#

It's ultimately not a good situation because there is the possibility of invoicing customers with the incorrect line items.

#

The main question I have is how do you suggest we have a checkout-like flow for one-off payments using invoices when a user could (by nature of how we have configured the invoice API integration) create line items for two separate things at the exact same time ?

crisp sail
#

Hi there 👋 I'm jumping in to lend a hand, please bear with me a moment while I catch up on the context here.

rustic tundra
#

Sure no probs

crisp sail
#

I'm not sure to fully understand the race-condition-esque issues you are having ?
You are creating the invoice and then you attach the invoice_item to that invoice. In other words, you set the invoice property when creating the invoice_item, no ?

rustic tundra
#

Yes that is true

#

I guess the best way to explain it is through what actually happened

#

In fact, let me see if I can find the webhook logs

#

we_1LibZqIlSjun4h3swLsFoj6D

#

This is our webhook ID

crisp sail
rustic tundra
#

Yeah so that's maybe what's causing the issue

#

Do you have any suggestions for guaranteeing continuity between webhook events and our database?

#

We keep records of every Stripe Transaction in our database

#

Here is the odd one

#

Now, if you click the invoiceDownloadUrl

#

You will see the description. Well, the description is incorrect. This description was set by a Webhook event

#

evt_1LzLFEIlSjun4h3s9C8NQGMT

#

It's a really challenging problem to solve

crisp sail
#

If your implementation is based on webhook event order. then you need to redesign your flow.

rustic tundra
#

Yes I was about to say

#

I think the webhooks are messing things up

rustic tundra
#

Basically what I meant is that an invoice was sent and in our database, the Stripe Transaction record has a related ID for the item the invoice was for. However the related item ID and the actual invoice description do not match.

#

Same with all the other fields in our database

#

If you look above at the JSON I sent, at the bottom it shows VAT

#

VAT: 58000

#

And you check the VAT, it is not the same. Basically, something has gone wrong in the webhooks.

#

Could the solution be to move all invoice finalization logic our of the webhook and into a controller instead?

#

I'm 95% sure it's the webhooks that are making our database records out of sync, and ultimately the invoices being associated with incorrect items in our database

crisp sail
#

So the event you shared evt_1LzLFEIlSjun4h3s9C8NQGMT is for this invoiceId in_1LzLFCIlSjun4h3s1Trzpweo. While the record you are showing is for another invoice which is in_1LzLFDIlSjun4h3sVeuwJmZT

#

Those are two different invoices

rustic tundra
#

Yes exactly

#

So let me show you

#

These are the three rows in question

#

Let me know if you are able to view this?

crisp sail
#

Could you please provide the content here in messages

crisp sail
# rustic tundra Yes exactly

I'm not sure I'm following you. The webhook event is related to an invoice and you are referring in your database to completly another invoiceId

#

so you'll have different values at the end

rustic tundra
#

Ok let me see if I can explain concisely

crisp sail
#

yes please!

rustic tundra
#

evt_1Lz2N8IlSjun4h3sxNFv5xdX

#

Please first check this event

#

As you can see, the invoice ID for this event is in_1Lz2N8IlSjun4h3sbRa3z7rD

#

And the idempotency key is create-invoice-ef27aad3-17db-4c92-a731-4350571df7d5

#

Make note of the createdAt time as well 1667239566

#

Note that the idempotency key is matching the webhook event, but the invoice ID is not

#

As you can see in our webhook event code, we are updating the record in our database when the event comes through

#

We then update the record again when the invoice is finalized

#

But yes, as you can see it is causing some weird inconsistencies. The data in our database is not correct, the relational data is correct but the data the is updated via the webhook is out of sync.

#

I guess it all comes back to what you said earlier:** Stripe does not guarantee delivery of events in the order in which they are generated**

#

So my question becomes, how do we keep the integrity in our database when Stripe cannot guarantee delivery of events in the order in which they are generated?

crisp sail
#

This record has an idempotencyKey: ef27aad3-17db-4c92-a731-4350571df7d5 and an invoiceId in_1LzLFCIlSjun4h3s1Trzpweo different to the webhook event Id (create-invoice-ef27aad3-17db-4c92-a731-4350571df7d5 and in_1Lz2N8IlSjun4h3sbRa3z7rD

#

The idempotencyKey are not the same also not just the invoiceId

rustic tundra
#

It's because we append it

#

The idempotency key is appended, sorry forgot to mention that

crisp sail
#

first off all you need to keep the same idempotencyKey on all sides

rustic tundra
#

It would be the same from Stripe point of view

#

Another thing I noticed

crisp sail
#

In your database, persist the event_id also

#

not sure that you are referring to the same event, which did triggered the record in your database

rustic tundra
#

evt_1Lz2N8IlSjun4h3sxNFv5xdX
evt_1LzLFDIlSjun4h3s5SOBYCIY

#

Both of these events have the same metadata

{ transactionId: 1 }

#

However, according to my code I am surprised that is the case.

#

They should have different transactionIds

#

Okay so you suggest persisting the event ID

#

I will redesign this flow then. There's clearly something wrong. I think I might try to stay away from webhooks as it can be quite confusing and often getting unexpected behaviour which, to be fair, might be my fault but yeah, it's not what we need when it comes to payments

kind salmon
#

Hello, soma had to step out but I can help. Taking a minute to catch up in this thread...

rustic tundra
#

No worries, I think we are done here

#

I am struggling a bit but it seems like the solution is to just not use webhooks as much as feasibly possible

kind salmon
#

Gotcha, good to hear you have a way forward at least. Let me know if you come across any further questions