#naveed-web3auth_best-practices
1 messages ยท Page 1 of 1 (latest)
๐ 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/1386618562608890026
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
This is the code Im using on my webhook endpoint to decide on sending an email
if !isOnLatestPhase(stripeSubSchedule.Phases) {
lastPhase := stripeSubSchedule.Phases[len(stripeSubSchedule.Phases)-1]
fmt.Printf("lastPhase %+v\n", lastPhase)
downgradePlan := lastPhase.Metadata["downgrade_plan"]
isDowngradeScheduled := downgradePlan != ""
if isDowngradeScheduled {
fmt.Println("send email for downgrade:", downgradePlan)
// go s.sendDowngradeEmail(stripeSubSchedule, downgradePlan)
}
}
I go through the phases and make sure im not already on the latest phase (cuz that would mean im already downgraded)
One thing I dont like is that the metadata even after subscription schedule is released remains on the subscription
and also idk if this is the best approach for subscription schedule downgrade
Yes, you'd need to unset that when the schedule releases if that is a requirement
this part remains basically
how to do that
i have to look out for subscription_schedule.released event to do that?
Yep, should work. You can get the sub_xxx ID from the subscription property in that event payload and then call this API passing metadata: ''
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
Is there a way to detect plan downgrade without resorting to metadata?
There are other things that we do on our dashboard like upgrade to higher plan and whatnot without using metadata. We just detect the price items on the subscription to see what the items are before sending an email e.g. "thanks for upgrading to Scale"
This approach may have some flaws like what if subscription.updated event is fired for reasons other than upgrades
And comparing between previous attributes and latest seems complicated
And comparing between previous attributes and latest seems complicated
That's the only way to understand the action that caused the event to fire really
So for subscription schedule that I just mentioned to detect a plan downgrade the non-metadata approach is to compare the actual phase items? evt_1Rd5CcImFOsfVEtUtwuLleNi
You can see in the event payload that the second phase item has metadata attached to it
Yes you'd compare the phases[][items][][price]
It seems that I'd have to keep record of what price ids correspond to what plan, but that seems not the best approach given that we use lookup keys
Yes the lookup keys aren't a part of those payloads unfortunately
Is there a better way to achieve what im looking for?
Not really, no. You need some kind of mapping to you know if a phase item(s) changes it corresponds to a downgrade/upgrade
(or leverage metadata like you are)
In terms of leveraging webhook i think that the metadata remaining on the subscription may not necessarily pose any issue (unless I utilise it elsewhere)
removing it on release seems like a bonus but a good cleanup step
but i have to ensure that the subscription.updated event does not trigger subscription provisioning and email flows
so this might indicate a flaw in the design of my webhook subscription.updated handler
You'll likely need logic to discard those events yes (i.e. check for the metadata key)
this is what im currently doing
func (s *billingService) handleEventSubscriptionUpdated(tx *gorm.DB, event stripe.Event) error {
// ...
// validate subscription, if invalid, notify devs via Sentry
s.validateSubscription(event)
customerStripeID := event.Data.Object["customer"].(string)
return s.provisionPlan(tx, customerStripeID, event)
}
Oh hey maybe i wont need to do anything
if dbCustomer.Plan == *plan {
// skip if plan is not changed
return nil
}
it seems if plan remains unchanged i dont do anything
so i guess i wont have to worry about it
Worth testing for sure! Can leverage a test clock to simulate a downgrade
Alright
One more thing
Are there any design patterns or abstractions utilised in the industry that cover stripe webhooks esp. the detection of business events based on webhooks payload esp. abstracting those aspects about comparing current vs prev attributes
the mapping of webhook events to specific business events basically
Or any famous clients that utilise stripe and have documented their approach to this stuff
Nothing that I'm aware of
Most do leverage the previous_attributes hash and do a comparison to determine the nature of the change. Granted that can be complex as noted
Yes, and now that I think about it I realised this code here may cause some issues
if dbCustomer.Plan == *plan {
// skip if plan is not changed
return nil
}
It may cause the plan provisioning steps related to upgrades to be triggered even for downgrades!
because the only condition is that the plan is different
If i use the metadata approach it seems that I would absolutely have to clean it up, because otherwise a user after downgrading may wish to upgrade again and the subscription.updated endpoint if it makes an exception based on if metadata.downgrade_plan exists things would not go as planned if the metadata is not cleared from the subscription by this point in time
Yep, definitely
okay so ill have to handle subscription event released and then within it i have to basically unset the downgrade_plan key. I guess it should not be an issue whether that metadata key exists or not.
As for determining whether the release event should indeed clear that key i guess it doesnt matter atm what action triggered the release.
Tbh I think the cleanup code is still not where it needs to be. Because
subscription schedules linger until all the phases are complete. So e.g. Scale downgrade to Growth, At end of month I am downgraded to Growth but sub schedule is not yet released. It needs to progress for the end of another month before it is finally relaesed
But if before that happens I trigger an upgrade again. to say Scale the sub schedule would be added a new phase automatically
lol
So that delays the release
oh wait im supposed to listen for subschedule.updated event right
i though there was a .released event
oh hold on yeah there is a .released event
but i guess thats not the event i should be looking out for
clearing metadata is all about the downgrade having completed
im starting to think metadata is really not a good approach at all
Then you'll want customer.subscription.updated which will fire then the sub transitions to the new period of the downgraded plan
true, only one concern is that within this webhook i am updating the sub to remove its metadata which again triggers the customer.subscription.updated event
but yeah i think thats alright
seems like the only way to make the metadata approach work
Try it out with a test clock and let us know!
Thanks for the help. It really helped clear out everything!
Stripe Developer Debugging (SDD) > Rubber Duck Debugging (RDD) ๐
Happy to help! ๐ฆ