@happyvertical/smrt-commerce 0.51.29 → 0.51.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -31,7 +31,13 @@ for usage.
31
31
  - **Port, not provider.** Period close, events, and credit checkout call only
32
32
  the `BillingProvider` port (integer minor units). `stripe.ts` adapts
33
33
  `@happyvertical/accounting`, which takes currency *major* units; convert with
34
- `units.ts` (ISO 4217 exponent) and never hand-roll a Stripe call here.
34
+ `units.ts` and never hand-roll a Stripe call here. `units.ts` exponents are
35
+ an explicit ISO 4217 table matching the SDK's, never `Intl` display digits
36
+ (CLDR differs for IQD, MGA, … and drifts by ICU release). The SDK's
37
+ `*Minor` fields are already ISO minor units. Capabilities a rail may lack
38
+ (`chargeSavedPaymentMethod`, `createSetupCheckout`, `getCheckout`,
39
+ `setDefaultPaymentMethod`, `markInvoiceUncollectible`) are optional port
40
+ methods: detect them by presence, and keep additions optional (#3139).
35
41
  `sendAndReconcile` refuses a provider invoice whose subtotal or total
36
42
  disagrees with the local invoice.
37
43
  - **Replay safety is identity.** Close, invoice, line, payment, allocation,
@@ -70,20 +76,35 @@ for usage.
70
76
  and only `smrt_*` checkout metadata is kept; it is
71
77
  HMAC-signed with the webhook secret at creation (empty values are omitted:
72
78
  Stripe drops them), so another integration on the same account cannot forge
73
- a credit purchase; credit is granted only when the collected total equals
74
- it. Rotating the webhook secret strands in-flight checkouts (up to 24 h). `observe()` re-reads provider state, so
75
- ordering never depends on delivery order. The standing hook runs inside the
76
- event transaction and must be idempotent.
79
+ a credit purchase or a card setup; credit is granted only when the
80
+ collected total equals it plus provider tax. Checkout amounts come from the
81
+ re-read session (`getCheckout()`), never the Stripe event, whose amounts are
82
+ in Stripe's unit. Rotating the webhook secret strands in-flight checkouts
83
+ (up to 24 h). `observe()` re-reads provider state, so ordering never depends
84
+ on delivery order; the only provider writes in `observe()` are idempotent
85
+ (making a saved card the default). The standing hook runs inside the event
86
+ transaction and must be idempotent.
87
+ - **Card on file and top-ups (#3139).** A saved card is the payer customer's
88
+ default `PaymentInstrument` (seller tenant, id from the provider method).
89
+ `autoChargeInvoices` bills such payers `charge_automatically`, decided at
90
+ first push; activation follows `paid`, never send. An auto top-up attempt
91
+ is a `PENDING` `Payment` (`reference` `auto-top-up:<policyId>`, id from the
92
+ policy and `count()` of its attempts) inserted before the charge, so racing
93
+ evaluations derive one id and one charge; the charge key is derived from
94
+ that id. `applyAutoTopUpOutcome()` must run in a transaction and starts with
95
+ a conditional `UPDATE … WHERE status = 'pending'` row lock, so the hook and
96
+ the `payment` webhook settle once; the grant is keyed by the charge key.
97
+ Never settle an attempt outside that function. Taxed accounts are skipped
98
+ unless `taxedAccounts: 'charge_untaxed'` (no tax on off-session charges,
99
+ happyvertical/sdk#1283). A provider write-off moves the local invoice to
100
+ `WRITTEN_OFF` (a later payment is recorded; the status stays).
77
101
  - **`Invoice.providerTaxAmount`** is added to line-item tax; it is
78
102
  server-managed (not API-writable). `toAccountingInput()` emits major units.
79
- - **Known limits** (each tracked upstream): provider customer creation is not
80
- idempotent (happyvertical/sdk#1268); credit checkouts are untaxed and
81
- two-decimal only (sdk#1269); `autoTopUp` cannot charge a saved card
82
- (sdk#1270); Stripe line discounts and uncollectible status are worked around
83
- as negative lines and event types (sdk#1271). `RetailCharge` has no
84
- adjustment ledger. Flat plans are monthly, in arrears; plan changes are not
85
- prorated (#3119). The Stripe adapter passes line service periods but
86
- the accounting SDK does not send them to Stripe yet (happyvertical/sdk#1274).
103
+ - **Known limits**: write-offs post no bad-debt journal (AR stays until paid
104
+ or journaled by an operator); discounts still reach Stripe as negative lines (the SDK's
105
+ line `discount` would change the lines a replayed push reconciles, so it
106
+ needs its own migration); `RetailCharge` has no adjustment ledger. Flat
107
+ plans are monthly, in arrears; plan changes are not prorated (#3119).
87
108
 
88
109
  ## Cross-Package References
89
110
 
package/README.md CHANGED
@@ -153,6 +153,7 @@ minor units.
153
153
 
154
154
  ```ts
155
155
  import { getAccountingProvider } from '@happyvertical/accounting';
156
+ import { SpendingPolicyEvaluator } from '@happyvertical/smrt-subscriptions';
156
157
  import {
157
158
  BillingRuntime,
158
159
  createStripeBillingProvider,
@@ -210,14 +211,36 @@ if (intake.type?.endsWith(':unverified_credit_purchase')) {
210
211
  }
211
212
  await billing.processEvents(); // or enqueueBillingEvents({ runtime: 'platform' })
212
213
 
213
- // Prepaid credit through provider checkout.
214
+ // Prepaid credit through provider checkout: tax is added on top when the
215
+ // payer's account is taxed; `savePaymentMethod` keeps the card for top-ups.
214
216
  const { url } = await billing.createCreditCheckout({
215
217
  spendingPolicyId,
216
218
  amount: 5000,
217
219
  purchaseId: cartId,
220
+ savePaymentMethod: true,
218
221
  successUrl,
219
222
  cancelUrl,
220
223
  });
224
+
225
+ // Card on file at signup: a setup checkout that charges nothing. Its
226
+ // completion event makes the card the payer's default and adopts the billing
227
+ // address collected at checkout as the tax location.
228
+ const setup = await billing.createCardSetupCheckout({
229
+ payerTenantId,
230
+ currency: 'CAD',
231
+ setupId: signupId,
232
+ successUrl,
233
+ cancelUrl,
234
+ });
235
+
236
+ // Automatic top-ups: charge the saved card when a balance would run out.
237
+ // Accounts are taxed by default (`automaticTax`), and a taxed account is not
238
+ // topped up (no tax on off-session charges, sdk#1283): set
239
+ // `automaticTax: false` on the account or pass `taxedAccounts: 'charge_untaxed'`.
240
+ const evaluator = await SpendingPolicyEvaluator.create({
241
+ db,
242
+ autoTopUp: billing.autoTopUpHook({ amount: () => 2500 }),
243
+ });
221
244
  ```
222
245
 
223
246
  - **What is billed.** A `provider` runtime bills `ClientCharge`s (and their
@@ -284,9 +307,8 @@ const { url } = await billing.createCreditCheckout({
284
307
  with its own service period. Stop workers running a pre-#3116 version
285
308
  before relying on this: they claim flat plans outside the numbering.
286
309
  - **Service periods.** Each flat-plan invoice line carries its billed window
287
- as `periodStart`/`periodEnd`, down to the provider port. The Stripe adapter
288
- passes them on; `@happyvertical/accounting` does not send them to Stripe yet
289
- (happyvertical/sdk#1274).
310
+ as `periodStart`/`periodEnd`, down to the provider port and on to Stripe's
311
+ invoice item `period`.
290
312
  - **Upgrading to #3116.** Additive schema only: `_smrt_billing_accounts` gains
291
313
  `billing_anchor_at` (nullable) and `prorate_flat_plans` (default false), and
292
314
  `_smrt_billing_line_sources` gains `chain_sequence` (default 0) and an index
@@ -299,11 +321,57 @@ const { url } = await billing.createCreditCheckout({
299
321
  - **Events** are verified, stored in smrt-jobs' durable delivery inbox, and
300
322
  applied against current provider state: paid invoices record a payment and
301
323
  allocation; failures and overdue notices mark the payer `past_due` and its
302
- flat-plan subscriptions `past_due`; payment reinstates them. Dunning is the
303
- provider's.
324
+ flat-plan subscriptions `past_due`; an invoice written off at the provider
325
+ (`markInvoiceUncollectible(invoiceId)`, or in Stripe) is written off
326
+ locally and marks the payer `uncollectible` (no bad-debt journal is
327
+ posted; AR stays until it is paid or an operator journals it); payment
328
+ reinstates them, including a late payment of the written-off invoice. Dunning is the provider's.
329
+ Subscribe the webhook endpoint to `invoice.*`, `customer.subscription.*`,
330
+ `checkout.session.completed`, `checkout.session.async_payment_succeeded`,
331
+ and `payment_intent.*`.
304
332
  - **Prepaid credit** purchases credit a `period: 'balance'` spending policy
305
333
  once per checkout session, paid by the policy's tenant or, for a delegated
306
- balance, the parent that set it.
334
+ balance, the parent that set it. Amounts are ISO 4217 minor units in any
335
+ currency the provider supports. When the payer's account is taxed
336
+ (`automaticTax`, not tax-exempt; override per call), provider tax is
337
+ charged on top and collected at checkout with the buyer's address: the
338
+ credit is the amount bought, the payment is the total collected, and the
339
+ tax is booked to the tax account. For a payer with a provider customer but
340
+ no local tax location, the address collected at checkout becomes its tax
341
+ location. `savePaymentMethod` requires a provider that can re-read the
342
+ checkout and set a default payment method, and is refused otherwise.
343
+ - **Card on file (#3139).** `createCardSetupCheckout()` (or a credit purchase
344
+ with `savePaymentMethod`) saves the payer's card without charging it. On
345
+ completion the card becomes the provider customer's default and the
346
+ payer's default `PaymentInstrument`. When the checkout collected the billing
347
+ address (a taxed payer with no tax location), it becomes the payer's tax
348
+ location.
349
+ - **Automatically charged invoices.** With `autoChargeInvoices: true` on the
350
+ runtime, a payer with a default card is invoiced `charge_automatically`:
351
+ the provider charges the card after the invoice is sent, on its own
352
+ schedule, and retries failures. Activate service on the `current` standing
353
+ from the `paid` event, not on send; a failure marks the payer `past_due`.
354
+ - **Automatic top-ups.** Taxed accounts (the default: `automaticTax` on, not
355
+ tax-exempt) are never topped up unless the hook is built with
356
+ `taxedAccounts: 'charge_untaxed'`, because an off-session charge carries no
357
+ tax yet (happyvertical/sdk#1283); the skip is silent (no attempt row).
358
+ `billing.autoTopUpHook()` is the `autoTopUp` hook for
359
+ `SpendingPolicyEvaluator`: when a balance would run out it charges the
360
+ payer's saved card off-session (the delegating parent's, for a delegated
361
+ balance) and credits the balance only when the charge succeeds. A charge
362
+ still processing is credited from its `payment_intent.succeeded` event; a
363
+ decline or an authentication requirement credits nothing, closes the
364
+ attempt, and calls the runtime's `onAutoTopUpFailed` (ask the payer to
365
+ re-save their card with a setup checkout). One attempt runs per policy at a
366
+ time, retries of a declined card wait `retryAfterMs` (default one hour),
367
+ and the credit is granted exactly once however the outcome arrives. An
368
+ off-session charge carries no tax (happyvertical/sdk#1283), so taxed
369
+ accounts are not topped up unless the seller passes
370
+ `taxedAccounts: 'charge_untaxed'`; they buy credit through checkout.
371
+ - **Upgrading to #3139.** Requires `@happyvertical/accounting` 0.92 or later.
372
+ No schema change. Credit checkouts are now taxed for taxed accounts (pass
373
+ `automaticTax: false` to keep them untaxed), and Stripe customers are
374
+ created idempotently.
307
375
 
308
376
  See [`AGENTS.md`](./AGENTS.md#billing-period-close-3060) for invariants and
309
377
  known limits.
@@ -0,0 +1,64 @@
1
+ import { DatabaseInterface } from '@happyvertical/smrt-core/migrations';
2
+ import { BillingAccount } from '../models/billing.js';
3
+ import { BillingProviderCheckoutSession, BillingProviderCheckoutState } from './provider.js';
4
+ import { BillingRuntime } from './runtime.js';
5
+ export declare const CARD_SETUP_PURPOSE = "card_setup";
6
+ /** Checkout metadata flag: the session saves its payment method. */
7
+ export declare const SAVE_CARD_METADATA = "smrt_save_card";
8
+ /**
9
+ * Checkout metadata flag: the session collects the billing address, which is
10
+ * adopted as the payer's tax location when the card is saved.
11
+ */
12
+ export declare const COLLECT_ADDRESS_METADATA = "smrt_collect_address";
13
+ export interface CreateCardSetupCheckoutInput {
14
+ payerTenantId: string;
15
+ /** The currency the saved card will be charged in. */
16
+ currency: string;
17
+ successUrl: string;
18
+ cancelUrl: string;
19
+ /**
20
+ * Caller-owned id for this setup attempt. A retried request with the same
21
+ * id returns the same checkout; a new attempt (for example after a declined
22
+ * card) needs a new id.
23
+ */
24
+ setupId: string;
25
+ /**
26
+ * Collect the billing address at checkout and adopt it as the payer's tax
27
+ * location. Default: when the account is taxed and has no tax location.
28
+ */
29
+ collectBillingAddress?: boolean;
30
+ }
31
+ /** Only the payer (or a system/operator context) manages its card. */
32
+ export declare function assertPayerContext(payerTenantId: string): void;
33
+ export declare function createCardSetupCheckout(runtime: BillingRuntime, input: CreateCardSetupCheckoutInput): Promise<BillingProviderCheckoutSession>;
34
+ /**
35
+ * What a completed checkout saved for one of this seller's accounts: a card
36
+ * (setup, or a purchase with `savePaymentMethod`) and/or a billing address it
37
+ * was asked to collect. Validated against the account.
38
+ */
39
+ export interface SavedCard {
40
+ account: BillingAccount;
41
+ providerCustomerId: string;
42
+ paymentMethodId?: string;
43
+ billingAddress?: BillingProviderCheckoutState['billingAddress'];
44
+ }
45
+ /** Whether the provider can apply a saved card from a checkout event. */
46
+ export declare function assertCanSaveCards(runtime: BillingRuntime): void;
47
+ /**
48
+ * The card and/or collected address a completed checkout saved for one of
49
+ * this seller's accounts, or null when it saved neither. Throws when the
50
+ * session and its (verified) metadata disagree, so the event dead-letters
51
+ * visibly.
52
+ */
53
+ export declare function savedCardFromCheckout(runtime: BillingRuntime, metadata: Record<string, string>, state: BillingProviderCheckoutState, savesCard: boolean): Promise<SavedCard | null>;
54
+ /**
55
+ * Record a saved card as the customer's default instrument, and adopt a
56
+ * collected billing address. Idempotent; runs in the event transaction.
57
+ */
58
+ export declare function recordSavedCard(runtime: BillingRuntime, db: DatabaseInterface, card: SavedCard): Promise<void>;
59
+ /**
60
+ * Whether the payer's default card is with this runtime's provider customer:
61
+ * what `autoChargeInvoices` bills and automatic top-ups charge.
62
+ */
63
+ export declare function defaultCardFor(runtime: BillingRuntime, account: BillingAccount, providerCustomerId: string): Promise<boolean>;
64
+ //# sourceMappingURL=cards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cards.d.ts","sourceRoot":"","sources":["../../src/billing/cards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAU7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EACV,8BAA8B,EAC9B,4BAA4B,EAC7B,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQnD,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAC/C,oEAAoE;AACpE,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD;;;GAGG;AACH,eAAO,MAAM,wBAAwB,yBAAyB,CAAC;AAE/D,MAAM,WAAW,4BAA4B;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,sEAAsE;AACtE,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAU9D;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,4BAA4B,GAClC,OAAO,CAAC,8BAA8B,CAAC,CA0CzC;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,cAAc,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,4BAA4B,CAAC,gBAAgB,CAAC,CAAC;CACjE;AAED,yEAAyE;AACzE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAShE;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,KAAK,EAAE,4BAA4B,EACnC,SAAS,EAAE,OAAO,GACjB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CA8B3B;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,cAAc,EACvB,EAAE,EAAE,iBAAiB,EACrB,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,IAAI,CAAC,CAYf;AA0CD;;;GAGG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,cAAc,EACvB,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,OAAO,CAAC,CAUlB"}
@@ -15,6 +15,18 @@ export interface CreateCreditCheckoutInput {
15
15
  purchaseId: string;
16
16
  /** Checkout line description (default `Prepaid credit`). */
17
17
  description?: string;
18
+ /**
19
+ * Charge provider-calculated tax on top of the credit (#3139). Default:
20
+ * the payer's account setting (`automaticTax`, off for tax-exempt
21
+ * customers). The credit granted is always `amount`; tax is booked to the
22
+ * tax account.
23
+ */
24
+ automaticTax?: boolean;
25
+ /**
26
+ * Also save the card as the payer's default for automatic top-ups and
27
+ * automatically charged invoices (#3139).
28
+ */
29
+ savePaymentMethod?: boolean;
18
30
  }
19
31
  /** The checkout metadata a completed purchase is settled from. */
20
32
  export interface CreditPurchaseMetadata {
@@ -1 +1 @@
1
- {"version":3,"file":"credits.d.ts","sourceRoot":"","sources":["../../src/billing/credits.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQnD,eAAO,MAAM,uBAAuB,oBAAoB,CAAC;AAEzD,MAAM,WAAW,yBAAyB;IACxC,yDAAyD;IACzD,gBAAgB,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,kEAAkE;AAClE,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAuBD,uEAAuE;AACvE,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1B,sBAAsB,GAAG,IAAI,CAwB/B;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,8BAA8B,CAAC,CAgEzC"}
1
+ {"version":3,"file":"credits.d.ts","sourceRoot":"","sources":["../../src/billing/credits.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQnD,eAAO,MAAM,uBAAuB,oBAAoB,CAAC;AAEzD,MAAM,WAAW,yBAAyB;IACxC,yDAAyD;IACzD,gBAAgB,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,kEAAkE;AAClE,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAuBD,uEAAuE;AACvE,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1B,sBAAsB,GAAG,IAAI,CAwB/B;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,8BAA8B,CAAC,CA4FzC"}
@@ -1,5 +1,6 @@
1
1
  import { ForgeProjector } from '@happyvertical/smrt-jobs';
2
- import { BillingProviderEvent, BillingProviderInvoiceState, BillingProviderSubscriptionState } from './provider.js';
2
+ import { SavedCard } from './cards.js';
3
+ import { BillingProviderCheckoutState, BillingProviderEvent, BillingProviderInvoiceState, BillingProviderSubscriptionState } from './provider.js';
3
4
  import { BillingRuntime } from './runtime.js';
4
5
  type InvoiceEvent = Extract<BillingProviderEvent, {
5
6
  kind: 'invoice';
@@ -10,6 +11,9 @@ type SubscriptionEvent = Extract<BillingProviderEvent, {
10
11
  type CheckoutEvent = Extract<BillingProviderEvent, {
11
12
  kind: 'checkout_completed';
12
13
  }>;
14
+ type PaymentEvent = Extract<BillingProviderEvent, {
15
+ kind: 'payment';
16
+ }>;
13
17
  type ObservedEvent = {
14
18
  event: InvoiceEvent;
15
19
  invoice: BillingProviderInvoiceState;
@@ -18,6 +22,13 @@ type ObservedEvent = {
18
22
  subscription: BillingProviderSubscriptionState;
19
23
  } | {
20
24
  event: CheckoutEvent;
25
+ /** The session re-read from the provider, when it can be. */
26
+ checkout: BillingProviderCheckoutState | null;
27
+ /** A card the session saved, already the provider default. */
28
+ card: SavedCard | null;
29
+ } | {
30
+ event: PaymentEvent;
31
+ paymentId: string;
21
32
  };
22
33
  /** Apply up to `limit` queued events for a runtime; returns how many ran. */
23
34
  export declare function processBillingEvents(runtime: BillingRuntime, limit: number): Promise<number>;
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/billing/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,0BAA0B,CAAC;AAoBlC,OAAO,KAAK,EACV,oBAAoB,EACpB,2BAA2B,EAC3B,gCAAgC,EACjC,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQnD,KAAK,YAAY,GAAG,OAAO,CAAC,oBAAoB,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,CAAC;AACvE,KAAK,iBAAiB,GAAG,OAAO,CAC9B,oBAAoB,EACpB;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,CACzB,CAAC;AACF,KAAK,aAAa,GAAG,OAAO,CAC1B,oBAAoB,EACpB;IAAE,IAAI,EAAE,oBAAoB,CAAA;CAAE,CAC/B,CAAC;AAEF,KAAK,aAAa,GACd;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,2BAA2B,CAAA;CAAE,GAC7D;IACE,KAAK,EAAE,iBAAiB,CAAC;IACzB,YAAY,EAAE,gCAAgC,CAAC;CAChD,GACD;IAAE,KAAK,EAAE,aAAa,CAAA;CAAE,CAAC;AAI7B,6EAA6E;AAC7E,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,cAAc,GACtB,cAAc,CAAC,aAAa,CAAC,CA+D/B"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/billing/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,0BAA0B,CAAC;AAoBlC,OAAO,EAKL,KAAK,SAAS,EAEf,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EACV,4BAA4B,EAC5B,oBAAoB,EACpB,2BAA2B,EAC3B,gCAAgC,EACjC,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAInD,KAAK,YAAY,GAAG,OAAO,CAAC,oBAAoB,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,CAAC;AACvE,KAAK,iBAAiB,GAAG,OAAO,CAC9B,oBAAoB,EACpB;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,CACzB,CAAC;AACF,KAAK,aAAa,GAAG,OAAO,CAC1B,oBAAoB,EACpB;IAAE,IAAI,EAAE,oBAAoB,CAAA;CAAE,CAC/B,CAAC;AACF,KAAK,YAAY,GAAG,OAAO,CAAC,oBAAoB,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,CAAC;AAEvE,KAAK,aAAa,GACd;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,2BAA2B,CAAA;CAAE,GAC7D;IACE,KAAK,EAAE,iBAAiB,CAAC;IACzB,YAAY,EAAE,gCAAgC,CAAC;CAChD,GACD;IACE,KAAK,EAAE,aAAa,CAAC;IACrB,6DAA6D;IAC7D,QAAQ,EAAE,4BAA4B,GAAG,IAAI,CAAC;IAC9C,8DAA8D;IAC9D,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;CACxB,GACD;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAI/C,6EAA6E;AAC7E,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,cAAc,GACtB,cAAc,CAAC,aAAa,CAAC,CAiF/B"}
@@ -1,14 +1,16 @@
1
1
  /**
2
- * Billing-period close, provider events, and prepaid credit purchases
3
- * (#3060).
2
+ * Billing-period close, provider events, prepaid credit purchases (#3060),
3
+ * card on file, and automatic top-ups (#3139).
4
4
  * @packageDocumentation
5
5
  */
6
+ export type { CreateCardSetupCheckoutInput } from './cards.js';
6
7
  export type { CreateCreditCheckoutInput } from './credits.js';
7
8
  export { addBillingMonths, billingPeriodContaining, lastEndedBillingPeriod, prorateMinorUnits, type ScheduledBillingPeriod, } from './cycles.js';
8
9
  export { type EnqueueBillingJobOptions, enqueueBillingEvents, enqueueBillingPeriodClose, getBillingRuntime, registerBillingRuntime, unregisterBillingRuntime, } from './jobs.js';
9
10
  export { type BillingPeriod, BillingPeriodCloseError, type ClosePeriodInput, type PeriodCloseGroupResult, type PeriodCloseOutcome, type PeriodCloseResult, previousCalendarMonth, } from './period-close.js';
10
- export { type BillingInvoiceEventType, type BillingProvider, type BillingProviderCheckoutInput, type BillingProviderCheckoutSession, type BillingProviderCustomerInput, type BillingProviderEvent, type BillingProviderInvoiceInput, type BillingProviderInvoiceLine, type BillingProviderInvoiceState, type BillingProviderInvoiceStatus, type BillingProviderSubscriptionState, BillingWebhookVerificationError, } from './provider.js';
11
- export { type BillingLedgerAccounts, BillingRuntime, type BillingRuntimeOptions, type PayerStandingChange, type PayerStandingHook, type SyncedBillingAccount, type UpsertBillingAccountInput, } from './runtime.js';
11
+ export { type BillingChargeStatus, type BillingCollectionMethod, type BillingInvoiceEventType, type BillingProvider, type BillingProviderChargeInput, type BillingProviderChargeResult, type BillingProviderCheckoutInput, type BillingProviderCheckoutSession, type BillingProviderCheckoutState, type BillingProviderCustomerInput, type BillingProviderEvent, type BillingProviderInvoiceInput, type BillingProviderInvoiceLine, type BillingProviderInvoiceState, type BillingProviderInvoiceStatus, type BillingProviderSetupCheckoutInput, type BillingProviderSubscriptionState, BillingWebhookVerificationError, } from './provider.js';
12
+ export { type BillingLedgerAccounts, BillingRuntime, type BillingRuntimeOptions, type EnsureProviderCustomerOptions, type PayerStandingChange, type PayerStandingHook, type SyncedBillingAccount, type UpsertBillingAccountInput, } from './runtime.js';
12
13
  export { createStripeBillingProvider, type StripeBillingProviderOptions, } from './stripe.js';
14
+ export type { AutoTopUpFailure, AutoTopUpFailureHook, AutoTopUpHookOptions, } from './top-up.js';
13
15
  export { currencyMinorUnitExponent, majorToMinorUnits, minorToMajorUnits, } from './units.js';
14
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/billing/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,YAAY,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,EACtB,iBAAiB,EACjB,KAAK,sBAAsB,GAC5B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,wBAAwB,EAC7B,oBAAoB,EACpB,yBAAyB,EACzB,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,KAAK,aAAa,EAClB,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,eAAe,EACpB,KAAK,4BAA4B,EACjC,KAAK,8BAA8B,EACnC,KAAK,4BAA4B,EACjC,KAAK,oBAAoB,EACzB,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EAChC,KAAK,4BAA4B,EACjC,KAAK,gCAAgC,EACrC,+BAA+B,GAChC,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,KAAK,qBAAqB,EAC1B,cAAc,EACd,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,GAC/B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,2BAA2B,EAC3B,KAAK,4BAA4B,GAClC,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/billing/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,YAAY,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC;AAC/D,YAAY,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,EACtB,iBAAiB,EACjB,KAAK,sBAAsB,GAC5B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,wBAAwB,EAC7B,oBAAoB,EACpB,yBAAyB,EACzB,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,KAAK,aAAa,EAClB,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,eAAe,EACpB,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EAChC,KAAK,4BAA4B,EACjC,KAAK,8BAA8B,EACnC,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,EACjC,KAAK,oBAAoB,EACzB,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EAChC,KAAK,4BAA4B,EACjC,KAAK,iCAAiC,EACtC,KAAK,gCAAgC,EACrC,+BAA+B,GAChC,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,KAAK,qBAAqB,EAC1B,cAAc,EACd,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,EAClC,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,GAC/B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,2BAA2B,EAC3B,KAAK,4BAA4B,GAClC,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,yBAAyB,EACzB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"period-close.d.ts","sourceRoot":"","sources":["../../src/billing/period-close.ts"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQnD,MAAM,WAAW,aAAa;IAC5B,uBAAuB;IACvB,WAAW,EAAE,IAAI,CAAC;IAClB,8DAA8D;IAC9D,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,iDAAiD;IACjD,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,OAAO,GACP,MAAM,GACN,iBAAiB,GACjB,QAAQ,CAAC;AAEb,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,WAAW,EAAE,IAAI,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,sBAAsB,EAAE,CAAC;CAClC;AAED,yEAAyE;AACzE,qBAAa,uBAAwB,SAAQ,KAAK;IACpC,QAAQ,CAAC,MAAM,EAAE,iBAAiB;gBAAzB,MAAM,EAAE,iBAAiB;CAW/C;AAmDD,4DAA4D;AAC5D,wBAAgB,qBAAqB,CAAC,GAAG,OAAa,GAAG,aAAa,CAQrE;AAkCD,wBAAgB,aAAa,CAC3B,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,gBAAgB,GAAG,MAAM,CAAC,EACxD,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,CAAC,CAUjB;AAsED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,cAAc,EACvB,KAAK,GAAE,gBAAqB,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CAwE5B"}
1
+ {"version":3,"file":"period-close.d.ts","sourceRoot":"","sources":["../../src/billing/period-close.ts"],"names":[],"mappings":"AA6CA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQnD,MAAM,WAAW,aAAa;IAC5B,uBAAuB;IACvB,WAAW,EAAE,IAAI,CAAC;IAClB,8DAA8D;IAC9D,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,iDAAiD;IACjD,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,OAAO,GACP,MAAM,GACN,iBAAiB,GACjB,QAAQ,CAAC;AAEb,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,WAAW,EAAE,IAAI,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,sBAAsB,EAAE,CAAC;CAClC;AAED,yEAAyE;AACzE,qBAAa,uBAAwB,SAAQ,KAAK;IACpC,QAAQ,CAAC,MAAM,EAAE,iBAAiB;gBAAzB,MAAM,EAAE,iBAAiB;CAW/C;AAmDD,4DAA4D;AAC5D,wBAAgB,qBAAqB,CAAC,GAAG,OAAa,GAAG,aAAa,CAQrE;AAkCD,wBAAgB,aAAa,CAC3B,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,gBAAgB,GAAG,MAAM,CAAC,EACxD,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,CAAC,CAUjB;AAsED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,cAAc,EACvB,KAAK,GAAE,gBAAqB,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CAwE5B"}
@@ -18,6 +18,14 @@ export interface BillingProviderInvoiceLine {
18
18
  periodStart?: Date;
19
19
  periodEnd?: Date;
20
20
  }
21
+ /**
22
+ * How the provider collects an invoice. `charge_automatically` charges the
23
+ * payer's saved default payment method after the invoice is sent, on the
24
+ * provider's own schedule; the outcome arrives as a `paid` or
25
+ * `payment_failed` event. A provider that cannot pull funds from a saved
26
+ * method must reject it, never fall back to `send_invoice`.
27
+ */
28
+ export type BillingCollectionMethod = 'send_invoice' | 'charge_automatically';
21
29
  export interface BillingProviderInvoiceInput {
22
30
  /** Local invoice id; the provider tags its invoice with it. */
23
31
  invoiceId: string;
@@ -33,9 +41,15 @@ export interface BillingProviderInvoiceInput {
33
41
  idempotencyKey: string;
34
42
  /** Ask the provider to calculate tax from the customer's tax location. */
35
43
  automaticTax: boolean;
44
+ /** Default `send_invoice` (#3139). */
45
+ collectionMethod?: BillingCollectionMethod;
36
46
  memo?: string;
37
47
  }
38
- export type BillingProviderInvoiceStatus = 'draft' | 'open' | 'paid' | 'void';
48
+ /**
49
+ * `uncollectible` is an open balance the seller wrote off (#3139); it can
50
+ * still be paid or voided later.
51
+ */
52
+ export type BillingProviderInvoiceStatus = 'draft' | 'open' | 'paid' | 'void' | 'uncollectible';
39
53
  export interface BillingProviderInvoiceState {
40
54
  providerInvoiceId: string;
41
55
  status: BillingProviderInvoiceStatus;
@@ -70,11 +84,88 @@ export interface BillingProviderCheckoutInput {
70
84
  cancelUrl: string;
71
85
  /** Opaque values returned verbatim on the completion event. */
72
86
  metadata: Record<string, string>;
87
+ /**
88
+ * Charge provider-calculated tax on top of `amount` (#3139). The buyer's
89
+ * tax location is collected at checkout when the customer has none.
90
+ */
91
+ automaticTax?: boolean;
92
+ /**
93
+ * Also save the payment method for later off-session charges (for example
94
+ * automatic top-ups). Requires `providerCustomerId`.
95
+ */
96
+ savePaymentMethod?: boolean;
73
97
  }
74
98
  export interface BillingProviderCheckoutSession {
75
99
  sessionId: string;
76
100
  url: string | null;
77
101
  }
102
+ /** A checkout that saves a payment method without charging (#3139). */
103
+ export interface BillingProviderSetupCheckoutInput {
104
+ /** Stable key reused when retrying the same checkout creation. */
105
+ idempotencyKey: string;
106
+ providerCustomerId: string;
107
+ /** The currency the saved method will be charged in. */
108
+ currency: string;
109
+ successUrl: string;
110
+ cancelUrl: string;
111
+ /** Collect the billing address (tax location) and save it to the customer. */
112
+ collectBillingAddress: boolean;
113
+ /** Opaque values returned verbatim on the completion event. */
114
+ metadata: Record<string, string>;
115
+ }
116
+ /** A checkout session as the provider reports it now (#3139). */
117
+ export interface BillingProviderCheckoutState {
118
+ sessionId: string;
119
+ mode: 'payment' | 'setup' | 'other';
120
+ /** The session completed (paid, or a payment method was saved). */
121
+ complete: boolean;
122
+ /** A payment-mode session collected its money. */
123
+ paid: boolean;
124
+ providerCustomerId?: string;
125
+ /** The payment method the session collected. */
126
+ paymentMethodId?: string;
127
+ currency?: string;
128
+ /** Line amount before discounts and tax, minor units. */
129
+ amountSubtotal?: number;
130
+ /** Provider-calculated tax, minor units. */
131
+ amountTax?: number;
132
+ /** Amount collected, minor units. */
133
+ amountTotal?: number;
134
+ /**
135
+ * The customer's billing address after a completed session that was asked
136
+ * to collect one.
137
+ */
138
+ billingAddress?: Address;
139
+ }
140
+ /**
141
+ * The outcome of an off-session charge (#3139). `processing` settles later
142
+ * through a `payment` event; `requires_action` (the issuer wants the payer
143
+ * present), `failed`, and `canceled` charged nothing.
144
+ */
145
+ export type BillingChargeStatus = 'succeeded' | 'processing' | 'requires_action' | 'failed' | 'canceled';
146
+ export interface BillingProviderChargeInput {
147
+ providerCustomerId: string;
148
+ /** Positive integer minor units. */
149
+ amount: number;
150
+ currency: string;
151
+ /**
152
+ * Stable key for this logical charge. Every retry with it returns the
153
+ * original charge; a new attempt needs a new key.
154
+ */
155
+ idempotencyKey: string;
156
+ description?: string;
157
+ metadata?: Record<string, string>;
158
+ }
159
+ export interface BillingProviderChargeResult {
160
+ status: BillingChargeStatus;
161
+ /** The provider payment id, when one was created. */
162
+ providerPaymentId?: string;
163
+ /** Minor units. */
164
+ amount: number;
165
+ currency: string;
166
+ failureCode?: string;
167
+ failureMessage?: string;
168
+ }
78
169
  /** Invoice lifecycle changes this package acts on. */
79
170
  export type BillingInvoiceEventType = 'paid' | 'payment_failed' | 'overdue' | 'uncollectible' | 'voided';
80
171
  /** A verified provider event, normalized and stripped of customer data. */
@@ -91,14 +182,35 @@ export type BillingProviderEvent = {
91
182
  kind: 'checkout_completed';
92
183
  eventId: string;
93
184
  sessionId: string;
185
+ /** `payment` (credit purchase) or `setup` (card on file, #3139). */
186
+ mode?: 'payment' | 'setup';
94
187
  /** Only `paid` sessions settle a credit purchase. */
95
188
  paid: boolean;
96
189
  currency: string;
97
- /** Line-item amount before discounts and tax, minor units. */
98
- amountSubtotal: number;
190
+ /**
191
+ * Line-item amount before discounts and tax, minor units. Omitted by a
192
+ * provider whose event amounts are not minor units; `observe()` then
193
+ * re-reads the session with `getCheckout()`.
194
+ */
195
+ amountSubtotal?: number;
196
+ /** Provider-calculated tax, minor units. */
197
+ amountTax?: number;
99
198
  /** Amount actually collected (after discounts, with tax), minor units. */
100
- amountTotal: number;
199
+ amountTotal?: number;
101
200
  metadata: Record<string, string>;
201
+ } | {
202
+ /** An off-session charge made by `chargeSavedPaymentMethod` (#3139). */
203
+ kind: 'payment';
204
+ eventId: string;
205
+ /** The `idempotencyKey` the charge was made with. */
206
+ chargeKey: string;
207
+ status: BillingChargeStatus;
208
+ providerPaymentId: string;
209
+ providerCustomerId?: string;
210
+ /** Minor units, when the provider amount converts exactly. */
211
+ amount?: number;
212
+ currency?: string;
213
+ failureCode?: string;
102
214
  } | {
103
215
  kind: 'ignored';
104
216
  eventId: string;
@@ -129,6 +241,20 @@ export interface BillingProvider {
129
241
  * anything verified but not actionable is returned as `ignored`.
130
242
  */
131
243
  verifyWebhook(payload: string, signature: string): Promise<BillingProviderEvent>;
244
+ /**
245
+ * Charge the customer's saved default payment method off-session,
246
+ * idempotently by `input.idempotencyKey`. A decline or an authentication
247
+ * requirement is a result, not a throw.
248
+ */
249
+ chargeSavedPaymentMethod?(input: BillingProviderChargeInput): Promise<BillingProviderChargeResult>;
250
+ /** Start a checkout that saves a payment method without charging. */
251
+ createSetupCheckout?(input: BillingProviderSetupCheckoutInput): Promise<BillingProviderCheckoutSession>;
252
+ /** Re-read a checkout session, with amounts in minor units. */
253
+ getCheckout?(sessionId: string): Promise<BillingProviderCheckoutState>;
254
+ /** Make a saved payment method the customer's default. Idempotent. */
255
+ setDefaultPaymentMethod?(providerCustomerId: string, paymentMethodId: string): Promise<void>;
256
+ /** Write an open invoice off as uncollectible. Idempotent. */
257
+ markInvoiceUncollectible?(providerInvoiceId: string): Promise<void>;
132
258
  }
133
259
  export declare class BillingWebhookVerificationError extends Error {
134
260
  constructor(message?: string);
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/billing/provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/billing/provider.ts"],"names":[],"mappings":"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"}