#mark-subscriptions
1 messages · Page 1 of 1 (latest)
I was setting it to the beginning of the day. This didn't work as if updating the subscription on the same day as creation, it said that the proration_date couldn't be before the subscription created date. I also, tried it at the end of the day but then no invoice was generated.
Are you also setting proration_behavior: always_invoice?
yes
subscription = await stripe.subscriptions.update(
subscriptionId,
{
items: Object.values(updatedItems),
payment_behavior: 'default_incomplete',
proration_behavior: 'always_invoice',
expand: ['latest_invoice.payment_intent'],
metadata: { userId, familyId },
proration_date: Math.floor(startOfDay.getTime() / 1000),
}
);
Can you share an example subscription or update request ID?
Initial creation: req_wbTm6ShQZvWa4p
Successful update (no proation_date): req_ZyRfgBrT0Riv96
Failed (proation_date set to start of day): req_q85laUS4aIs0YZ
Hi there 👋 taking over for @dense sentinel
Give me a few minutes to get caught up.
It looks like the request is failing because the proration_date is being set to a time that occurs outside of the billing cycle. So if you look at billing_cycle_anchor, that's the time that the Subscription's billing cycle starts. Do you get the desired behavior when setting the proration_date to a later time after the billing_cycle_anchor time?
When I set proration_date to the end of the day, it does seem be succeeding now req_8gGvv4oz2tqkDq. However, the amount at 860 still appears to calculated in seconds as it should be 2 x 434. What should I be setting billing_cycle_anchor to?
Basically I want the prorated amount to be per day - so always the same until tomorrow, whatever time I update.
thanks
Okay so to summarize you don't care when during the day the update occurs, you want the proration amount to be the same
Yes, so if an update occurs 2 days after the subscription creation and 1 item is added, it should charge the full item cost less the 2 days cost, regardless of the time of day the update occurs.
Okay and for the request above that succeeded using proration_date, what was unexpected there?
req_8gGvv4oz2tqkDq specifically
I don't understand However, the amount at 860 still appears to calculated in seconds as it should be 2 x 434
The update involved adding 2 items with a unit cost of 434. Therefore, since the update occurred on the same day as creation I would expect the cost to be 2 x 434 = 868. However, it was 860.
If the update was tomorrow I would like the charge to be (2 x 434) - (2 x cost of item for one day)
Ah okay I think I understand. If you want it per-day you still need to use the period_start when setting your proration_date
So if it is same day you don't want any proration taken into account, right?
Versus if it is sometime during day 1-2 you want 1 day of proration?
Got it, so yeah, when you set your proration_date you should examine the period_start timestamp
Then you set your proration_date based on that timestamp. If it is day 0 then you would set proration_date equal to current_period_start
If day 1-2 then you would set proration_date equal to current_period_start plus 24h
Etc.
Is the period_start timestamp on the invoice? If so, how to I get that value before calling subscriptions.update as that is what generates the invoice?
You would retrieve the Subscription ahead of updating.
Hrmm actually good point. If you update doesn't reset the billing cycle anchor then multiple updates would break this logic
Oh nvm
You are using always_invoice
So yeah, this is fine.
So something like?
let subscription = await stripe.subscriptions.retrieve(subscriptionId);
const currentPeriodStart = subscription.current_period_start;
// Work out integer number of days from currentPeriodStart to now
const numWholeDays = ...
subscription = await stripe.subscriptions.update(
subscriptionId,
{
items: Object.values(updatedItems),
payment_behavior: 'default_incomplete',
proration_behavior: 'always_invoice',
expand: ['latest_invoice.payment_intent'],
metadata: { userId, familyId },
proration_date: currentPeriodStart + numWholeDays // in secs
}
);
Thanks - I'll give it a try.