Automattic / woocommerce-payments

Accept payments via credit card. Manage transactions within WordPress.
https://wordpress.org/plugins/woocommerce-payments/
Other
177 stars 69 forks source link

Error creating WCPay Subscription with delayed first payment (trial/sync) from the update payment method flow #4908

Open mattallan opened 2 years ago

mattallan commented 2 years ago

Describe the bug

When creating a WCPay Subscription that has a delayed first payment (trial/sync) through the update payment method flow, we received the following error message from Stripe:

When billing_cycle_anchor follows a trial, the anchored invoice must be prorated. For a longer free period, use a longer trial.

Slack thread: p1665243603695169-slack-C46H1UYN4

I can't seem to find anything about this error message in the Stripe docs but I've been reading this https://stripe.com/docs/billing/subscriptions/trials#combine-trial-anchor to see if we're doing anything wrong. Based on my understanding, the billing_cycle_anchor argument is used to tell stripe that the first payment is anchored to a later date (i.e. a pseudo-free trial period), so when we create a WCPay subscription via the update payment method flow that also has a delayed payment (trial/sync), I think we're incorrectly setting both the billing cycle anchor and trial end date to be the same timestamp.

From our logs, here's the request data that was sent to stripe when trying to create a subscription:

"items":[{"metadata":{"wc_item_id":3331},"quantity":1,"price_data":{"currency":"USD","product":"xxx","unit_amount_decimal":1595,"recurring":{"interval":"month","interval_count":5}}}],"trial_end":1667665923,"add_invoice_items":[{"price_data":{"currency":"USD","product":"xxx","unit_amount_decimal":1595}}],"backdate_start_date":1665243024,"billing_cycle_anchor":1667665923}

Notice the same trial_end and billing_cycle_anchor fields.

How does this happen?

I haven't replicated this issue yet, however, the area of code that is responsible for setting up the subscription data for creation is found in our prepare_wcpay_subscription_data() function.

When the subscription has a delayed payment and the is_creating_subscription_from_update_payment_method flag is set to true, we attempt to create a subscription with both the trial_end and billing_cycle_anchor fields set to the same value, which I believe it causing Stripe to throw this error.

How to fix?

Fixing this will require some further investigation into the problem. My initial take was the billing cycle anchor is there to set a "custom" first payment time for the subscription and when the subscription has a free trial, the trial end date is usually the same as the first payment date so maybe we need to unset the trial_end whenever we're using the billing_cycle_anchor.

Needs Investigation

That seems pretty straightforward, but the reason this needs more investigation is because I recall there being a limit to the billing_cycle_anchor period. I don't remember the exact details but there was some limit like not being able to set a billing_cycle_anchor that is more than one renewal cycle in the future.

The other thing we need to investigate is whether we need to set proration_behaviour to none when the billing_cycle_anchor is being absorbed by a free trial period. Since it's a free trial we don't want customers to pay for the billing_cycle_anchor period on their next renewal invoice.

To Reproduce

I haven't reproduced this yet but I think you will need to:

  1. Deactivate WooCommerce Subscriptions and make sure the free WCPay Subscriptions feature is enabled
  2. Manually create a Subscription via the Edit Subscription page that has a free trial, set the subscription to active
  3. Make sure the next payment date and trial end are the same
  4. Update/set the Payment Method of this new subscription to Woocommerce Payments

This will trigger the flow of creating a new WCPay Subscription where the delayed first payment is equal to the billing cycle anchor, which should throw an error from Stripe similar to the error shared above.

haszari commented 2 years ago

Next steps:

Marking this as low priority for now, based on the combination of trial period or synchronised subscriptions (?) and the update payment method flow (which is likely less commonly used than e.g. purchase subscription via checkout).