@zippypay/checkout 1.0.0 → 1.1.10

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/dist/index.d.cts CHANGED
@@ -9,12 +9,39 @@ declare function parseZippyEnvironment(value: string): ZippyEnvironment;
9
9
  type PaymentSessionStatus = 'CREATED' | 'AWAITING_PAYMENT' | 'COMPLETED' | 'EXPIRED' | 'CANCELLED' | 'FAILED';
10
10
  type PaymentSessionPhase = 'IDLE' | 'PAYING';
11
11
  /** Server checkout method — locks after checkout start. */
12
- type ApiCheckoutMethod = 'QR' | 'MANUAL';
12
+ type ApiCheckoutMethod = 'QR' | 'MANUAL' | 'MOBILE_APP';
13
+ /** SDK init — omit to allow both QR and Manual. */
14
+ type CheckoutPolicy = 'QR' | 'MANUAL';
15
+ /** SDK init — phone-only app handoff preference. */
16
+ type MobileAppPolicy = 'off' | 'option' | 'enforce';
17
+ /** Explicit checkout restriction returned by the API. */
18
+ type ApiCheckoutPolicy = 'QR' | 'MANUAL';
19
+ /** Bound checkout policy — `null` means full chooser (QR + manual). */
20
+ type BoundCheckoutPolicy = ApiCheckoutPolicy | null;
21
+ /** Bound mobile app policy returned by the API. */
22
+ type ApiMobileAppPolicy = 'OFF' | 'OPTION' | 'ENFORCE';
23
+ type BindCheckoutPolicyRequest = {
24
+ checkoutPolicy?: ApiCheckoutPolicy;
25
+ mobileAppPolicy?: ApiMobileAppPolicy;
26
+ };
27
+ type CheckoutSurface = 'phone' | 'desktop';
28
+ type StartCheckoutRequest = {
29
+ method: ApiCheckoutMethod;
30
+ surface: CheckoutSurface;
31
+ };
32
+ type ZippyMobileAppConfig = {
33
+ policy?: MobileAppPolicy;
34
+ };
13
35
  type PaymentSessionPayer = {
14
36
  paymentId: string;
15
37
  displayName: string;
16
38
  profileImage: string | null;
17
39
  };
40
+ /** Payer preview returned from verify — same fields as session payer. */
41
+ type PayerPreview = PaymentSessionPayer;
42
+ type VerifyPayerResponse = {
43
+ items: PayerPreview[];
44
+ };
18
45
  type PaymentSession = {
19
46
  sessionId: string;
20
47
  amount: string;
@@ -32,12 +59,15 @@ type PaymentSession = {
32
59
  absoluteExpiresAt: string;
33
60
  phase: PaymentSessionPhase;
34
61
  checkoutMethod: ApiCheckoutMethod | null;
62
+ /** Set after bind-policy — `null` = full chooser when `mobileAppPolicy` is set. */
63
+ checkoutPolicy: BoundCheckoutPolicy;
64
+ /** Set after bind-policy succeeds; null until then. */
65
+ mobileAppPolicy: ApiMobileAppPolicy | null;
35
66
  paymentStartAt: string | null;
36
67
  /** Pay window countdown — only meaningful when phase is PAYING. */
37
68
  paymentExpiryAt: string | null;
38
69
  createdAt: string;
39
70
  };
40
- type VerifyPayerResponse = PaymentSessionPayer;
41
71
  type ProblemJson = {
42
72
  type?: string;
43
73
  title?: string;
@@ -71,6 +101,10 @@ type ZippyPayConfig = {
71
101
  mode?: EmbedMode;
72
102
  container?: HTMLElement | string;
73
103
  theme?: ZippyTheme;
104
+ /** When omitted, customer can choose QR or Manual. */
105
+ checkoutPolicy?: CheckoutPolicy;
106
+ /** Phone-only app handoff. Ignored on non-phone devices. */
107
+ mobileApp?: ZippyMobileAppConfig;
74
108
  locale?: 'en';
75
109
  redirectOnComplete?: boolean;
76
110
  redirectOnFailure?: boolean;
@@ -83,8 +117,8 @@ type ZippyPayConfig = {
83
117
  onError?: (error: ZippyPayError) => void;
84
118
  onClose?: () => void;
85
119
  };
86
- type CheckoutMethod = 'qr' | 'manual';
87
- type CheckoutPhase = 'loading' | 'choose-method' | 'qr-active' | 'manual-entry' | 'manual-confirm' | 'awaiting' | 'success' | 'expired' | 'cancelled' | 'declined' | 'failed' | 'error' | 'invalid-session';
120
+ type CheckoutMethod = 'qr' | 'manual' | 'mobileApp';
121
+ type CheckoutPhase = 'loading' | 'choose-method' | 'qr-active' | 'mobile-app-active' | 'manual-entry' | 'manual-picker' | 'manual-confirm' | 'awaiting' | 'success' | 'expired' | 'cancelled' | 'declined' | 'failed' | 'error' | 'invalid-session';
88
122
  declare const TERMINAL_STATUSES: readonly PaymentSessionStatus[];
89
123
  declare const POLLABLE_STATUSES: readonly PaymentSessionStatus[];
90
124
  declare class ZippyPayError extends Error {
@@ -111,11 +145,13 @@ declare class PaymentSessionClient {
111
145
  private readonly clientToken;
112
146
  constructor(config: ApiClientConfig);
113
147
  getSession(): Promise<PaymentSession>;
114
- verifyPayer(paymentId: string): Promise<VerifyPayerResponse>;
148
+ bindCheckoutPolicy(body: BindCheckoutPolicyRequest): Promise<PaymentSession>;
149
+ verifyPayer(query: string): Promise<VerifyPayerResponse>;
115
150
  attachPayer(paymentId: string): Promise<PaymentSession>;
116
- startCheckout(method: ApiCheckoutMethod): Promise<PaymentSession>;
117
- startQrCheckout(): Promise<PaymentSession>;
118
- startManualCheckout(): Promise<PaymentSession>;
151
+ startCheckout(method: StartCheckoutRequest['method'], surface: CheckoutSurface): Promise<PaymentSession>;
152
+ startQrCheckout(surface: CheckoutSurface): Promise<PaymentSession>;
153
+ startMobileAppCheckout(surface: CheckoutSurface): Promise<PaymentSession>;
154
+ startManualCheckout(surface: CheckoutSurface): Promise<PaymentSession>;
119
155
  private sessionPath;
120
156
  private headers;
121
157
  private request;
@@ -166,6 +202,8 @@ declare class CheckoutController implements ZippyPayCheckoutInstance {
166
202
  private session;
167
203
  private paymentId;
168
204
  private verifiedPayer;
205
+ private verifyMatches;
206
+ private lastVerifiedQuery;
169
207
  private committedMethod;
170
208
  private phase;
171
209
  private errorMessage;
@@ -174,6 +212,14 @@ declare class CheckoutController implements ZippyPayCheckoutInstance {
174
212
  private modalOpen;
175
213
  private exitMode;
176
214
  private terminalFailureReason;
215
+ private uiOptions;
216
+ private appHandoffStatus;
217
+ private clearAppHandoffWatch;
218
+ private methodSwitchInProgress;
219
+ private entryRoutingDone;
220
+ private payWindowExpiryTimer;
221
+ private unsubscribeSurface;
222
+ private static readonly PAY_WINDOW_PHASES;
177
223
  constructor(config: ZippyPayConfig);
178
224
  open(): void;
179
225
  close(): void;
@@ -181,7 +227,13 @@ declare class CheckoutController implements ZippyPayCheckoutInstance {
181
227
  private snapshotUiState;
182
228
  private syncUi;
183
229
  private bootstrap;
230
+ private bindPolicy;
231
+ private applyBoundUiOptions;
232
+ private handleSurfaceChange;
184
233
  private applySession;
234
+ private schedulePayWindowExpiryWatch;
235
+ private clearPayWindowExpiryWatch;
236
+ private handlePayWindowExpired;
185
237
  private resolveActivePhase;
186
238
  private handleSessionUpdate;
187
239
  private handleFailure;
@@ -191,8 +243,21 @@ declare class CheckoutController implements ZippyPayCheckoutInstance {
191
243
  private failurePhaseFromReason;
192
244
  private teardownView;
193
245
  private handleBootstrapError;
246
+ private handlePollError;
194
247
  private handleError;
248
+ private routeIdleEntry;
249
+ private openMobileApp;
250
+ private beginMobileAppHandoff;
251
+ private installZippy;
252
+ private startMobileAppFlow;
253
+ private canStartAppClaim;
195
254
  private chooseMethod;
255
+ private chooseFallbackMethod;
256
+ private backToChooseMethod;
257
+ private backToManualEntry;
258
+ private backToMobileAppFallback;
259
+ private isMobileAppManualFallbackActive;
260
+ private selectPayer;
196
261
  private verify;
197
262
  private attach;
198
263
  private handleFlowError;
@@ -227,11 +292,74 @@ declare global {
227
292
 
228
293
  /** Personal Zippy handles: 3–20 chars, optional single dot, no leading/trailing dot. */
229
294
  declare const PAYMENT_ID_PATTERN: RegExp;
295
+ declare const E164_PHONE_PATTERN: RegExp;
296
+ declare const EMAIL_PATTERN: RegExp;
230
297
  declare function normalizePaymentId(value: string): string;
298
+ /** Normalize a payer verify query before sending to the API. */
299
+ declare function normalizePayerQuery(value: string): string;
231
300
  declare function isValidPaymentId(value: string): boolean;
301
+ /** Client-side pre-validation for payer verify `query` (server is authoritative). */
302
+ declare function isValidPayerQuery(value: string): boolean;
232
303
  declare function paymentIdValidationMessage(): string;
304
+ declare function payerQueryValidationMessage(): string;
233
305
  declare function formatAmount(amount: string, currency: string): string;
234
306
 
307
+ type MobileStorePlatform = 'ios' | 'android';
308
+ /** True when checkout runs on a phone-sized touch device. */
309
+ declare function isPhoneDevice(): boolean;
310
+ /** True when the browser reports an Android user agent. */
311
+ declare function isAndroidDevice(): boolean;
312
+ declare function detectCheckoutSurface(): CheckoutSurface;
313
+ declare function subscribeCheckoutSurface(onChange: (surface: CheckoutSurface) => void): () => void;
314
+
315
+ /** Fixed App Store / Google Play URLs for Zippy Pay (managed server-side; not merchant-configurable). */
316
+ type AppStoreLinks = {
317
+ ios: string;
318
+ android: string;
319
+ };
320
+ declare const ANDROID_APP_PACKAGE = "com.zippy.pay";
321
+ /** HTTPS store URLs — used for QR codes and desktop fallback links. */
322
+ declare const APP_STORE_LINKS: AppStoreLinks;
323
+ /** Opens the native App Store app on iOS (no specific listing until app id is available). */
324
+ declare const IOS_APP_STORE_NATIVE_URL = "itms-apps://apps.apple.com/";
325
+ /** Opens the native Play Store app on Android. */
326
+ declare const ANDROID_PLAY_STORE_NATIVE_URL = "market://details?id=com.zippy.pay";
327
+ declare function resolveAppStoreUrl(platform: MobileStorePlatform): string;
328
+ /**
329
+ * URL used when the customer taps Install Zippy.
330
+ * iOS and Android both use native store schemes from a user gesture.
331
+ */
332
+ declare function resolveAppStoreOpenUrl(platform: MobileStorePlatform): string;
333
+
334
+ type EntryRoutingAction = 'chooser' | 'auto-qr' | 'auto-manual' | 'enforce-mobile-app';
335
+ type MethodAvailability = {
336
+ qr: boolean;
337
+ manual: boolean;
338
+ mobileApp: boolean;
339
+ };
340
+ type ResolvedCheckoutUiOptions = {
341
+ checkoutPolicy: BoundCheckoutPolicy;
342
+ mobileAppPolicy: ApiMobileAppPolicy;
343
+ surface: CheckoutSurface;
344
+ methodAvailability: MethodAvailability;
345
+ allowManualBack: boolean;
346
+ };
347
+ type AppClaimCheckoutMethod = Extract<ApiCheckoutMethod, 'QR' | 'MOBILE_APP'>;
348
+ declare function isCheckoutPolicyBound(session: PaymentSession): boolean;
349
+ declare function isFullChooserPolicy(checkoutPolicy: BoundCheckoutPolicy): boolean;
350
+ declare function resolveMobileAppPolicy(mobileApp?: ZippyMobileAppConfig): ApiMobileAppPolicy;
351
+ declare function buildBindPolicyRequest(config: {
352
+ checkoutPolicy?: CheckoutPolicy;
353
+ mobileApp?: ZippyMobileAppConfig;
354
+ }): BindCheckoutPolicyRequest;
355
+ declare function resolveMethodAvailability(checkoutPolicy: BoundCheckoutPolicy, mobileAppPolicy: ApiMobileAppPolicy, surface: CheckoutSurface): MethodAvailability;
356
+ declare function resolveEntryRouting(checkoutPolicy: BoundCheckoutPolicy, mobileAppPolicy: ApiMobileAppPolicy, surface: CheckoutSurface): EntryRoutingAction;
357
+ declare function isCheckoutStartAllowed(checkoutPolicy: BoundCheckoutPolicy, mobileAppPolicy: ApiMobileAppPolicy, surface: CheckoutSurface, method: AppClaimCheckoutMethod): boolean;
358
+ declare function resolveAutoStartMethod(checkoutPolicy: BoundCheckoutPolicy, mobileAppPolicy: ApiMobileAppPolicy, surface: CheckoutSurface): AppClaimCheckoutMethod | null;
359
+ declare function resolveCheckoutUiOptionsFromBound(checkoutPolicy: BoundCheckoutPolicy, mobileAppPolicy: ApiMobileAppPolicy, surface?: CheckoutSurface): ResolvedCheckoutUiOptions;
360
+ declare function resolveCheckoutUiOptionsFromSession(session: PaymentSession, surface?: CheckoutSurface): ResolvedCheckoutUiOptions;
361
+ declare function resolveCheckoutUiOptions(checkoutPolicy?: CheckoutPolicy, mobileApp?: ZippyMobileAppConfig, surface?: CheckoutSurface): ResolvedCheckoutUiOptions;
362
+
235
363
  /** Deep link scanned by the Zippy app — sessionId only, never clientToken. */
236
364
  declare function buildPaymentQrPayload(sessionId: string): string;
237
365
  type QrErrorCorrection = 'L' | 'M' | 'Q' | 'H';
@@ -242,6 +370,20 @@ declare function renderPaymentQrSvg(sessionId: string, cellSize?: number, errorC
242
370
  declare function renderBrandedPaymentQrSvg(sessionId: string, cellSize?: number): string;
243
371
  /** QR markup wrapper for the checkout UI. */
244
372
  declare function renderPaymentQrMarkup(sessionId: string, cellSize?: number): string;
373
+ /** Plain QR markup for arbitrary URLs (e.g. app store links). */
374
+ declare function renderUrlQrMarkup(url: string, cellSize?: number): string;
375
+
376
+ /** Android intent URL — more reliable than raw `zippy://` in Chrome. */
377
+ declare function buildAndroidPaymentIntentUrl(sessionId: string): string;
378
+ /** Platform-aware deep link used when the customer taps Pay with Zippy / Try again. */
379
+ declare function buildPaymentDeepLinkOpenUrl(sessionId: string, platform?: MobileStorePlatform): string;
380
+ /** Sends the current tab to the App Store or Google Play for this device. */
381
+ declare function openAppStore(platform?: MobileStorePlatform): void;
382
+ /**
383
+ * Opens the Zippy app from a user gesture (Pay with Zippy / Try again).
384
+ * Keeps the checkout page visible so failed-handoff UI can appear afterward.
385
+ */
386
+ declare function openPaymentDeepLink(sessionId: string): void;
245
387
 
246
388
  /** Aligned with zippy-kyc-web-sdk `src/styles/tokens.css` */
247
389
  declare const DEFAULT_THEME: Required<Omit<ZippyTheme, 'mode'>> & {
@@ -262,4 +404,4 @@ declare const ZippyPay: {
262
404
  create(config: ZippyPayConfig): ZippyPayCheckoutInstance;
263
405
  };
264
406
 
265
- export { type ApiCheckoutMethod, CheckoutController, type CheckoutMethod, type CheckoutPhase, DEFAULT_THEME, ELEMENT_TAG, type EmbedMode, PAYMENT_ID_PATTERN, POLLABLE_STATUSES, type PaymentSession, PaymentSessionClient, type PaymentSessionPayer, type PaymentSessionPhase, type PaymentSessionStatus, type ProblemJson, SessionPoller, TERMINAL_STATUSES, type VerifyPayerResponse, ZIPPY_API_BASE_URLS, ZIPPY_API_PATH_PREFIX, type ZippyEnvironment, ZippyPay, ZippyPayCheckoutElement, type ZippyPayCheckoutInstance, type ZippyPayConfig, ZippyPayError, type ZippyTheme, applyThemeToHost, attachPayerWithRetry, buildPaymentQrPayload, createCheckout, ZippyPay as default, defineZippyPayCheckoutElement, formatAmount, getCountdownTarget, getPayWindowRemainingRatio, getSoftIdleHint, isTerminalStatus, isValidPaymentId, isZippyEnvironment, msUntil, normalizePaymentId, parseZippyEnvironment, paymentIdValidationMessage, phaseFromSession, renderBrandedPaymentQrSvg, renderPaymentQrMarkup, renderPaymentQrSvg, renderQrSvg, resolveApiBaseUrl, resolveTheme, shouldShowPayProgress };
407
+ export { ANDROID_APP_PACKAGE, ANDROID_PLAY_STORE_NATIVE_URL, APP_STORE_LINKS, type ApiCheckoutMethod, type ApiCheckoutPolicy, type ApiMobileAppPolicy, type AppStoreLinks, type BindCheckoutPolicyRequest, type BoundCheckoutPolicy, CheckoutController, type CheckoutMethod, type CheckoutPhase, type CheckoutPolicy, type CheckoutSurface, DEFAULT_THEME, E164_PHONE_PATTERN, ELEMENT_TAG, EMAIL_PATTERN, type EmbedMode, IOS_APP_STORE_NATIVE_URL, type MobileAppPolicy, PAYMENT_ID_PATTERN, POLLABLE_STATUSES, type PayerPreview, type PaymentSession, PaymentSessionClient, type PaymentSessionPayer, type PaymentSessionPhase, type PaymentSessionStatus, type ProblemJson, SessionPoller, type StartCheckoutRequest, TERMINAL_STATUSES, type VerifyPayerResponse, ZIPPY_API_BASE_URLS, ZIPPY_API_PATH_PREFIX, type ZippyEnvironment, type ZippyMobileAppConfig, ZippyPay, ZippyPayCheckoutElement, type ZippyPayCheckoutInstance, type ZippyPayConfig, ZippyPayError, type ZippyTheme, applyThemeToHost, attachPayerWithRetry, buildAndroidPaymentIntentUrl, buildBindPolicyRequest, buildPaymentDeepLinkOpenUrl, buildPaymentQrPayload, createCheckout, ZippyPay as default, defineZippyPayCheckoutElement, detectCheckoutSurface, formatAmount, getCountdownTarget, getPayWindowRemainingRatio, getSoftIdleHint, isAndroidDevice, isCheckoutPolicyBound, isCheckoutStartAllowed, isFullChooserPolicy, isPhoneDevice, isTerminalStatus, isValidPayerQuery, isValidPaymentId, isZippyEnvironment, msUntil, normalizePayerQuery, normalizePaymentId, openAppStore, openPaymentDeepLink, parseZippyEnvironment, payerQueryValidationMessage, paymentIdValidationMessage, phaseFromSession, renderBrandedPaymentQrSvg, renderPaymentQrMarkup, renderPaymentQrSvg, renderQrSvg, renderUrlQrMarkup, resolveApiBaseUrl, resolveAppStoreOpenUrl, resolveAppStoreUrl, resolveAutoStartMethod, resolveCheckoutUiOptions, resolveCheckoutUiOptionsFromBound, resolveCheckoutUiOptionsFromSession, resolveEntryRouting, resolveMethodAvailability, resolveMobileAppPolicy, resolveTheme, shouldShowPayProgress, subscribeCheckoutSurface };
package/dist/index.d.ts CHANGED
@@ -9,12 +9,39 @@ declare function parseZippyEnvironment(value: string): ZippyEnvironment;
9
9
  type PaymentSessionStatus = 'CREATED' | 'AWAITING_PAYMENT' | 'COMPLETED' | 'EXPIRED' | 'CANCELLED' | 'FAILED';
10
10
  type PaymentSessionPhase = 'IDLE' | 'PAYING';
11
11
  /** Server checkout method — locks after checkout start. */
12
- type ApiCheckoutMethod = 'QR' | 'MANUAL';
12
+ type ApiCheckoutMethod = 'QR' | 'MANUAL' | 'MOBILE_APP';
13
+ /** SDK init — omit to allow both QR and Manual. */
14
+ type CheckoutPolicy = 'QR' | 'MANUAL';
15
+ /** SDK init — phone-only app handoff preference. */
16
+ type MobileAppPolicy = 'off' | 'option' | 'enforce';
17
+ /** Explicit checkout restriction returned by the API. */
18
+ type ApiCheckoutPolicy = 'QR' | 'MANUAL';
19
+ /** Bound checkout policy — `null` means full chooser (QR + manual). */
20
+ type BoundCheckoutPolicy = ApiCheckoutPolicy | null;
21
+ /** Bound mobile app policy returned by the API. */
22
+ type ApiMobileAppPolicy = 'OFF' | 'OPTION' | 'ENFORCE';
23
+ type BindCheckoutPolicyRequest = {
24
+ checkoutPolicy?: ApiCheckoutPolicy;
25
+ mobileAppPolicy?: ApiMobileAppPolicy;
26
+ };
27
+ type CheckoutSurface = 'phone' | 'desktop';
28
+ type StartCheckoutRequest = {
29
+ method: ApiCheckoutMethod;
30
+ surface: CheckoutSurface;
31
+ };
32
+ type ZippyMobileAppConfig = {
33
+ policy?: MobileAppPolicy;
34
+ };
13
35
  type PaymentSessionPayer = {
14
36
  paymentId: string;
15
37
  displayName: string;
16
38
  profileImage: string | null;
17
39
  };
40
+ /** Payer preview returned from verify — same fields as session payer. */
41
+ type PayerPreview = PaymentSessionPayer;
42
+ type VerifyPayerResponse = {
43
+ items: PayerPreview[];
44
+ };
18
45
  type PaymentSession = {
19
46
  sessionId: string;
20
47
  amount: string;
@@ -32,12 +59,15 @@ type PaymentSession = {
32
59
  absoluteExpiresAt: string;
33
60
  phase: PaymentSessionPhase;
34
61
  checkoutMethod: ApiCheckoutMethod | null;
62
+ /** Set after bind-policy — `null` = full chooser when `mobileAppPolicy` is set. */
63
+ checkoutPolicy: BoundCheckoutPolicy;
64
+ /** Set after bind-policy succeeds; null until then. */
65
+ mobileAppPolicy: ApiMobileAppPolicy | null;
35
66
  paymentStartAt: string | null;
36
67
  /** Pay window countdown — only meaningful when phase is PAYING. */
37
68
  paymentExpiryAt: string | null;
38
69
  createdAt: string;
39
70
  };
40
- type VerifyPayerResponse = PaymentSessionPayer;
41
71
  type ProblemJson = {
42
72
  type?: string;
43
73
  title?: string;
@@ -71,6 +101,10 @@ type ZippyPayConfig = {
71
101
  mode?: EmbedMode;
72
102
  container?: HTMLElement | string;
73
103
  theme?: ZippyTheme;
104
+ /** When omitted, customer can choose QR or Manual. */
105
+ checkoutPolicy?: CheckoutPolicy;
106
+ /** Phone-only app handoff. Ignored on non-phone devices. */
107
+ mobileApp?: ZippyMobileAppConfig;
74
108
  locale?: 'en';
75
109
  redirectOnComplete?: boolean;
76
110
  redirectOnFailure?: boolean;
@@ -83,8 +117,8 @@ type ZippyPayConfig = {
83
117
  onError?: (error: ZippyPayError) => void;
84
118
  onClose?: () => void;
85
119
  };
86
- type CheckoutMethod = 'qr' | 'manual';
87
- type CheckoutPhase = 'loading' | 'choose-method' | 'qr-active' | 'manual-entry' | 'manual-confirm' | 'awaiting' | 'success' | 'expired' | 'cancelled' | 'declined' | 'failed' | 'error' | 'invalid-session';
120
+ type CheckoutMethod = 'qr' | 'manual' | 'mobileApp';
121
+ type CheckoutPhase = 'loading' | 'choose-method' | 'qr-active' | 'mobile-app-active' | 'manual-entry' | 'manual-picker' | 'manual-confirm' | 'awaiting' | 'success' | 'expired' | 'cancelled' | 'declined' | 'failed' | 'error' | 'invalid-session';
88
122
  declare const TERMINAL_STATUSES: readonly PaymentSessionStatus[];
89
123
  declare const POLLABLE_STATUSES: readonly PaymentSessionStatus[];
90
124
  declare class ZippyPayError extends Error {
@@ -111,11 +145,13 @@ declare class PaymentSessionClient {
111
145
  private readonly clientToken;
112
146
  constructor(config: ApiClientConfig);
113
147
  getSession(): Promise<PaymentSession>;
114
- verifyPayer(paymentId: string): Promise<VerifyPayerResponse>;
148
+ bindCheckoutPolicy(body: BindCheckoutPolicyRequest): Promise<PaymentSession>;
149
+ verifyPayer(query: string): Promise<VerifyPayerResponse>;
115
150
  attachPayer(paymentId: string): Promise<PaymentSession>;
116
- startCheckout(method: ApiCheckoutMethod): Promise<PaymentSession>;
117
- startQrCheckout(): Promise<PaymentSession>;
118
- startManualCheckout(): Promise<PaymentSession>;
151
+ startCheckout(method: StartCheckoutRequest['method'], surface: CheckoutSurface): Promise<PaymentSession>;
152
+ startQrCheckout(surface: CheckoutSurface): Promise<PaymentSession>;
153
+ startMobileAppCheckout(surface: CheckoutSurface): Promise<PaymentSession>;
154
+ startManualCheckout(surface: CheckoutSurface): Promise<PaymentSession>;
119
155
  private sessionPath;
120
156
  private headers;
121
157
  private request;
@@ -166,6 +202,8 @@ declare class CheckoutController implements ZippyPayCheckoutInstance {
166
202
  private session;
167
203
  private paymentId;
168
204
  private verifiedPayer;
205
+ private verifyMatches;
206
+ private lastVerifiedQuery;
169
207
  private committedMethod;
170
208
  private phase;
171
209
  private errorMessage;
@@ -174,6 +212,14 @@ declare class CheckoutController implements ZippyPayCheckoutInstance {
174
212
  private modalOpen;
175
213
  private exitMode;
176
214
  private terminalFailureReason;
215
+ private uiOptions;
216
+ private appHandoffStatus;
217
+ private clearAppHandoffWatch;
218
+ private methodSwitchInProgress;
219
+ private entryRoutingDone;
220
+ private payWindowExpiryTimer;
221
+ private unsubscribeSurface;
222
+ private static readonly PAY_WINDOW_PHASES;
177
223
  constructor(config: ZippyPayConfig);
178
224
  open(): void;
179
225
  close(): void;
@@ -181,7 +227,13 @@ declare class CheckoutController implements ZippyPayCheckoutInstance {
181
227
  private snapshotUiState;
182
228
  private syncUi;
183
229
  private bootstrap;
230
+ private bindPolicy;
231
+ private applyBoundUiOptions;
232
+ private handleSurfaceChange;
184
233
  private applySession;
234
+ private schedulePayWindowExpiryWatch;
235
+ private clearPayWindowExpiryWatch;
236
+ private handlePayWindowExpired;
185
237
  private resolveActivePhase;
186
238
  private handleSessionUpdate;
187
239
  private handleFailure;
@@ -191,8 +243,21 @@ declare class CheckoutController implements ZippyPayCheckoutInstance {
191
243
  private failurePhaseFromReason;
192
244
  private teardownView;
193
245
  private handleBootstrapError;
246
+ private handlePollError;
194
247
  private handleError;
248
+ private routeIdleEntry;
249
+ private openMobileApp;
250
+ private beginMobileAppHandoff;
251
+ private installZippy;
252
+ private startMobileAppFlow;
253
+ private canStartAppClaim;
195
254
  private chooseMethod;
255
+ private chooseFallbackMethod;
256
+ private backToChooseMethod;
257
+ private backToManualEntry;
258
+ private backToMobileAppFallback;
259
+ private isMobileAppManualFallbackActive;
260
+ private selectPayer;
196
261
  private verify;
197
262
  private attach;
198
263
  private handleFlowError;
@@ -227,11 +292,74 @@ declare global {
227
292
 
228
293
  /** Personal Zippy handles: 3–20 chars, optional single dot, no leading/trailing dot. */
229
294
  declare const PAYMENT_ID_PATTERN: RegExp;
295
+ declare const E164_PHONE_PATTERN: RegExp;
296
+ declare const EMAIL_PATTERN: RegExp;
230
297
  declare function normalizePaymentId(value: string): string;
298
+ /** Normalize a payer verify query before sending to the API. */
299
+ declare function normalizePayerQuery(value: string): string;
231
300
  declare function isValidPaymentId(value: string): boolean;
301
+ /** Client-side pre-validation for payer verify `query` (server is authoritative). */
302
+ declare function isValidPayerQuery(value: string): boolean;
232
303
  declare function paymentIdValidationMessage(): string;
304
+ declare function payerQueryValidationMessage(): string;
233
305
  declare function formatAmount(amount: string, currency: string): string;
234
306
 
307
+ type MobileStorePlatform = 'ios' | 'android';
308
+ /** True when checkout runs on a phone-sized touch device. */
309
+ declare function isPhoneDevice(): boolean;
310
+ /** True when the browser reports an Android user agent. */
311
+ declare function isAndroidDevice(): boolean;
312
+ declare function detectCheckoutSurface(): CheckoutSurface;
313
+ declare function subscribeCheckoutSurface(onChange: (surface: CheckoutSurface) => void): () => void;
314
+
315
+ /** Fixed App Store / Google Play URLs for Zippy Pay (managed server-side; not merchant-configurable). */
316
+ type AppStoreLinks = {
317
+ ios: string;
318
+ android: string;
319
+ };
320
+ declare const ANDROID_APP_PACKAGE = "com.zippy.pay";
321
+ /** HTTPS store URLs — used for QR codes and desktop fallback links. */
322
+ declare const APP_STORE_LINKS: AppStoreLinks;
323
+ /** Opens the native App Store app on iOS (no specific listing until app id is available). */
324
+ declare const IOS_APP_STORE_NATIVE_URL = "itms-apps://apps.apple.com/";
325
+ /** Opens the native Play Store app on Android. */
326
+ declare const ANDROID_PLAY_STORE_NATIVE_URL = "market://details?id=com.zippy.pay";
327
+ declare function resolveAppStoreUrl(platform: MobileStorePlatform): string;
328
+ /**
329
+ * URL used when the customer taps Install Zippy.
330
+ * iOS and Android both use native store schemes from a user gesture.
331
+ */
332
+ declare function resolveAppStoreOpenUrl(platform: MobileStorePlatform): string;
333
+
334
+ type EntryRoutingAction = 'chooser' | 'auto-qr' | 'auto-manual' | 'enforce-mobile-app';
335
+ type MethodAvailability = {
336
+ qr: boolean;
337
+ manual: boolean;
338
+ mobileApp: boolean;
339
+ };
340
+ type ResolvedCheckoutUiOptions = {
341
+ checkoutPolicy: BoundCheckoutPolicy;
342
+ mobileAppPolicy: ApiMobileAppPolicy;
343
+ surface: CheckoutSurface;
344
+ methodAvailability: MethodAvailability;
345
+ allowManualBack: boolean;
346
+ };
347
+ type AppClaimCheckoutMethod = Extract<ApiCheckoutMethod, 'QR' | 'MOBILE_APP'>;
348
+ declare function isCheckoutPolicyBound(session: PaymentSession): boolean;
349
+ declare function isFullChooserPolicy(checkoutPolicy: BoundCheckoutPolicy): boolean;
350
+ declare function resolveMobileAppPolicy(mobileApp?: ZippyMobileAppConfig): ApiMobileAppPolicy;
351
+ declare function buildBindPolicyRequest(config: {
352
+ checkoutPolicy?: CheckoutPolicy;
353
+ mobileApp?: ZippyMobileAppConfig;
354
+ }): BindCheckoutPolicyRequest;
355
+ declare function resolveMethodAvailability(checkoutPolicy: BoundCheckoutPolicy, mobileAppPolicy: ApiMobileAppPolicy, surface: CheckoutSurface): MethodAvailability;
356
+ declare function resolveEntryRouting(checkoutPolicy: BoundCheckoutPolicy, mobileAppPolicy: ApiMobileAppPolicy, surface: CheckoutSurface): EntryRoutingAction;
357
+ declare function isCheckoutStartAllowed(checkoutPolicy: BoundCheckoutPolicy, mobileAppPolicy: ApiMobileAppPolicy, surface: CheckoutSurface, method: AppClaimCheckoutMethod): boolean;
358
+ declare function resolveAutoStartMethod(checkoutPolicy: BoundCheckoutPolicy, mobileAppPolicy: ApiMobileAppPolicy, surface: CheckoutSurface): AppClaimCheckoutMethod | null;
359
+ declare function resolveCheckoutUiOptionsFromBound(checkoutPolicy: BoundCheckoutPolicy, mobileAppPolicy: ApiMobileAppPolicy, surface?: CheckoutSurface): ResolvedCheckoutUiOptions;
360
+ declare function resolveCheckoutUiOptionsFromSession(session: PaymentSession, surface?: CheckoutSurface): ResolvedCheckoutUiOptions;
361
+ declare function resolveCheckoutUiOptions(checkoutPolicy?: CheckoutPolicy, mobileApp?: ZippyMobileAppConfig, surface?: CheckoutSurface): ResolvedCheckoutUiOptions;
362
+
235
363
  /** Deep link scanned by the Zippy app — sessionId only, never clientToken. */
236
364
  declare function buildPaymentQrPayload(sessionId: string): string;
237
365
  type QrErrorCorrection = 'L' | 'M' | 'Q' | 'H';
@@ -242,6 +370,20 @@ declare function renderPaymentQrSvg(sessionId: string, cellSize?: number, errorC
242
370
  declare function renderBrandedPaymentQrSvg(sessionId: string, cellSize?: number): string;
243
371
  /** QR markup wrapper for the checkout UI. */
244
372
  declare function renderPaymentQrMarkup(sessionId: string, cellSize?: number): string;
373
+ /** Plain QR markup for arbitrary URLs (e.g. app store links). */
374
+ declare function renderUrlQrMarkup(url: string, cellSize?: number): string;
375
+
376
+ /** Android intent URL — more reliable than raw `zippy://` in Chrome. */
377
+ declare function buildAndroidPaymentIntentUrl(sessionId: string): string;
378
+ /** Platform-aware deep link used when the customer taps Pay with Zippy / Try again. */
379
+ declare function buildPaymentDeepLinkOpenUrl(sessionId: string, platform?: MobileStorePlatform): string;
380
+ /** Sends the current tab to the App Store or Google Play for this device. */
381
+ declare function openAppStore(platform?: MobileStorePlatform): void;
382
+ /**
383
+ * Opens the Zippy app from a user gesture (Pay with Zippy / Try again).
384
+ * Keeps the checkout page visible so failed-handoff UI can appear afterward.
385
+ */
386
+ declare function openPaymentDeepLink(sessionId: string): void;
245
387
 
246
388
  /** Aligned with zippy-kyc-web-sdk `src/styles/tokens.css` */
247
389
  declare const DEFAULT_THEME: Required<Omit<ZippyTheme, 'mode'>> & {
@@ -262,4 +404,4 @@ declare const ZippyPay: {
262
404
  create(config: ZippyPayConfig): ZippyPayCheckoutInstance;
263
405
  };
264
406
 
265
- export { type ApiCheckoutMethod, CheckoutController, type CheckoutMethod, type CheckoutPhase, DEFAULT_THEME, ELEMENT_TAG, type EmbedMode, PAYMENT_ID_PATTERN, POLLABLE_STATUSES, type PaymentSession, PaymentSessionClient, type PaymentSessionPayer, type PaymentSessionPhase, type PaymentSessionStatus, type ProblemJson, SessionPoller, TERMINAL_STATUSES, type VerifyPayerResponse, ZIPPY_API_BASE_URLS, ZIPPY_API_PATH_PREFIX, type ZippyEnvironment, ZippyPay, ZippyPayCheckoutElement, type ZippyPayCheckoutInstance, type ZippyPayConfig, ZippyPayError, type ZippyTheme, applyThemeToHost, attachPayerWithRetry, buildPaymentQrPayload, createCheckout, ZippyPay as default, defineZippyPayCheckoutElement, formatAmount, getCountdownTarget, getPayWindowRemainingRatio, getSoftIdleHint, isTerminalStatus, isValidPaymentId, isZippyEnvironment, msUntil, normalizePaymentId, parseZippyEnvironment, paymentIdValidationMessage, phaseFromSession, renderBrandedPaymentQrSvg, renderPaymentQrMarkup, renderPaymentQrSvg, renderQrSvg, resolveApiBaseUrl, resolveTheme, shouldShowPayProgress };
407
+ export { ANDROID_APP_PACKAGE, ANDROID_PLAY_STORE_NATIVE_URL, APP_STORE_LINKS, type ApiCheckoutMethod, type ApiCheckoutPolicy, type ApiMobileAppPolicy, type AppStoreLinks, type BindCheckoutPolicyRequest, type BoundCheckoutPolicy, CheckoutController, type CheckoutMethod, type CheckoutPhase, type CheckoutPolicy, type CheckoutSurface, DEFAULT_THEME, E164_PHONE_PATTERN, ELEMENT_TAG, EMAIL_PATTERN, type EmbedMode, IOS_APP_STORE_NATIVE_URL, type MobileAppPolicy, PAYMENT_ID_PATTERN, POLLABLE_STATUSES, type PayerPreview, type PaymentSession, PaymentSessionClient, type PaymentSessionPayer, type PaymentSessionPhase, type PaymentSessionStatus, type ProblemJson, SessionPoller, type StartCheckoutRequest, TERMINAL_STATUSES, type VerifyPayerResponse, ZIPPY_API_BASE_URLS, ZIPPY_API_PATH_PREFIX, type ZippyEnvironment, type ZippyMobileAppConfig, ZippyPay, ZippyPayCheckoutElement, type ZippyPayCheckoutInstance, type ZippyPayConfig, ZippyPayError, type ZippyTheme, applyThemeToHost, attachPayerWithRetry, buildAndroidPaymentIntentUrl, buildBindPolicyRequest, buildPaymentDeepLinkOpenUrl, buildPaymentQrPayload, createCheckout, ZippyPay as default, defineZippyPayCheckoutElement, detectCheckoutSurface, formatAmount, getCountdownTarget, getPayWindowRemainingRatio, getSoftIdleHint, isAndroidDevice, isCheckoutPolicyBound, isCheckoutStartAllowed, isFullChooserPolicy, isPhoneDevice, isTerminalStatus, isValidPayerQuery, isValidPaymentId, isZippyEnvironment, msUntil, normalizePayerQuery, normalizePaymentId, openAppStore, openPaymentDeepLink, parseZippyEnvironment, payerQueryValidationMessage, paymentIdValidationMessage, phaseFromSession, renderBrandedPaymentQrSvg, renderPaymentQrMarkup, renderPaymentQrSvg, renderQrSvg, renderUrlQrMarkup, resolveApiBaseUrl, resolveAppStoreOpenUrl, resolveAppStoreUrl, resolveAutoStartMethod, resolveCheckoutUiOptions, resolveCheckoutUiOptionsFromBound, resolveCheckoutUiOptionsFromSession, resolveEntryRouting, resolveMethodAvailability, resolveMobileAppPolicy, resolveTheme, shouldShowPayProgress, subscribeCheckoutSurface };