@sunbay/checkout-sdk-js 0.0.2 → 0.0.3
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/README.md +72 -0
- package/dist/index.cjs +181 -147
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +250 -218
- package/dist/index.d.ts +250 -218
- package/dist/index.global.js +181 -147
- package/dist/index.global.js.map +1 -1
- package/dist/index.mjs +181 -147
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.d.cts
CHANGED
|
@@ -2,249 +2,273 @@ import { ElementType, CommandName, EventName, ElementOptions, Appearance, Elemen
|
|
|
2
2
|
export { AddressElementOptions, AddressInfo, Appearance, CardElementOptions, CardFieldElementOptions, CheckoutError, CheckoutErrorCategory, ElementOptions, ElementStatus, ElementType, ErrorCode, ErrorCodeValue, ExpressCheckoutElementOptions, PaymentMethod, PaymentMethodFilter, PaymentOutcome, PublicPaymentMethod, PublicProductLine, PublicSessionView, TxnStatus } from '@sunbay/checkout-sdk-protocol';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* CheckoutElement
|
|
5
|
+
* CheckoutElement — the merchant-side Element handle (spec 6).
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
9
|
-
*
|
|
10
|
-
* -
|
|
11
|
-
*
|
|
12
|
-
*
|
|
7
|
+
* Responsibilities:
|
|
8
|
+
* - Constructed by `CheckoutInstance.create` (in unit tests, injected via a mock transport +
|
|
9
|
+
* constructor args).
|
|
10
|
+
* - Mount a **visible** iframe at the merchant DOM target and forward Element commands through the
|
|
11
|
+
* transport.
|
|
12
|
+
* - Maintain the state machine `created → loading → ready → destroyed` (with `loadError` as a side branch).
|
|
13
|
+
* - Subscribe to the transport's `elementReady` / `loadError` events, filter by **its own elementId**,
|
|
14
|
+
* and drive the resolve / reject of `mount()`.
|
|
13
15
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
+
* Security constraint (AGENTS/spec): this layer only does DOM mounting and protocol command
|
|
17
|
+
* forwarding and **never touches card values**. Card data exists only inside the hosted iframe and
|
|
18
|
+
* is never transmitted via this handle or the transport.
|
|
16
19
|
*/
|
|
17
20
|
|
|
18
21
|
/**
|
|
19
|
-
* transport
|
|
22
|
+
* The minimal interface the transport depends on (satisfied by MainFrameTransport).
|
|
20
23
|
*
|
|
21
|
-
*
|
|
24
|
+
* Only declares the methods the Element handle needs, to make mock injection in unit tests easy.
|
|
22
25
|
*/
|
|
23
26
|
interface ElementTransport {
|
|
24
27
|
request(name: CommandName, payload: unknown): Promise<unknown>;
|
|
25
28
|
on(event: EventName, handler: (payload: unknown) => void): void;
|
|
26
29
|
off(event: EventName, handler: (payload: unknown) => void): void;
|
|
27
30
|
}
|
|
28
|
-
/** CheckoutElement
|
|
31
|
+
/** CheckoutElement constructor parameters (assembled by CheckoutInstance.create). */
|
|
29
32
|
interface CheckoutElementOptions {
|
|
30
|
-
/** Element
|
|
33
|
+
/** Unique Element id (generated by the instance, used to pair commands/events). */
|
|
31
34
|
elementId: string;
|
|
32
|
-
/** Element
|
|
35
|
+
/** Element type (determines the iframe path and available actions). */
|
|
33
36
|
type: ElementType;
|
|
34
|
-
/**
|
|
37
|
+
/** Hosted page origin (without a trailing slash). */
|
|
35
38
|
hostOrigin: string;
|
|
36
39
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
+
* The current checkout session id. Sent with the iframe src as `?checkoutId=`, so that hosted
|
|
41
|
+
* fields/element iframes join the correct same-origin signaling channel
|
|
42
|
+
* (`sunbay-checkout:<checkoutId>`) and pair with main; missing it causes the field channel name
|
|
43
|
+
* to mismatch and never become ready.
|
|
40
44
|
*/
|
|
41
45
|
checkoutId: string;
|
|
42
|
-
/**
|
|
46
|
+
/** The transport layer. */
|
|
43
47
|
transport: ElementTransport;
|
|
44
|
-
/**
|
|
48
|
+
/** Initial Element configuration (sent with createElement). */
|
|
45
49
|
initialOptions?: ElementOptions;
|
|
46
50
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
+
* Handle destruction callback (injected by CheckoutInstance). Called with this elementId when
|
|
52
|
+
* `destroy()` successfully destroys the handle, so the instance removes itself from the
|
|
53
|
+
* mutual-exclusion registry (elements Map), thereby allowing a mutually-exclusive Element of the
|
|
54
|
+
* same kind to be recreated after destruction (e.g. switching expressCheckout's
|
|
55
|
+
* buttonType/buttonHeight requires recreating the iframe). Not called by `unmount()` (which
|
|
56
|
+
* keeps the handle, still occupies the slot, and can remount).
|
|
51
57
|
*/
|
|
52
58
|
onDestroy?: (elementId: string) => void;
|
|
53
59
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
60
|
+
* Initial color scheme (from createCheckout's appearance.colorScheme).
|
|
61
|
+
* Only when provided is it appended to the iframe src's `&colorScheme=<value>`, so the hosted
|
|
62
|
+
* iframe renders with that scheme on the first frame (no flash). When absent it is not appended
|
|
63
|
+
* and the hosted side handles the default (light). Runtime switching goes through the
|
|
64
|
+
* updateCheckout command, not here.
|
|
58
65
|
*/
|
|
59
66
|
colorScheme?: 'light' | 'dark' | 'auto';
|
|
60
67
|
/**
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* `&appearance=<encodeURIComponent(JSON)
|
|
64
|
-
*
|
|
65
|
-
*
|
|
68
|
+
* Initial appearance customization (from createCheckout's appearance).
|
|
69
|
+
* Only when it contains `variables` or `rules` is it serialized into the iframe src's
|
|
70
|
+
* `&appearance=<encodeURIComponent(JSON)>`, so the hosted iframe renders with that appearance on
|
|
71
|
+
* the first frame (no flash). When it contains only `colorScheme` (no variables/rules) it is not
|
|
72
|
+
* appended, to avoid an empty appearance string; colorScheme goes via the separate
|
|
73
|
+
* `&colorScheme=`. Runtime switching goes through the updateCheckout command, not here.
|
|
66
74
|
*/
|
|
67
75
|
appearance?: Appearance;
|
|
68
76
|
}
|
|
69
77
|
declare class CheckoutElement {
|
|
70
|
-
/** Element
|
|
78
|
+
/** Unique Element id. */
|
|
71
79
|
readonly elementId: string;
|
|
72
|
-
/** Element
|
|
80
|
+
/** Element type. */
|
|
73
81
|
readonly type: ElementType;
|
|
74
|
-
/**
|
|
82
|
+
/** The address Element's mode (billing/shipping; only meaningful for address), used by the instance to judge mutual exclusion by mode. */
|
|
75
83
|
readonly mode: string | undefined;
|
|
76
84
|
private readonly hostOrigin;
|
|
77
85
|
private readonly checkoutId;
|
|
78
86
|
private readonly transport;
|
|
79
87
|
private options;
|
|
80
|
-
/**
|
|
88
|
+
/** Initial color scheme (appended to the iframe src; not appended when absent). */
|
|
81
89
|
private readonly colorScheme;
|
|
82
|
-
/**
|
|
90
|
+
/** Initial appearance customization (appended to the iframe src when it contains variables/rules; not appended when absent or colorScheme-only). */
|
|
83
91
|
private readonly appearance;
|
|
84
|
-
/**
|
|
92
|
+
/** Destruction callback (injected by the instance): called at the end of destroy() so the instance removes itself from the mutual-exclusion registry to free the slot. */
|
|
85
93
|
private readonly onDestroy;
|
|
86
94
|
private status;
|
|
87
95
|
private container;
|
|
88
96
|
private iframe;
|
|
89
|
-
/** mount
|
|
97
|
+
/** Event handlers temporarily subscribed during mount (unbound after resolve/reject). */
|
|
90
98
|
private readyHandler;
|
|
91
99
|
private loadErrorHandler;
|
|
92
100
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
101
|
+
* expressCheckout only: a snapshot of each wallet's availability.
|
|
102
|
+
* Initially from elementReady.availableWallets, then updated by expressAvailabilityChange.
|
|
95
103
|
*/
|
|
96
104
|
private availableWallets;
|
|
97
|
-
/**
|
|
105
|
+
/** expressCheckout only: the persistently subscribed expressAvailabilityChange handler (unbound on destroy). */
|
|
98
106
|
private availabilityHandler;
|
|
99
107
|
/**
|
|
100
|
-
* iframe
|
|
101
|
-
*
|
|
108
|
+
* iframe auto-height: the window 'message' listener that stays resident during mount (unbound
|
|
109
|
+
* when the iframe disappears/is destroyed). Keeps a reference so removeEventListener can be
|
|
110
|
+
* called; null means not listening.
|
|
102
111
|
*/
|
|
103
112
|
private resizeHandler;
|
|
104
|
-
/**
|
|
113
|
+
/** The most recently applied iframe height (px), used for deduplication to avoid redundant style writes; null means not yet set. */
|
|
105
114
|
private lastHeight;
|
|
106
115
|
constructor(opts: CheckoutElementOptions);
|
|
107
|
-
/**
|
|
116
|
+
/** The current status (read-only snapshot, for external/test observation). */
|
|
108
117
|
getStatus(): ElementStatus;
|
|
109
118
|
/**
|
|
110
|
-
*
|
|
119
|
+
* expressCheckout only: return the current snapshot of each wallet's availability (always
|
|
120
|
+
* undefined for other types).
|
|
111
121
|
*
|
|
112
|
-
*
|
|
122
|
+
* The initial value comes from elementReady's availableWallets, then is updated by
|
|
123
|
+
* expressAvailabilityChange.
|
|
113
124
|
*
|
|
114
|
-
* @returns
|
|
125
|
+
* @returns The availability snapshot; undefined when not yet ready or non-express.
|
|
115
126
|
*/
|
|
116
127
|
getAvailableWallets(): AvailableWallets | undefined;
|
|
117
128
|
/**
|
|
118
|
-
*
|
|
129
|
+
* Mount at the merchant DOM target: insert a visible iframe, send createElement, await elementReady.
|
|
119
130
|
*
|
|
120
|
-
* @param selectorOrEl - CSS
|
|
121
|
-
* @returns elementReady
|
|
122
|
-
* @throws
|
|
131
|
+
* @param selectorOrEl - A CSS selector or an HTMLElement container; the container must be unique and empty.
|
|
132
|
+
* @returns Resolves after elementReady; on failure removes the node and rejects (loadError / INVALID_OPTIONS).
|
|
133
|
+
* @throws INSTANCE_DESTROYED when already destroyed.
|
|
123
134
|
* @example
|
|
124
135
|
* await element.mount('#card-field');
|
|
125
136
|
*/
|
|
126
137
|
mount(selectorOrEl: string | HTMLElement): Promise<void>;
|
|
127
138
|
/**
|
|
128
|
-
*
|
|
139
|
+
* Unmount: send destroyElement, remove the iframe; idempotent; keeps the handle and configuration.
|
|
129
140
|
*
|
|
130
|
-
* @returns
|
|
131
|
-
* @throws
|
|
141
|
+
* @returns Resolves on completion (resolves directly when not mounted).
|
|
142
|
+
* @throws INSTANCE_DESTROYED when already destroyed.
|
|
132
143
|
*/
|
|
133
144
|
unmount(): Promise<void>;
|
|
134
145
|
/**
|
|
135
|
-
*
|
|
146
|
+
* Destroy the handle: idempotent; remove the iframe; afterwards any non-destroy/off call throws INSTANCE_DESTROYED.
|
|
136
147
|
*/
|
|
137
148
|
destroy(): void;
|
|
138
149
|
/**
|
|
139
|
-
*
|
|
150
|
+
* Update the Element configuration: send updateElement; illegal fields are rejected wholesale by the hosted side.
|
|
140
151
|
*
|
|
141
|
-
* @param patch -
|
|
142
|
-
* @returns
|
|
143
|
-
* @throws
|
|
152
|
+
* @param patch - Configuration delta.
|
|
153
|
+
* @returns Resolves after successfully writing back the local options.
|
|
154
|
+
* @throws INSTANCE_DESTROYED when already destroyed.
|
|
144
155
|
*/
|
|
145
156
|
update(patch: Partial<ElementOptions>): Promise<void>;
|
|
146
157
|
/**
|
|
147
|
-
*
|
|
158
|
+
* Register an event handler (passed through to the transport, dispatched by event name).
|
|
148
159
|
*
|
|
149
|
-
* @param event -
|
|
150
|
-
* @param handler -
|
|
151
|
-
* @throws
|
|
160
|
+
* @param event - Event name.
|
|
161
|
+
* @param handler - Callback.
|
|
162
|
+
* @throws INSTANCE_DESTROYED when already destroyed.
|
|
152
163
|
*/
|
|
153
164
|
on(event: EventName, handler: (payload: unknown) => void): void;
|
|
154
165
|
/**
|
|
155
|
-
*
|
|
166
|
+
* Unregister an event handler (still safe to call after destruction).
|
|
156
167
|
*
|
|
157
|
-
* @param event -
|
|
158
|
-
* @param handler -
|
|
168
|
+
* @param event - Event name.
|
|
169
|
+
* @param handler - The previously registered callback.
|
|
159
170
|
*/
|
|
160
171
|
off(event: EventName, handler: (payload: unknown) => void): void;
|
|
161
|
-
/**
|
|
172
|
+
/** Focus (input classes only, not provided by expressCheckout). */
|
|
162
173
|
focus?: () => Promise<void>;
|
|
163
|
-
/**
|
|
174
|
+
/** Blur (input classes only, not provided by expressCheckout). */
|
|
164
175
|
blur?: () => Promise<void>;
|
|
165
|
-
/**
|
|
176
|
+
/** Clear (input classes only, not provided by expressCheckout). */
|
|
166
177
|
clear?: () => Promise<void>;
|
|
167
|
-
/**
|
|
178
|
+
/** Install input-class action methods (automatically called after construction). */
|
|
168
179
|
private installInputActions;
|
|
169
180
|
/**
|
|
170
|
-
*
|
|
181
|
+
* expressCheckout only: persistently subscribe to expressAvailabilityChange and update the local availability snapshot.
|
|
171
182
|
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
183
|
+
* This event payload has no elementId; express is a singleton (guaranteed by CheckoutInstance),
|
|
184
|
+
* so there is no need to filter by elementId. Non-express types do not subscribe.
|
|
174
185
|
*/
|
|
175
186
|
private installExpressAvailability;
|
|
176
|
-
/**
|
|
187
|
+
/** Send one input-class action command (synchronously throws INSTANCE_DESTROYED after destruction). */
|
|
177
188
|
private sendAction;
|
|
178
|
-
/**
|
|
189
|
+
/** Throw INSTANCE_DESTROYED if already destroyed. */
|
|
179
190
|
private assertAlive;
|
|
180
|
-
/**
|
|
191
|
+
/** Resolve the mount container (the selector must uniquely match a single element). */
|
|
181
192
|
private resolveContainer;
|
|
182
193
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
* `&appearance=<encodeURIComponent(JSON.stringify(appearance))
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
194
|
+
* Resolve the iframe src: split fields go to /sdk/field/, the rest to /sdk/element/, with
|
|
195
|
+
* checkoutId and elementId; if an initial colorScheme is provided, append `&colorScheme=<value>`
|
|
196
|
+
* (no flash on the first frame); if the initial appearance contains variables or rules, append
|
|
197
|
+
* `&appearance=<encodeURIComponent(JSON.stringify(appearance))>` (takes effect on the first
|
|
198
|
+
* frame, no flash). An appearance containing only colorScheme (no variables/rules) is not
|
|
199
|
+
* appended, to avoid an empty appearance string. For expressCheckout, additionally append the
|
|
200
|
+
* wallet toggles / per-wallet buttonType / global buttonHeight (see {@link resolveExpressQuery}).
|
|
190
201
|
*
|
|
191
|
-
* elementId
|
|
192
|
-
*
|
|
202
|
+
* elementId is sent with the src so the hosted child echoes it verbatim in iframe-resize
|
|
203
|
+
* messages, letting the parent window dispatch the height per handle among multiple iframes on
|
|
204
|
+
* the same page.
|
|
193
205
|
*/
|
|
194
206
|
private resolveSrc;
|
|
195
207
|
/**
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
208
|
+
* Extract a per-element appearance (from the Element's own options, i.e. the second
|
|
209
|
+
* argument of create(type, options)). Returns undefined when absent. Used so per-element
|
|
210
|
+
* customization (e.g. CardFieldElementOptions.appearance) is honored on the first frame.
|
|
211
|
+
*/
|
|
212
|
+
private perElementAppearance;
|
|
213
|
+
/**
|
|
214
|
+
* Build the expressCheckout-specific query fragment (only called for expressCheckout):
|
|
215
|
+
* - a wallet explicitly set to `false` → `&applePay=false` / `&googlePay=false` (force hidden,
|
|
216
|
+
* preserving the existing toggle semantics; `true` / absent → automatic, no toggle appended);
|
|
217
|
+
* - a wallet configured in object form containing `buttonType` → `&applePayButtonType=<v>` /
|
|
218
|
+
* `&googlePayButtonType=<v>` (boolean toggle / absent → not appended);
|
|
219
|
+
* - global `buttonHeight` (a finite number) → `&buttonHeight=<n>`.
|
|
202
220
|
*
|
|
203
|
-
*
|
|
221
|
+
* Appended only when there is a value; empty strings are not appended. This fragment never
|
|
222
|
+
* touches card values and only carries display configuration.
|
|
204
223
|
*
|
|
205
|
-
* @returns
|
|
224
|
+
* @returns A query fragment starting with `&` (returns an empty string when nothing is appendable).
|
|
206
225
|
*/
|
|
207
226
|
private resolveExpressQuery;
|
|
208
227
|
/**
|
|
209
|
-
*
|
|
210
|
-
* `contentWindow`
|
|
211
|
-
*
|
|
228
|
+
* Install the iframe auto-height listener: subscribe to window 'message', only trust a valid
|
|
229
|
+
* {@link IframeResizeMessage} from this iframe's `contentWindow` with origin === hostOrigin, and
|
|
230
|
+
* when the elementId matches this handle, adjust the outer iframe's height to the content's real
|
|
231
|
+
* height (width stays 100%).
|
|
212
232
|
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
233
|
+
* Security: first verify `event.source === iframe.contentWindow` (the key source check), then
|
|
234
|
+
* verify `event.origin === hostOrigin` (a stricter same-origin check), to prevent cross-origin forgery.
|
|
235
|
+
* Height deduplication: skip if identical to the last one, to avoid redundant style writes.
|
|
216
236
|
*/
|
|
217
237
|
private installResizeListener;
|
|
218
|
-
/**
|
|
238
|
+
/** Unbind the iframe auto-height listener and reset the deduplication state (idempotent). */
|
|
219
239
|
private teardownResizeListener;
|
|
220
|
-
/**
|
|
240
|
+
/** Remove the iframe DOM node (if present) and unbind the auto-height listener. */
|
|
221
241
|
private removeIframe;
|
|
222
|
-
/**
|
|
242
|
+
/** Factory: equivalent to `new CheckoutElement(opts)` (a unified entry for CheckoutInstance). */
|
|
223
243
|
static create(opts: CheckoutElementOptions): CheckoutElement;
|
|
224
244
|
}
|
|
225
245
|
|
|
226
246
|
/**
|
|
227
|
-
* CheckoutInstance
|
|
247
|
+
* CheckoutInstance — the merchant-side checkout instance handle (spec 4 / 7 / 8).
|
|
228
248
|
*
|
|
229
|
-
*
|
|
230
|
-
* -
|
|
231
|
-
* runtimeId
|
|
232
|
-
* - `create`
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
249
|
+
* Responsibilities:
|
|
250
|
+
* - Constructed by `createCheckout` after a successful handshake + initialize (holds the ready
|
|
251
|
+
* transport, runtimeId, capabilities, and the initial PublicSessionView).
|
|
252
|
+
* - `create` assembles and returns a {@link CheckoutElement}, maintaining a **mutual-exclusion
|
|
253
|
+
* registry** (card and split fields are mutually exclusive, same-mode addresses are mutually
|
|
254
|
+
* exclusive, expressCheckout is a singleton → `ELEMENT_CONFLICT`).
|
|
255
|
+
* - `confirm` generates an operationId, sends the confirm command to obtain accepted, and the
|
|
256
|
+
* Promise is fulfilled by a later `paymentResult` event with the same operationId; calling
|
|
257
|
+
* confirm again while in progress → `CHECKOUT_BUSY`.
|
|
258
|
+
* - `getSession/refresh/getPaymentStatus/updateCheckout` pass through to the corresponding commands.
|
|
259
|
+
* - `destroy` is idempotent: releases Elements, unbinds listeners, rejects the pending confirm with
|
|
260
|
+
* INSTANCE_DESTROYED, sends the destroy command and destroys the transport; any late
|
|
261
|
+
* `paymentResult` afterwards is ignored.
|
|
239
262
|
*
|
|
240
|
-
*
|
|
263
|
+
* Security constraint (AGENTS/spec): this layer only ferries protocol commands/events and
|
|
264
|
+
* **never touches card values**.
|
|
241
265
|
*/
|
|
242
266
|
|
|
243
267
|
/**
|
|
244
|
-
*
|
|
268
|
+
* The minimal transport interface CheckoutInstance depends on (satisfied by MainFrameTransport).
|
|
245
269
|
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
270
|
+
* Adds `onHello/createHiddenIframe/destroy` beyond ElementTransport, used by createCheckout for
|
|
271
|
+
* handshake wiring and for instance destruction. Tests can inject a mock.
|
|
248
272
|
*/
|
|
249
273
|
interface InstanceTransport {
|
|
250
274
|
request(name: CommandName, payload: unknown): Promise<unknown>;
|
|
@@ -255,211 +279,219 @@ interface InstanceTransport {
|
|
|
255
279
|
createHiddenIframe(): unknown;
|
|
256
280
|
destroy(): void;
|
|
257
281
|
}
|
|
258
|
-
/** CheckoutInstance
|
|
282
|
+
/** CheckoutInstance constructor parameters (assembled by createCheckout). */
|
|
259
283
|
interface CheckoutInstanceOptions {
|
|
260
|
-
/**
|
|
284
|
+
/** Unique checkout id. */
|
|
261
285
|
checkoutId: string;
|
|
262
|
-
/**
|
|
286
|
+
/** Negotiated runtime id (from RuntimeHello). */
|
|
263
287
|
runtimeId: string;
|
|
264
|
-
/**
|
|
288
|
+
/** Hosted page origin (without a trailing slash). */
|
|
265
289
|
hostOrigin: string;
|
|
266
|
-
/**
|
|
290
|
+
/** The ready transport. */
|
|
267
291
|
transport: InstanceTransport;
|
|
268
|
-
/**
|
|
292
|
+
/** The capabilities returned by initialize. */
|
|
269
293
|
capabilities: string[];
|
|
270
|
-
/** initialize
|
|
294
|
+
/** The initial session view returned by initialize. */
|
|
271
295
|
session: PublicSessionView;
|
|
272
296
|
/**
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
* -
|
|
277
|
-
*
|
|
297
|
+
* Initial appearance customization (from createCheckout's appearance).
|
|
298
|
+
* Passed through to every created Element and serialized into its iframe src (no flash on the
|
|
299
|
+
* first frame):
|
|
300
|
+
* - colorScheme appended as `&colorScheme=`;
|
|
301
|
+
* - variables/rules appended as `&appearance=` (only when non-empty).
|
|
302
|
+
* Not appended when absent. Runtime switching goes through the updateCheckout command.
|
|
278
303
|
*/
|
|
279
304
|
appearance?: Appearance;
|
|
280
305
|
}
|
|
281
|
-
/** confirm
|
|
306
|
+
/** Optional confirm parameters (aligned with ConfirmReq, minus the instance-generated operationId). */
|
|
282
307
|
type ConfirmOptions = Omit<ConfirmReq, 'operationId'>;
|
|
283
308
|
declare class CheckoutInstance {
|
|
284
|
-
/**
|
|
309
|
+
/** Unique checkout id. */
|
|
285
310
|
readonly checkoutId: string;
|
|
286
|
-
/**
|
|
311
|
+
/** Negotiated runtime id. */
|
|
287
312
|
readonly runtimeId: string;
|
|
288
|
-
/**
|
|
313
|
+
/** Negotiated capability set. */
|
|
289
314
|
readonly capabilities: readonly string[];
|
|
290
315
|
private readonly hostOrigin;
|
|
291
316
|
private readonly transport;
|
|
292
317
|
private session;
|
|
293
|
-
/**
|
|
318
|
+
/** Initial appearance customization (passed through to each created Element's iframe src). */
|
|
294
319
|
private readonly appearance;
|
|
295
|
-
/**
|
|
320
|
+
/** Created Elements (indexed by elementId). */
|
|
296
321
|
/**
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
* {@link
|
|
322
|
+
* The **single source of truth** for the mutual-exclusion registry: elementId → the created
|
|
323
|
+
* CheckoutElement. Mutual-exclusion decisions are derived live from this Map (see
|
|
324
|
+
* {@link assertNoConflict}); an element's `destroy()` removes itself from this Map via
|
|
325
|
+
* {@link releaseElement} to free the slot (allowing a mutually-exclusive Element of the same
|
|
326
|
+
* kind to be recreated after destruction).
|
|
300
327
|
*/
|
|
301
328
|
private readonly elements;
|
|
302
|
-
/**
|
|
329
|
+
/** The current pending confirm (at most one at a time). */
|
|
303
330
|
private pendingConfirm;
|
|
304
|
-
/** paymentResult
|
|
331
|
+
/** The paymentResult event subscription handler (unbound on destroy). */
|
|
305
332
|
private readonly paymentResultHandler;
|
|
306
333
|
private destroyed;
|
|
307
334
|
constructor(opts: CheckoutInstanceOptions);
|
|
308
335
|
/**
|
|
309
|
-
*
|
|
336
|
+
* Create an Element handle (not auto-mounted; a mutual-exclusion conflict throws ELEMENT_CONFLICT).
|
|
310
337
|
*
|
|
311
|
-
*
|
|
312
|
-
* -
|
|
313
|
-
* -
|
|
314
|
-
* - `expressCheckout`
|
|
338
|
+
* Mutual-exclusion rules (spec 6):
|
|
339
|
+
* - The combined `card` and any split field (cardNumber/cardExpiry/cardCvc) are mutually exclusive.
|
|
340
|
+
* - An address with the same `mode` (billing/shipping) cannot be duplicated.
|
|
341
|
+
* - `expressCheckout` is a singleton.
|
|
315
342
|
*
|
|
316
|
-
* @param type - Element
|
|
317
|
-
* @param options -
|
|
318
|
-
* @returns
|
|
319
|
-
* @throws
|
|
343
|
+
* @param type - Element type.
|
|
344
|
+
* @param options - Initial Element configuration.
|
|
345
|
+
* @returns The newly created CheckoutElement.
|
|
346
|
+
* @throws INSTANCE_DESTROYED when already destroyed; ELEMENT_CONFLICT on a mutual-exclusion conflict.
|
|
320
347
|
*/
|
|
321
348
|
create(type: ElementType, options?: ElementOptions): CheckoutElement;
|
|
322
349
|
/**
|
|
323
|
-
*
|
|
324
|
-
*
|
|
350
|
+
* Initiate a payment confirmation. Generates an operationId, sends the confirm command to obtain
|
|
351
|
+
* accepted, and the returned Promise is fulfilled by a later paymentResult event with the same
|
|
352
|
+
* operationId. Calling again while in progress → CHECKOUT_BUSY.
|
|
325
353
|
*
|
|
326
|
-
* @param opts -
|
|
327
|
-
* @returns
|
|
328
|
-
* @throws
|
|
354
|
+
* @param opts - Optional parameters such as billing/shipping address, name, email, returnUrl.
|
|
355
|
+
* @returns The terminal PaymentOutcome.
|
|
356
|
+
* @throws rejects INSTANCE_DESTROYED when destroyed; rejects CHECKOUT_BUSY when in progress.
|
|
329
357
|
*/
|
|
330
358
|
confirm(opts?: ConfirmOptions): Promise<PaymentOutcome>;
|
|
331
359
|
/**
|
|
332
|
-
*
|
|
360
|
+
* Get the latest session view (passes through the getSession command and writes back the local snapshot).
|
|
333
361
|
*
|
|
334
|
-
* @returns
|
|
335
|
-
* @throws
|
|
362
|
+
* @returns The latest PublicSessionView.
|
|
363
|
+
* @throws rejects INSTANCE_DESTROYED when destroyed.
|
|
336
364
|
*/
|
|
337
365
|
getSession(): Promise<PublicSessionView>;
|
|
338
366
|
/**
|
|
339
|
-
*
|
|
367
|
+
* Refresh the session (passes through the refresh command and writes back the local snapshot).
|
|
340
368
|
*
|
|
341
|
-
* @returns
|
|
342
|
-
* @throws
|
|
369
|
+
* @returns The refreshed PublicSessionView.
|
|
370
|
+
* @throws rejects INSTANCE_DESTROYED when destroyed.
|
|
343
371
|
*/
|
|
344
372
|
refresh(): Promise<PublicSessionView>;
|
|
345
373
|
/**
|
|
346
|
-
*
|
|
374
|
+
* Query the payment status (returns TxnStatus as-is, no transformation).
|
|
347
375
|
*
|
|
348
|
-
* @returns txnStatus
|
|
349
|
-
* @throws
|
|
376
|
+
* @returns txnStatus (may include txnId).
|
|
377
|
+
* @throws rejects INSTANCE_DESTROYED when destroyed.
|
|
350
378
|
*/
|
|
351
379
|
getPaymentStatus(): Promise<GetPaymentStatusResp>;
|
|
352
380
|
/**
|
|
353
|
-
*
|
|
381
|
+
* Update the checkout appearance/locale (does not change the session or the amount).
|
|
354
382
|
*
|
|
355
|
-
* @param patch - locale / appearance
|
|
356
|
-
* @throws
|
|
383
|
+
* @param patch - locale / appearance delta.
|
|
384
|
+
* @throws rejects INSTANCE_DESTROYED when destroyed.
|
|
357
385
|
*/
|
|
358
386
|
updateCheckout(patch: {
|
|
359
387
|
locale?: string;
|
|
360
388
|
appearance?: Appearance;
|
|
361
389
|
}): Promise<void>;
|
|
362
390
|
/**
|
|
363
|
-
*
|
|
391
|
+
* Register a Checkout-level event handler (passes through the transport).
|
|
364
392
|
*
|
|
365
|
-
* @param event -
|
|
366
|
-
* @param handler -
|
|
367
|
-
* @throws
|
|
393
|
+
* @param event - Event name.
|
|
394
|
+
* @param handler - Callback.
|
|
395
|
+
* @throws INSTANCE_DESTROYED when destroyed.
|
|
368
396
|
*/
|
|
369
397
|
on(event: EventName, handler: (payload: unknown) => void): void;
|
|
370
398
|
/**
|
|
371
|
-
*
|
|
399
|
+
* Unregister an event handler (safe to call after destruction).
|
|
372
400
|
*
|
|
373
|
-
* @param event -
|
|
374
|
-
* @param handler -
|
|
401
|
+
* @param event - Event name.
|
|
402
|
+
* @param handler - The previously registered callback.
|
|
375
403
|
*/
|
|
376
404
|
off(event: EventName, handler: (payload: unknown) => void): void;
|
|
377
405
|
/**
|
|
378
|
-
*
|
|
379
|
-
*
|
|
380
|
-
*
|
|
406
|
+
* Destroy the instance: idempotent. Releases all Elements, unbinds the paymentResult listener,
|
|
407
|
+
* rejects the pending confirm with INSTANCE_DESTROYED, sends the destroy command and destroys
|
|
408
|
+
* the transport. Any late paymentResult afterwards is ignored and does not overwrite an already
|
|
409
|
+
* settled Promise.
|
|
381
410
|
*/
|
|
382
411
|
destroy(): void;
|
|
383
|
-
/**
|
|
412
|
+
/** Throw INSTANCE_DESTROYED if already destroyed. */
|
|
384
413
|
private assertAlive;
|
|
385
|
-
/**
|
|
414
|
+
/** Mutual-exclusion check: throws ELEMENT_CONFLICT on conflict (derived live from the elements Map, does not mutate the registry). */
|
|
386
415
|
private assertNoConflict;
|
|
387
416
|
/**
|
|
388
|
-
*
|
|
389
|
-
*
|
|
390
|
-
*
|
|
417
|
+
* Element `destroy()` callback: remove this elementId from the mutual-exclusion registry (the
|
|
418
|
+
* elements Map) to free the slot. Idempotent; when the whole instance is destroyed (destroyed
|
|
419
|
+
* already set) it goes through the unified `elements.clear()` path, so this is a no-op here,
|
|
420
|
+
* avoiding concurrent modification while iterating elements to call element.destroy().
|
|
391
421
|
*/
|
|
392
422
|
private releaseElement;
|
|
393
|
-
/**
|
|
423
|
+
/** Handle the paymentResult event: fulfill the pending confirm by operationId; late/mismatched ones are ignored. */
|
|
394
424
|
private handlePaymentResult;
|
|
395
425
|
}
|
|
396
426
|
|
|
397
427
|
/**
|
|
398
|
-
*
|
|
399
|
-
* - `dev
|
|
400
|
-
* - `
|
|
428
|
+
* Runtime environment identifier.
|
|
429
|
+
* - `dev`: development hosted page.
|
|
430
|
+
* - `test`: UAT/test hosted page.
|
|
431
|
+
* - `prod`: production hosted page.
|
|
401
432
|
*/
|
|
402
|
-
type Env = 'dev' | 'prod';
|
|
433
|
+
type Env = 'dev' | 'test' | 'prod';
|
|
403
434
|
|
|
404
435
|
/**
|
|
405
|
-
* createCheckout
|
|
436
|
+
* createCheckout — the merchant SDK's single async entry (spec 4).
|
|
406
437
|
*
|
|
407
|
-
*
|
|
408
|
-
* 1.
|
|
409
|
-
* 2.
|
|
410
|
-
* 3.
|
|
411
|
-
* 4.
|
|
412
|
-
* 5.
|
|
413
|
-
* capabilities + PublicSessionView
|
|
414
|
-
* 6.
|
|
438
|
+
* Flow:
|
|
439
|
+
* 1. Generate `checkoutId`, derive the hosted origin via `resolveHostOrigin(env, hostOrigin)`.
|
|
440
|
+
* 2. Build the transport, `createHiddenIframe()` to load the hosted main iframe.
|
|
441
|
+
* 3. Register onHello; wait for RuntimeHello (timeout 15s → reject RUNTIME_LOAD_FAILED).
|
|
442
|
+
* 4. Pick a common major version (no intersection → reject PROTOCOL_UNSUPPORTED).
|
|
443
|
+
* 5. Send `initialize` (sessionId/locale/appearance/paymentMethods) to obtain
|
|
444
|
+
* capabilities + PublicSessionView; any step failing rejects and destroys the transport.
|
|
445
|
+
* 6. Inject the handshake runtimeId into the transport, construct and resolve {@link CheckoutInstance}.
|
|
415
446
|
*
|
|
416
|
-
*
|
|
447
|
+
* Security constraint (AGENTS/spec): this layer only orchestrates handshake/initialization and
|
|
448
|
+
* **never touches card values**.
|
|
417
449
|
*/
|
|
418
450
|
|
|
419
451
|
/**
|
|
420
|
-
*
|
|
452
|
+
* Internal transport factory injectable when creating a CheckoutInstance (test/advanced use only).
|
|
421
453
|
*
|
|
422
|
-
*
|
|
454
|
+
* Real scenarios use the built-in MainFrameTransport; tests may inject a mock to drive hello/events.
|
|
423
455
|
*/
|
|
424
456
|
type TransportFactory = (args: {
|
|
425
457
|
checkoutId: string;
|
|
426
458
|
hostOrigin: string;
|
|
427
459
|
}) => InstanceTransport;
|
|
428
|
-
/** createCheckout
|
|
460
|
+
/** createCheckout parameters. */
|
|
429
461
|
interface CreateCheckoutOptions {
|
|
430
|
-
/**
|
|
462
|
+
/** Checkout session id created by the backend (required). */
|
|
431
463
|
sessionId: string;
|
|
432
|
-
/**
|
|
464
|
+
/** Runtime environment (dev/test/prod), defaults to prod. */
|
|
433
465
|
env?: Env;
|
|
434
|
-
/**
|
|
466
|
+
/** Override the hosted origin (takes precedence over env). */
|
|
435
467
|
hostOrigin?: string;
|
|
436
|
-
/**
|
|
468
|
+
/** Locale. */
|
|
437
469
|
locale?: string;
|
|
438
|
-
/**
|
|
470
|
+
/** Appearance customization. */
|
|
439
471
|
appearance?: Appearance;
|
|
440
|
-
/**
|
|
472
|
+
/** Payment method filter (subtractive/reordering only). */
|
|
441
473
|
paymentMethods?: PaymentMethodFilter;
|
|
442
|
-
/**
|
|
474
|
+
/** Internal injection point: custom transport factory (test use; not part of the public API contract). */
|
|
443
475
|
__transportFactory?: TransportFactory;
|
|
444
476
|
}
|
|
445
477
|
/**
|
|
446
|
-
*
|
|
478
|
+
* Create a checkout instance: resolves after a successful handshake + initialization.
|
|
447
479
|
*
|
|
448
|
-
* @param opts -
|
|
449
|
-
* @returns
|
|
450
|
-
* @throws reject RUNTIME_LOAD_FAILED
|
|
451
|
-
* /
|
|
480
|
+
* @param opts - Checkout parameters.
|
|
481
|
+
* @returns A ready CheckoutInstance.
|
|
482
|
+
* @throws reject RUNTIME_LOAD_FAILED (handshake timeout) / PROTOCOL_UNSUPPORTED (no common major
|
|
483
|
+
* version) / or the initialize business error.
|
|
452
484
|
* @example
|
|
453
485
|
* const checkout = await createCheckout({ sessionId: 'sess_x', env: 'prod' });
|
|
454
486
|
*/
|
|
455
487
|
declare function createCheckout(opts: CreateCheckoutOptions): Promise<CheckoutInstance>;
|
|
456
488
|
|
|
457
489
|
/**
|
|
458
|
-
* @sunbay/checkout-js
|
|
490
|
+
* @sunbay/checkout-js public entry (source of truth).
|
|
459
491
|
*
|
|
460
|
-
*
|
|
461
|
-
*
|
|
462
|
-
* IIFE
|
|
492
|
+
* Exports the `createCheckout` entry, the `CheckoutInstance` / `CheckoutElement` handle types,
|
|
493
|
+
* and the public protocol types (for TS consumers).
|
|
494
|
+
* In the IIFE build, additionally exposes `{ createCheckout }` on `window.SunbayCheckout`.
|
|
463
495
|
*/
|
|
464
496
|
|
|
465
497
|
declare const version: string;
|