#Ema - Subscriptions
1 messages ยท Page 1 of 1 (latest)
const priceId = req.body.priceId
const userId = req.decoded.user
try {
const session = await stripe.checkout.sessions.create({
mode: "subscription",
payment_method_types : ["card"],
line_items: [ {
price: priceId,
quantity: 1,
},
],
subscription_data: {
metadata: {"userId": userId},
},
success_url: `${keys.CLIENT_URL}/payment/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${keys.CLIENT_URL}/payment/cancel`,
automatic_tax: {enabled: true}
})
console.log(session)
return res.redirect(303, session.url)
} catch(e) {
return res.status(400).json(e)
}
})
I have some boiler code to send you
Basically I want to manage the subscription through a boolean (valid subscription y/n) and through storing the stripe customer ID on the User document (I'm using Mongo).
I can't seem to find a way to send the userId to my webhook that processes the events to perform update operations tho sadly
Which event(s) are you sending to your webhook endpoint?
Whatever is sent when a subscription is successfully created/canceled
so customer.subscription.created/updated, payment_intent.created/succeeded, invoice.created/paid, charge.succeeded etc.
Can you give me the event ID of one of the customer.subscription.created events that you expected to have the metadata?
Sure, one second.
evt_1Jw92FK4b2fM2OBhV0dsqbIY
I expected the session created to have the metadata tho, not the event. Is that how I'm approaching it wrong?
Let me take a look, hang on. ๐
Looks like you didn't specify Subscription metadata when you created that Checkout Session: https://dashboard.stripe.com/test/logs/req_bxtHi3QwiPnVGW
Are you sure userId has the value you expect?
Wait, I am going to test something real quick
was thinking of the same thing haha
Meanwhile, I have three small questions.
- The example I took the code from has auto-completion for the customer address (entering 5th Avenue suggests NYC 5th Ave.), is this supported out of the box and is it a setting in the dashboard?
- The same example also has Apple Pay support, it is supported out of the box with the payment method [card]?
- If a subscriber tries to subscribe again, will it have the same customerId as long as they use the same email?
- The example I took the code from has auto-completion for the customer address (entering 5th Avenue suggests NYC 5th Ave.), is this supported out of the box and is it a setting in the dashboard?
If you're talking about the address fields inside Checkout, that is supported out of the box and I don't know of a Dashboard setting to change it.
Oh, no there is a setting for it here: https://dashboard.stripe.com/settings/checkout
evt_1Jw9BlK4b2fM2OBhSGCFoYye Another subscription creation event, I managed to have some metadata in session through "metadata" so I assume subscription_data.metadata is not the correct way to do it
- The same example also has Apple Pay support, it is supported out of the box with the payment method [card]?
Apple Pay is supported out of the box in Checkout. You can turn it on/off at the link above.
- If a subscriber tries to subscribe again, will it have the same customerId as long as they use the same email?
No, it will be a new Customer with the same email address. Checkout will only use an existing Customer if you provide the Customer ID when creating the Checkout Session: https://stripe.com/docs/api/checkout/sessions/create#create_checkout_session-customer
So, to make sure that'd be the case, I'd have to pass the customerId to the session, and in case it is null it handles the generation on its own, right?
Yep.
Like, new user having no customerId vs. old user having cust_1337 as ID
I just send the customerId in request and if it's null the system won't crash anyway and generate a new one
Well, you shouldn't specify customer at all ifย you don't have an ID to pass.
evt_1Jw9BlK4b2fM2OBhSGCFoYye Another subscription creation event, I managed to have some metadata in session through "metadata" so I assume subscription_data.metadata is not the correct way to do it
I'm not sure what you mean here? You use subscription_data.metadata to specify the metadata that showed up on the Subscription successfully: https://dashboard.stripe.com/test/logs/req_UAjJYx04IaU49p
So the data sent through "subscription_data.metadata" is sent through the subscription.create event, correct?
I am very sorry about the beginner questions, first experience with Stripe :p
Yeah, when you specify subscription_data.metadata inside a Checkout Session creation request the metadata you specify there will be added to the Subscription Checkout creates.
You're doing the right thing in your Checkout code, it's just that I think userId is empty or null when your code runs, so the metadata isn't getting set.
Thank you so much for the help.
I tried sending a prefixed string and it worked fine, I was confused between Session.metadata and Session.subscription_data.metadata
Always happy to help!
You can set metadata on the Checkout Session itself as well.
Metadata can be set on most Stripe objects.
Where would I find subscription_data? I tried console.log(event) when event is equal to customer.subscription.created and there is no mention of it
subscription_data is something you set on the Checkout Session when you create it. It's basically you saying, "Hey, Checkout, if you create a Subscription for this session, I want that Subscription to use the following data" and one of the things you can specify there is metadata for the Subscription.
The Subscription itself won't have subscription_data, it will have metadata as a top-level property though.
Okay, so in my case it is not adequate to what I'm trying to achieve since I want to send my UserID to the events, right? I'm better off using the metadata field of the checkout session
In other words, setting metadata here: https://stripe.com/docs/api/checkout/sessions/create#create_checkout_session-subscription_data-metadata
Is like asking Checkout to set metadata here: https://stripe.com/docs/api/subscriptions/create#create_subscription-metadata
Okay, so in my case it is not adequate to what I'm trying to achieve since I want to send my UserID to the events, right?
No, you're doing the right thing. Look at the second Event you mentioned above in your Dashboard: https://dashboard.stripe.com/test/events/evt_1Jw9BlK4b2fM2OBhSGCFoYye
It has the metadata you specified, as expected:
metadata: {
userId: "test"
},
So in this event it's in data.object.metadata?
Yep.
Because you told the Checkout Session to set the metadata on the Subscription it creates, and a customer.subscription.created contains the Subscription object.
Would it be safe to set the "subscribed" flag in customer.subscription.created? Someone earlier suggested I'd do it in invoice.paid
but I have no clue on how to send that user ID to invoice.paid and I can't set it in the subscription.created event to use it in invoice.paid because it is not guaranteed that the first event will come first
Would it be safe to set the "subscribed" flag in customer.subscription.created? Someone earlier suggested I'd do it in invoice.paid
As long as you're checking the Subscription's status to make sure it's in a state you consider "subscribed" that should be fine.
invoice.paid will also work. You can get back to the Subscription from the Invoice by looking at the Invoice's subscription property, then get the metadata from there: https://stripe.com/docs/api/invoices/object#invoice_object-subscription
I see, is there an event that guarantees the Subscription status to be completed?
Not sure what you mean, can you provide more details?
An event where I'm 100% sure the subscription is valid and paid for, and I can set the flag without having to worry about the status
I think invoice.paid would be it
The closest thing would be invoice.paid, yeah. But what's the issue with checking the status of the Subscription?
Not sure about how to wait for the subscription status to change in what I want to set the flag
Hang on, I think I'm missing something. What do you mean by "wait for the subscription status to change"?
If I handle it through the subscription.create event and the status is still "incomplete", I cannot set my user to subscribed because I'm not sure if the subscription will ever be completed
I'm sorry if I'm missing something
You're also listening for customer.subscription.updated, correct? That event will fire every time the status changes. If your code listens for both customer.subscription.created and customer.subscription.updated and updates the "subscribed" flag on your end based on the current status of the Subscription will that work?
I found a page in the docs I can't seem to find again that discussed in depth about how and when to handle these operations in the database
Maybe this page? https://stripe.com/docs/billing/subscriptions/overview
That would work! So I can listen for the customer.subscription.updated event and check if the status is completed
There is no "completed" status. All of the values are here: https://stripe.com/docs/api/subscriptions/object#subscription_object-status
active, sorry
You may also want to include trialing as well. ๐
One other thing I want to suggest is, if you store the Subscription ID on your end on your customer record it will likely make things easier for you. That way you wouldn't need to depend on the metadata so much.
Yes, this was more about the first time the user subscribes!
Does Stripe handle the expiration of subscriptions on its own or do I need to store an unix timestamp and check for it in my backend?
That would enable things like this:
- New
invoice.paidevent - Get the
subscriptionID - Find the customer record on your end with that
subscriptionID
That depends what you mean by expiration. Are you talking about when payment fails or something else?
When a subscription is canceled/payment fails, yes
Thank you for the tip! The reason why I needed metadata was the first instance of a subscription, saving the subscription ID and customer ID on my user record
How that's handled depends on the settings in your Dashboard here: https://dashboard.stripe.com/settings/billing/automatic
Look at the Manage failed payments for subscriptions section.
Thank you so much!
Happy to help!
Doing this still requires metadata, correct?
I don't think so, but maybe I'm misunderstanding something.
Let's say you are a new user in my platform!
You register, and you want to buy a subscription.
The first time a subscription is bought, how would I set your subscription ID, Stripe ID and subscription validity once you're coming to my success URL from the Checkout Session?
You could tie it all together with the Checkout Session's ID if you wanted to, but the metadata approach works fine too. ๐
How would I tie it from the Checkout Session ID? Access the Checkout Session object and somehow get the subscription ID and customer ID?
Yep. The Checkout Session will have both the customer and subscription properties filled in when you get the checkout.session.completed event.
So when you create the Checkout Session you can store the Checkout Session ID with the customer record on your end, then when you get the checkout.session.completed event later you'll know which customer record it belongs to.
Or you can use metadata. Whichever works better for you is fine! ๐
Thank you so much for your help! Everything is much clearer now.
Hope you have a wonderful rest of your day :D
You too! If you need anything else just let us know!
Sure! c:
Oh, one small quick question I forgot about
is there any way to change the behavior of canceled subscriptions to cancel instantly?
I want to trigger a customer.subscription.canceled to see what it returns.
๐ I'm just hopping in since @clever acorn has to head out
Hello!
Are you just looking for a way to immediately cancel a Subscription? If so, you can do this through the API : https://stripe.com/docs/api/subscriptions/cancel
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
okay! This will trigger the customer.subscription.cancel event on my webhook, right?
Oh I don't even actually need to do that if what the API docs provide is the body of the event object sent as response.
One small thing - the event will be customer.subscription.deleted not customer.subscription.cancel
Is there something specific you're looking for in the body of the response?
The subscription ID!
Gotcha! So in general, all the customer.subscription.* IDs will have a Subscription object in data.object on the webhook event (https://stripe.com/docs/api/events/object#event_object-data-object). If you want a faster way of testing this event out and you already have the CLI installed you can run stripe trigger customer.subscription.deleted to generate an event that will be sent to your webhooks
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
Thank you so much!
I got it all to work after a long day :3 thank you again and hope you have a nice day