#maufcost - subscription payment intent
1 messages · Page 1 of 1 (latest)
Good morning! Subscriptions automatically create invoices which themselves create payment intents
So you can check your subscription's latest invoice's payment intent to get your client secret
Which means you can either retrieve the subscription's latest_invoice by its ID and then retrieve that invoice's payment_intent or you can expand latest_invoice.payment_intent when creating your subscription and check the object that is returned from that. https://stripe.com/docs/api/expanding_objects
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
Does that make sense? I feel like I made some leaps there
No worries. I was able to follow. So, I went to that route of expanding the subscription object when I'm creating a new subscription as such:
const schedule = await stripe.subscriptionSchedules.create({
customer: customerId,
start_date: 'now',
end_behavior: 'cancel',
phases: [
{
items: [{
price: price.id,
quantity: 1,
}],
iterations: numberOfIterations,
},
],
// Allows us to simultaneously create a payment
// intent and get its client secret.
expand: ['latest_invoice.payment_intent']
})
const clientSecret = subscription.latest_invoice.payment_intent.client_secret
return { scheduleId: schedule.id, clientSecret }
However, I still get an error because of that expansion. Let me get the error again for you 1 sec
Just 1 sec. I am recompiling everything
Sounds good.
Ah you are creating a subscription schedule
You will want to expand subscription.latest_invoice.payment_intent
Ooooooo... Got it. I'm gonna make this change and see if any errors come up
I also think that you will want to switch to const clientSecret = schedule.subscription.latest_invoice.payment_intent.client_secret
Quick question: are you only creating a schedule so that the subscription ends at the end of its first period or are you doing more complex scheduling with it?
I am only creating a subscription to simulate installment payments. So, let's say a user wants to buy a TV on my app and pay in 6 installments. That's the only use case
Gotcha. Great reason to use schedules. I misread your code for a moment and thought there would be an easier way
Got it. With this approach of mine, the user is going to be charged the first installment at the time the payment intent is confirmed, correct?
Correct
And the next months, the user's card will be charged automatically by stripe? I don't have to have the user pay again on my app manually just like they did for the first installment, is that right?
Correct, the user should be automatically charged on the next period start.
You can use a test clock to simulate what you/the user will see in the next month https://stripe.com/docs/api/test_clocks
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
Perfect. I thought I had to use stripe to save the user's card information and then retrieve it and do stuff manually, so that's awesome.
Is it okay if I ask other technical questions here regarding payment intents and refunds?
Of course
Sweet. Is it possible to create a payment intent on, let's say, a react native app, and then have that payment intent confirmed by another react dashboard?
Just to give you some context: think about how food delivery apps work. A user makes an order on the app (at this time, I'd like to create a payment intent, but not confirm), and that order is sent to a restaurant. If that restaurant accepts the order on their dashboard, the payment intent is confirmed; otherwise, nothing happens to it.
I may have a workaround, but I just wanted to check with you.
So the react client itself shouldn't be creating a payment intent. The pattern that we typically recommend is that your app would send data to your server on what the payment intent should look like and then the server creates it. Creating the PI and only conditionally confirming it is a great pattern but typically the only thing about an intent that the clients should interact with is its client secret
Correct. Yea. I'm using a node server to create the PIs. Makes sense.
Now, when I create a payment intent, I am placing a hold on a user's card, correct? And when I confirm the payment intent, that's when I actually charge that card. Is that correct?
No, creating a payment intent doesn't really do anything by itself. You can place holds on a customer's card through a payment intent but you have to either pass specific things in when creating it or you have to confirm it a specific way
Finding the doc on that
Thank you for asking, that is a great thing to clarify
Here is our guide on holding and capturing funds https://stripe.com/docs/payments/capture-later
Let me know if you have any questions there.
Oh good. That's the doc I had open. So, when it says:
"You can do this by setting the confirm parameter to true while creating the PaymentIntent",
is it talking about adding a confirm prop when I am calling
const paymentIntent = await stripe.paymentIntents.create({...})
on the server?
Yes, so something like
amount: 1099,
currency: 'usd',
payment_method_types: ['card'],
capture_method: 'manual',
payment_method: '{{PAYMENT_METHOD_ID}}',
confirm: true
});```
Perfect. And what's this prop: payment_method: '{{PAYMENT_METHOD_ID}}'? Should I pass it literally like this? Or will I have to create a payment method object?
That is supposed to be replaced with an actual payment method ID pm_123...
Do you already have a customer's payment method on file at this point in your process?
No. I only create a customer object whenever a user gets to checkout page.
So, will I not only have to create a customer object, I also have to create a payment method for that customer and only then be able to place holds with payment intents?
Gotcha. In that case, you wouldn't want to pass either the payment_method or confirm params when creating your payment intent. Passing those are for when you already have their info and already know what card you are placing a hold on. Here, you can create the payment intent without either, and then pass its client secret to your app, when the user puts in their info there, the payment intent will be confirmed and a hold will be placed on their card.
Also, I may have not connected a couple of dots that you mentioned here. Are these payments for the same thing that you are doing installment payments via schedules? Or are you looking to do a hold for something else?
I ask that because subscriptions can't place holds on cards so those two needs might conflict here.
Got it. So, as long as I pass the capture method: manual property, the hold will be placed?
In terms of the subscription: The holds will only be placed if the user selects a payment option on my app to pay everything upfront. If they select to pay in installments, no hold will be placed (since holds can be put on subscriptions)
Yes, capture method manual means exactly that, just make sure you are making the call to actually capture the funds later on or they will be automatically released after 7 days
And good to hear, those are both viable uses for those tools, just wanted to make sure I didn't tell you to do something that was impossible
Got it. I’m almost done with all the questions :). Now, about refunds.
Is it possible to cancel a subscription and issue refunds on it?
Hi 👋 I"m stepping in as @gleaming sparrow has to go.
Yes you can do this, it's just not automatic
Canceling the Sub will create a credit balance for the Customer. To issue a refund you would use the List Invoice API (https://stripe.com/docs/api#list_invoices) to get the most recent invoice and expand the Charges. Use the Charge object to create a refund for the amount of the credit. Then update the customers account balance to 0.
No worries! Nice to meet you.
Let’s say my customer only paid for the first installment and I had previously created a subscription schedule for 6 installments. Would it be possible to cancel the subscription and refund them that first installment using the procedure you outlined above?
Yes it would. The List API for Invoices would return the invoice for that first installment with the completed charge associated with that invoice. You could then create a refund from that charge object.
Thanks a lot. I will read more about it and if I have any more questions, I will post here. You guys rock 🤘