#jscripts_invoice-expand
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/1226942244909482004
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
Hi ๐
When you say "have them display as line items" where are you referring to?
- Yes it is entirely possible to use the Payment Element with Invoices
- You create the Invoice and use the
invoice.payment_intent.client_secretwhen rendering the Payment Element
But I want to be sure you get the experience you are looking for
i am referring to stripe dashboard -> customers -> invoices -> summary
Ah, okay
In that case then yes you can use invoicing with the Payment Element. Our doc here has the details of using the Invoicing API: https://docs.stripe.com/invoicing/integration
And you can use the Payment Inten that is created along with the Invioce in this step in our Accept a Payment guide: https://docs.stripe.com/payments/accept-a-payment?platform=web&ui=elements#retrieve-the-client-secret
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?
You can use this setion of the Invoicing guide here: https://docs.stripe.com/invoicing/integration?method=elements#accept-invoice-payment
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"], });
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})
you're likely passing the wrong variable. You want the PaymentIntent id
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
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
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",
});```
You are using Invoices those require a different integration path. How are you initializing Elements client-side?
i am using this guide: https://docs.stripe.com/payments/accept-a-payment-deferred?platform=web&type=payment&client=react&lang=node#web-fulfillment react + nodejs
can i use invoices with the PaymentElement?
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
is that like this: <PaymentElement options={{ mode: "subscription", }} />
werever you have mode: 'payment' you replace it with subscription instead
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?
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
Well not really "card only". Whatever is the list you have for your Invoices really
https://dashboard.stripe.com/settings/billing/invoice?tab=general at the bottom of that page is where you configure the list of payment methods available for your Invoices
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
You are likely using collection_method: 'send_invoice' and have an old account where those create a legacy Source object for receiving funds per https://docs.stripe.com/payments/sources/credit-transfers
should i not be using send_invoice?
I didn't say that, I'm just explaining what caused the Source which you were asking about that's all
do i have another option, i guess is my question
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
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?
yeah you then have to update the underlying PaymentIntent to set setup_future_usage
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
);
separate API requests you have to call https://docs.stripe.com/api/payment_intents/update not retrieve
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?
You have to make an extra call to the Update Customer API https://docs.stripe.com/api/customers/update to set invoice_settings[default_payment_method] to that new PaymentMethod id in that case
awesome. thank you very, very much! everything is working now
Amazing!
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
perfect, thank you