#bumbzor_code
1 messages ¡ Page 1 of 1 (latest)
đ Welcome to your new thread!
â˛ď¸ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.
âąď¸ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.
đ This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1275791269456515162
đ Have more to share? Add more details, code, screenshots, videos, etc. below.
Below are links to other discussions we've had with you in the past week in case you want to review that information. If your question is related to one of these previous discussions, please provide a comprehensive summary of the current state and what you need help with now. We help many users simultaneously, so a summary allows us to resolve your issue as soon as possible.
- bumbzor_api, 4 days ago, 7 messages
I don't have more info at the moment so hopefully the initial message can give you an idea of what the issue is.
We have that working for one time payments in our code but for some different payment methods the location of the payment method is different.
I don't understand. the PaymentIntent object always has a payment_method property containing the PaymentMethod ID: https://docs.stripe.com/api/payment_intents/object#payment_intent_object-payment_method
like the actual data location is different depending on the payment method used so our code fails because it's looking in for example $intent->payment_method, which works fine for a normal Card payment, but for something like sofort it's not there
can you share a PaymentIntent ID (pi_xxx) where you see this issue?
one sec trying to get that for you
so that's the location (in the right) where our code looks for the data
that's an order with iDeal
but you can see both IDs here, the one we look for and the one Stripe connects to the customer:
can you share the exactly object ID or event ID your code is looking at?
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
"payment_method": "pm_1PqDmpG2lcdV7TvNh58sozlU", exists and it's correct but that;s not the same one that is attached to the Customer
and if you look at the Customer: https://dashboard.stripe.com/test/customers/cus_Qhd21gL9GmeMWT. the payment method attached to it is different.
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
o the payment intent data that you have when the order is created is actually different from when it's completed
"payment_method": "pm_1PqDmpG2lcdV7TvNh58sozlU", exists and it's correct
yes, like I said every PaymentIntent have apayment_methodproperty. so it's working as expected
but that;s not the same one that is attached to the Customer
I agree it's a different PaymentMethod. is that an issue?
Yes thats the issue. that the data is different when it's completed. And this happens only with some of the other payment method options like you see here with iDeal and others
the ID (if you look at the customer's payment method) pm_1PqDn1G2lcdV7TvNvw7Q6c1i is something that Stripe adds after the original creation. A conversion of something.
because of that, when our users try to purchase a recurring product now, with the way it is being handled for some payment methods, like iDeal above, they get this error
The customer does not have a payment method with the ID pm_1PqDmpG2lcdV7TvNh58sozlU. The payment method must be attached to the customer.
that existed initially pm_1PqDmpG2lcdV7TvNh58sozlU but now, the actual customer has a different one that Stripe added.
basically if there is an automated way we can get the converted/custom/new payment method ID from the one that's stored in $payment_intent->payment_method, without having to loop through sepa, sofort, etc. etc. that would be what we need
sorry for the delay, we'll look into this
Hello
Taking over
Give me a moment to catch up
Ok here's something you can actually look at. This is the event: https://dashboard.stripe.com/test/workbench/events/evt_3PqDmrG2lcdV7TvN1RYch76p
In there you can see "payment_method": "pm_1PqDmpG2lcdV7TvNh58sozlU", so far so good. In our code, this is the Event that our Webhook is listening to (for recurring purchases) payment_intent.succeeded (the link I just sent). But in this Event, the pm_1PqDmpG2lcdV7TvNh58sozlU payment_method is NOT the one that Stripe creates and attaches to the Customer. Stripe creates/attaches a different one.
If there is a way for us to get the actual payment method that is attached to the customer via "payment_method": "pm_1PqDmpG2lcdV7TvNh58sozlU" somehow, that would work. Has to be on the same Webhook event: payment_intent.succeeded as that's what the code runs for Recuring purchases.
So if you check https://dashboard.stripe.com/test/workbench/events/evt_3PqDmrG2lcdV7TvN1RYch76p you can see that pm_1PqDmpG2lcdV7TvNh58sozlU is NOT what actually exists on the Customer, but instead pm_1PqDn1G2lcdV7TvNvw7Q6c1i which is generated by Stripe for this payment method, and that does NOT exist in the payment_intent.succeeded event.
Let me ask a colleague to take a look, this might need a deeper look and discord is running busy
hang on
nd that does NOT exist in the payment_intent.succeeded event.
it's thelatest_charge.payment_method_details.ideal.generated_sepa_debit
@burnt gate that's in the charge.succeeded event and we don't listen for that for Recurring purchases.
it's normal to e.g. listen for invoice.paid and or payment_intent.succeeded and in the handler to make API calls to retrieve and expand related objects; not everything is in the payload of the event since that's a base view of the object
so in the payment_intent.succeeded event, how could we obtan the actual payment method attached to the Customer? latest_charge.payment_method_details.ideal.generated_sepa_debit this might be different for each payment option.
to clarify in case it's unclear, when a subscription starts with IDEAL, the first payment uses the iDEAL pm_xxx and then the recurring payments use the generated SEPA Debit PM(who's ID is available as the generated_sepa_debit on the first payment) https://docs.stripe.com/payments/ideal/save-during-payment?platform=web#web-charge-sepa-pm:~:text=can then use the SEPA Direct Debit PaymentMethod ; that can require some special handling in your code since it's different from most payment methods
I'd retrieve the PI expanding the latest_charge(see docs above), check if charge.payment_method_details.type == 'ideal' , branch to special-casing iDEAL and then if payment_method_details.ideal.generated_sepa_debit is set , then that's the one attached to the customer
you should probably also branch for other European payment methods that have the same behaviour like bancontact and sofort , and then test out each scenario and payment method in test mode to confirm
ok so to sum it up. on the payment_intent.succeeded event, Retrieve the PI pm_1PqDmpG2lcdV7TvNh58sozlU (original one) and expand it for latest_charge and the correct Payment Method ID, which is the one actually attached to the customer will. bethere. Sounds about right?
Retrieve the PI pm_1PqDmpG2lcdV7TvNh58sozlU (original one)
pm_xxx is a PaymentMethod not a PaymentIntent.
But yes, you recieve if the event, if (event.type==payment_intent.succeeded) { pi = paymentIntents.retrieve(event.data.object.id, {expand:['latest_charge']}}and then in handlingpiyou can look at those details and figure out if it's a recurring payment or the first payment and what ID you need to save.
one problem here is that payment_intent.succeeded runs before charge.succeeded so there is no latest_charge ? is this possible.
or running what you said, will have the latest_charge as it has ocurred in Stripe already?
you can recieve the events in any order but if you are looking at a payment_intent.succeeded it will have a latest_charge set.
great!