@openrails/billing-ui 0.235.0 → 0.236.0

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.
Files changed (60) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/README.md +103 -73
  3. package/dist/account/account-billing.d.ts +1 -3
  4. package/dist/account/payment-methods-panel.d.ts +1 -3
  5. package/dist/buy-button.d.ts +35 -0
  6. package/dist/cart.d.ts +18 -0
  7. package/dist/checkout.d.ts +1 -3
  8. package/dist/client/checkout.d.ts +28 -0
  9. package/dist/client/client.d.ts +71 -47
  10. package/dist/client/errors.d.ts +4 -0
  11. package/dist/client/generated/error-codes.d.ts +1 -1
  12. package/dist/client/generated/routes.d.ts +117 -88
  13. package/dist/client/generated/wire.d.ts +88 -66
  14. package/dist/client/index.d.ts +2 -2
  15. package/dist/client/types.d.ts +230 -17
  16. package/dist/{client-BpzCZes3.js → client-BuvolBPT.js} +477 -316
  17. package/dist/client-BuvolBPT.js.map +1 -0
  18. package/dist/client.js +2 -2
  19. package/dist/components/stripe-card.d.ts +8 -2
  20. package/dist/components/stripe-wallets.d.ts +12 -0
  21. package/dist/components/ui/badge.d.ts +1 -1
  22. package/dist/components/ui/button.d.ts +1 -1
  23. package/dist/frame.d.ts +5 -5
  24. package/dist/hooks-2d-XjpuI.js +526 -0
  25. package/dist/hooks-2d-XjpuI.js.map +1 -0
  26. package/dist/i18n/context.d.ts +1 -1
  27. package/dist/index.d.ts +7 -5
  28. package/dist/index.js +1966 -1655
  29. package/dist/index.js.map +1 -1
  30. package/dist/lib/money.d.ts +1 -0
  31. package/dist/lib/offer-label.d.ts +4 -0
  32. package/dist/locales/de.js +20 -0
  33. package/dist/locales/de.js.map +1 -1
  34. package/dist/locales/en.d.ts +20 -0
  35. package/dist/locales/en.js +20 -0
  36. package/dist/locales/en.js.map +1 -1
  37. package/dist/locales/es.js +20 -0
  38. package/dist/locales/es.js.map +1 -1
  39. package/dist/locales/ja.js +11 -0
  40. package/dist/locales/ja.js.map +1 -1
  41. package/dist/locales/ko.js +11 -0
  42. package/dist/locales/ko.js.map +1 -1
  43. package/dist/locales/zh.js +11 -0
  44. package/dist/locales/zh.js.map +1 -1
  45. package/dist/offers.d.ts +33 -0
  46. package/dist/order-checkout.d.ts +30 -0
  47. package/dist/react/hooks.d.ts +8 -7
  48. package/dist/react/index.d.ts +1 -1
  49. package/dist/react/provider.d.ts +24 -2
  50. package/dist/react.js +2 -33
  51. package/dist/save-payment-method.d.ts +0 -6
  52. package/dist/styles.css +1 -1
  53. package/dist/types.d.ts +16 -16
  54. package/docs/payment-form-contract.md +6 -6
  55. package/package.json +1 -1
  56. package/dist/client-BpzCZes3.js.map +0 -1
  57. package/dist/config-qLcHvK0Q.js +0 -341
  58. package/dist/config-qLcHvK0Q.js.map +0 -1
  59. package/dist/provider.d.ts +0 -18
  60. package/dist/react.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,108 @@
1
1
  # Changelog
2
2
 
3
+ ## Apple Pay and Google Pay
4
+
5
+ - `<OrderCheckout wallets>` offers Apple Pay and Google Pay through a Stripe
6
+ PSP's Express Checkout Element, above the saved and new cards. Off by
7
+ default: the page's host must be a payment-method domain registered on that
8
+ Stripe account.
9
+
10
+ ## Renewals are orders
11
+
12
+ - `Order` gains `renewal` (a subscription renewal's period and `due_at`) and
13
+ `voided_at`; `expires_at` is null on a renewal; `status` may be `void`.
14
+ - `PaymentRecovery` gains `order_id`: an engine-owned subscription's unpaid
15
+ renewal, paid through `<OrderCheckout>`.
16
+ - `<OrderCheckout>` offers new card entry only where the order takes one (a
17
+ renewal takes saved cards), and lets the customer authenticate a payment
18
+ their bank challenged while they were away.
19
+
20
+ ## Hosted checkout
21
+
22
+ - `getConfig()` returns `merchant` (`PublicMerchant`: `display_name`, and
23
+ `logo_url` and `support_url` when they are https), null when the request
24
+ resolves no merchant.
25
+ - `Order` carries `checkout` (its hosted checkout: `expires_at`,
26
+ `success_url`, `cancel_url`, `saved_payment_methods`; `url` only on the
27
+ answer that made it), null without one.
28
+
29
+ ## Orders take Solana and hosted pages
30
+
31
+ - `<OrderCheckout>` offers an order's Solana option: one button per token,
32
+ then the Solana Pay QR of the order's `solana_pay` next action, confirmed
33
+ until the transfer lands.
34
+ - A PSP with no fields in the page (Stripe without a publishable key) takes
35
+ the order on its hosted page: `<OrderCheckout>` sends the customer there and
36
+ back to `returnUrl` (default: the current page).
37
+ - `OrderPaymentInput` gains `{ token_symbol, psp_id? }` and
38
+ `{ return_url, psp_id? }`.
39
+
40
+ ## OrderCheckout pays an order
41
+
42
+ - `<OrderCheckout orderId>` shows an order and pays it with a saved card or a
43
+ new card in the PSP's fields, running any `next_action` and `confirm`. It
44
+ takes an optional `client` and offers only cards kept for one-click buys
45
+ (`PaymentMethod.reusable`).
46
+ - The client gains `getOrder`, and `payOrder` and `confirmOrder`, which answer
47
+ `{ order, error? }`: a declined payment (402) is the order with
48
+ `payment.last_payment_error`, not a throw. `BillingError` carries `order`.
49
+ - `StripeCardEntry`'s handle gains `tokenize()` and `handleNextAction()`.
50
+
51
+ ## A card is saved in one call
52
+
53
+ - `addPaymentMethod` takes `token` (was `payment_token`). A Stripe card is a
54
+ `pm_` from Stripe's fields, saved by the same call; a card the bank wants to
55
+ authenticate answers `status: "requires_action"` with `next_action`, and
56
+ `confirmPaymentMethod(id)` finishes it after Stripe.js `handleNextAction`.
57
+ `StripeCardEntry` and `SavePaymentMethod` do this themselves.
58
+ - `createCardSetup`, `getCardSetup`, `confirmCardSetup`, the `CardSetup` type
59
+ and the `returnURL` / `cardSetupReturnURL` props are gone: 3-D Secure runs in
60
+ the page.
61
+
62
+ ## Offers sell products by key
63
+
64
+ - The public catalog is a lookup by product key: `listProducts({ keys })` and
65
+ `useProducts({ keys })` take the keys alone (1 to 100) and read one page;
66
+ `entitlements`, `limit` and `cursor` are gone, and so is
67
+ `ProductsState.nextCursor`. No keys fetch nothing.
68
+ - `<Offers keys>` replaces `<Offers entitlements>`: your server names the
69
+ products, with the Go `Client.ListOffers` when it finds them by
70
+ entitlement.
71
+
72
+ ## Apps buy through BuyButton and Offers
73
+
74
+ - `Checkout` and `CheckoutModal` (and their props), the fixture sources and
75
+ the `CheckoutSource` type are no longer exported; the client no longer has
76
+ `createCheckoutSession` or `checkoutSource`. Buy with `<BuyButton>` (it takes
77
+ `amount`, `autoRenew` and `successUrl`) or `<Offers>`. `CheckoutPage` and
78
+ `CheckoutFrame` stay, for the shared payment page.
79
+ - The main entry also exports `createBillingClient` (with `BillingClient`,
80
+ `BillingClientOptions` and `ProductListOptions`) beside `formatAmount`, so a
81
+ React app imports from `@openrails/billing-ui` alone; `./client` and
82
+ `./react` are unchanged.
83
+
84
+ ## One provider
85
+
86
+ - `BillingProvider` takes what `BillingUiProvider` took (`appearance`,
87
+ `messages`, `t`, `locale`, `navigate`) beside `client` and `onChange`, and
88
+ `BillingUiProvider` is gone. The main entry exports it; `./react` exports the
89
+ same component for hook-only apps, without the stylesheet. `client` is
90
+ optional: leave it out where no customer signs in, such as `CheckoutPage`.
91
+ - Inside a provider with a client, the checkout saves a new card to the
92
+ customer first and pays on the customer surface.
93
+
94
+ ## Offers sell an entitlement
95
+
96
+ - `<BuyButton product price onPaid onSignInRequired>` buys one price, labelled
97
+ from the catalog unless given `label`. The app never touches a checkout
98
+ session: when orders take a new card (#1168) it creates an order instead.
99
+ - `<Offers entitlements onPaid onSignInRequired>` lists every product on sale
100
+ granting any of the entitlements, a `BuyButton` per price; `products` feeds
101
+ it from the host's server instead.
102
+ - `listProducts({ entitlements, keys })` and `useProducts({ entitlements, keys })`
103
+ filter the public catalog. One of them is required: OpenRails no longer
104
+ lists the whole catalog publicly.
105
+
3
106
  ## Checkout saves a new card under its PSP
4
107
 
5
108
  - Inside a `BillingProvider`, `Checkout` saved a new card with the session
package/README.md CHANGED
@@ -6,13 +6,13 @@ billing (subscriptions, saved cards, payment history).
6
6
  | Import | Contents |
7
7
  | --------------------------------- | ---------------------------------------------------------------------------------- |
8
8
  | `@openrails/billing-ui/client` | Framework-free typed client for `/billing/v1/me/*` and the catalog, `BillingError` |
9
- | `@openrails/billing-ui/react` | `BillingProvider` and headless hooks |
10
- | `@openrails/billing-ui` | Styled checkout and account components, `BillingUiProvider`, i18n |
9
+ | `@openrails/billing-ui/react` | `BillingProvider` and headless hooks, without styles |
10
+ | `@openrails/billing-ui` | `BillingProvider`, styled checkout and account components, i18n |
11
11
  | `@openrails/billing-ui/locales/*` | `en de es ja ko zh` message bundles |
12
12
 
13
- The checkout owns the browser payment flow. OpenRails holds the checkout
14
- session: the signed-in customer mints one for a price, and its `ocs_` id alone
15
- reads and pays it. Card data is tokenized in NMI-hosted Collect.js iframes and
13
+ The checkout owns the browser payment flow, behind `<BuyButton>` and
14
+ `<Offers>`. OpenRails holds the checkout session: the signed-in customer mints
15
+ one for a price, and its `ocs_` id alone reads and pays it. Card data is tokenized in NMI-hosted Collect.js iframes and
16
16
  never enters the host application, unless the PSP takes cards on OpenRails
17
17
  itself (`card_entry: server`, driver `card`).
18
18
 
@@ -28,35 +28,58 @@ provenance.
28
28
  pnpm add @openrails/billing-ui@X.Y.Z
29
29
  ```
30
30
 
31
- ## Checkout
31
+ ## Buying
32
+
33
+ A React app imports from one place:
32
34
 
33
35
  ```tsx
34
- import { createBillingClient } from "@openrails/billing-ui/client"
35
- import { Checkout, CheckoutFrame } from "@openrails/billing-ui"
36
- import "@openrails/billing-ui/styles.css"
37
-
38
- const billing = createBillingClient({ fetch: auth.authFetch })
39
- const session = await billing.createCheckoutSession({
40
- productKey: "pro",
41
- priceKey: "monthly",
42
- })
36
+ import { BillingProvider, BuyButton, Offers, createBillingClient, formatAmount } from "@openrails/billing-ui"
43
37
 
44
- // A shared payment page (Config.Checkout.PageURL) answers with a url:
45
- <CheckoutFrame url={session.url} theme="dark" onComplete={() => refetchAccess()} />
46
- // Without one, the app renders the checkout itself:
47
- <Checkout source={billing.checkoutSource(session.id)} onComplete={() => refetchAccess()} />
38
+ // auth-ui's authFetch attaches the bearer and retries once after a refresh;
39
+ // `getToken: () => token` works for any other auth.
40
+ const billing = createBillingClient({ baseUrl: "/billing/v1", fetch: auth.authFetch })
41
+
42
+ <BillingProvider client={billing} appearance={{ theme: "auto" }}>
43
+ <App />
44
+ </BillingProvider>
48
45
  ```
49
46
 
50
- `onComplete` is a hint: confirm access from your own authenticated API before
51
- granting anything. Pass `successUrl` to return the buyer from a redirect step
52
- (Stripe's hosted page); it must be on one of your app's return origins. A
53
- server that starts checkout itself mints the session with the Go
54
- `Client.CreateCheckoutSession` and hands the browser its `id` and `url`.
47
+ `<BuyButton>` buys one price, `<Offers>` the products your server names by
48
+ key (a course, its bundle and the membership that also unlocks it; the Go
49
+ `Client.ListOffers` finds the products granting an entitlement): a
50
+ `BuyButton` per price ("$4.99", "Rent for 3 days, $1.99",
51
+ "$10.00 every 30 days"). The purchase is theirs from start to payment, so the
52
+ app never handles a checkout session: today a button opens one in a checkout
53
+ dialog; when orders take a new card it will create an order instead,
54
+ and apps won't change. Signing in is the host's: with `signedIn={false}`, or
55
+ when OpenRails answers 401, they call `onSignInRequired` instead. `onPaid`
56
+ follows a successful payment only; it is a hint, so confirm access from your
57
+ own API (your gate) before granting anything.
55
58
 
56
- For prepaid credits, a fixed pack is another product/price selection. A
57
- `customer_amount` price also accepts `amount` when minting. Collect the amount
58
- on your product page before opening checkout; the resulting session shows and
59
- charges that exact amount, and its payment form cannot change it:
59
+ ```tsx
60
+ <BuyButton
61
+ product="course-101"
62
+ price="rent" // labelled from the catalog unless you pass label
63
+ signedIn={signedIn}
64
+ onSignInRequired={() => openSignIn()}
65
+ onPaid={() => navigate("/courses/css-101")} // your gate now admits them
66
+ />
67
+
68
+ <Offers
69
+ keys={["course-101", "course-bundle", "channel-membership"]} // from your server, or products={...} from its Client.ListOffers
70
+ signedIn={signedIn}
71
+ onSignInRequired={() => openSignIn()}
72
+ onPaid={() => navigate("/courses/css-101")}
73
+ />
74
+ ```
75
+
76
+ `successUrl` returns the buyer from a redirect step (Stripe's hosted page); it
77
+ must be on one of your app's return origins. `autoRenew={false}` buys a
78
+ recurring price's first term only.
79
+
80
+ For prepaid credits, a fixed pack is another product/price. A
81
+ `customer_amount` price takes the buyer's `amount`: collect it on your product
82
+ page, and the checkout charges exactly that:
60
83
 
61
84
  ```tsx
62
85
  import { decimalToAmount } from "@openrails/billing-ui/client"
@@ -65,42 +88,46 @@ import { decimalToAmount } from "@openrails/billing-ui/client"
65
88
  // `enteredAmount` is the text from an <input inputMode="decimal">, e.g. "100".
66
89
  const amount = decimalToAmount(enteredAmount, currency.decimals)
67
90
  const bounds = depositPrice.customer_amount
68
- if (
69
- !amount ||
70
- !bounds ||
71
- BigInt(amount) < BigInt(bounds.min_amount) ||
72
- BigInt(amount) > BigInt(bounds.max_amount)
73
- ) {
74
- throw new Error("Choose an amount within the deposit limits")
75
- }
76
- const session = await billing.createCheckoutSession({
77
- priceId: depositPrice.id,
78
- amount, // USD 100 becomes "100000000"; no floating-point conversion
79
- })
91
+ const valid = amount && bounds && BigInt(amount) >= BigInt(bounds.min_amount) && BigInt(amount) <= BigInt(bounds.max_amount)
92
+
93
+ <BuyButton product="api-credits" price="deposit" amount={valid ? amount : undefined} label="Add credits" {...handlers} />
80
94
  ```
81
95
 
82
96
  OpenRails validates the bounds and whole currency minor units before accepting
83
97
  payment. Fixed prices reject `amount`; their pack benefit can be greater than
84
98
  the purchase price for a bulk discount. Customer-selected deposits currently
85
- use NMI or Stripe. Changing the selected amount requires minting a new session.
99
+ use NMI or Stripe.
86
100
 
87
101
  A rail's own step is the pay result's `next_action`: `redirect_to_url` (an
88
102
  https page, opened in the top window) or `solana_pay` (a `solana:` link shown
89
103
  as a QR code). A card challenge is its `operation`, authenticated in the page.
90
- Stripe Elements needs the buyer's billing client (`<Checkout>` inside a
91
- `BillingProvider`): the shared payment page offers token rails only.
104
+
105
+ ### A shared payment page
106
+
107
+ Several sites selling for one merchant can share one payment page
108
+ (`Config.Checkout.PageURL`). A server mints the session with the Go
109
+ `Client.CreateCheckoutSession` and hands the browser its `url`, which the site
110
+ frames:
111
+
112
+ ```tsx
113
+ <CheckoutFrame url={session.url} theme="dark" onComplete={() => refetchAccess()} />
114
+ ```
115
+
116
+ Stripe Elements needs the buyer's own client, so the shared page offers token
117
+ rails only.
92
118
 
93
119
  The payment host serves `<CheckoutPage>` from one HTML entry at `PageURL`,
94
120
  behind its adapter's `CheckoutFramePolicy` (only the sites in
95
- `Config.Checkout.EmbedOrigins` may frame it):
121
+ `Config.Checkout.EmbedOrigins` may frame it). No customer signs in there, so
122
+ its `BillingProvider` has no client:
96
123
 
97
124
  ```tsx
98
- import { BillingUiProvider, CheckoutPage } from "@openrails/billing-ui"
125
+ import { BillingProvider, CheckoutPage } from "@openrails/billing-ui"
99
126
 
100
127
  createRoot(root).render(
101
- <BillingUiProvider>
128
+ <BillingProvider>
102
129
  <CheckoutPage appearance={{ variables: brand }} />
103
- </BillingUiProvider>
130
+ </BillingProvider>
104
131
  )
105
132
  ```
106
133
 
@@ -112,25 +139,30 @@ cannot navigate the top window, so the app does); app to page
112
139
 
113
140
  ## Account billing
114
141
 
142
+ One `BillingProvider`, usually at the app's root, gives every component the
143
+ client, the appearance and the words. `@openrails/billing-ui/react` exports the
144
+ same provider for an app that uses only the hooks; it loads no stylesheet.
145
+
115
146
  ```tsx
116
- import { createBillingClient } from "@openrails/billing-ui/client"
117
- import { BillingProvider } from "@openrails/billing-ui/react"
118
- import { AccountBilling, BillingUiProvider } from "@openrails/billing-ui"
147
+ import { AccountBilling, BillingProvider, createBillingClient } from "@openrails/billing-ui"
119
148
  import { de } from "@openrails/billing-ui/locales/de"
120
149
 
121
- // auth-ui's authFetch attaches the bearer and retries once after a refresh;
122
- // `getToken: () => token` works for any other auth.
123
150
  const billing = createBillingClient({ baseUrl: "/billing/v1", fetch: auth.authFetch })
124
151
 
125
- <BillingUiProvider appearance={{ theme: "auto" }} messages={de} locale="de" navigate={navigate}>
126
- <BillingProvider client={billing} onChange={() => queryClient.invalidateQueries({ queryKey: ["billing"] })}>
127
- <AccountBilling
128
- plansHref="/plans"
129
- defaultCurrency="USD" // offers "Make default"
130
- sendSolanaTransaction={(tx) => wallet.signAndSend(tx)} // signs a Solana cancel
131
- />
132
- </BillingProvider>
133
- </BillingUiProvider>
152
+ <BillingProvider
153
+ client={billing}
154
+ appearance={{ theme: "auto" }}
155
+ messages={de}
156
+ locale="de"
157
+ navigate={navigate}
158
+ onChange={() => queryClient.invalidateQueries({ queryKey: ["billing"] })}
159
+ >
160
+ <AccountBilling
161
+ plansHref="/plans"
162
+ defaultCurrency="USD" // offers "Make default"
163
+ sendSolanaTransaction={(tx) => wallet.signAndSend(tx)} // signs a Solana cancel
164
+ />
165
+ </BillingProvider>
134
166
  ```
135
167
 
136
168
  The panels read OpenRails' public configuration (`GET /config`) themselves,
@@ -143,13 +175,12 @@ for host components.
143
175
  ## Catalog and plan changes
144
176
 
145
177
  The client also reads the public catalog and changes a subscription's plan.
146
- No UI ships for these; hosts render their own. The catalog and Solana reads
147
- are public routes, served only when the host mounts OpenRails' checkout
148
- routes; `GET /config` is always served.
178
+ The catalog and Solana reads are public routes, served only when the host
179
+ mounts OpenRails' checkout routes; `GET /config` is always served.
149
180
 
150
181
  | Call | Route |
151
182
  | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
152
- | `listProducts()` (each product embeds its prices on sale) | `GET /catalog/products` |
183
+ | `listProducts({ keys })`: the products on sale named by `keys` (1 to 100 product keys), each with its prices, in one page; `useProducts` reads the same | `GET /catalog/products` |
153
184
  | `getConfig()` (capabilities, `currencies`, `payment` with PSPs, `solana.network` and tokens; `client.currencies` is the pinned registry) | `GET /config` |
154
185
  | `previewSubscriptionChange(id, { priceId?, quantity? })` | `POST /me/subscriptions/{id}/change/preview` |
155
186
  | `changeSubscription(id, { priceId?, quantity?, idempotencyKey, signature? })` | `POST /me/subscriptions/{id}/change` |
@@ -195,8 +226,9 @@ provider:
195
226
  Card rails (`collect_js`, `card`, `stripe_elements`) render one panel: saved cards,
196
227
  an inline new card and one Pay/Subscribe button, which is the customer's
197
228
  confirmation of the displayed terms. No provider chooser with one rail.
198
- - Inside a `BillingProvider`, a new card is always saved to the account first
199
- and the source is paid with `payment_method_id`; `requires_action` results
229
+ - Inside a `BillingProvider` with a client, a new card is always saved to the
230
+ account first and the session is paid with `payment_method_id` on the
231
+ customer surface; `requires_action` results
200
232
  carrying an `operation` run 3-D Secure in the page. A `failed` result stays
201
233
  on the panel with `failure.message` next to its `field`, so the buyer can
202
234
  pick another card; the host gives each new attempt a new idempotency key.
@@ -208,10 +240,8 @@ provider:
208
240
  `returnURL(setupId)`; confirm with `client.confirmCardSetup(id)`.
209
241
  - `authenticatePayment(client, operationId, psp)` completes a pending
210
242
  payment's 3-D Secure challenge when `canAuthenticatePayment(psp)`.
211
- - `defaultCountry` (Checkout, SavePaymentMethod, AccountBilling) preselects
212
- the billing country, else the browser locale's region.
213
- - `CheckoutModal gate={<SignIn />}` renders host content (e.g. sign-in) in
214
- the modal instead of the checkout until cleared.
243
+ - `defaultCountry` (CheckoutPage, SavePaymentMethod, AccountBilling)
244
+ preselects the billing country, else the browser locale's region.
215
245
 
216
246
  - Panels: `SubscriptionsPanel` (cancel, resume, change card),
217
247
  `PaymentMethodsPanel`, `PaymentHistory`, `BillingStatusBadge`,
@@ -220,8 +250,8 @@ provider:
220
250
  subscription row; `useBillingRefresh()` refetches after host-side changes.
221
251
  - Hooks: `useSubscriptions` (`cancel`, `resume`, `setPaymentMethod`,
222
252
  `changeSubscription`, per-row `pending`, `nextCursor`), `usePaymentMethods` (`add`,
223
- `remove`, `setDefault`), `usePayments` (cursor pages), `useProducts` (the
224
- catalog).
253
+ `remove`, `setDefault`), `usePayments` (cursor pages), `useProducts` (a
254
+ catalog lookup by product key).
225
255
  Actions resolve to `null` or a `BillingError`; they never throw.
226
256
  `changeSubscription` resolves to the `SubscriptionChange` instead of `null`. Cancel, resume
227
257
  and the card change answer the subscription, which replaces the row.
@@ -1,9 +1,7 @@
1
1
  import { CheckoutAppearance } from '../appearance';
2
2
  import { SendSolanaTransaction } from '../client/client';
3
- import { PaymentMethodsPanelProps } from './payment-methods-panel';
4
3
  import { SubscriptionsPanelProps } from './subscriptions-panel';
5
4
  export interface AccountBillingProps {
6
- cardSetupReturnURL?: PaymentMethodsPanelProps["cardSetupReturnURL"];
7
5
  /**
8
6
  * Offers to make a card the default for this currency: it pays the
9
7
  * currency's invoices and every subscription in it without its own card.
@@ -19,4 +17,4 @@ export interface AccountBillingProps {
19
17
  className?: string;
20
18
  }
21
19
  /** Subscriptions, payment methods and history in one column. */
22
- export declare function AccountBilling({ cardSetupReturnURL, defaultCurrency, defaultCountry, sendSolanaTransaction, plansHref, renderSubscriptionFooter, historyPageSize, appearance, className, }: AccountBillingProps): import("react").JSX.Element;
20
+ export declare function AccountBilling({ defaultCurrency, defaultCountry, sendSolanaTransaction, plansHref, renderSubscriptionFooter, historyPageSize, appearance, className, }: AccountBillingProps): import("react").JSX.Element;
@@ -1,8 +1,6 @@
1
1
  import { CheckoutAppearance } from '../appearance';
2
2
  import * as React from "react";
3
3
  export interface PaymentMethodsPanelProps {
4
- /** Return target after off-page card verification; see `SavePaymentMethod`. */
5
- cardSetupReturnURL?: (setupId: string) => string;
6
4
  /**
7
5
  * Offers to make a card the default for this currency: it pays the
8
6
  * currency's invoices and every subscription in it without its own card.
@@ -17,4 +15,4 @@ export interface PaymentMethodsPanelProps {
17
15
  * The customer's saved cards. "Add card" offers each PSP of the merchant's
18
16
  * payment setup (`GET /config`) that saves a card in the page.
19
17
  */
20
- export declare function PaymentMethodsPanel({ cardSetupReturnURL, defaultCurrency, defaultCountry, appearance, className, }: PaymentMethodsPanelProps): React.JSX.Element;
18
+ export declare function PaymentMethodsPanel({ defaultCurrency, defaultCountry, appearance, className, }: PaymentMethodsPanelProps): React.JSX.Element;
@@ -0,0 +1,35 @@
1
+ import { CheckoutAppearance } from './appearance';
2
+ import { PayResult } from './types';
3
+ import * as React from "react";
4
+ export interface BuyButtonProps {
5
+ /** The product's catalog key. */
6
+ product: string;
7
+ /** The price's key within the product. */
8
+ price: string;
9
+ /** The button's text; by default the price's amount and terms, from the catalog. */
10
+ label?: string;
11
+ /**
12
+ * A customer-chosen deposit, in the price currency's native units, for a
13
+ * price with `customer_amount`; the checkout charges exactly this.
14
+ */
15
+ amount?: string;
16
+ /** false buys a recurring price's first term only; default: renews. */
17
+ autoRenew?: boolean;
18
+ /** Where a redirect rail (Stripe's hosted page) returns the buyer: one of the app's return origins. */
19
+ successUrl?: string;
20
+ /**
21
+ * The purchase succeeded. A hint: the host's own gate decides access, so
22
+ * send the buyer to the content it guards.
23
+ */
24
+ onPaid: (result: PayResult) => void;
25
+ /**
26
+ * Buying needs a signed-in customer: called instead of the checkout when
27
+ * `signedIn` is false or OpenRails answers 401.
28
+ */
29
+ onSignInRequired: () => void;
30
+ /** false when the host knows the visitor is signed out. */
31
+ signedIn?: boolean;
32
+ appearance?: CheckoutAppearance;
33
+ className?: string;
34
+ }
35
+ export declare function BuyButton(props: BuyButtonProps): React.JSX.Element;
package/dist/cart.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { CheckoutAppearance } from './appearance';
2
+ import { BillingClient } from './client/client';
3
+ import { Order } from './client/types';
4
+ import * as React from "react";
5
+ export interface CartProps {
6
+ /** The client to read and buy through; default: the provider's. */
7
+ client?: BillingClient;
8
+ /**
9
+ * The order made from the cart. Default: pay it here with OrderCheckout.
10
+ */
11
+ onOrder?: (order: Order) => void;
12
+ /** Passed to OrderCheckout: the order is complete, or processing. */
13
+ onSettled?: (order: Order) => void;
14
+ appearance?: CheckoutAppearance;
15
+ className?: string;
16
+ }
17
+ /** The customer's cart. Requires `BillingProvider`. */
18
+ export declare function Cart({ client: given, onOrder, onSettled, appearance, className, }: CartProps): React.JSX.Element;
@@ -9,8 +9,6 @@ export interface CheckoutProps {
9
9
  layout?: CheckoutLayout;
10
10
  /** Billing country to preselect; default: the browser locale's region. */
11
11
  defaultCountry?: string;
12
- /** Return target after an off-page card verification (Stripe setup). */
13
- cardSetupReturnURL?: (setupId: string) => string;
14
12
  onComplete?: (result: PayResult) => void;
15
13
  /**
16
14
  * Leaves for a redirect rail's page. Default: navigate the top window,
@@ -21,4 +19,4 @@ export interface CheckoutProps {
21
19
  completionMode?: "embedded" | "redirect";
22
20
  className?: string;
23
21
  }
24
- export declare function Checkout({ source, appearance, layout, defaultCountry, cardSetupReturnURL, onComplete, onRedirect, onPhaseChange, completionMode, className, }: CheckoutProps): React.JSX.Element;
22
+ export declare function Checkout({ source, appearance, layout, defaultCountry, onComplete, onRedirect, onPhaseChange, completionMode, className, }: CheckoutProps): React.JSX.Element;
@@ -0,0 +1,28 @@
1
+ import { CheckoutSource } from '../source';
2
+ import { CheckoutSessionLink } from './types';
3
+ export interface CheckoutSourceOptions {
4
+ /**
5
+ * A customer surface's base: its `/me` prefix, such as `/billing/v1/me` or
6
+ * a host's own `/api/v1/merchants/acme/billing/me`. The session is read and
7
+ * paid there with this client's credential, which proves the session's
8
+ * customer, so its saved cards pay. Default: the session id alone, at
9
+ * `{baseUrl}/checkout-sessions`.
10
+ */
11
+ customerBase?: string;
12
+ }
13
+ export interface CheckoutCalls {
14
+ createCheckoutSession(input: {
15
+ priceKey?: string;
16
+ productKey?: string;
17
+ priceId?: string;
18
+ /** Customer-selected deposit in the price currency's native units. */
19
+ amount?: string;
20
+ /** Defaults to true for recurring prices; false buys the initial term only. */
21
+ autoRenew?: boolean;
22
+ successUrl?: string;
23
+ }): Promise<CheckoutSessionLink>;
24
+ checkoutSource(sessionId: string, opts?: CheckoutSourceOptions): CheckoutSource;
25
+ }
26
+ export declare function registerCheckout(client: object, checkout: CheckoutCalls): void;
27
+ /** The checkout calls of a client from createBillingClient. */
28
+ export declare function checkoutOf(client: object): CheckoutCalls;