#tomek_checkout-subscription

1 messages ¡ Page 1 of 1 (latest)

sly boneBOT
keen abyssBOT
#

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.

sly boneBOT
#

👋 Welcome to your new thread!

⏲️ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.

⏱️ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.

🔗 This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1276309936778772573

📝 Have more to share? Add more details, code, screenshots, videos, etc. below.

merry leaf
#

@cunning tangle When you get the checkout.session.completed Event, it will have subscription: 'sub_1234' with the id of the Subscription. At that point you can call the Retrieve Subscription API https://docs.stripe.com/api/subscriptions/retrieve and look at the current_period_end property

#

tomek_checkout-subscription

cunning tangle
#

so I need to make 2 calls to stripe then? 1 for retrieving session object, and second one to Subscription API?

isn't it possible to get that info from the SessionObject itself?

why do we then retrieve the session in the tutorial?

  checkout_session = stripe.checkout.Session.retrieve(
    session_id,
    expand=['line_items'],
  )
merry leaf
cunning tangle
#

so it's not visible by default for sure? I HAVE to expand it?

merry leaf
#

I mean by default you get subscription: 'sub_123' which is the id of the Subscription yes

cunning tangle
#

why is "line-items" then suggested to be put in 'expanded' in the tutorial?

merry leaf
#

because line_items isn't returned by default so the tutorial shows you how to access that information in the API.
I'm sorry but I highly recommend reading the doc I shared and watching the video as it covers exactly those questions in details

cunning tangle
#

but as I understand you're talking about how "Expand" works... I'm more asking about, for what do I need the "line-items" information, do those links also cover that?

merry leaf
#

the line_items property has the list of Price(s) that are part of the Checkout Session. So it's common to want to look at it to do some reporting, email receipts, anything you would find useful
You don't have to keep it if you don't use it in that flow

cunning tangle
#

thank you

#

2 more questions

merry leaf
#

feel free to just ask, sorry I was waiting on you to type them but you might be waiting on me to say yes

cunning tangle
#

I see that there is "status" in the checkout_session object and in the subscription API as well - which one should be used to determine if the user has paid?

as I see in the docs, the Subscription object has the current_period_end field - is it best to use this field for determining if the current user has activated AND paid for the "premium features"?

merry leaf
#

I recommend reading https://docs.stripe.com/checkout/fulfillment to start. It explains how to do fulfillment on Checkout and it explains how to look at payment_status.

A Subscription models recurring payments. So it's a "state machine" overall and for future billing cycles/future Invoices you'd use the Subscription's status

cunning tangle
#

I've read the tutorial, sorry I guess I need a little confirmation...

not sure if I understand everything correctly.

So to put it all together, the answer that you're giving me:

I should basically do:

if checkout_session.payment_status != 'unpaid': 

as the tutorial suggests, and then for example:

if checkout_session.payment_status != 'unpaid':
  user = User.get(pk=this_user_pk)
  user.subscription_end_period = checkout_session.subscription.current_period_end   # (take current_period_end from stripe expanded session object and save to database)
  user.has_active_subscription = checkout_session.subscription.current_period_end > current_date

(this is pseudo code, but I hope you get the gist)

Would something like that be what you're suggesting?

merry leaf
#

yep

cunning tangle
#

thank you

merry leaf
#

you can try all of this in Test mode to get a feel for it

cunning tangle
#

that doesn't sound that hard!

merry leaf
#

yeah it's a bit convoluted at first to grasp all the relevant objects

cunning tangle
#

yep

merry leaf
cunning tangle
#

thanks

#

do you see usually people implementing those kind of things by themselves, or is it recommended to hire someone who know this stuff (stripe) through and through?

merry leaf
#

hard to say, depends on how comfortable you are writing code and deploying it. Lots of people definitely do it themselves

cunning tangle
#

I got only 2 more technical questions that come to my mind for now, thank you for your help so far.

  1. What is the best/recommended way to keep track of the User/StripeSession relation?
  • as I can imagine, the recommended way would be to create assign SessionID to a particular user, when first creating a Session in the checkout_stage on my server? correct?
merry leaf
#

Yes that's what I would do. And once the Checkout Session is completed successfully you store the Subscription id sub_123 because the Checkout Session doesn't matter as much anymore, it was just for the first payment

cunning tangle
#

right, and then when the User logs in I would check whether the current_period_end is in the past, and if it is I would query Stripe Subscription API again to check whether they made payment and whether I should update the subscription status and end period in my DB?

#

would that be a correct way of doing this?

merry leaf
#

also remember that the next Invoice is only created after current_period_end so don't block access immediately on that date. check the Subscription, the most recent Invoice, etc.

cunning tangle
#

thanks I will check that

#

is there any adventage with Webhooks over what I described above?

merry leaf
#

webhooks are kind of required with Billing/Subscriptions. You need to handle failed payments, automatically cancellation, retries. So really go with the webhook approach

cunning tangle
#

ok thanks

#

I also see that it provides best flow as you get notification event couple days before the payment actually, so I guess that's better

#

one last question I would have:

how to best determine the type of product that the user has paid for?

is the recommended way just to keep track in the code / project - which product ID relates to which product features for example:

PREMIUM_FEATURES_SILVER= "prod_Na6dGcTsmU0I4R" # product ID take from stripe (normally probably set it as environmental variable and retrieve it from env here)
PREMIUM_FEATURES_GOLD = "prod_342523452345" # another product ID taken from stripe dashboard

and then after receiving the event from webhook (for example invoice.updated), get the product ID from that event and compare it with saved values in the code that you already checked to which products they relate?

(and analogously with first payment and the checkout success landing page, but then compare it with the page_id retrieved from the session object)

would that be correct?

merry leaf
#

yes that is what I'd do

cunning tangle
#

thank you, so that's the recommended way I mean, you don't see any risk of error here?

#

I was thinking that maybe you suggest something like retrieving the information about the product also from the API

merry leaf
#

no I would have that all cached in my own database personally

sly boneBOT
cunning tangle
#

I mean you don't need that in the DB, as the products are single items per app, so they don't need to be per user, so I guess you can store them in code

#

I'm not sure if we understand each other here, but feel free to skip, might be late hour on my side

#

I you have something to add, I will happily read some more answer to this (can read when I'm back), but also any way thank you for the help anyway

#

I will be going now,

#

ty