#rohailkamran
1 messages ยท Page 1 of 1 (latest)
Hello! We'll be with you shortly. Below are links to other discussions we've had with you in the past week in case you want to review that information. If your question is related to one of these previous discussions, please provide a comprehensive summary of the current state and what you need help with now. We help many users simultaneously, so a summary allows us to resolve your issue as soon as possible.
- rohailkamran, 21 hours ago, 50 messages
- rohail-checkout-embedded, 1 day ago, 5 messages
Hi!
So Soma yesterday you sent me this link to follow through for customer creation and payments/charges:
https://stripe.com/docs/payments/save-and-reuse?platform=web&ui=checkout
I am about 4/5 of the way there.
I have set up an endpoint at '/api/create-checkout' that does the following:
exports.createCheckoutSession = async (req, res) => {
console.log("request recieved to create session");
try {
const session = await stripe.checkout.sessions.create({
mode: 'setup',
currency: 'usd',
customer: req.customer_id,
success_url: 'http://localhost:3001/success',
cancel_url: 'http://localhost:3001/cancel',
});
const setupIntent = await stripe.setupIntents.retrieve(session.data.object.setup_intent);
res.json(setupIntent);
} catch (error) {
res.json(error);
}
The problem is that I am receiving {} in response.
If I remove the setup_intent part and just return the session, I do get a valid response. How do I move from here?
I have hooks set up as well to listen to checkout.session.completed that I have tested to be working through stripe cli
wait, why are you creating a SetupIntent?
you don't need one
just create the Checkout Session and nothing else
and return the session.url and redirect the user there.
hmmm I see... do you remember my exact use case? Should I re-open the ticket from yesterday?
yes, and I remember mentionning you can either use SetupIntent or Checkout Session. Not both at the same time.
rightt
ohh lolol
okay... so if I return session.url
hmmm
I think I am missing something here. Give me a sec to type out exactly what I am doing here.
Step 1: Creating a customer (DONE)
const customer = await stripe.customers.create({
name: fullName,
email: email,
});
Step 2: Attaching a payment method to the customer (DONE)
const checkoutSession = await stripe.checkout.sessions.create({
payment_method_types: ["card"],
mode: "setup",
customer: customer.id,
success_url: `<what-should-I-put-here-on-localhost>`,
cancel_url: `<what-should-I-put-here-on-localhost>`
});
Step 3: (NOT DONE)
redirect the user to the Checkout Session URL
Step 4: Getting payment methods for customer when they buy a product: (PENDING)
const paymentMethods = await stripe.paymentMethods.list({
customer: '{{CUSTOMER_ID}}',
type: 'card',
});
Step 5: Charge a payment from one of their payment methods: (PENDING)
const paymentIntent = await stripe.paymentIntents.create({
amount: 2000,
currency: 'usd',
confirm:true,
customer: customerId,
payment_method: paymentMethods[0].id,
return_url:'http://localhost:3001/paid
});
yep that's correct
Great. I have a couple of confusions regarding this
Q1: In step 2, I am literally doing:
payment_method_types:["card"]
Should I instead put an actual card number or something?
Question 2 depends on answer to question 1
No, the card details are collected from the customer when you redirect them to the Checkout Session page
You use the payment_method_types parameter tp specify the types of PMs, like card, you want your customers to be able to use
I see I see.
So the url I return in step 3 should be a stripe hosted url, correct?
Yes, it'll be in the response payload from your request in step 2. checkoutSession.url
Great!
So when the user is on the stripe hosted page, the page where the user will enter their payment info and click "Pay" or something I am assuming, what happens after they click pay?
Where would my server and client come back into play?
In other words, when and how do I get to perform steps 4 and 5?
You'd likely setup webhooks to be notified of the successful Checkout Session to save the card (checkout.session.completed events) andn then you can action that accordingly
In your flow, step 1 is redundant really. You can just tell Checkout to create a customer for you: https://docs.stripe.com/api/checkout/sessions/create#create_checkout_session-customer_creation
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
I see! This sounds good. Because I have hooks set up to listen for that event, I was worried why they were not being triggered. Now I know.
So the checkout.session.completed event will get triggered from the stripe hosted checkout page.
Once the event is triggered, I have to do as follows (correct me if I am wrong):
.
.
.
if(event.type == "checkout.session.completed"){
//step 4
const paymentMethods = await stripe.paymentMethods.list({
customer: '{{CUSTOMER_ID}}',
type: 'card',
});
//step 5
const paymentIntent = await stripe.paymentIntents.create({
amount: 2000,
currency: 'usd',
confirm:true,
customer: customerId,
payment_method: paymentMethods[0].id,
return_url:'http://localhost:3001/paid
});
}
Yes, you can get the cus_xxx from the event too
I should have the customer_id, amount, currency in the event right?
what should I return as a response after step 5 is done? Like standard approach
No there wouldn't be an amount or currency as your setup session doesn't involve a payment
hmmm what would be the easiest way for me to have access to amount and currency in step 5? Because when I receive the event, I won't know what product the checkout session event was triggered for...
There 'd be no amount or currency in a mode: 'setup' session. It simply collect payment information โ there's no payment
You'd need to provide those values for the payment you want to create
I see, is there any mode that would allow me to do both?
You'd use mode: 'payment' and pass setup_future_usage: 'off_session' parameter to save the payment method: https://docs.stripe.com/payments/accept-a-payment?platform=web&ui=checkout#save-payment-method-details
hmmm
I see.
Thanks for this. I just completed step 1,2,3 and I have code in place for steps 4 and 5 as well.
As soon as I fill info on the stripe hosted page and click save, I am redirected to the success url.
However, my hook does not hear the event being triggered....
Is it because I am on localhost and that is not publicly accessible to stripe for events?
Yes you need to use the CLI to forward the events to your local handler: https://docs.stripe.com/docs/stripe-cli
Thanks! I was able to complete the stripe customer creation flow. Now I am heading on to payment. Thanks!!
Great! But as I said that API call is redundant really
So you are saying that I can potentially accomplish both
a. customer creation
b. payment completion
only by changing step 2 from:
const checkoutSession = await stripe.checkout.sessions.create({
payment_method_types: ["card"],
mode: "setup",
customer: customer.id,
success_url: `<what-should-I-put-here-on-localhost>`,
cancel_url: `<what-should-I-put-here-on-localhost>`
});
to:
const checkoutSession = await stripe.checkout.sessions.create({
payment_method_types: ["card"],
mode: "payment",
customer: customer.id,
success_url: `<what-should-I-put-here-on-localhost>`,
cancel_url: `<what-should-I-put-here-on-localhost>`,
pass setup_future_usage: 'off_session'
});
Well, yes, but the parameters are wrong:
await stripe.checkout.sessions.create({
payment_method_types: ["card"],
mode: "payment",
success_url: `<what-should-I-put-here-on-localhost>`,
cancel_url: `<what-should-I-put-here-on-localhost>`,
payment_intent_data: {
setup_future_usage: 'off_session'
}
});
righttt. If I merge steps 1 and 2, and also I want to have a payment at the end of it all, what will change in my code? Probably only step 2 will change, right?
When passing setup_future_usage Checkout will automatically create the customer for you
NICE! So I would be getting cusXXXX in the session object, right?
Yes exactly
Sounds really neat. Thanks
Shouldn't I be able to tell the amount here?
await stripe.checkout.sessions.create({
payment_method_types: ["card"],
mode: "payment",
success_url: `<what-should-I-put-here-on-localhost>`,
cancel_url: `<what-should-I-put-here-on-localhost>`,
payment_intent_data: {
setup_future_usage: 'off_session'
}
});
๐ taking over for my colleague. Let me catch up.
Aoa hey! ๐
Sure
yes you need to pass in the line_items param
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
I see...
so:
await stripe.checkout.sessions.create({
payment_method_types: ["card"],
mode: "payment",
success_url: `<what-should-I-put-here-on-localhost>`,
cancel_url: `<what-should-I-put-here-on-localhost>`,
payment_intent_data: {
setup_future_usage: 'off_session'
}
line_items: [
{
price: '{{PRICE_ID}}',
quantity: 1,
},
],
});
Oh lol wait lemme see
yeah
but now new question lolol
sure
you can using the price_data https://docs.stripe.com/api/checkout/sessions/create#create_checkout_session-line_items-price_data
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 you can also manage your products and prices in Stripe either through the dashboard or via the API
So correct me if I am wrong but this would mean:
await stripe.checkout.sessions.create({
payment_method_types: ["card"],
mode: "payment",
success_url: `<what-should-I-put-here-on-localhost>`,
cancel_url: `<what-should-I-put-here-on-localhost>`,
payment_intent_data: {
setup_future_usage: 'off_session'
}
line_items: [
{
price_data:{
unit_amount:10,
currency: "usd"
},
quantity: 10,
},
],
});
Which according to my understanding should result in:
a. customer being created IF they don't exist
b. payment of $100 being made
Will this work? Or is price_id compulsory?
you would also need to pass in either a Product ID or a product_data hash within the price_data
the unit_amount is in cents
so you're passing 10* 0.10 which is only 1$
payment_method_types: ["card"],
mode: "payment",
success_url: `<what-should-I-put-here-on-localhost>`,
cancel_url: `<what-should-I-put-here-on-localhost>`,
payment_intent_data: {
setup_future_usage: 'off_session'
}
line_items: [
{
price_data:{
product_id:<xyzid_generated_by_stripe>,
unit_amount:1000,
currency: "usd"
},
quantity: 10,
},
],
});
So this should result in:
๐ก customer creation if customer does not exist
๐ก payment of 100$
right?
This eliminates the need for a price_id, right?
sorry it's been a bit busy on discord
I'm back
that wouldn't create a customer though
you need to pass in https://docs.stripe.com/api/checkout/sessions/create#create_checkout_session-customer_creation always
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
if you want to automatically create a new customer each time
I see, so this would become:
await stripe.checkout.sessions.create({
payment_method_types: ["card"],
mode: "payment",
success_url: `<what-should-I-put-here-on-localhost>`,
cancel_url: `<what-should-I-put-here-on-localhost>`,
payment_intent_data: {
setup_future_usage: 'off_session'
},
customer_creation: 'always',
line_items: [
{
price_data:{
product_id:<xyzid_generated_by_stripe>,
unit_amount:1000,
currency: "usd"
},
quantity: 10,
},
],
});
Right?
yes if you already created a Product
wait, it's product not product_id
the name of the param
Oh okayy
@boreal grotto please look at the API references we share to you
you have all of the different properties there
Right lol sorry I missed that
so you either use product if you already created a Product or product_data if you want to generate one inline
Right, I am currently going to hard code the id of a product that I have created.
as
product: product_id
ok
Thanks for all the help you guys. This is awesome.
sure thing let me know if you need any more help