#stiggz_api
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/1352037892347662448
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
Here's a code snippet that shows what I'm trying to do:
- Get the line items for the current subscription from stripe
- Create a map from a known enum of our products to the number on the subscription
- Convert any legacy products to modern products
- Preview the invoice, given the new line items
// handle the modern preview
const lineItemsBefore: Partial<Record<Product, number>> = {}
subscription.items.data.forEach((item) => {
console.log('item', item)
const quantity = item.quantity ?? 1
const existing = StripeProduct.fromStripeId(item.plan.product as string)
if (
!desiredInterval &&
['month', 'year'].includes(item.plan.interval)
) {
desiredInterval = item.plan.interval as IPricing.Interval
}
lineItemsBefore[existing.product] =
(lineItemsBefore[existing.product] ?? 0) + quantity
})
if (!desiredInterval) {
console.warn('No interval provided, defaulting to monthly')
desiredInterval = IPricing.Interval.Monthly
}
const lineItemsAfter = this.convertLegacyProducts(lineItemsBefore)
console.log('lineItemsBefore', lineItemsBefore)
console.log('lineItemsAfter', lineItemsAfter)
// construct final invoice line items
const items = Object.entries(lineItemsAfter)
.map(([item, quantity]) => ({
price: new StripeProduct(item as Product).prices[desiredInterval!],
quantity,
}))
.filter((s) => s.quantity > 0)
console.log('final line items', items)
const invoice = await Stripe.client.invoices.retrieveUpcoming({
customer: subscription.customer.id,
subscription: subscription.id,
subscription_details: {
proration_behavior: 'always_invoice',
items,
},
})
The ideal thing might actually be to be able to set a fixed discount amount when calling retrieveUpcoming or the corresponding subscription.update. That way, I could do the following:
- Check the user's usage of their current subscription since the billing start date
- Calculate the appropriate discount, and manually apply it, resetting the billing period start date to today
Hi there, looking
Thanks!
Did you find this guide in our docs already? https://docs.corp.stripe.com/billing/subscriptions/prorations#preview-proration
One other thing is - are you aware of test clocks? I highly recommend using them for this kind of thing so you can actually test it: https://docs.corp.stripe.com/billing/testing/test-clocks
One moment, browser doesn't like that cert
Yes, but from the docs it's somewhat unclear what the behavior of items is. The example shown there passes {id: string, price: string} for each item. Am I allowed to drop/add items? I.e., is the items parameter a comprehensive override of the existing items on the subscription?
It sort of appears that what might be happening is when I don't specify an {id}, it's interpreted as a new item. i.e., items can only be added, but not removed?
In the example I'm working with, a subscription has a single item (quantity 1), priced at $1000, and I'm trying to replace it with a new item (quantity 5), where each item is priced at $200. I would expect such a change to be effectively free, since the total price of the new subscription is equal to the total price of the old subscription
Yeah, in messing around a little further, if I specify the id of the previous item, it looks correct. If I don't specify an id, it's additive. Is there a way to preview with something like remove_item_ids: []?
Hi hi! Iโm going to be taking over for my colleague here; can you please summarize your issue/question for me?
Sure, are you able to see the previous messages?
Yes, but often the original question morphs over time so I just wanted to find out where things were at.
Fair enough. The question is about the behavior of the subscription_details.items argument when calling invoices.retrieveUpcoming or subscription.update. What I'm wanting is to preview/update a subscription, removing some items, and adding others. But it looks like all I can do is update existing items or add more items
i.e., it seems like the behavior is items = merge(existingItems, newItems) rather than items = newItems.
(on your end)
Oh wait, maybe what I want is the deleted flag on items!
Ok that gets me most of the way there I think. The next question is about how to have more fine-grained control over the final invoice. If I wanted to apply a discount of say, exactly $10, but that discount is calculated on the fly when we call retrieveUpcoming, would that be possible?
The use case is that our subscriptions grant credits to users, which can then be consumed. If the user is halfway through their subscription, but all the way through their credits when they upgrade their subscription, the easiest thing would probably be to calculate a discount, issue it against the full price of the new subscription item, and reset their billing cycle
As an example, imagine we have 2 plans, standard and pro, which have 500 and 1000 monthly credits respectively, and are priced at $20 and $40/mo. If the user was on standard and exhausts all of their credit usage, then upgrades to pro, we'd want to charge them $20, the difference in price between standard and pro, regardless of where they are in the billing cycle
So, that call to see the 'upcoming invoice' will not actually change the Subscription - you're aware of that, right?
Yes, but the corresponding call to subscription.update which has a very similar method signature will
The idea is to show retrieveUpcoming and then call subscription.update a few moments later after the user confirms
You can create a coupon for a specific amount: https://docs.stripe.com/billing/subscriptions/coupons
That might pollute my stripe dashboard with a bunch of one-off programatically created coupons though
I suppose I could also manipulate proration_date to achieve a similar effect...
This actually might be useful for you here too: https://docs.stripe.com/billing/subscriptions/pending-updates
Does that answer your question? Or is there still the question of how to structure things given your usecase?
Awesome! We do close idle threads, but if this is closed, just make a new one - the closed threads are always visible to you and to us. ๐