#jscripts_invoice-expand

1 messages ยท Page 1 of 1 (latest)

honest gorgeBOT
#

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

๐Ÿ“ Have more to share? Add more details, code, screenshots, videos, etc. below.

native cairnBOT
graceful trench
#

Hi ๐Ÿ‘‹

When you say "have them display as line items" where are you referring to?

#
  1. Yes it is entirely possible to use the Payment Element with Invoices
#
  1. You create the Invoice and use the invoice.payment_intent.client_secret when rendering the Payment Element
#

But I want to be sure you get the experience you are looking for

slate pagoda
#

i am referring to stripe dashboard -> customers -> invoices -> summary

graceful trench
#

Ah, okay

slate pagoda
#

some test mode examples of that

graceful trench
slate pagoda
#

when i create the invoice: ``` // create an invoice
const invoice = await stripe.invoices.create({
customer: customerId,
collection_method: "send_invoice",
days_until_due: 1,
});

#

what collection_method and other options do i need?

#

because ill be creating an invoice first, and then charging immediately for it when they submit the payment intent right?

native cairnBOT
graceful trench
slate pagoda
#

ok so it looks like const invoice = await stripe.invoices.create({ customer: '{{CUSTOMER_ID}}', collection_method: 'send_invoice', days_until_due: 30, });

#

and then i need to add expand payment_intent: const finalizedInvoice = await stripe.invoices.finalizeInvoice(invoice.id, { expand: ["payment_intent"], });

fringe eagle
#

yep!

#

jscripts_invoice-expand

slate pagoda
#

testing it right now

#

im getting this error, in my node endpoint: Error: Stripe: Argument "intent" must be a string, but got: [object Object] (on API request to GET /v1/payment_intents/{intent})

fringe eagle
#

you're likely passing the wrong variable. You want the PaymentIntent id

slate pagoda
#

not sure what you mean: ``` const finalizedInvoice = await stripe.invoices.finalizeInvoice(invoice.id, {
expand: ["payment_intent"],
});

// retrieve the paymentIntent using the finalized invoice paymentIntent
const paymentIntent = await stripe.paymentIntents.retrieve(
finalizedInvoice.payment_intent
);```

#

im getting paymentIntent id from the invoice. can i not do that?

#
    customer: customerId,
    collection_method: "send_invoice",
    days_until_due: 30,
  });

  for (const item of items) {
    /// add the invoice item
    const invoiceItem = await stripe.invoiceItems.create({
      invoice: invoice.id,
      customer: customerId,
      price: item.id,
      quantity: item.quantity,
    });
  }

  const finalizedInvoice = await stripe.invoices.finalizeInvoice(invoice.id, {
    expand: ["payment_intent"],
  });

  // retrieve the paymentIntent using the finalized invoice paymentIntent
  const paymentIntent = await stripe.paymentIntents.retrieve(
    finalizedInvoice.payment_intent
  );

 
  res.status(200).json({
    customerId: customerId,
    clientSecret: paymentIntent.client_secret,
  });```
#

thats my whole endpoint body. create the invoice, add the items, finalize the invoice (with expand: payment_intent"), and then retrieve the paymentIntent + clientSecret from the finalizedInvoice

fringe eagle
#

you are passing finalizedInvoice.payment_intent which used to be a **string ** pi_123 and is not a full API resource { id: 'pi_123', object: 'payment_intent', ...}`

#

so you have to change your code to pass finalizedInvoice.payment_intent.id instead

slate pagoda
#

got it. so that did pass again now, but i get the same error on the client side again: "Payment details were collected through Stripe Elements using automatic payment methods and cannot be confirmed with a Payment Intent configured with payment_method_types."

#

thats when i call:

#
          elements,
          clientSecret: response.data.clientSecret,
          confirmParams: {
            return_url: "http://localhost:3000?step=purchase",
          },
          redirect: "if_required",
        });```
fringe eagle
#

You are using Invoices those require a different integration path. How are you initializing Elements client-side?

slate pagoda
#

can i use invoices with the PaymentElement?

fringe eagle
#

yes but you have to use mode: 'subscription' instead I think because our Invoices are not using our "dynamic payment method type calculation"
So try switching to mode: 'subscription' to see if it solves your issue

slate pagoda
#

is that like this: <PaymentElement options={{ mode: "subscription", }} />

fringe eagle
#

werever you have mode: 'payment' you replace it with subscription instead

slate pagoda
#

got it, so now im getting: "The provided setup_future_usage (null) does not match the expected setup_future_usage (off_session). Try confirming with a Payment Intent that is configured to use the same parameters as Stripe Elements."

#

is that because susbscriptions require future_usage? do i need to set that on my invoice paymentIntent?

fringe eagle
#

you can't set that on your Invoice

#

So yeah I think in the end you have to go back to payment for mode and then force the list of paymentMethodTypes that matches what you have configure for your Invoice unfortunately

#

or change and go back to creating the Invoice first and then using the underlying PaymentIntent for it

slate pagoda
#

force the list, on the paymentElement?

#

meaning, make it card only?

fringe eagle
#

Well not really "card only". Whatever is the list you have for your Invoices really

slate pagoda
#

got it. when i switch my payment method to ['card'], it works, but, the payment method default gets set as ACH Credit Transfer? i used test card 4242

fringe eagle
slate pagoda
#

should i not be using send_invoice?

fringe eagle
#

I didn't say that, I'm just explaining what caused the Source which you were asking about that's all

slate pagoda
#

do i have another option, i guess is my question

fringe eagle
#

If you collect card payments synchronously though then no it doesn't make sense to use send_invoice at all

#

What you want in that case is charge_automatically which is the default really so you don't need to pass that parameter

slate pagoda
#

that makes a lot more sense. so that is now not saving a payment method, which is to be expected right? and now can i use setup_future_usage to save the payment method?

fringe eagle
#

yeah you then have to update the underlying PaymentIntent to set setup_future_usage

slate pagoda
#

is that a seperate api call i can make using my finalizedInvoice.payment_intent.id? in this part? ``` const finalizedInvoice = await stripe.invoices.finalizeInvoice(invoice.id, {
expand: ["payment_intent"],
});

// retrieve the paymentIntent using the finalized invoice paymentIntent
const paymentIntent = await stripe.paymentIntents.retrieve(
  finalizedInvoice.payment_intent.id
);
fringe eagle
slate pagoda
#

thank you, got that working, i now see the invoice, payment and payment method all coming through. and then my last question, can i make that the default payment method?

fringe eagle
slate pagoda
#

awesome. thank you very, very much! everything is working now

fringe eagle
#

Amazing!

slate pagoda
#

sorry im back. im getting a successful response on this ``` const paymentIntent = await stripe.paymentIntents.update(
finalizedInvoice.payment_intent.id,
{
setup_future_usage: "on_session",
}
);

 const cusUpdated = await stripe.customers.update(customerId, {
  invoice_settings: {
    default_payment_method: paymentMethodId,
  },
});
console.log("cusUpdated", cusUpdated); ``` but its not updating the default payment method
#
  id: 'cus_Pt98kumxTOXTi8',
  object: 'customer',
  address: null,
  balance: 0,
  created: 1712600563,
  currency: 'usd',
  default_source: null,
  delinquent: false,
  description: null,
  discount: null,
  email: 'hklsjghkjshjg@gmail.com',
  invoice_prefix: 'F6AB8585',
  invoice_settings: {
    custom_fields: null,
    default_payment_method: null,
    footer: null,
    rendering_options: null
  },```
#

and its null

#

aw paymentMethodId is null

#

this needs to be a seperate call i make, afterwords?

#

cuz this is while im generating the client secret

fringe eagle
#

yes

#

1/ Pay the Invoice successfully
2/ After that, update the Customer

slate pagoda
#

perfect, thank you