#marcus-invoice-finalization
1 messages ยท Page 1 of 1 (latest)
Hello ๐
It looks like the PaymentIntent is still in requires_confirmation status hence the invoice is in incomplete state.
payment intent - where / how should I get it from? The invoice, the invoice item, or the finalize part?
If you retrieve the Invoice then it should have a PaymentIntent property
https://stripe.com/docs/api/invoices/object#invoice_object-payment_intent
You can expand it to get the clientSecret and use Stripe.js to confirm the payment client-side
you mean before or after finalizing it?
after it has been finalised and is in open status
and if I retrieve the payment intent earlier it wont work?
so creating the invoice, adding the item, finalizing the invoice and then finally. retrieving it AGAIN just for the payment intent?
sounds very unefficient ๐ฆ
The alternative would be to store the payment method of a customer prior to creating an invoice by using a SetupIntent
And then relying on Automatic Invoice Advancement
https://stripe.com/docs/invoicing/integration/automatic-advancement-collection
but at this point the customer alreadt has a payment method attached, because hte customer has also an active subscription at this point
so creating the invoice, adding the item, finalizing the invoice and then finally. retrieving it AGAIN just for the payment intent?
To be clear, the payment intent will be on the invoice as soon as you finalize it, no need for that last retrieval
great thanks
but... is the confirmation actually needed.. given that we already have the customer's payment method
Do I need add an expand?
If the payment intent is in a requires_confirmation state then yes the confirm call is needed. What collection_method are you using when creating this invoice? If it it charge_auomatically we will attempt to charge the user's default payment method if they have one on file
Though keep in mind the payment method needs to be set as the customer's invoice_settings.default_payment_method , just having it attached won't do that
You don't necessarily need to expand but that could be helpful if you need its client secret or if you want to check its status
private Invoice createInvoice(String stripeCustomerId) throws StripeException {
return Invoice.create(InvoiceCreateParams.builder()
.addDefaultTaxRate(stripeTaxRateId)
.setCustomer(stripeCustomerId)
.setCollectionMethod(InvoiceCreateParams.CollectionMethod.CHARGE_AUTOMATICALLY)
.build(), requestOptions);
}
private void createInvoiceItem(String stripeCustomerId, String stripePriceId, int units, Invoice invoice) throws StripeException {
InvoiceItem.create(InvoiceItemCreateParams.builder()
.setCustomer(stripeCustomerId)
.setPrice(stripePriceId)
.setQuantity(Long.valueOf(units))
.setInvoice(invoice.getId())
.build(), requestOptions);
}
CHARGE_AUTOMATICALLY
pm_1M56G4F2iEUqWxhT1zHzKIYW
is that the default.. or not?
Checked in the dashboard... looks like default to me
Interesting, maybe that setting is only for subscription invoices. Can you try directly passing pm_1M56G4F2iEUqWxhT1zHzKIYW as the payment method to the invoice create call?
? I should manually set the payment method to the invoice create call???
While I could do this for a test.. How would I do this then later.. we dont store the payment method.. so I would have to retrieve the payment method before hand???
Yeah I was thinking of doing it just for the test
Trying to think of what that would actually look like in live mode as well, but that test will be informative
in my current test.. I first of all fail already with the payment intent expand
somehow it is empty still
Invoice.create(InvoiceCreateParams.builder()
.addExpand("payment_intent")
That would probably still be because the invoice isn't finalized immediately. I think there is a way to create the invoice items first, and create the invoice in a way where it immediately finalizes. That may be closest to the flow you are looking for here. I will need to look in to this and get back to you
Sorry, was just getting to this now. So it looks like we don't have a doc, but you can create the invoice items on the customer first, then create the invoice and pass auto_advance: true , that will automatically finalize the invoice and should attempt to automatically charge the user
wait... create the invoice items before the invoice? on the customer? now I am confused
Invoice.create(InvoiceCreateParams.builder()
.addDefaultTaxRate(stripeTaxRateId)
.setCustomer(stripeCustomerId)
.setAutoAdvance(true)
.setCollectionMethod(InvoiceCreateParams.CollectionMethod.CHARGE_AUTOMATICALLY)
do I still need the charge automatically?
Yes, you can create the invoice items on the user, then when creating the invoice will collect all of those invoice items and put them on the invoice. Depending on your API version you may need to explicitly set pending_invoice_item_behavior to include to have them automatically included https://stripe.com/docs/api/invoices/create#create_invoice-pending_invoice_items_behavior
pi_3M5X6eF2iEUqWxhT13cBIUby
not sure if I did correctly.. but the invoice is still incompletre it seems
InvoiceItem.create(InvoiceItemCreateParams.builder()
.setCustomer(stripeCustomerId)
.setPrice(stripePriceId)
.setQuantity(Long.valueOf(units))
.setInvoice(invoice.getId())
.build(), requestOptions);
so I should create the invoice item WITHOUT the invoice???
It looks like that was set up properly. I think that charging the default PM automatically may only be for subscription invoices. Can you try making the pay call without providing a specific payment method ID and see if that works here? https://stripe.com/docs/api/invoices/pay
It isn't ideal to make another call, but that would probably be better than needing to look up the ID and then use it in another call
Again should i
a) create the invoice item, THEN the invoice. or first the invoice, then the invoice item?
pi_3M5XJHF2iEUqWxhT143UDLNR
that invoice.pay() seems to have done the trick
will that work, without a payment intent, also for 3dSecure which is default in Germany?
Also, it seems I dont actually need to finalize it? pi_3M5XNWF2iEUqWxhT15ceLXBv
set AutoAdvance true seems also not required?
will that work, without a payment intent,
Yes, if this is a $0 invoice without a payment intent, the call should still work, though you might want to explicitly test that to see the behavior better.
also for 3dSecure which is default in Germany?
Yes, if the invoice requires 3DS its payment intent will go in to a requires_action state. If you are charging these users when they are not around, you can passoff_session: trueto signal to the banks that the user may not be able to do 3DS auth at the moment, which can make them less likely to request it.
marcus-invoice-finalization
yes, if this is a $0 invoice
Well it is not a 0$ invoice!
so how to implement it with a amount > 0 and with 3D secure in place???
when the invoice is charged, theoretically the user is present
they did click to buy the one time thing
You have an Invoice, you finalize that Invoice, you then get a PaymentIntent in payment_intent and you confirm this client-side
what about the pay call?
my latest status is - I have an invoice, I add an invoice item, I call pay
finanlize I had done.. but could remove... it didnt seem required?
1/ Create an Invoice
2/ Add line items
3/ Finalize Invoice
4/ client-side collect card details and confirm the PaymentIntent you got at finalization
You never need to call pay
the card details are already collected, at least for the subscription
or do thye need to be collected againf or the one time paymen??
why do you have a new Invoice on session if you already have a subscription?
The customer has a subscription, AND a one time payment
they are nort directly related
at least not from stripe
's perspective
but still, same customer, same card
Why? You're going to pay more fees and risk higher decline rates
?
like if someone owes you $100 for a sub and $20 for a one-off, it's cheaper and simpler to make a $120 invoice and pay once
Many banks don't like multiple sequential payments a few seconds apart
well the idea was. the subscription is paid at the beginning / end of the cycle only
if the customer - NOW wants to buy something additionally
why not charging them - NOW??
what if for example the customer credit card expires in the meantime or the customer dies or whatever
the one time thing is bought NOW, so I think it should also be PAID now
?
the subscription is paid at the beginnign of the cycle, in advance, so thats save
wether the client dies or not ๐
Okay I see.
So yeah in that case you call pay, and if that fails because 3DS is needed and such you confirm client-side
ok wait. so again
your last statement was:
1/ Create an Invoice
2/ Add line items
3/ Finalize Invoice
4/ client-side collect card details and confirm the PaymentIntent you got at finalization
To me it seems with pay, I dont need the finalize call?
if I should use a payment intent to confirm the payemtn... from which of these calls to take it?
1/ Create an Invoice
2/ Add line items
3/ Pay
4) Send payyment intent to client to confirm payment???
"if that fails because 3DS is needed" - I would not want it to fail... I think I would rather proactively want to confirm with a payment intent???
to me it seems with pay, I dont need the finalize call?
It's cleaner to finalize, get the PaymentIntent and all the info and then decide what to do then. But yes you do not have to
you can't do what you're hoping for
So pay, and if payment fails then go client-side to confirm the PaymentIntent and collect new card details
1/ Create an Invoice
2/ Add line items
3) finanlize invoice
4/ Pay
5) Send payyment intent to client to confirm payment???
From which of the calls should I get the payment intent? Do I need an expand?
ah wait... you mean "pay" is the final thing... and it could throw an exception?
so I should catch the exception and then get the payment intent???
yes
please try all of this one step at a time in Test mode, look at the API Reference and the raw response to help you debug this
I did try.. and it just worked ๐ฆ
without any payment intent
so anyway.. you are saying, I catch an exception that comes in sync from the api call "pay"... and then.. where to get the payment intent?
try this and look first!
Sorry it's a really long thread with questions about things you can self serve in seconds if you do look so I'm trying to nudge you to spend a few minutes trying first
well I tried the whole time in my sandbox code.. thats how I found out that pat is working
pay
but with the client library.. I cant do this so easily without involving the frontend guy
you can do all of this without any frontend. We have test cards for everything in https://stripe.com/docs/testing#cards
also you can use the Dashboard to attach card details quickly if you prefer
Trying to add a 3d Secure always card: 4000002760003184 in the dasboard.. but it fails: Your card was declined. This transaction requires authentication.