#beastboy_subscription-updates-manual-prorations

1 messages ยท Page 1 of 1 (latest)

humble ingotBOT
#

๐Ÿ‘‹ 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/1326949928471367730

๐Ÿ“ Have more to share? Add more details, code, screenshots, videos, etc. below.

visual birch
#

For example, in test mode, take a look at this customer:

https://dashboard.stripe.com/test/customers/cus_RXpWwAMgZLQJ3F

They were on a 477.15 3-month product, I call the function and it updates the user immediately to the new product, doesn't charge them anything, then I have my own code that creates a refund for the difference, which is great

#

However, this customer in live:

https://dashboard.stripe.com/customers/cus_QweFut1IaB4xOW

I do the same exact process, and it does the same thing BUT it attempts to charge the customer again for the new price, even though it shouldn't as it's cheaper (which is the same case as the one above). My refunding code works correctly as you can see. But why is this happening?

#

Everytime I test this it works in test mode, but in prod it operates completely differently

past fable
#

Hi sorry for the delay

#

Looking

humble ingotBOT
past fable
#

Sorry was in a bunch of other threads

#

There's a bunch of requests on both those customers

#

Will be easier if you can link the exact requests or share the exact request id's you're referring to

visual birch
#

Okay actually if you could help me with this I can fix it on my own

#

what's the best way to update a customer's subscription to a new product (resetting the billing cycle) and NOT charging them for the new product on the subscription

#

So charging them $0

#

Creating an credit balance? Applying a 100% discount when updating the subscription?

past fable
#

I personally would create a negative amount invoice item

#

Those act as credits/discounts

#

You could discount the invoice to $0

#

They're automatically pulled into the customer's next invoice

#

So you'd need to create it before making the update request

visual birch
#

I see

#

got it

#

Wait how to discount to zero?

#

By passing in the exact amount to discount by?

#

Or is there a universal way

past fable
#

So if the invoice amount is $10, you'd create a -$10 invoice item

visual birch
#

i see

#

okay thank you let me try

past fable
#

Sure, np

visual birch
#

Okay so everything is looking good

#

One thing I'm hung up on is

#

await stripe.invoiceItems.create({
customer: subscription.customer as string,
amount: difference, // positive => charge
currency: oldPrice.currency,
description: Upgrade charge: switching from price ${oldPrice.id} to ${newPrice.id},
subscription: stripe_subscription_id,
});

    const invoice = await stripe.invoices.create({
        customer: subscription.customer as string,
        subscription: stripe_subscription_id,
    });

    await stripe.invoices.finalizeInvoice(invoice.id);
#

I want the user to pay for this immediately, but when I run this code, you can see that the invoice is marked incomplete

#

As seen here

#

So do I need to call invoice.pay? Why im confused is that the docs say finalizing an invoice makes the customer attempt to pay it? Unless im reading ti wrong

#

it

latent axle
#

Hi ๐Ÿ‘‹

I'm stepping in as my colleague had to go

visual birch
#

Okay

#

Hi

latent axle
visual birch
#

evt_1QfPH0DyFtOu3ZuTfEn2OScf

#

oh whoops

#

req_vZQ8rp928NZwU0

latent axle
#

Brilliant, thanks

visual birch
#

req_EW0afcpQwW9f1h

#

I did finalize it tho

#

so idk why it didnt attempt to charge the customer automatically

latent axle
#

It looks like this was a one-off Invoice but it's also associated with a Subscription. What is it you are trying to do here?

visual birch
#

This is the invoice I created with that previous req

#

than I finalized it using that second request I sent

#

I want to just charge the user for the invoice I created, which you said to finalize the invoice to do this, which I did, but it never charged the user

#

So how do I charge the user for this invoice?

latent axle
#

Right but you provided the Subscription in the request. Why is this associated with a Subscription if you just want a one-off payment?

visual birch
#

Because I want the invoice to be attributed to the subscription

#

for my system to handle the invoice.paid event correctly

#

What is going on here is I'm writing code to update a subscription from its existing price to a new price. This is the case where its more expensive, so I need to charge the user the difference between the old price and the new price, hence me creating the new invoiceItem

#

I want it to be attributed to the subscription so when I receive an invoice.paid event for the successful charge of the price difference, by system will know its for the particular subscription

#

Does that make sense>

latent axle
#

All the business case makes perfect sense. The API usage does not.

I'm writing code to update a subscription from its existing price to a new price. This is the case where its more expensive, so I need to charge the user the difference between the old price and the new price, hence me creating the new invoiceItem

You shouldn't take this approach. You should update the Subscription directly as we describe here: https://docs.stripe.com/billing/subscriptions/upgrade-downgrade#changing

To charge the customer immediately, you would include proration_behavior: 'always_invoice'. This would create a new invoice that only charges for the increased cost of the new price for the current billing cycle.

visual birch
#

But why doesnt my approach work?

#

I've tried that method before, but have faced so many issues with it

#

this is my third time coming back for help to work on this 'function' because it seems to not work for some cases

#

So I want to do it another way

latent axle
#

Creating an off-cycle manual invoice that is linked to the Subscription will likely cause more issues.

visual birch
#

Damn

#

Okay so

#

back to square 1

#

I actually only need to address the case where I'm upgrading the customer from cheaper price -> older price (so charge them the difference)

I'm using this code as previously recommended:

await stripe.subscriptions.update(stripeSubscription.id, {
items: [
{
id: stripeSubscription.items.data[0].id,
price: new_price_id,
},
],
billing_cycle_anchor: 'now',
proration_behavior: 'always_invoice',
payment_behavior: 'pending_if_incomplete',
proration_date: stripeSubscription.current_period_start,
});

#

However when I ran this here:

req_JsCWhd0VcGZGUM

#

It charged the customer the full price

#

or tried to at least

#

Oh wait sorry

#

ignore that example

#

Sorry, that's for the case more exp price -> cheaper price

latent axle
#

Yeah, that's because you changed the billing cycle

visual birch
#

I want this to universally work for products of either diff or the same billing cycle

#

As I described

#

Or I can write diff code for the diff cases of billing cycles, whatever I need to do I'm down

latent axle
#

When you update the billing cycle in changes the time period being charged, so that is going to impact what prorations get charged

visual birch
#

Ok

latent axle
#

If it were me, I would code every scenario you are describing, then keep making adjustments to the parameters to validate different behaviors and dial in how you want the changes to behave.

#

You are already making good use of Test mode

visual birch
#

why is this so difficult haha

#

This seems so straight forward to me

#

Is stripe really that bad with just fixed prorations?

latent axle
#

Prorations are dynamic by definition.

visual birch
#

Prortations is the incorrect word in this case. Makes sense for a usage / service based product, but if we're selling physical products this is quite painful

#

I appreciate your help though

latent axle
#

You can even add those items for update requests that do not create an Invoice. They will just get added to the next Invoice for that Subscription

visual birch
#

Oh that's very helpful

#

thank you

latent axle
#

Sure thing! Happy to do it ๐Ÿ™‚

visual birch
#

Hey last question: If I'm gonna be adding in negative unit amounts to add_invoice_items that will be relatively dynamic as customers can go between multiple products, do I HAVE to generate a new price every time (looks like I have to use price_data here)?

#

I would ideally just have an invoice_item where it's just the unit_amount

#

or is this unavoidable

latent axle
#

Because of the relationship required between Invoice line items and Prices, you would need to specify price_data and have a Product that you use to map to these negative amounts.

visual birch
#

I see

#

should I have a product that is designated specifically for these 'manual prorations'?

#

Is that the best practice?

latent axle
#

Depending on whether you anticipate doing this only for discounts (negative items) or both discounts and additional charges, I would either create one or two Products.

That would make it easier to review the manual prorations of each type

visual birch
#

Got it got it

#

and sorry one more q haha

#

is there a difference between calling subscription.update for add_invoice_items

and

calling invoiceItems.create (specifying the subscription in the param)?

#

Or is it the same thing

latent axle
#

I think updating the Subscription directly, both with the new price and add_invoice_items for the manual proration, would be more likely to have the behavior you are looking for (charging the customer automatically once finalized).

visual birch
#

got it

#

Thank you!