#Ema - Subscriptions

1 messages ยท Page 1 of 1 (latest)

clever acorn
#

Hello! Not a bother at all, we're here to help!

knotty crane
#
  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

clever acorn
#

Which event(s) are you sending to your webhook endpoint?

knotty crane
#

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.

clever acorn
#

Can you give me the event ID of one of the customer.subscription.created events that you expected to have the metadata?

knotty crane
#

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?

clever acorn
#

Let me take a look, hang on. ๐Ÿ™‚

knotty crane
#

That's confusing

#

if you check the code I sent you, the metadata is there

clever acorn
#

Are you sure userId has the value you expect?

knotty crane
#

Wait, I am going to test something real quick

#

was thinking of the same thing haha

#

Meanwhile, I have three small questions.

  1. 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?
  2. The same example also has Apple Pay support, it is supported out of the box with the payment method [card]?
  3. If a subscriber tries to subscribe again, will it have the same customerId as long as they use the same email?
clever acorn
#
  1. 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.

knotty crane
#

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

clever acorn
#
  1. 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.

knotty crane
clever acorn
#

Yep.

knotty crane
#

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

clever acorn
#

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

knotty crane
#

I am very sorry about the beginner questions, first experience with Stripe :p

clever acorn
#

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.

knotty crane
#

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

clever acorn
#

Always happy to help!

#

You can set metadata on the Checkout Session itself as well.

#

Metadata can be set on most Stripe objects.

knotty crane
#

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

clever acorn
#

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.

knotty crane
#

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

clever acorn
#

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"
    },
knotty crane
clever acorn
#

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.

knotty crane
#

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

clever acorn
#

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

knotty crane
clever acorn
#

Not sure what you mean, can you provide more details?

knotty crane
#

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

clever acorn
#

The closest thing would be invoice.paid, yeah. But what's the issue with checking the status of the Subscription?

knotty crane
#

Not sure about how to wait for the subscription status to change in what I want to set the flag

clever acorn
#

Hang on, I think I'm missing something. What do you mean by "wait for the subscription status to change"?

knotty crane
#

I'm sorry if I'm missing something

clever acorn
#

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?

knotty crane
#

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

clever acorn
knotty crane
clever acorn
knotty crane
#

active, sorry

clever acorn
#

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.

knotty crane
#

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?

clever acorn
#

That would enable things like this:

  1. New invoice.paid event
  2. Get the subscription ID
  3. Find the customer record on your end with that subscription ID
#

That depends what you mean by expiration. Are you talking about when payment fails or something else?

knotty crane
knotty crane
clever acorn
#

Look at the Manage failed payments for subscriptions section.

knotty crane
#

Thank you so much!

clever acorn
#

Happy to help!

knotty crane
clever acorn
#

I don't think so, but maybe I'm misunderstanding something.

knotty crane
#

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?

clever acorn
#

You could tie it all together with the Checkout Session's ID if you wanted to, but the metadata approach works fine too. ๐Ÿ™‚

knotty crane
#

How would I tie it from the Checkout Session ID? Access the Checkout Session object and somehow get the subscription ID and customer ID?

clever acorn
#

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! ๐Ÿ™‚

knotty crane
#

Thank you so much for your help! Everything is much clearer now.

#

Hope you have a wonderful rest of your day :D

clever acorn
#

You too! If you need anything else just let us know!

knotty crane
#

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.

bitter obsidian
#

๐Ÿ‘‹ I'm just hopping in since @clever acorn has to head out

knotty crane
#

Hello!

bitter obsidian
knotty crane
#

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.

bitter obsidian
#

One small thing - the event will be customer.subscription.deleted not customer.subscription.cancel

knotty crane
#

Yeah, my bad!

bitter obsidian
#

Is there something specific you're looking for in the body of the response?

knotty crane
#

The subscription ID!

bitter obsidian
#

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

knotty crane
#

I got it all to work after a long day :3 thank you again and hope you have a nice day