-
Notifications
You must be signed in to change notification settings - Fork 453
feat(js): support new checkout totals shape #8727
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feat/per-seat-costs
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| --- | ||
| '@clerk/clerk-js': patch | ||
| '@clerk/shared': patch | ||
| '@clerk/ui': patch | ||
| '@clerk/localizations': patch | ||
| '@clerk/msw': patch | ||
| --- | ||
|
|
||
| Update checkout totals to support the new `totals` shape from the API: | ||
|
|
||
| - Add `discounts` to `BillingCheckoutTotals` / `BillingCheckoutTotalsJSON`. It exposes a `proration` (a `BillingProrationDiscountDetail` with `amount`, `cycleDaysPassed`, `cycleDaysTotal`, `cyclePassedPercent`) describing the prorated discount applied when adding seats mid-billing-period — i.e. the part of the cycle that has already passed and is not charged — plus a `total` of all discounts. | ||
| - Add `totalsDuePerPeriod` / `totals_due_per_period` (`BillingPerPeriodTotals`) with `subtotal`, `baseFee`, `taxTotal`, `grandTotal`, and `perUnitTotals`: the full renewal charge breakdown covering all seats and the base plan fee, as opposed to the top-level totals which now only cover what is actively being purchased in the current checkout. | ||
| - Add `totalDuePerPeriod` / `total_due_per_period` (money amount) for backwards compatibility. | ||
| - Add `baseFee` / `base_fee` to the top-level totals. | ||
| - Parse all new fields in `billingTotalsFromJSON`. | ||
| - Render the prorated discount line item in `CheckoutForm` when present. | ||
| - Render a renewal subtotal and renewal total section in `CheckoutForm` when `totalsDuePerPeriod` is present. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| '@clerk/ui': patch | ||
| --- | ||
|
|
||
| Fix the `Subtotal` row in the payment attempt details view to read from `paymentAttempt.totals.subtotal` so it matches the value shown in the Clerk Dashboard. Previously it rendered `subscriptionItem.amount` which caused the displayed subtotal to disagree with the dashboard. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -876,24 +876,101 @@ export interface BillingCreditsJSON { | |
| total: BillingMoneyAmountJSON; | ||
| } | ||
|
|
||
| /** | ||
| * Details about a prorated discount applied when adding a seat mid-cycle. The discount covers the part of the | ||
| * billing period that has already passed, so the payer is only charged for the time remaining in the cycle. | ||
| */ | ||
| export interface BillingProrationDiscountDetailJSON { | ||
| amount: BillingMoneyAmountJSON; | ||
| cycle_days_passed: number; | ||
| cycle_days_total: number; | ||
| cycle_passed_percent: number; | ||
| } | ||
|
|
||
| /** | ||
| * Discounts applied to the checkout, such as prorated discounts for mid-cycle seat additions. | ||
| * | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to [pin](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes. | ||
| */ | ||
| export interface BillingCheckoutDiscountsJSON { | ||
| /** | ||
| * The prorated discount for the part of the billing period that has already passed when adding a seat mid-cycle. | ||
| * Unlike the proration credit (which refunds the unused remainder of a plan you already paid for), this discount | ||
| * means you are not charged for the portion of the new seat's cycle that has already elapsed. | ||
| */ | ||
| proration: BillingProrationDiscountDetailJSON | null; | ||
| /** | ||
| * The total of all discounts applied to the checkout. | ||
| */ | ||
| total: BillingMoneyAmountJSON; | ||
| } | ||
|
|
||
| /** | ||
| * Per-period renewal totals, describing what the subscription renewal charge will look like after the current checkout. | ||
| * Unlike the top-level checkout totals (which only reflect the items actively being purchased), | ||
| * this object contains the full renewal breakdown including all seats and the base plan fee. | ||
| * | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to [pin](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes. | ||
| */ | ||
| export interface BillingPerPeriodTotalsJSON { | ||
| subtotal: BillingMoneyAmountJSON; | ||
| base_fee: BillingMoneyAmountJSON; | ||
| tax_total: BillingMoneyAmountJSON; | ||
| grand_total: BillingMoneyAmountJSON; | ||
| /** | ||
| * Per-unit cost breakdown for the renewal period, covering all units purchased to date | ||
| * (not just the ones being added in this checkout). | ||
| */ | ||
| per_unit_totals?: BillingPerUnitTotalJSON[]; | ||
| } | ||
|
|
||
| /** | ||
| * @experimental This is an experimental API for the Billing feature that is available under a public beta, and the API is subject to change. It is advised to [pin](https://clerk.com/docs/pinning) the SDK version and the clerk-js version to avoid breaking changes. | ||
| */ | ||
| export interface BillingCheckoutTotalsJSON { | ||
| grand_total: BillingMoneyAmountJSON; | ||
| /** | ||
| * The price of items actively being purchased in this checkout, before taxes and discounts. | ||
| * When only adding seats mid-cycle, this reflects just the new seats and excludes the base plan fee and | ||
| * seats that were already paid for. | ||
| */ | ||
| subtotal: BillingMoneyAmountJSON; | ||
| /** | ||
| * The base plan fee portion of the totals, before per-unit charges and adjustments. | ||
| */ | ||
| base_fee: BillingMoneyAmountJSON; | ||
| tax_total: BillingMoneyAmountJSON; | ||
| /** | ||
| * Per-unit cost breakdown for this checkout (for example, seats). | ||
| * Per-unit cost breakdown for items actively being purchased in this checkout (for example, seats being added). | ||
| * When only adding seats mid-cycle, this only covers the seats being added, not seats already paid for. | ||
| * Omitted when the checkout is not seat-based. | ||
| */ | ||
| per_unit_totals?: BillingPerUnitTotalJSON[]; | ||
| total_due_now: BillingMoneyAmountJSON; | ||
| total_due_per_period: BillingMoneyAmountJSON; | ||
| /** | ||
| * Legacy credit field. Kept for backwards compatibility; prefer the unified `credits` breakdown. | ||
| */ | ||
| credit: BillingMoneyAmountJSON | null; | ||
| credits: BillingCreditsJSON | null; | ||
| account_credit: BillingMoneyAmountJSON | null; | ||
| past_due: BillingMoneyAmountJSON | null; | ||
| total_due_after_free_trial: BillingMoneyAmountJSON | null; | ||
| /** | ||
| * Discounts applied to this checkout such as mid-cycle prorated seat discounts. | ||
| * The key is always present; the value is `null` when no discounts apply. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure we need this disclaimer since we don't have something similar elsewhere |
||
| */ | ||
| discounts: BillingCheckoutDiscountsJSON | null; | ||
| /** | ||
| * The expected recurring payment for each future billing period. | ||
| * Kept for backwards compatibility. Prefer `totals_due_per_period` for the full breakdown. | ||
| */ | ||
| total_due_per_period: BillingMoneyAmountJSON; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why are we adding a deprecated field? maybe we just expose |
||
| /** | ||
| * Full renewal period totals after this checkout completes. | ||
| * Contains the complete breakdown of what the next recurring charge will look like, | ||
| * including all seats and the base plan fee. | ||
| */ | ||
| totals_due_per_period: BillingPerPeriodTotalsJSON; | ||
| } | ||
|
|
||
| /** | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is an internal-only package, so we don't need to bump it