#tomasfejfar_code

1 messages ยท Page 1 of 1 (latest)

smoky stagBOT
#

๐Ÿ‘‹ 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.

lean lake
brisk wharf
#

How can I help? We can continue the discussion here

lean lake
#

This is an invoice that didn't have any payment intent update and still it worked correctly (old API)

brisk wharf
lean lake
#

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

brisk wharf
#

It was a client-side request from Stripe.js, not PHP

lean lake
#

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) ๐Ÿ™ˆ

brisk wharf
#

(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)

lean lake
#

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

brisk wharf
#

Of course!

lean lake
#

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.?

smoky stagBOT
brisk wharf
#

I don't think so, no

#

Why would that method allow null? What would you be retrieving?

lean lake
#

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_intent is 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.

vague bluff
#

hi! I'm taking over this thread.

lean lake
#

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:

vague bluff
#

let me know if you have other questions

lean lake
#

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.

vague bluff
#

now:

  • first create the (blank) invoice
  • then add each items to the invoice
lean lake
#

Yes. Exactly what I did.

#

here is the updated diff

vague bluff
#

can you share the Request ID (req_xxx) to create the Invoice?

lean lake
#

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.

vague bluff
#

I'm not sur eI follow. the invoice you shared does have a PaymentIntent.

lean lake
#

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.

vague bluff
#

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

smoky stagBOT
lean lake
#

Want to screenshare? ๐Ÿ™‚

#

I'll at least provide a screenshot from debugger, give me a minute

vague bluff
#

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

lean lake
#

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.

terse radish
#

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?

lean lake
#

I stepped to the next line

#

Another step would cause exception, because the parameter to retrieve is null

terse radish
#

Gotcha, you can focus on the first part of what I asked then. (I'm still backscrolling for context)

lean lake
#

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!

terse radish
#

Oh it doesn't? (I'm not super familiar with PHP)

lean lake
#

Payment intent is not there

#

req_r8TGx7cBIv8eJ3

#

The request is from 3:07:54

terse radish
#

UTC, or in a specific timezone?

lean lake
#

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)

terse radish
#

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

lean lake
#

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.

smoky stagBOT