(core) Changes to Billing to better handle error scenarios.

Summary:
- Bad status of a subscription is now reported, along with the last payment error, if any.
- Error caused when getting valueRemaining of a subscription in a bad state is now ignored.
- Certain kinds of errors from Stripe are now reported to the user in a
  friendlier way (avoiding statusCode of 500 when there is a better one)
- A wide range of Stripe errors are logged with metadata.
- Show a link to the Stripe-hosted last invoice, which seems useful generally,
  and also gives the user more options to pay after a payment failure.
- Get default_source along with customer to save a roundtrip to Stripe.
- Use a simpler (single) Stripe call for updating a customer’s card.
- Retry paying an invoice when updating a card when there is an unpaid invoice
  with a payment error.

Some refactoring included:
- Simplified ISubscriptionModel by extending IBillingSubscription.
- Factor out common portions from several Billing tests.

Add a test case for how some card errors are reported
Add bits to the new billing test, still WIP.

Test Plan:
Added a test suite for incomplete and past_due subscriptions, and a
test case one for better error reporting.

Reviewers: paulfitz

Reviewed By: paulfitz

Differential Revision: https://phab.getgrist.com/D2553
This commit is contained in:
Dmitry S 2020-07-22 12:52:11 -04:00
parent 5ef889addd
commit a19f19b503

View File

@ -88,6 +88,13 @@ export interface IBillingSubscription {
lastPlanId: string|null; lastPlanId: string|null;
// Whether there is a valid plan in effect // Whether there is a valid plan in effect
isValidPlan: boolean; isValidPlan: boolean;
// Stripe status, documented at https://stripe.com/docs/api/subscriptions/object#subscription_object-status
// such as "active", "trialing" (reflected in isInTrial), "incomplete", etc.
status?: string;
lastInvoiceUrl?: string; // URL of the Stripe-hosted page with the last invoice.
lastChargeError?: string; // The last charge error, if any, to show in case of a bad status.
lastChargeTime?: number; // The time of the last charge attempt.
} }
export interface IBillingOrgSettings { export interface IBillingOrgSettings {