#Shoesole-duplicate-transactions
1 messages · Page 1 of 1 (latest)
Yep, we're running this (using jQuery), and that does disable the submit button:
$("#submit").disabled = true;
K, and how do you handle success?
Are you showing a clear indication of a successful payment?
The reason I ask is because if the payments are a couple minutes apart then that mostly just means customer-error/confusion.
Where they go all the way back through your checkout flow without realizing they successfully completed a payment already
I believe so, we send the user to a confirmation page and use this check:
if (in_array($paymentIntent->status, ['succeeded', 'processing'])) {
So, we're checking against succeeded, and processing as "good" responses and failing all others. Could that be it? Additionally we rely on webhooks to actually save the order in our DB and send the receipt emails.
If you weren't using webhooks then I would have said yes, that could be it, since the user could drop off before reaching your success page but after payment.
We have had SOME users say they got an error, but I feel like more would say that they are going through the entire process again, if they were.
But if you are ingesting data using Webhooks (which is recommended) then that should catch all payments
When do you create the PaymentIntent?
Can you walk through your flow?
We create a payment intent on the final page of our checkout where we display the payment form (however, I create the key used for indempotency earlier on, so I can reuse it if a person is editing their order, etc.
Correct.
Payment Element?
Yes, payment element. Our code for setting that up on the front-end is pretty much from the docs.
I can share the JS we're using to create the element if helpful.
Nah that shouldn't really matter
k
What happens on a page refresh?
As in... you stated you tested the back button
When the page refreshes do you use the same client secret from the previous PaymentIntent?
To render Payment Element?
I'm pretty stumped
Can you give me two PaymentIntents I can take a quick look at?
I don't think I'll be able to see much from my end
I think the best thing to do is going to be to contact a customer who has experienced this and try and get them to tell you exactly what they saw/did on their end.
Sure thing. You're wanting one that had a duplicate I assume
One moment.
np
pi_3LbTGxQpbI6mU6Fo09FLBxSi
pi_3LbTMAQpbI6mU6Fo072lfJm7
The first one is the one stored within our DB, but the client reported a duplicate and that one appears to be it.
So the second one isn't in your Database at all?
correct
I mean I can see you responded to the Webhook
So that's really weird. You have something on your end that is filtering out ingestion of duplicates?
No, but it may be that something prevented it from actually saving on my end... like missing order info from our side (because we already cleared a cart). that's the flow I can seem to nail-down.
Mostly I don't think you are doing anything wrong. This really seems like customer error to me — 4 minutes is too much time for it really to be an integration issue (other than if your success isn't clear and the customer goes back through the flow, but doesn't sound like that is the case here)
But yeah
The database thing is something to investigate
Because that part is odd
For instance, what I originally thought was happening was a user getting to the "success page" after payment, hitting back and then resubmitting, but we clear out their cart and give and error if that is the case). That's worked for me in all my tests.
So, I THINK what I may do is add some logging on my end in the webhook (*since you can see that I responded to both those payment intents). and see what the rest of the order looks like, if anything at all.
Yep I think that is the right thing to do
Also, agreed that it seems there is a customer error in here. I wonder if I'm doing something in our UI to cause confusion to it.
Ah interesting. You do send a different response in the webhook
Which checks out
On the duplicate your response is blank
But on the initial one I can see you send back a <?xml version="1.0" encoding="UTF-8"?> <response><authUser/><createEventLink><controller>Promoters</controller><action>signUp</action><prefix>promoter</prefix></createEventLink><promoterTracking/><usePromoterBranding>0</usePromoterBranding><brandedPromoter>0</brandedPromoter></response> response
Which I assume just has to do with the order and some stuff
If you go to https://dashboard.stripe.com/acct_1LX4BFQpbI6mU6Fo/events/evt_3LbTGxQpbI6mU6Fo0fUU6LFo for instance you can see the response you send back for that event by dropping down the webhook attempt
Versus https://dashboard.stripe.com/acct_1LX4BFQpbI6mU6Fo/events/evt_3LbTMAQpbI6mU6Fo0zj1Ju73 which has no response body
Yeah, that's definitely interesting. So the payload we're sending the second webhook is just empty... right now I'm just sending php://input in the payload... probably from some boilerplate. I could update that with something more useful... I'm so interested in why that second one is showing blank.
Yeah all of this is a bit strange. It almost does feel like there is a bug somewhere...
Also what's weird, totally different application fees on those two. Otherwise they seem identical.
I just am having a really hard pinpointing what it could even be
Oh I missed the different app fees
How is that set?
Welcome to my world. I've been staring at this code wondering what the situation could be that's causing this.
Let me verify how we set that.
We do it when creating the payment intent. It's based on the quantity of tickets sold in the order... which lends further credence to the idea that our cart is empty, or somehow changed.
Yeah
So maybe adding some logic to prevent payment confirmation with an empty cart
And add some logs there too
Even just log on page-load if the cart is empty?
Like... the customer should never be at that point with an empty cart, correct?
yeah, technically I can't event GET to the payment page without a cart. But I'll add some logging like mad just to see what the paths here may be.
I appreciate you taking the time to confirm I'm not entirely insane... I think it's simply something that's causing confusion.
Final question. I show a failure if the order doesn't have a status of pending or succeeded. There isn't any other type I could receive (from a regular payment) that would eventually succeed, is there?
When you say "pending" do you mean "processing"?
Yep, that's what I meant🙄
Yep no worries I figured. Yeah those two are the only ones that would indicate the payment can reach (or already-is) succeeded
Assuming you aren't using manual capture
Which doesn't look like you are
Yeah, okay. I thought so, good to confirm. Thanks I'll take some of these steps and see what I can determine. I'll follow-up if I find out more! Thanks.
Good luck!
Sorry, one other... I just saw this (and it also looks like a dup). But there is something interesting I see.
pi_3LcrqhQpbI6mU6Fo0IIdjWih
that one happened first, but it appears to have failed an zip code check but then succeeded.
Then this one happens a minute later and looks normal:
pi_3Lcrt2QpbI6mU6Fo0GUHG6ew
Yeah I mean overall that is the same really. Only main difference is that one looks to have an actual cart and the cart looks duplicated?
The failed payment is normal.
That decline would appear right in the Payment Element UI and the customer could try again with a different Zip
Yeah, I may totally be reading this wrong, but it seems like the one that had the address validation failure still succeeded, though? Or am I just missing something?
It succeeded on the second attempt
Not on the failure itself
This attempt was declined: https://dashboard.stripe.com/logs/req_IQhhek977n9HOq. Then it succeeded after they changed their postal code: https://dashboard.stripe.com/logs/req_Du4tlsozHsu3Jy
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Then the duplicate (https://dashboard.stripe.com/logs/req_uZPCzQWbaTKpk7) is for a completely different PaymentIntent