#kyle-heat-engineer_code
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/1271564027759169566
📝 Have more to share? Add more details, code, screenshots, videos, etc. below.
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.
- kyle-heat-engineer_api, 1 day ago, 19 messages
export const updateOwnerSubscription = async (customer_id: string, plans: PLAN[]) => {
const currentSubscriptions = await stripeClient.subscriptions.list({
customer: customer_id,
status: 'active',
})
if (currentSubscriptions.data.length > 1) {
throw new Error('Multiple subscriptions found')
}
const subscription = currentSubscriptions.data.at(0)
if (!subscription) {
throw new Error('Subscription not found')
}
const {
subscriptionItemsIdsToRemove,
subscriptionItemsUnChanged,
subscriptionItemsToAdd,
} = await generateSubscriptions(subscription, plans)
console.log({
subscriptionItemsIdsToRemove,
subscriptionItemsUnChanged,
subscriptionItemsToAdd,
})
const updateSubscription = await stripeClient.subscriptions.update(subscription.id, {
items: [
...subscriptionItemsIdsToRemove,
...subscriptionItemsUnChanged,
...subscriptionItemsToAdd,
],
proration_behavior: 'none',
automatic_tax: { enabled: true },
})
return updateSubscription
}
async function generateSubscriptions(subscription: Stripe.Subscription, plans: PLAN[]) {
const prices = (
await stripeClient.prices.list({
lookup_keys: plans,
})
)?.data?.map(({ id, lookup_key, nickname }) => ({
id,
lookup_key: lookup_key ?? nickname,
}))
if (!subscription) {
throw new Error('Subscription not found')
}
const subscriptionItems = subscription.items.data
return {
subscriptionItemsIdsToRemove: subscriptionItems
.filter(
(item) =>
!plans.includes(
(item.price.lookup_key ?? item.price.nickname) as PLAN,
),
)
.map(({ id }) => ({ id, deleted: true })),
subscriptionItemsUnChanged: subscriptionItems
.filter((item) =>
plans.includes((item.price.lookup_key ?? item.price.nickname) as PLAN),
)
.map(({ id }) => ({ id })),
subscriptionItemsToAdd: prices
.filter(
(price) =>
!subscriptionItems.some(
(item) =>
item.price.lookup_key === price.lookup_key ||
item.price.nickname === price.lookup_key,
),
)
.map(({ id }) => ({ price: id })),
}
}
You have proration behavior set to none, so what that should do is bill for everthing you passed in at the next cycle
What's happening exactly?
And can you share a sample subscription id
Let me get a screen shot of the dashboard
Ok one sec
sub_1Plq5oJ3mXHphgmzJ6wXChxY its from test dashboard
essentially if I was setting my user to have a updated subscription where I am only removing subscription items. The user is getting charged for the unchanged subscription
If I set the proration to a different value would this result in the 'invoice.payment_succeeded' event being triggered, as this is what I use to update my db with application business logic
Let me update on my end so you can see the issue I am trying to raise
Ok you should be able to see how I updated my sole trader to have 0 cad which charged me for the full sole trader year
Not sure what you mean. The request you just made didn't charge you anything
It's not set to bill again until 2025
You're referring to this request right? https://dashboard.stripe.com/test/logs/req_LePafPX9aZ3dhI
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Ok, looks like I have been a bit dumb here
Thank you for pointing this out too me
But when I do want to change my users subscription I do want them to be charged straight away for it
I think the confusing arrised because when I changed them from a monthly subscription to a yearly subscripton this resulted in the charge occuring (how I would expect it too). But when changing the subscripiton from a yearly to another yearly one its not getting charged till the next year
Essentailly I need my users to be charged for the parts they change and not charged for the parts that are constant within the subscription update
Not sure I understand exactly, but sounds like you should charge immediately for the proration
Let me try and explain it again.
Say I have a subscription for A £10 a month and B £20 a month. The user updates the subscription to be A £10 a month and C £30 a month. Currnetly in the logic I have the user is getting charged £40 a month but really they need to be charged £30 on the update of subscription and then the next month they need to be charged £40. Does this make sense?
Kind of. This upgrade would be part way through the month?
Yeah this would be part way
Ok so then if you were to bill them 30, that would actually be overcharging them
Since they'd only be on the 30 price for part of the month
Really prorations handles this for you
So you should set proration_behavior to always_invoice: https://docs.stripe.com/api/subscriptions/update#update_subscription-proration_behavior
In our business context this can be a unit amount so the system would handle it on our end for the over charge
In our context it would be £30 for 15 surveys which immidaitly gets added to the user
So wouldn't want to charge less than 30 in this case
We are happy to over charge for the updated item but don't want to recharge for the unchanged items
So really in the current month they'd pay 10 + 20 + 30 = 60 across 2 invoices?
Thats why I had it set to none
You'd need to create an invoice for the 30
LIke expliclty create and bill them 30 for the update and set proration behavior to none
That way next month they get charged 40
And you have to manually charge them 30
That could work for our use case. Just thinking if I would still see the subscription items from the webhook side as this event 'invoice.payment_succeeded' needs to be able to pick up the subscription items to know to update the users account
Well you wouldn't get invoice.payment_succeeded until the next month/billing cycle
since proration behavior is none
Ah that would be an issue cause the users account wouldn't be updated till next billing cycle
You'd need to create an invoice for the 30, this wouldn't trigger a invoice success?
It would
I guess I could put meta data in the custom created invoice to then detect in the invoice.payment_succeeded event.
But it would only have the $30 amount not all the subscription items
Since this is a separate invoice you have to manually bill them not a part of the subscription's cycle
I think this would still work in our uses case
Thank you, I feel like I can see a soltuion to this issue now
Happy to help!
I know our system is overally complex 😅