#marcus-invoice-finalization

1 messages ยท Page 1 of 1 (latest)

gentle prawnBOT
smoky garnet
#

Hello ๐Ÿ‘‹
It looks like the PaymentIntent is still in requires_confirmation status hence the invoice is in incomplete state.

broken cloak
#

payment intent - where / how should I get it from? The invoice, the invoice item, or the finalize part?

smoky garnet
broken cloak
#

you mean before or after finalizing it?

smoky garnet
#

after it has been finalised and is in open status

broken cloak
#

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 ๐Ÿ˜ฆ

smoky garnet
broken cloak
#

but at this point the customer alreadt has a payment method attached, because hte customer has also an active subscription at this point

solid osprey
#

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

broken cloak
#

great thanks

#

but... is the confirmation actually needed.. given that we already have the customer's payment method

#

Do I need add an expand?

solid osprey
#

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

broken cloak
#

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

solid osprey
#

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?

broken cloak
#

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

solid osprey
#

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

broken cloak
#

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

solid osprey
#

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

broken cloak
#

ok thanks

#

(When) will you be back?

solid osprey
#

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

broken cloak
#

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?

solid osprey
broken cloak
#

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

solid osprey
#

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

broken cloak
#

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?

solid osprey
#

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 pass off_session: true to 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.

stone mantle
#

marcus-invoice-finalization

broken cloak
#

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

stone mantle
#

You have an Invoice, you finalize that Invoice, you then get a PaymentIntent in payment_intent and you confirm this client-side

broken cloak
#

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?

stone mantle
#

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

broken cloak
#

the card details are already collected, at least for the subscription

#

or do thye need to be collected againf or the one time paymen??

stone mantle
#

why do you have a new Invoice on session if you already have a subscription?

broken cloak
#

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

stone mantle
#

Why? You're going to pay more fees and risk higher decline rates

broken cloak
#

?

stone mantle
#

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

broken cloak
#

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 ๐Ÿ˜‰

stone mantle
#

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

broken cloak
#

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

stone mantle
#

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

broken cloak
#

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

stone mantle
#

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

broken cloak
#

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?

stone mantle
#

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

broken cloak
#

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

stone mantle
#

also you can use the Dashboard to attach card details quickly if you prefer

broken cloak
#

Trying to add a 3d Secure always card: 4000002760003184 in the dasboard.. but it fails: Your card was declined. This transaction requires authentication.