#baruco-subscription

1 messages · Page 1 of 1 (latest)

ivory panther
#

👋 happy to help

#

is the invoice_settings.default_payment_method set on the customer object?

untold ridge
#

Yes

#

I expanded it with this

#

Oh wait

#

Actually, yeah, I just rechecked

#

I'm using GO for my backend, and this is the object I'm creating to create the customer

#
customerParams := &stripe.CustomerParams{
        Email:         stripe.String(CustomerEmail),
        PaymentMethod: stripe.String(PaymentMethodId),
        Address: &stripe.AddressParams{
            City:       stripe.String(City),
            Country:    stripe.String(Country.Alpha2()),
            Line1:      stripe.String(Address1),
            Line2:      stripe.String(Address2),
            PostalCode: stripe.String(ZipPostalCode),
            State:      stripe.String(State),
        },
        InvoiceSettings: &stripe.CustomerInvoiceSettingsParams{
            DefaultPaymentMethod: stripe.String(PaymentMethodId),
        },
    }
ivory panther
#

could you please share the customer id?

untold ridge
#

cus_Lvbgr1XQ7pc3ue

ivory panther
#

and the subscription id please?

untold ridge
#

sub_1LDlAOA155AgO8fTpaxx6MXp

ivory panther
#

thanks I'll take a look

untold ridge
#

Thank you!

ivory panther
#

when you created the subscription you shared you passed the payment_settings: { save_default_payment_method: "on_subscription" },
parameter which expects the subscription to be paid with a new payment method that would be attached to the subscription

#

although you already have a default payment method for invoices saved on your customer

untold ridge
#

OK, let me try to delete it

#

And also, I changed something in the account settings to accept "cards" and now I keep getting requires_confirmation

#

I don't know if that's ok or not

#

p.s - I removed this configuration and I get the same response back

#

Is there a difference between creating a customer with a payment method ID or creating a customer and then attaching the payment method to that customer later?

#

Because I've been going through the "subscription" example for "usage based" and I changed the flow a bit, and in there the response always returns correctly

ivory panther
#

could you please describe the flow that you're using and share a request id for each step?

untold ridge
#

Sure, one sec

#
1) Create a "payment method" through `paymentmethods.New` - request ID - req_KhYmmLAFQ9Ojsc
2) Send the backend a `payment_method_id`
3) The backend (In golang) creates a customer using `customer.New` with the following parameters: - request - req_MVrzG1O4C79AAX
customerParams := &stripe.CustomerParams{
        Email:         stripe.String(CustomerEmail),
        PaymentMethod: stripe.String(PaymentMethodId),
        Address: &stripe.AddressParams{
            City:       stripe.String(City),
            Country:    stripe.String(Country.Alpha2()),
            Line1:      stripe.String(Address1),
            Line2:      stripe.String(Address2),
            PostalCode: stripe.String(ZipPostalCode),
            State:      stripe.String(State),
        },
        InvoiceSettings: &stripe.CustomerInvoiceSettingsParams{
            DefaultPaymentMethod: stripe.String(PaymentMethodId),
        },
    }

4) Create a subscription using `sub.New` with the following parameters: - request - req_xrBafWgD400boz
    subscriptionParams := &stripe.SubscriptionParams{
        Customer: stripe.String(cust.ID),
        Items: []*stripe.SubscriptionItemsParams{
            {
                Plan: stripe.String(stripePriceId),
            },
        },
        PaymentBehavior: stripe.String("default_incomplete"),
    }
    subscriptionParams.AddExpand("latest_invoice.payment_intent")
    subscriptionParams.AddExpand("pending_setup_intent")

5) Return the entire `subscription` object to the frontend
6) In here we see the `subscription.pending_setup_intent.client_secret` is there, but the `status` is `requires_payment_method`.

Now we see it's requires_confirmation after enabling cards in the entire account, but the example we followed doesn't even take this status into consideration and It's quite confusing.
We don't even know if that's ok what we did

untold ridge
#

@ivory panther Still here?

ivory panther
#

yes sorry I'm taking a look at your requests

#

I'm a bit confused because that's not how we usually integrate with the subscription

untold ridge
#

OK

#

How should a subscription integration be then?

#

This is how I saw in the example

ivory panther
#

I think it's better if you keep

    save_default_payment_method: "on_subscription"
  },```
this part on the subscription and forget about attaching the payment method to the customer
#

I still haven't got the chance to look at your requests, sorry it's a bit busy on discord this morning

untold ridge
#

OK, can you just send me perhaps a doc to explain how you would usually expect a subscription integration to be?
Specifically for usage-based since it's a bit different as I understand it.

I tried the example that I sent you and it seems it's not the usual way?

ivory panther
#

if you'd wait a bit (roughly 15min) I would have the time to go into details with you, my shift will come to an end by then and I would have some time to go over more details with you

#

does that sound good to you?

untold ridge
#

Yes, very good, thank you so much!

#

I'm also free for a voice chat if that's an option

ivory panther
#

unfortunately it isn't

#

just give me a few minutes and I'll be right here with you

untold ridge
#

np, thanks

ivory panther
#

sorry for keeping you waiting

untold ridge
#

I'm here, thank you!

ivory panther
#

do you want me to investigate what was happening in your requests first or would you prefer I start with giving you my recommendation for the implementation?

untold ridge
#

I would prefer getting a recommendation for the implementation, perhaps I'm missing something.
And while I'm working on that from my end, perhaps just changing a few things, you can investigate on your end if that's OK?

ivory panther
#

I just saw that the invoice was created and paid successfully for the request you just sent

#

this is because you're only passing the customer id to when creating the subscription

#

so the approach you described works (as I explained the request you sent shows a subscription that was paid)

#

but the caveats of that are two things

#

first you're creating a payment method on the backend instead of for example using the SetupIntent API or other methods I will get back to later on

#

this means that if the Payment Method(PM) was a card that needs auth(SCA/3DS) your customer would have to be on-session and you'd have to go back and do the auth on the front-end

untold ridge
#

OK

ivory panther
#

second caveat is that you're creating a subscription for a customer but you're not asking them to pay for the first invoice(SetupIntent), which means that your authorization request would have an amount of 0 instead of the actual amount, which generates a lot of confusion amongst customers

untold ridge
#

Just to make sure, the flow I presented you with is a "test" flow, I create the PM through Go in my backend just for tests.
But in a real flow, I would create the PM through stripe's JS library

untold ridge
ivory panther
#

yes

#

I would have done things a bit differently to be honest

#

I would create the subscription with the payment_settings: { save_default_payment_method: "on_subscription" },

#

expand on the latest_invoice.payment_intent

untold ridge
ivory panther
#

pass only the client_secret to the front-end, because there's no reason to ship the whole object to the front-end

#

if that is null then you could use the pending_setup_intent as suggested yesterday

untold ridge
#

OK, regarding what you said:

which means that your authorization request would have an amount of 0 instead of the actual amount
As I understand it, by the document I sent earlier, my subscription is "usage-based", so because of that, I can't have a non-0 invoice since the total cost of the invoice depends on the customer's usage

ivory panther
#

yes that's true

#

on the front-end you would use a CardElement or PaymentElement with the generated client_secret from the backend

#

and finally you would confirmSetup (for the pending_setup_intent ) or confirmPayment(for the latest_invoice.payment_intent)

#

with that you would have a subscription with the proper payment method saved on it

#

would that be enough for your use case?

untold ridge
#

I'm missing a payment method creation in the process

ivory panther
#

not really

#

because when you pass the client_secret to the PaymentElement or the CardElement, the payment method will be created from the front-end

#

and attached to the subscription

untold ridge
#

So I do not need to send the "payment method ID" to the backend?

ivory panther
#

based on the payment_setting.save_default_payment_method parameter

#

So I do not need to send the "payment method ID" to the backend?
no need

untold ridge
#

So that also includes for the customer creation yeah? No need to attach a payment method to it from the backend

ivory panther
#

yes you can create the customer without attaching any PM

#

sorry I have to leave you now. if you don't mind, I could put you in contact with my colleague that's working the discord shift right now

untold ridge
#

that's fine but I still do not fully understand

#

Yes please connect me with your colleague

#

The example I looked at is so painfully confusing, what is it sending the payment method ID to the backend?

ivory panther
#

the docs/example you read were designed before the introduction of the payment_setting.save_default_payment_method which was added recently

#

could you please try the steps I suggested?

untold ridge
#

Yes I am trying

#

So if I picture a flow from high-level:

 - User sees subscription creation page and fills their details and clicks "Submit"
 - A request is sent to backend to create the customer and subscription and a "client secret" is returned
 - client secret is sent to "stripe.confirmCardSetup()" in JS frontend
 - If success -> Subscription and Customer have correct payment method
 - If 3DS -> Frontend shows authorization and succeeds accordingly
 - In backend I listen to webhook for "subscription created" to ensure flow is complete

Correct?

ivory panther
#

so you need 4 things:

  • create a customer with no PM
  • create a subscription for that customer with the payment_setting.save_default_payment_method set to on_subscription and expand on the pending SetupIntent and the PaymentIntent of the latest_invoice
  • send the client_secret of the one that isn't null (in your case it's most likely the pending setup intent)
  • on the front-end receive the client_secret and pass it to the CardElement or PaymentElement and confirmSetup
    after doing so you should be able to see that we handled all of the PM stuff for you
#

the PM wouldn't be saved as a default payment method on the customer but it would be directly saved on the subscription

#

does that make sense?

#

in all cases, if you need anymore help, @naive burrow will be here shortly and would help you out with your request

untold ridge
#

OK

ivory panther
#

in the meantime try those steps and see whether it works for you

untold ridge
#

I wish we could find a way to make it work with the way I suggested but I just want to work for now

#

Will do! Thank you so much!

#

Last thing

#

No need to run create payment method in FE

#

Right?

ivory panther
#

your way is already working, but I explained why it's not really recommended

#

No need to run create payment method in FE
no confirmSetup would do that for you

untold ridge
#

Awesome, thanks

#

Trying now...

untold ridge
#

Hey @naive burrow

#

And I give it a "payment method" object as data with the card element?

naive burrow
#

Hi! I'm taking over this thread.

#

If you are using a SetupIntent with the Card Element, then yes: confirmCardSetup

untold ridge
#

Awsome, just to update, we managed to get it to work.
I want to understand my customer object is as expected now, can you please have a look?
cus_Lvfcljb9BOshqc

#

I can see the Set up for future use configured with a setup intent.
Do I need to use it explicitly in the future at the end of every billing cycle to charge the customer or is that out of the box?

#

As I understand it I just need to update the usage of the subscription and Stripe takes care of the rest?

naive burrow
#

Awesome! That customer has a subscription, and that subscription has a default payment method. So everything looks correct! There's nothing else to do, the default payment method will be automatically charged at the next billing cycle.

untold ridge
#

Awesome sauce

#

Lastly, when I listen to webhooks:

  • Do I need to update the customer object with the subscription's payment method?
  • On which event do I need to listen to in order to check whether the process completed successfully?
naive burrow
#
  • Do I need to update the customer object with the subscription's payment method?
    No, the subscription already has a default payment method
  • On which event do I need to listen to in order to check whether the process completed successfully?
    Depends what you want to check. We have a documentation page about this: https://stripe.com/docs/billing/subscriptions/webhooks
untold ridge
#

Technically, when the process is completed, that would be a "payment method added" event which is - customer.subscription.updated, no?

#

Because the customer and subscription objects are already created from the backend

naive burrow