#nerder
1 messages ยท Page 1 of 1 (latest)
for extra details
invoice = await this.stripe.invoices.finalizeInvoice(
invoice.id,
{ expand: ['payment_intent'] },
{
stripeAccount: stripeAccountId,
},
);
this is how i'm completing retrieve the payment_intent client secret and return it to the frontend to complete
Hi, without extra details, if you just wanted to have a default Payment Method for invoices, you can add it here on the customer object: https://stripe.com/docs/api/customers/create#create_customer-invoice_settings-default_payment_method
nono, is not that scenario
i'm not looking for setup intents here
i'm doing a payment of an invoice with a payment method, and i want that payment method attached to the customer as soon as they have complete the payment for the first time
so that they can use it again in the future
Thank you for the added details, looking
with subscriptions it works properly, but i'm not sure why with invoice it doesnt
Can you share which Setup Intent document you're using here?
ill show you the code
async create(accountId: AccountId, customerId: string, priceId: string, fee: Fee): Promise<Invoice> {
const stripeAccountId = accountId.value;
//Creating the invoice
let invoice = await this.stripe.invoices.create(
{
customer: customerId,
application_fee_amount: fee.amount,
},
{
stripeAccount: stripeAccountId,
},
);
//Add products to the invoice
await this.stripe.invoiceItems.create(
{
invoice: invoice.id,
customer: customerId,
price: priceId,
},
{
stripeAccount: stripeAccountId,
},
);
// finalize the invoice and expand the payment_intent
invoice = await this.stripe.invoices.finalizeInvoice(
invoice.id,
{ expand: ['payment_intent'] },
{
stripeAccount: stripeAccountId,
},
);
//extract the client secret
const clientSecret = (invoice.payment_intent as Stripe.PaymentIntent).client_secret;
//return it back to the frontend
return Invoice.of(invoice.id, ClientSecret.of(clientSecret));
}
this is the method i'm using to create the payment_intent
in the frontend instead (using flutter_stripe)
await _stripe.confirmPayment(
clientSecret,
PaymentMethodParams.card(
paymentMethodData: PaymentMethodData(
billingDetails: BillingDetails(
email: customerEmail,
name: customerName,
),
),
options: PaymentMethodOptions(
setupFutureUsage: PaymentIntentsFutureUsage.OffSession,
),
),
);
so basically the fronted call the API for create the invoice and wait for the secret to come back then completes the payment intent when the customer confirms
the payment succeed but there is not payment method attacched to the customer
I see, do the issue is that after you confirm the Payment Method on the client-side, you're not using the resulting Payment Method. As for next steps, you'd want to get the Payment Method from the confirmed Payment Intent and make a customer update call to make that Payment Method the default here, https://stripe.com/docs/api/customers/create#create_customer-invoice_settings-default_payment_method
ok, so i should listen to a webhook event and update the payment method?
but why this works for subscriptions instead?
is done by default there when you create a subscription?
Subscription works differently.
Yes, you can listen to the payment intent succeeded event, and retrieve that Payment Intent to get the Payment Method id.
ok ill try this
i've tried by the way and for some reason when creating a sub i receive payment_method.attached event and the default payment method is set automatically
i guess that in that case i should skip the payment_intent.succeeded event for when is coming from a subscription in order to avoid attach the default payment method again
But that is for subscription correct? The above integration is for creating an invoice, then adding the Payment Method to the customer for a default Payment Method.
yes this is correct, there should be something i don't understand because when in the fronted i setup PaymentIntentsFutureUsage.OffSession my understanding was that this is what the fronted library is calling under the hood: https://stripe.com/docs/api/payment_intents/object#payment_intent_object-setup_future_usage
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
which is the case when the payment_intent originates from a subscription.create but not from a invoice.finalize
now, i can "force it" with the approach you propose of setting it manually, but i feel there is something wrong
From you client-side code, you set the up setupFutureUsage: PaymentIntentsFutureUsage.OffSession so you can charge this Payment Method later. Attach it to the customer's invoice default settings.
With Subscriptions, it just works.
ok, i'll fix it as you propose ๐
sorry to be a pain, just wanted to understand why they act differenly (or at least not in the way I expected it)
btw, seems the proposed solution doesnt work
This PaymentMethod was previously used without being attached to a Customer or was detached from a Customer, and may not be used again.
if I try to do this:
await stripe.paymentMethods.attach(
paymentMethodId,
{ customer: customerId },
{
stripeAccount: connectedAccountID,
},
);
await stripe.customers.update(
customerId,
{
email,
invoice_settings: {
default_payment_method: paymentMethodId,
},
},
{
stripeAccount: connectedAccountID,
},
);
๐ taking over here. Gimme a few mins to go through this thread
Can you give the PaymentMethod Id here? For easier tracking
in my last was: pm_1M7UeoLAVB3C1lDIDF2PgwoE
this is the payment instead pi_3M7UhjLAVB3C1lDI0wp7ifab
my suspicious now goes down to this: https://dashboard.stripe.com/test/logs/req_vExIqm4Dj4Acqr
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
i don't see something that indicated that the payment method should be used for future usage
hey did you manage to find anything?
Hi, sorry gimme a few mins
To avoid confusion let me clarify. I am looking at pm_1M7UeoLAVB3C1lDIDF2PgwoE. It's created and confirmed by in_1M7UelLAVB3C1lDIvhXK9zxw and pi_3M7UenLAVB3C1lDI1CC8Vqgl
there is something quite odd here, the payment intent created by the subscription has indeed setup_future_usage: "off_session"
It's different than pi_3M7UhjLAVB3C1lDI0wp7ifab you mentioned
I think you probably mixed things up
might be
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 one
they are all the same, all the PI created from an invoice.finalize create a PI which as setup_future_usage set as null
in_1M7UhhLAVB3C1lDIYpslJLOf
pm_1M7UhlLAVB3C1lDIQOcqxtaL
pi_3M7UhjLAVB3C1lDI0wp7ifab
correct
check the logs from this one for instance
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Okie they are tighted to cus_MrD7vzb27CmRj0
you will see that the POST request that the fronted made is the same
but for some reason in the PI response the setup_future_usage is null
and if I try to set it up by myself handling payment_intent.succeeded it fails
Hey let's take a step back. By this state, what request you made after receiving payment_intent.succeeded and what is its request id? req_xxx
after?
this 2
await stripe.paymentMethods.attach(
paymentMethodId,
{ customer: customerId },
{
stripeAccount: connectedAccountID,
},
);
await stripe.customers.update(
customerId,
{
email,
invoice_settings: {
default_payment_method: paymentMethodId,
},
},
{
stripeAccount: connectedAccountID,
},
);
attaching the payment method i retreive from the PI and try to set it as default
but it fails with: This PaymentMethod was previously used without being attached to a Customer or was detached from a Customer, and may not be used again.
if you want i can try another example fresh
No, let's find that errors in your request log
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
req_WAkr5PZTLlQN1r
this one for instance
this feels like a bug in how invoice creates the payment intent underneath
Ummm let me try it myself
Hi I just reproduced it. You were correct that this is like a limitation on our side, that when you confirm an Invoice's PaymentIntent via frontend, the confirmed PaymentMethod is treated as an one time used PM and can't be attached to the Customer later
wow
My suggestion is try to collect the PaymentMethod beforehand, via a SetupIntent
then once you have it and attached to the Customer, then you can use it later on in Invoice without thinking of confirmation
that's not ideal for how my flow works i should rethink the entire thing
Just simply set it on the Invoice's default_payment_method, or the Customer's invoice_settings.default_payment_method
can't i create the payment intent myself then?
Independent of the Invoice? Yes but that wouldn't link to the Invoice