@tuppence/js 0.0.0-stage → 0.1.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.
@@ -0,0 +1,278 @@
1
+ import type { ConfirmationTokenCreateParams, Stripe, StripeElementLocale, StripeElements, StripeElementsOptionsMode } from "@stripe/stripe-js";
2
+ import { TuppenceError } from "./errors.js";
3
+ import { AddressField, type AddressOptions, ExpressCheckout, type ExpressCheckoutOptions } from "./express.js";
4
+ import { type Fetch } from "./http.js";
5
+ import { PaymentSheet, type PaymentSheetOptions, SetupSheet, type SetupSheetOptions } from "./sheet.js";
6
+ import { StorefrontCartClient, type StorefrontOptions } from "./storefront.js";
7
+ import type { BankAccountDetails, ExternalAccountParams, PublicPayment, PublicSetupSession, PublicTopupLinkPage, SdkConfig } from "./types.js";
8
+ /**
9
+ * Loads Stripe.js for one publishable key and connected account. The default is Stripe's own
10
+ * loader, which adds js.stripe.com's script to the page when first asked: Stripe.js is never
11
+ * bundled, as Stripe's terms and PCI guidance require.
12
+ */
13
+ export type LoadStripe = (publishableKey: string, options: {
14
+ /** The connected account whose card fields these are. */
15
+ stripeAccount: string;
16
+ /** The payer's language for Stripe's fields and messages, as Stripe names it (`stripeLocale`). */
17
+ locale: StripeElementLocale;
18
+ }) => Promise<Stripe | null>;
19
+ export interface TuppenceOptions {
20
+ /** Where Tuppence's API is: `https://api.tuppence.ai` unless you say otherwise. */
21
+ apiBase?: string;
22
+ /** The `fetch` to call it with — the browser's own unless you pass one. */
23
+ fetch?: Fetch;
24
+ /** How Stripe.js is loaded — Stripe's own loader unless you pass one. */
25
+ loadStripe?: LoadStripe;
26
+ /**
27
+ * The payer's language, a BCP 47 tag such as `de-AT`: Stripe's card fields and messages speak
28
+ * it (`de`). The browser's unless you pass one. Stripe's `pt` is Brazilian Portuguese, so a
29
+ * payer in Portugal (`pt-PT`) gets Stripe's English; only `pt-BR` gets Stripe's Portuguese.
30
+ */
31
+ locale?: string;
32
+ /**
33
+ * While a payment settles: how often it is read back, for how long, and how to wait (also
34
+ * between the retries of a read the server briefly couldn't answer).
35
+ */
36
+ poll?: {
37
+ intervalMs?: number;
38
+ timeoutMs?: number;
39
+ sleep?: (ms: number) => Promise<void>;
40
+ };
41
+ /** How the page is sent elsewhere (`topups.redirect`) — `window.location.assign` unless you pass one. */
42
+ navigate?: (url: string) => void;
43
+ }
44
+ /**
45
+ * What Stripe's fields need to know about a charge before it exists (deferred mode): a
46
+ * payment, or what a store's checkout says it will charge.
47
+ */
48
+ export type Payable = Pick<PublicPayment, "amount" | "currency" | "stripe_publishable_key" | "stripe_account"> & Partial<Pick<PublicPayment, "branding" | "capture_method" | "setup_future_usage" | "excluded_payment_method_types">>;
49
+ /** How Stripe's card fields look and read — Stripe's own options, passed as they are. */
50
+ export type ElementsOptions = Pick<StripeElementsOptionsMode, "appearance" | "fonts" | "locale" | "loader"> & {
51
+ /** What is charged, when the page adds to it (a tip): the payment's `amount` otherwise. */
52
+ amount?: number;
53
+ };
54
+ export interface ConfirmPaymentOptions {
55
+ /** The payment's client secret (`pay_…_secret_…`), from your server. */
56
+ clientSecret: string;
57
+ /** Stripe's card fields, from `tuppence.elements(payment)`. */
58
+ elements?: StripeElements;
59
+ /** More for Stripe to know about the card (billing details), passed as it is. */
60
+ params?: ConfirmationTokenCreateParams;
61
+ /** Pay with the card the customer saved, for a charge that waits for them. */
62
+ savedCard?: boolean;
63
+ /**
64
+ * TEST MODE, on the simulated gateway only (where there are no card fields): one of Stripe's
65
+ * test payment methods by name, such as `pm_card_gb`.
66
+ */
67
+ testPaymentMethod?: string;
68
+ /** A tip the payer adds, where the payment offers one — in the smallest unit, as `amount`. */
69
+ tipAmount?: number;
70
+ }
71
+ export interface ConfirmSetupOptions {
72
+ /** The setup session's client secret (`sets_…_secret_…`), from your server. */
73
+ clientSecret: string;
74
+ /** Stripe's card fields, from `tuppence.setupElements(session)`. */
75
+ elements?: StripeElements;
76
+ params?: ConfirmationTokenCreateParams;
77
+ /** TEST MODE, on the simulated gateway only: one of Stripe's test payment methods by name. */
78
+ testPaymentMethod?: string;
79
+ }
80
+ export type BankAccountDetailsResult = {
81
+ externalAccount: ExternalAccountParams;
82
+ error?: undefined;
83
+ } | {
84
+ error: TuppenceError;
85
+ externalAccount?: undefined;
86
+ };
87
+ export type PaymentResult = {
88
+ payment: PublicPayment;
89
+ error?: undefined;
90
+ } | {
91
+ error: TuppenceError;
92
+ payment: PublicPayment | null;
93
+ };
94
+ export type SetupResult = {
95
+ setupSession: PublicSetupSession;
96
+ error?: undefined;
97
+ } | {
98
+ error: TuppenceError;
99
+ setupSession: PublicSetupSession | null;
100
+ };
101
+ /**
102
+ * Takes a card in the browser for a Tuppence payment — through Stripe's own fields, on the
103
+ * business's own Stripe account. Card details go from the payer's device to Stripe and never
104
+ * through Tuppence, this code, or yours.
105
+ */
106
+ export declare class Tuppence {
107
+ /** What `loadTuppence` learned about its key; null for a page that only holds client secrets. */
108
+ readonly config: SdkConfig | null;
109
+ private readonly http;
110
+ private readonly fetchImpl;
111
+ private readonly loadStripe;
112
+ /** What Stripe.js is loaded with for the payer's language (100-18). */
113
+ private readonly locale;
114
+ private readonly stripes;
115
+ /** The Stripe instance each set of card fields came from: its token must come from it too. */
116
+ private readonly owners;
117
+ private readonly intervalMs;
118
+ private readonly timeoutMs;
119
+ private readonly sleep;
120
+ private readonly navigate;
121
+ /**
122
+ * The card balance's hosted top-up page (54-18). Your server makes a link
123
+ * (`POST /v1/issuing/topup_links`, with your secret key) and hands its `url` to the page;
124
+ * `tuppence.topups.redirect({ url })` sends the person there — to top up by card or by bank
125
+ * transfer, in your (or your Connect platform's) branding — and they come back to the link's
126
+ * `return_url`. Only a Tuppence top-up page's address is followed: anything else throws.
127
+ */
128
+ readonly topups: {
129
+ /**
130
+ * Stripe's card fields for a hosted top-up page's card (54-18), to charge `amount` (the
131
+ * card option's `total`). Null where no Stripe is behind the environment: there,
132
+ * `pay({ testPaymentMethod })` names one of Stripe's test cards.
133
+ */
134
+ elements: (page: PublicTopupLinkPage, options: ElementsOptions & {
135
+ amount: number;
136
+ }) => Promise<StripeElements | null>;
137
+ /**
138
+ * Tops up by card on a hosted top-up page (54-18): the card presented (Stripe's fields make a
139
+ * confirmation token), the top-up made, the bank's check in Stripe's own frame if it asks,
140
+ * then the page read back until the bank and Stripe have answered. `businessFunds: true` is
141
+ * the person's word that the card is the business's own money.
142
+ */
143
+ pay: (options: {
144
+ token: string;
145
+ businessFunds: boolean;
146
+ amount?: number;
147
+ elements?: StripeElements;
148
+ testPaymentMethod?: string;
149
+ }) => Promise<{
150
+ page: PublicTopupLinkPage;
151
+ error?: TuppenceError;
152
+ }>;
153
+ /**
154
+ * Finishes the bank's check on a hosted page's card top-up that waited for it when the page
155
+ * opened (a reload half-way), in Stripe's own frame, then reads the page back.
156
+ */
157
+ resume: (options: {
158
+ token: string;
159
+ }) => Promise<{
160
+ page: PublicTopupLinkPage;
161
+ error?: TuppenceError;
162
+ }>;
163
+ redirect: (options: {
164
+ url: string;
165
+ }) => void;
166
+ };
167
+ constructor(options?: TuppenceOptions,
168
+ /** What `loadTuppence` learned about its key; null for a page that only holds client secrets. */
169
+ config?: SdkConfig | null);
170
+ /** `loadTuppence`: the key checked here, then what the API says about it. */
171
+ static load(publishableKey: string, options?: TuppenceOptions): Promise<Tuppence>;
172
+ /** The payment a client secret belongs to, as its payer sees it. */
173
+ retrievePayment(clientSecret: string): Promise<PublicPayment>;
174
+ /** The setup session a client secret belongs to, as its customer sees it. */
175
+ retrieveSetupSession(clientSecret: string): Promise<PublicSetupSession>;
176
+ /**
177
+ * Stripe's card fields for a payment — `elements.create("payment").mount(el)` shows them. What
178
+ * they collect matches the charge Tuppence will make: its amount, currency, how it is
179
+ * captured and whether it saves the card. Null where no Stripe is behind the environment (the
180
+ * simulated gateway): there, `testPaymentMethod` names one of Stripe's test cards instead.
181
+ *
182
+ * A page that adds to the amount (a tip) says so with `elements.update({ amount })`.
183
+ */
184
+ elements(payment: Payable, options?: ElementsOptions): Promise<StripeElements | null>;
185
+ /** Stripe's card fields for saving a card with nothing charged — cards only, as the session saves. */
186
+ setupElements(session: PublicSetupSession, options?: Omit<ElementsOptions, "amount">): Promise<StripeElements | null>;
187
+ /**
188
+ * Stripe's Payment Element for a payment, dressed in the business's branding:
189
+ * `tuppence.paymentSheet({ clientSecret }).mount("#card")`, then `sheet.confirm()`. Its events
190
+ * say when the fields show (`ready`), whether they are complete (`change`), and why they
191
+ * cannot show (`error` — on the simulated gateway there are none).
192
+ */
193
+ paymentSheet(options: PaymentSheetOptions): PaymentSheet;
194
+ /**
195
+ * A store's basket (85-10): `get()` it, or `quote()` it for an address and a delivery choice
196
+ * without changing it. On the store's own hosts the basket is its cookie; headless (M94) pass
197
+ * `base: "https://api.tuppence.ai"`, the publishable key and the basket's token.
198
+ */
199
+ cart(options?: StorefrontOptions): StorefrontCartClient;
200
+ /**
201
+ * Apple Pay, Google Pay and Link for a store's basket (85-10): Stripe's Express Checkout
202
+ * Element in deferred mode, in the business's branding. The sheet's address and delivery
203
+ * choices are priced by the basket's quote, and the total in the sheet follows;
204
+ * `onConfirm` gets Stripe's confirmation token for your server to pay with.
205
+ * `tuppence.expressCheckout(payable, { onConfirm }).mount("#express")`.
206
+ */
207
+ expressCheckout(payable: Payable, options: ExpressCheckoutOptions): ExpressCheckout;
208
+ /**
209
+ * Stripe's Address Element, with Stripe's autocomplete (85-10): in a payment's own Elements
210
+ * group (from `elements()`) so a shipping address goes with the payment, or, from a payment
211
+ * alone, in Elements of its own in the business's branding.
212
+ */
213
+ address(from: StripeElements | Payable, options: AddressOptions): AddressField;
214
+ /**
215
+ * Stripe's confirmation token for fields this SDK made: the fields checked, then the token.
216
+ * @internal For the SDK's own wallets; pages pay through `confirmPayment`.
217
+ */
218
+ confirmationToken(elements: StripeElements, params?: ConfirmationTokenCreateParams): Promise<{
219
+ id: string;
220
+ } | {
221
+ error: TuppenceError;
222
+ }>;
223
+ /** The same for saving a card with nothing charged. */
224
+ setupSheet(options: SetupSheetOptions): SetupSheet;
225
+ /**
226
+ * Pays a payment: the card is presented (Stripe's fields make a confirmation token), the
227
+ * payer's bank checks it's them if it asks (in Stripe's own frame), and the payment is read
228
+ * back until it settles. A refused card is `{ error }` with the payment as it now stands —
229
+ * never an exception. If an answer is lost on the way, the outcome is read back: the card is
230
+ * never presented twice.
231
+ *
232
+ * A Bacs Direct Debit answers at once with `status: "processing"`, `payment_method_type:
233
+ * "bacs_debit"` and `processing.expected_debit_date` (`YYYY-MM-DD`): the mandate is set up and
234
+ * the money is collected in a few working days. Show the payer that; `succeeded` (or
235
+ * `failed`) comes later, by webhook — `payment.succeeded`, `payment.failed`.
236
+ */
237
+ confirmPayment(options: ConfirmPaymentOptions): Promise<PaymentResult>;
238
+ /** Saves a card with nothing charged — the same steps as a payment. */
239
+ confirmSetup(options: ConfirmSetupOptions): Promise<SetupResult>;
240
+ /**
241
+ * Finishes what a payment waits on when the page opens — the payer's bank checking it's them
242
+ * (a charge to a saved card that asked for it, a check left half-way) — in Stripe's own frame,
243
+ * then reads it back. On the simulated gateway it answers the payment as it stands.
244
+ */
245
+ resumePayment(options: {
246
+ clientSecret: string;
247
+ }): Promise<PaymentResult>;
248
+ /** The same for a card being saved. */
249
+ resumeSetup(options: {
250
+ clientSecret: string;
251
+ }): Promise<SetupResult>;
252
+ private resume;
253
+ /**
254
+ * A bank account, checked and shaped for `POST /v1/accounts/{id}/external_accounts` — the only
255
+ * way to add one (52-09, 52-17): your server sends `externalAccount` on to Tuppence as
256
+ * `external_account`, and Tuppence keeps the details (encrypted, for verification) and has Stripe
257
+ * make the bank account. Tuppence refuses a Stripe bank token. Nothing is sent from
258
+ * here; a wrong field comes back as an error naming it.
259
+ */
260
+ bankAccountDetails(details: BankAccountDetails): BankAccountDetailsResult;
261
+ /** Stripe.js for an object's publishable key and account — loaded once for each pair. */
262
+ private stripeFor;
263
+ /** A card, as the confirm route takes it: a confirmation token, a saved card, or a test card. */
264
+ private present;
265
+ /** Confirm, then the bank's check if it asks, then read back until it settles. */
266
+ private run;
267
+ /** What follows a confirm: the bank's check if it asks, then a read-back until it settles. */
268
+ private onward;
269
+ /** Reads an object back until neither the bank nor Stripe is still deciding, or time is up. */
270
+ private settle;
271
+ }
272
+ /** For a page that holds client secrets and no key — Tuppence's own pay pages. */
273
+ export declare function createTuppence(options?: TuppenceOptions): Tuppence;
274
+ /**
275
+ * Starts the SDK with your PUBLISHABLE key (`pk_test_…` or `pk_live_…`). A secret key is
276
+ * refused here, before it is sent anywhere: it must never be in a page.
277
+ */
278
+ export declare function loadTuppence(publishableKey: string, options?: TuppenceOptions): Promise<Tuppence>;