#nt_unexpected

1 messages ยท Page 1 of 1 (latest)

silent zincBOT
#

๐Ÿ‘‹ Welcome to your new thread!

โฒ๏ธ We'll be here soon! We typically respond in a few minutes, but in some cases we might need a bit more time (e.g., server's busy, you've got a complex question, etc.).

โฑ๏ธ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can 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/1250407065461985353

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

leaden nebula
flat kindle
#

Yes it is

#

Here's a complete code snippet for your convenience

#
now = Time.now.utc

params  = {
  "cancel_at_period_end": "false",
  "default_payment_method": "pm_1PQWAfDgQLhhFEp9HxSPY3O4",
  "backdate_start_date":  (Date.parse('2024-05-15').to_time.utc.change(hour: now.hour, sec: now.sec, min: now.min) - 1.second).to_i,
  "items": {
    "0": {
      "price_data": {
        "recurring": {
          "interval": "month"
        },
        "unit_amount": "17880",
        "product": "prod_NJnxvZ0pyt5Ciu",
        "currency": "USD"
      },
      "quantity": "1"
    }
  },
  "customer": "cus_QH4Dj4uIrbZCfI",
  "payment_settings": {
    "payment_method_options": {
      "us_bank_account": {
        "verification_method": "instant",
        "financial_connections": {
          "permissions": {
            "0": "payment_method"
          }
        }
      },
      "card": {
        "request_three_d_secure": "automatic"
      }
    },
    "save_default_payment_method": "on_subscription",
    "payment_method_types": {
      "0": "card",
      "1": "us_bank_account"
    }
  },
  "proration_behavior": "none",
  "billing_cycle_anchor":  (Date.parse('2024-05-15')+1.month).to_time.utc.change(hour: now.hour, sec: now.sec, min: now.min).to_i,
  "expand": {
    "0": "latest_invoice.payment_intent",
    "1": "pending_setup_intent"
  }
}

s = ::Stripe::Subscription.create(params)

update_params = {
  "payment_behavior": "pending_if_incomplete",
  "proration_date": (Time.now + 1.day).utc.to_i,
  "proration_behavior": "always_invoice",
  "items": {
    "0": {
      "price_data": {
        "recurring": {
          "interval": "month"
        },
        "unit_amount": "43200",
        "product": "prod_LxYG6NjewhGxMA",
        "currency": "USD"
      },
      "quantity": "1",
      "id": s.items.first.id
    }
  },
  "expand": {
    "0": "latest_invoice.payment_intent"
  }
}
::Stripe::Subscription.update(s.id,update_params)
leaden nebula
#

Hmm, I believe this is mostly expected in that example as you're opting not to charge users for the initial backdating period (https://docs.stripe.com/billing/subscriptions/backdating#backdating-no-charge) and consequently the current period is set to 2024-06-12 -> 2024-06-14 (can see that in the customer.subscription.created event: https://dashboard.stripe.com/test/events/evt_1PQowGDgQLhhFEp96neHFd0b)

Learn about backdating subscriptions.

flat kindle
#

Here's an example subscription with charging the customer for the initial backdating: "sub_1PQnecDgQLhhFEp9fEvqJ4qn"
Again stripe chooses to prorate based on a 30 day period instead of a 31-day period

#

I do not understand when this period is calculated as the actual one and when it is calculated as a 30-day period

leaden nebula
#

The examples of the 'miscalculated' proration are for updates requests though, yes? The documentation you're referencing is for the proration calculation when backdating start dates on creation

The update is different as the backdated start date is in effect in the previous period (either because the invoice was paid or you 'forgave' it). Part of that means that the subscription is in the next period (June in effect), so the update call is essentially for the June-July period (30 days)

#

As I said, that's reflected on the current_period_start/end timestamps returned in your creation calls

flat kindle
#

In that case the proration amount would have been calculated with a factor of like 2/3 and not 2/30. It is really confusing.. We prorate a customer for their existing billing period which started on May 14th for a cycle of 31 days and would end on 14th of June. If I update the price at any point while that period isn't over I would expect that the period will not change

leaden nebula
#
#

Help me understand where the calculation is wrong there, note that we prorate to the second

flat kindle
#

Ok give me a second to calulate the amounts

leaden nebula
#

This is for the period 2024/06/13-2024/07/12 (30 days)

#
  • 178.80 was previously paid
  • We applied credit of 172.84 for unused time
  • Prorated amount of 417.60 on new plan for remaining time
#

The 'remaining' time is about ~0.9666 of the full period โ€“ 432x0.966 = 417.57

flat kindle
#

Yes I understand what you are saying but here's the issue. The unused time of 172.84 is wrong. This is calculated by multiplying the list price of 178.80 with the rational number of (29/30) days. This calculation is for the backdated period of 15th of May till 13th of June.
This should have been 167.26 which is the result of the multiplication of 178.80 * Rational(29,31)

leaden nebula
#

The initial invoice (that we're crediting for) doesn't reflect that backdated period though: https://dashboard.stripe.com/test/invoices/in_1PQnecDgQLhhFEp9Seq2aifN

You forgave the backdated period on subscription creation by passing proration_behavior: 'none': https://dashboard.stripe.com/test/logs/req_NBKTOMLsH9ZNws

flat kindle
leaden nebula
#

That's on the update call, yes. I'm referencing how you're creating the subscriptions which is the root issue here

flat kindle
#
leaden nebula
flat kindle
#

No I just created a new one as you suggested: sub_1PQppVDgQLhhFEp9mrAdgNHn

#

I have sent the creation logs above...

leaden nebula
#

Yeah I just don't think this works as you expect regardless of proration behaviour. See the current_period_* timestamps in the creation call response: they're set for June-July and as such any subsequent updates will be prorated based on that period

#

Similarly, if you set the backdate_start_date to January 15, the proration calculation is based on an imagined month running January 15 to February 15. Because that month is 31 days, the prorated amount for the 17 days of January 15 to February 1 is 17/31 (or 0.548) of a normal monthly charge.
From here seemingly only applies to the creation proration. Not any subsequent updates, which is your expectation

Learn about backdating subscriptions.

flat kindle
#

But this is utterly incorrect. I backdate a subscription for the period of 15th of May - 15th of June. On the 12th I update the subscription while the customer has paid the full amount of those 31 days. And for the proration calculation, I change this cycle without any reason to 30 days. So 1 day is lost from that calculation because the update on the subscription has a different day subtotal than the creation? This is not how proration works...

#

I cannot seem to understand how in my initial example the billing cycle is for 31 days but the proration of the unused amount is then calculated for 30 days. If both calculations happened on May, the proration would have been for 31 days.

leaden nebula
#

But when you make that API call the subscription isn't in the 15/5/24-15/6/24 period, as proven on the API response

flat kindle
#

Yes but the API should be agnostic enough to know that the remaining unused time was when the subscription was backdate started....

#

If we move this experiment to June 15th - July 15th my experience would be different. the proration for both create and update would be 31 days.

hybrid yoke
#

hi! I'm taking over this thread.

#

Yes but the API should be agnostic enough to know that the remaining unused time was when the subscription was backdate started....
maybe, but that's not how the API was designed. so you need to take the existing behaviour into account for your implementation.

flat kindle
#

Ok, this is the first straightforward answer I receive. So it's a decision on your end. not how proration should work

#

Thanks