#alexzada-PaymentSheet
1 messages ยท Page 1 of 1 (latest)
hi ๐
the flow is as follows, the customer needs to pay for a ride and this amount can be paid in installments, with a number of installments of his choice, for example, if the ride has a value of 300, the customer can choose to pay in 2 installments of 150, or in 3 installments of 100
is it always the same amount planned on x months?
sorry, I did not understand the question
could the installments be different? e.g. the amount is 250 so the customer chooses 100 for 2 months and 50 for the last or is it always the same amount per installment
oh no, the value of the installments is always the same
in that case Stripe's subscriptions are enough for you
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
yes, i'm using subscription
but, i'm using CardField
and I would like to use PaymentSheet
ok so you have the subscription part figured out, now you just need to know how to integrate with PaymentSheet?
yep
ok when you create a subscription you can expand on latest_invoice.payment_intent which will give you access to a client_secret that you need to pass to the PaymentSheet
yep
`app.post('/pay', async (request, response) => {
try {
const customer = await stripe.customers.create({
description: 'Test Customer',
email: 'test@costumer.com'
});
let pm = await stripe.paymentMethods.attach(request.body.paymentMethodId, {customer: customer.id});
const product = await stripe.products.create({
name: 'Delivery',
})
const price = await stripe.prices.create({
unit_amount: 100000,
currency: 'brl',
product: product.id,
recurring: {interval: 'month'},
});
const subscription = await stripe.subscriptions.create({
customer: customer.id,
default_payment_method: pm.id,
items: [
{price: price.id},
],
expand: ['latest_invoice.payment_intent'],
});
return response.send({
clientSecret: subscription.latest_invoice.payment_intent.client_secret,
status: subscription.latest_invoice.payment_intent.status,
});
} catch (e) {
return response.send({ error: e.message });
}
});`
if you're going to use the Payment Sheet you would have to remove this
let pm = await stripe.paymentMethods.attach(request.body.paymentMethodId, {customer: customer.id});
ok, I wouldn't need to create a payment method on the frontend with const { paymentMethod, error } = await createPaymentMethod({ type: 'Card', }) correct?
right
so far i think i understand
and in your subscription creation you should put default_payment_method: pm.id,
the id is that PaymentSheet will handle all of this for you
I strip let pm = await stripe.paymentMethods.attach(request.body.paymentMethodId, {customer: customer.id}); but leave default_payment_method: pm.id in the subscription? I didn't understand
no you would remove them both
ah, ok
i then have this error now message: 'This customer has no attached payment source or default payment method. Consider adding a default payment method. For more information, visit https://stripe.com/docs/billing/subscriptions/payment-methods-setting#payment-method-priority.',
yeah sorry my bad, you need to add payment_behavior: "default_incomplete", when creating the subscription
ok, I managed to open the PaymentSheet, now how could I let the customer choose the number of installments for the payment?
you'd have to handle that in UI in your own app before opening the PaymentSheet.
Could you explain me better? I was a little confused
There's no built in UI (user interface) in Stripe's PaymentSheet for something like picking a number of installments in a subscription, and it's not possible to add custom UI to the sheet itself for that. So you'd have to get that information from the customer in your own app's interface before using the PaymentSheet(and probably send that information to your server so you can set up the subscription appropriately).
ah, I think I understand now, I'll try to do some tests here, thank you very much
I found out that I will need to use subscription_schedules instead of subscription, how can I do that with PaymentSheet?
It's quite complicated really
you'd use the Schedule to create the Subscription(https://stripe.com/docs/billing/subscriptions/subscription-schedules#managing), then you have to finalize the first invoice of that subscription(this is all done on the server), and then you can use the invoice.payment_intent.client_secret as described above with the PaymentSheet.
how can i finalize the first invoice of that subscription?
you'd call https://stripe.com/docs/api/invoices/finalize with the ID from schedule.subscription.latest_invoice
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
this is going to be quite hard to do so you need to experiment with the API a lot.
let me ask you a question, maybe I'm following the wrong path, the flow of our application is like Uber's, the customer requests the ride and pays for it, but in our app, this payment can be made in installments, the customer will be able to decide how many times he wants to make the payment of this amount, for example: the fare was 100, but he does not have 100 to pay in cash, so he will pay twice of 50 monthly, 50 once a month until finalize the total amount, in this example, it would be 2 months, this is very common in Brazil, I don't know if it is different in other countries
Hi there. Taking over for karllekko as they have to step out. For installments, the recommended way is to use a Subscription with a cancel_at date: https://stripe.com/docs/api/subscriptions/create#create_subscription-cancel_at
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
but following my example using Subscription, the customer chooses to pay 100 in two installments of 50, as I would say to Subscription that the payment will be 50 for two months?
Yes that's right
our use case is very similar to the example in this guide https://stripe.com/docs/billing/subscriptions/subscription-schedules/use-cases#installment-plans
Installment plans allow customers to make partial payments for a set amount of time until the total amount is paid. For example, when The Pacific buys new printing presses, they sell the used ones to other publications. Smaller publications rarely have enough funds to pay for a printing press upfront, so they pay using an installment plan instead.
this is exactly what we need
Yeah that's up to you if you want to use Subscription Schedules. A plain Subscription could work too
even reading the Subscription documentation I didn't find a way to do it, and from what @sudden violet said, doing it with subscription schedules is very difficult
๐
That's why I suggested a plain subscription while setting cancel_at. It's a bit simpler
any guide that can help me more?
You can use this: https://stripe.com/docs/billing/subscriptions/build-subscriptions and then when creating the subscription you need to specify cancel_at
The plan selection would have to be prior to creating the Subscription object
I did not understand this part
You will need to have the user select their plan prior to creating the Subscription. You won't be able to update the Subscription once it's been created with default_incomplete
I recommend reading that guide, as this should make a bit more sense after that
by select their plan do you mean the number of installments?
Yeah
now it makes more sense to me
see if I understand correctly what you mean by using Subscription with cancel_at, if the customer chooses to pay the amount of 100 in two times of 50, I would create the Subscription with the value of 50 and the cancel_at calculating two months?
Yes that's right. You would want cancel_at to be a timestamp after the second monthly payment. You should account for any retries (your payment settings define your retry behavior: https://dashboard.stripe.com/settings/billing/automatic)
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 did not understand this part You should account for any retries (your payment settings define your retry behavior: https://dashboard.stripe.com/settings/billing/automatic)
So if your retry schedule allows for payment retries for 7 days, then you would want cancel_at to be 2 months from the subscription creation timestamp + 7 days
But really if your use-case is installments only, then the Subscription Schedule option shouldn't be that complicated
If you want to go that route instead
Subscription Schedules usually just get rough when you have many phases
this is still a little unclear to me
Idea is you don't want the subscription to cancel before payment is collected (if it fails and then needs to retry a few times)
is the retry a parameter that needs to be in the Subscription creation or is that defined somewhere else?
No that's at the link I sent above in your account settings
But really if your Subscription Schedule use-case is just installments, it wouldn't be that difficult to go that route if you'd rather just do that
ok, it's starting to make a little more sense
If your payments are the same amount and same spacing in time, then a regular subscription with cancel_at can achieve the same result at the subscription schedule installment plan suggestion
the advantage of the subscription schedule approach is it allows you to easily customize the payment schedule (different amounts, different timing) without needing to track when up update the subscription in real time as payments happen
The schedule manages that for you
The payment retries are for each individual invoice the subscription creates (in either case)
ok, so in our use case Subscription is enough
thank you very much for the explanations
Minor clarification, you would not need to extend the cancellation like this, just cancel at the end of the last period or following the final invoice with no proration
The existing invoices can still be paid and will retry, but no new invoices will be created
Could you explain to me what proration is? I've never seen that term before
That means partial charges or credits based on partial periods of the billing cycle
eg: if you charge $10/month on the first of the month, if a customer cancels on the 15th of a month you might want to credit them $5 for the remaining half month of service they paid for but did not use.
(similarly when upgrading or downgrading plans)
Read more here: https://stripe.com/docs/billing/subscriptions/prorations
Most ways you can changes subscriptions support enabling or disabling prorations according to your business needs.
For the installment plan use case, this is mostly not relevant. You'd have the subscription cancel following the final invoice and there would be no proration.
got it, I don't think we will need to deal with this in our use case
why does the second installment of this Subscription have a different value than the first sub_1Kz1ExJ1bzV4VWW3fSlVYQrT?
`app.post('/pay', async (request, response) => {
const installmentsNumber = request.body.installments;
try {
const customer = await stripe.customers.create({
description: 'Test Customer',
email: 'test@costumer.com'
});
const product = await stripe.products.create({
name: 'Delivery',
})
const total = 1800
const price = await stripe.prices.create({
unit_amount: total / installmentsNumber,
currency: 'brl',
product: product.id,
recurring: {
interval: 'month',
}
});
const subscription = await stripe.subscriptions.create({
customer: customer.id,
payment_behavior: "default_incomplete",
cancel_at: new Date(new Date().getTime() + (installmentsNumber - 1) * 30 * 24 * 60 * 60 * 1000 + 7 * 24 * 60 * 60 * 1000),
items: [
{
quantity: 1,
price: price.id,
},
],
expand: ['latest_invoice.payment_intent'],
});
return response.send({
clientSecret: subscription.latest_invoice.payment_intent.client_secret,
});
} catch (e) {
return response.send({ error: e.message });
}
});`
Hi ๐ I'm stepping in for @steady dune Give me a minute to catch up
What value are you talking about here?
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Dashboard links are useless to. me.
Since it's your dashboard and I don't have access to it
What is the "value" you are referencing here?
the total amount is 18, so I made a subscription of 9 to count twice, the first installment had the value of 9 but the second is with the value of 1.80
Okay so the price amount?
can you actually copy/paste that price ID in here?
Or better yet, the subscription ID
sub_1Kz1IIJ1bzV4VWW31dLZFfUP
That is because the current monthly period goes from May 13th - June 13th. But you have the subscription cancelling on June 19th. That means the second invoice, by default, is only charging your customer for the 6 days of the second period.
what is the correct day to unsubscribe then?
If you want to charge them for 2 whole months then I would wait until the second invoice is created. That will update the current_period_start and current_period_end for the Subscription. Then you could update the the Subscription cancel_on_date to be the same as current_period_end.
This may be a bit more complicated but installments are a good use case for Subscription Schedules
Using Subscription Schedules you can specify how many times you want the billing cycle to repeat and then cancel the subscription when those cycles are over
another dev told me that Subscription with cancel_at was enough for my use case
๐
It definitely can be. You just need to make sure your cancel_on_date is at the end of the billing cycle so you don't create prorations
But you can try out using the Node snippet for creating a schedule and see how that works for you
Just drop than in your code where you create the Subscription and swap out your price ID and change the iterations to 2
and how would I integrate this with the PaymentSheet of stripe-react-native?
You would need to retrieve the subscription, invoice, and payment intent. Like you do currently, just one more layer.
hmmmm, ok
I'm doing some tests here but I'm having another problem, I've already tested several different versions of stripe-react-native in expo, but they are all having the same problem with confirmPayment and PaymentSheet, whenever I finish the additional authentication step, it redirects me out of the app
Where does it redirect you?
What version of the Stripe React Native SDK are you using?
currently "@stripe/stripe-react-native": "0.2.3", but I've tested 0.4.0, 0.5.0, 0.8.0 and 0.9.0
A huge number of changes have been introduced since then. I would request you upgrade your version.
but the Stripe SDK for expo in theory only supports version 0.2.3
This is a known bug with Expo and the Stripe RN SDK. You will need to update to resolve it.
ok, I'll update then, another question, how can I make my PaymentSheet have my local language? He always appears in English
๐ stepping in. Hi @honest hinge. PaymentSheet is localized based on the device's language settings.
You can't override this currently
I believe I managed to make the flow with Schedule Subscription, can you guys evaluate this code snippet and tell me if that's right?
`app.post('/pay', async (request, response) => {
const installmentsNumber = request.body.installments;
try {
const customer = await stripe.customers.create({
description: 'Test Customer',
email: 'test@costumer.com'
});
const product = await stripe.products.create({
name: 'Delivery',
})
const total = 10000
const price = await stripe.prices.create({
unit_amount: total / installmentsNumber,
currency: 'brl',
product: product.id,
recurring: {
interval: 'month',
}
});
const schedule = await stripe.subscriptionSchedules.create({
customer: customer.id,
start_date: 'now',
end_behavior: 'cancel',
phases: [
{
items: [
{
price: price.id,
quantity: 1,
},
],
iterations: installmentsNumber,
},
],
expand: ['subscription.latest_invoice.payment_intent']
});
const invoice = await stripe.invoices.finalizeInvoice(
schedule.subscription.latest_invoice.id
);
const paymentIntent = await stripe.paymentIntents.retrieve(
invoice.payment_intent
)
return response.send({
clientSecret: paymentIntent.client_secret,
});
} catch (e) {
return response.send({ error: e.message });
}
});`
Looks right to me. Have you tested it?
Actually I'm not sure you will be able to expand the sub when creating the schedule
yes, apparently it is working correctly according to the data I see on the dashboard
is it working, should i change it??
That's correct
No no
I misread
You are expanding the response by doing that
So you can properly grab the client secret
Looks good
would this be the flow to create a Schedule Subscription type payment (obviously that some fixed data in the code will be received by parameter)? Do I need to do anything else before going to the webhook or can I believe that everything is ok?
I don't know what you mean exactly by: "would this be the flow to create a Schedule Subscription type payment "
That flow will create a Subscription yes
And that Subscription will follow the Sub Schedule that you created
It all looks good to me. If you want to test it in full, you can use a test clock: https://stripe.com/docs/billing/testing/test-clocks
I expressed myself badly, sorry ๐
this looks cool
Yep test clocks will be helpful to ensure your schedule is working as you desire end-to-end!
I'm going to test using clocks now, thank you very much, I'm your fan
๐
should the charge keep happening even after reaching the threshold set in shcedule? In this example I put it as 2 iterations, which would be May and June, but it keeps charging each time I advance one month
No that shouldn't happen if you set end_behavior: cancel on your sub schedule
Can you provide the subscription ID for that test?
sub_1Kz2v8J1bzV4VWW304EeAsAZ
Ah okay that subscription wasn't created from a schedule
You created it via the Dashboarad
So it will continue after 2 months
make sense