#tomasfejfar_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/1356954524870377713
๐ 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.
- tomasfejfar_code, 18 minutes ago, 23 messages
Previous channel https://discord.com/channels/841573134531821608/1356941662131196065
How can I help? We can continue the discussion here
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
This is an invoice that didn't have any payment intent update and still it worked correctly (old API)
Because you passed payment details on confirmation: https://dashboard.stripe.com/test/logs/req_hM8ltRxuSjqGnt
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Oh ffs ๐คฆโโ๏ธ I'll debug why it's not happening now...
Thanks
But!
The single piece of code that contains confirm( in the whole codebase is
if ($paymentMethod !== null) {
$paymentIntent->payment_method = $paymentMethod;
$this->getStripeClient()->paymentIntents->update($paymentIntent->id, ['payment_method' => $paymentMethod->id]);
$this->getStripeClient()->paymentIntents->confirm($paymentIntent->id);
}
And that is not the request ๐ค
Aha! That's actually from the UI
It was a client-side request from Stripe.js, not PHP
Weird. The UI didn't change at all (I can't even build it - it's a node app that I have downloaded locally as build version) ๐
(we're going round in circles here, but this is absolutely an integration issue โ there's no behaviour change between API versions with regards to this)
Yes ๐ฆ Sorry. I'm trying to get to the bottom of it.
And I think it might be a race condition as the UI sends multiple requests
If the request to actually pay gets there first, it sets the method. If the request to setup topup does, it fails becase the method is missing... seems like
Anyway, your input was great and it helped me, thanks
Of course!
If you could keep this here open for a while, it would be great, in case I get stuck again or if my hunch about race condition is not correct. ๐
One last try - is it possible, that $stripeClient->paymentIntents->retrieve($paymentIntentId); would allow null previously as an argument and the new API returns The resource ID cannot be null or whitespace.?
I don't think so, no
Why would that method allow null? What would you be retrieving?
It could have been "vague" and return null for null id instead of exception ๐
So far my research:
- I create the invoice:
$invoice->default_payment_method = $paymentMethod;
return $this->getStripeClient()->invoices->finalizeInvoice($invoice->id);
- then i do
$paymentIntent = $this->getPaymentIntent($invoice); <---------
if ($paymentMethod !== null) {
$paymentIntent->payment_method = $paymentMethod;
$this->getStripeClient()->paymentIntents->update($paymentIntent->id, ['payment_method' => $paymentMethod->id]);
$this->getStripeClient()->paymentIntents->confirm($paymentIntent->id);
}
- inside I refetch the invoice from the server
$stripeClient = $this->getStripeClient();
$invoice = $stripeClient
->invoices
->retrieve($invoice->id);
$paymentIntentId = $invoice
->payment_intent;
return $stripeClient->paymentIntents->retrieve($paymentIntentId);
- And the last line fails because
$invoice->payment_intentis empty and the retrieve method fails. - one of the assumptions previously was that the paymentItents->update method sets the method. But that call only happens if $paymentMethod is not null - and it's only not null later, when actually doing the automated topup. When the user already paid before (and thus has payment method set up). In the "first payment and setup off-session" codepath it's not executed. It can't even be executed because the UI didn't send the confirm(), because it didn't receive the payment intent from my backend to act on. Therefore payment method is not build from the form data yet.
The high level logic is:
UI -> create-payment-request (my server) -> gets payment intent -> UI calls confirm
And the failure occurs in the "create payment request" part already.
I did actually now rolled back the API to previous version and it works and the payment intent is set ๐ค So it's likely related to the BC break changes (and the changes I did to accomodate them). I'll examine it further.
hi! I'm taking over this thread.
Now I'm somewhere! ๐
When I take the original code that works with the old API, it doesn't work. The problem is that price field was removed. So I do this change:
let me know if you have other questions
But this code with the new API doesn't add the item to the invoice.
But the docs say
Creates an item to be added to a draft invoice (up to 250 items per invoice). If no invoice is specified, the item will be on the next invoice created for the customer specified.
the way to add items to invoices has changed not too long ago. you can see the new way explained here: https://docs.stripe.com/invoicing/integration/quickstart
now:
- first create the (blank) invoice
- then add each items to the invoice
can you share the Request ID (req_xxx) to create the Invoice?
in_0R9QKE6BNHJembTsOIRAGzX6
But as soon as I do the above change the paymentIntent in the invoice is null.
Request to create the invoice is req_QXMScqi5nwnChn
So the likely difference is IMHO:
Previously:
all existing invoice items were added when creating invoice AND payment intent was created automatically
Currently:
invoice is created empty (thus no automatic payment intent) and items are added manually
Which result in invoice without specified payment intent.
I'm not sur eI follow. the invoice you shared does have a PaymentIntent.
I can show you on screenshare that this code
$stripeClient = $this->getStripeClient();
$invoice = $stripeClient
->invoices
->retrieve($invoice->id);
$paymentIntentId = $invoice
->payment_intent;
return $stripeClient->paymentIntents->retrieve($paymentIntentId);
Shows $invoice
->payment_intent === null
With the new API.
It does have the intent now.
Isn't the payment intent creation somehow async in the new API?
Because I call
return $this->getStripeClient()->invoices->finalizeInvoice($invoice->id);
And on the next line the above code and it's null.
The general issue is that if I rollback this diff (it's the only change I made) it works with the old API.
once the Invoice if finalized, it should contain a PaymentIntent.
unless the amont of the invoice is 0, in which case there is nothing to pay, so no PaymentIntent
Want to screenshare? ๐
I'll at least provide a screenshot from debugger, give me a minute
we can't do screenshare, sorry. the simplest option would be for you to prodive an Invoice ID where you don't see a PaymentIntent
in_0R9QkV6BNHJembTsS65x32Jj
And I see it has the intent pi_2R9QkX6BNHJembTs12BA9d8X in the UI
But above you can see live that the API did not return it.
Hi there ๐ jumping in as my teammate needs to step away. Bear with me a moment while I catch up here.
A couple things, have you tried retrieving the Invoice with a tool like our CLI and/or Postman to see the raw response from the API, or tried logging the full response from the API in your code?
Also, it looks like you have your breakpoint on the line that assigns a value to your variable, do you know if your IDE pauses before execution of a line that has a breakpoint or after?
I stepped to the next line
Another step would cause exception, because the parameter to retrieve is null
Gotcha, you can focus on the first part of what I asked then. (I'm still backscrolling for context)
I see the payment intent in cli, same as in UI with payment intent set
The client is official stripe client - here is the retrieve method
Oh, now I know!
$invoice = $stripeClient
->invoices
->retrieve($invoice->id);
This doesn't actually fetch the invoice from the API!
Oh it doesn't? (I'm not super familiar with PHP)
Sorry, my mistake it does.
Here is raw response from Stripe
Payment intent is not there
req_r8TGx7cBIv8eJ3
The request is from 3:07:54
UTC, or in a specific timezone?
And the request was finalized in req_VLQCPOl42Jm6rd
Check the request times yourself
The finalize finished in 3:06:52 PM
I'm copying them from UI, not sure what timezone is that
Likely my local one
UTC+2
yup,
UTC 1:06:52 PM
Sorry, but Ihave to step away from the computer to run an errand.
Have to pick up kids ๐
If you could keep this thread open so that I don't have to build the whole context again with someone, that would be great.
The current question is why
the invoice was finalized in req_VLQCPOl42Jm6rd (:06:54)
the api returned no payment intent in req_r8TGx7cBIv8eJ3 (:07:54)
It could be that the payment intetnt is missing payment method, but again, this exact same code worked in the previous API version (2020-08-27)
Based on what I'm seeing at this point, I think this is a change introduced by the newest API version. Where now Payment Intent details are stored within the payments hash on the Invoice object:
https://docs.stripe.com/api/invoices/object#invoice_object-payments
Specifically within payments.data.payment.payment_intent:
https://docs.stripe.com/api/invoices/object#invoice_object-payments-data-payment-payment_intent
Based on the response you shared, I think you'll need to use expand to include the payments hash in your request:
https://docs.stripe.com/api/expanding_objects
Ah, yup, mentioned here in the release notes:
https://docs.stripe.com/changelog/basil/2025-03-31/add-support-for-multiple-partial-payments-on-invoices
Oh! The title was so unassuming ๐
That looks like the root issue. I'll debug it when I get back.
Thanks a lot. And please keep the thread open if possible ๐ I'll write here as soon as I validate it.