@flopay/shared 1.0.3 → 1.1.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 +8 -4
- package/dist/index.cjs +103 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +217 -94
- package/dist/index.d.ts +217 -94
- package/dist/index.mjs +100 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -160,62 +160,84 @@ interface LineItem {
|
|
|
160
160
|
}
|
|
161
161
|
/** Checkout mode controlling the payment UI behavior. */
|
|
162
162
|
type CheckoutMode = 'full' | 'auto' | 'confirm';
|
|
163
|
-
/**
|
|
164
|
-
|
|
163
|
+
/**
|
|
164
|
+
* Discriminator describing whether a checkout product is a one-time item or a
|
|
165
|
+
* recurring subscription. Mirrors the backend's `ProductTypeEnum`.
|
|
166
|
+
*/
|
|
167
|
+
type CheckoutProductType = 'item' | 'subscription';
|
|
168
|
+
/** Unified checkout product from a session response. */
|
|
169
|
+
interface CheckoutSessionProduct {
|
|
165
170
|
uuid: string;
|
|
166
171
|
checkoutSessionId: string;
|
|
167
|
-
/**
|
|
172
|
+
/** Whether this product is a one-time item or a recurring subscription. */
|
|
173
|
+
type: CheckoutProductType;
|
|
174
|
+
/** Preferred catalog code for the product. */
|
|
168
175
|
code?: string;
|
|
169
|
-
/** @deprecated Use {@link CheckoutSessionItem.code}. Backend may stop returning this in a future major. */
|
|
170
|
-
providerItemId?: string;
|
|
171
176
|
/**
|
|
172
|
-
* Display-only name
|
|
173
|
-
*
|
|
174
|
-
* client-side display cache when the server response omits it.
|
|
177
|
+
* Display-only name. Resolved from the catalog server-side; the SDK
|
|
178
|
+
* populates this from the client-side display cache when missing.
|
|
175
179
|
*/
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
|
|
179
|
-
/** Display-only. Resolved from the catalog server-side; not part of the persisted session. */
|
|
180
|
-
providerItemDescription?: string | null;
|
|
180
|
+
name?: string | null;
|
|
181
|
+
/** Display-only description from the catalog. */
|
|
182
|
+
description?: string | null;
|
|
181
183
|
quantity: number;
|
|
182
|
-
/** Display-only.
|
|
184
|
+
/** Display-only. Populated from cache when the server omits it. */
|
|
183
185
|
totalAmount?: number;
|
|
184
|
-
/** Display-only.
|
|
186
|
+
/** Display-only. Populated from cache when the server omits it. */
|
|
185
187
|
overrideAmount?: number | null;
|
|
186
|
-
/** @deprecated Prefer the session-level `currency` on {@link CheckoutSession}.
|
|
188
|
+
/** @deprecated Prefer the session-level `currency` on {@link CheckoutSession}. */
|
|
187
189
|
currency?: string;
|
|
188
190
|
metadata?: Record<string, unknown> | null;
|
|
189
191
|
}
|
|
190
|
-
/**
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
192
|
+
/**
|
|
193
|
+
* Environment for an upstream gateway. Accepts both the gateway-native values
|
|
194
|
+
* (`'sandbox'` | `'live'`) and FloPay's internal aliases (`'stage'` |
|
|
195
|
+
* `'production'`) so the same string can flow from the billing API straight
|
|
196
|
+
* to gateway SDKs without translation at every call site. Use
|
|
197
|
+
* {@link normalizeGatewayEnvironment} to collapse to the canonical pair
|
|
198
|
+
* before handing the value to a gateway SDK.
|
|
199
|
+
*/
|
|
200
|
+
type GatewayEnvironment = 'sandbox' | 'live' | 'stage' | 'production';
|
|
201
|
+
/** Canonical gateway-native form returned by {@link normalizeGatewayEnvironment}. */
|
|
202
|
+
type NormalizedGatewayEnvironment = 'sandbox' | 'live';
|
|
203
|
+
/**
|
|
204
|
+
* Map FloPay's environment aliases to the gateway-native `'sandbox'`/`'live'`
|
|
205
|
+
* pair. `'stage'` → `'sandbox'`, `'production'` → `'live'`. Returns `undefined`
|
|
206
|
+
* for `undefined` input and logs a console warning for unrecognized strings
|
|
207
|
+
* (so misconfiguration surfaces immediately instead of hanging later — most
|
|
208
|
+
* gateway SDKs silently fall back to live endpoints on an unknown env, which
|
|
209
|
+
* then fails opaquely against sandbox credentials).
|
|
210
|
+
*/
|
|
211
|
+
declare function normalizeGatewayEnvironment(env: GatewayEnvironment | string | undefined | null): NormalizedGatewayEnvironment | undefined;
|
|
212
|
+
/** Per-gateway configuration returned by the billing API. */
|
|
213
|
+
interface CheckoutGateway {
|
|
214
|
+
/** Public client identifier (e.g. Stripe publishable key, PayPal client id). */
|
|
215
|
+
publishableKey?: string | null;
|
|
216
|
+
/** Sandbox or live mode for the gateway credentials. */
|
|
217
|
+
environment?: GatewayEnvironment;
|
|
198
218
|
/**
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
* response omits it.
|
|
219
|
+
* Optional Stripe PaymentIntent client secret exposed by the billing API
|
|
220
|
+
* when additional authentication is required for a saved payment method.
|
|
221
|
+
* Stripe-specific.
|
|
203
222
|
*/
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
223
|
+
stripeClientSecret?: string | null;
|
|
224
|
+
/**
|
|
225
|
+
* Optional publishable key for a dedicated Stripe sub-account that renders
|
|
226
|
+
* PayPal via Stripe Elements. Stripe-specific. Distinct from
|
|
227
|
+
* `gateways.paypal.publishableKey`, which is a PayPal client id used by the
|
|
228
|
+
* direct PayPal SDK.
|
|
229
|
+
*/
|
|
230
|
+
paypalPublishableKey?: string | null;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Map of gateways attached to a session, keyed by gateway code. A session can
|
|
234
|
+
* advertise multiple gateways concurrently — e.g. `gateways.stripe` for card
|
|
235
|
+
* + wallets and `gateways.paypal` for direct PayPal rendering.
|
|
236
|
+
*/
|
|
237
|
+
interface CheckoutGateways {
|
|
238
|
+
stripe?: CheckoutGateway;
|
|
239
|
+
paypal?: CheckoutGateway;
|
|
240
|
+
[key: string]: CheckoutGateway | undefined;
|
|
219
241
|
}
|
|
220
242
|
/** Represents a FloPay checkout session. */
|
|
221
243
|
interface CheckoutSession {
|
|
@@ -229,27 +251,35 @@ interface CheckoutSession {
|
|
|
229
251
|
customer?: Customer;
|
|
230
252
|
metadata?: Record<string, string>;
|
|
231
253
|
checkoutMode?: CheckoutMode;
|
|
232
|
-
|
|
233
|
-
|
|
254
|
+
/** Unified products array as returned by post-#760 backends. */
|
|
255
|
+
products?: CheckoutSessionProduct[];
|
|
234
256
|
successUrl?: string;
|
|
235
257
|
cancelUrl?: string;
|
|
236
258
|
coupons?: string[];
|
|
259
|
+
/**
|
|
260
|
+
* Pre-discount total in cart-currency major units (e.g. 24.95). Populated by
|
|
261
|
+
* billing API ≥ v1.1.2; `undefined` on older backends — readers must fall
|
|
262
|
+
* back to summing per-line `totalAmount`.
|
|
263
|
+
*/
|
|
264
|
+
subtotalAmount?: number;
|
|
265
|
+
/**
|
|
266
|
+
* Total reduction from applied coupons in cart-currency major units.
|
|
267
|
+
* Populated by billing API ≥ v1.1.2; `undefined` on older backends.
|
|
268
|
+
*/
|
|
269
|
+
discountAmount?: number;
|
|
270
|
+
/**
|
|
271
|
+
* Final charge amount in cart-currency major units (subtotal − discount,
|
|
272
|
+
* clamped ≥ 0). Populated by billing API ≥ v1.1.2; `undefined` on older
|
|
273
|
+
* backends — readers must fall back to summing per-line `overrideAmount`.
|
|
274
|
+
*/
|
|
275
|
+
totalAmount?: number;
|
|
237
276
|
createdAt?: string;
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
*/
|
|
245
|
-
stripeClientSecret?: string | null;
|
|
246
|
-
/**
|
|
247
|
-
* Dedicated Stripe publishable key for PayPal. When set, PayPal uses a
|
|
248
|
-
* separate Stripe account from the primary `publishableKey`. When `null`
|
|
249
|
-
* or missing, PayPal is disabled — there is no fallback to `publishableKey`.
|
|
250
|
-
*/
|
|
251
|
-
paypalPublishableKey?: string | null;
|
|
252
|
-
};
|
|
277
|
+
/**
|
|
278
|
+
* Per-gateway configuration. A session can advertise multiple concurrent
|
|
279
|
+
* gateways — read `gateways.stripe` for card/wallets, `gateways.paypal` for
|
|
280
|
+
* direct PayPal, and so on.
|
|
281
|
+
*/
|
|
282
|
+
gateways?: CheckoutGateways;
|
|
253
283
|
accountData?: {
|
|
254
284
|
userId: string;
|
|
255
285
|
email: string;
|
|
@@ -440,8 +470,8 @@ interface PaymentProviderAdapter {
|
|
|
440
470
|
createPayPalElements(options: ElementOptions): unknown;
|
|
441
471
|
destroy(): void;
|
|
442
472
|
}
|
|
443
|
-
/** Supported upstream
|
|
444
|
-
type BillingProvider = '
|
|
473
|
+
/** Supported upstream gateway codes. */
|
|
474
|
+
type BillingProvider = 'stripe' | 'paypal';
|
|
445
475
|
/** Token payload produced by client-side tokenization. */
|
|
446
476
|
interface TokenizedBody {
|
|
447
477
|
id?: string;
|
|
@@ -475,9 +505,13 @@ interface CheckoutProcessingPending {
|
|
|
475
505
|
}
|
|
476
506
|
/** Checkout mode: tokenize client-side or redirect to hosted page. */
|
|
477
507
|
type CheckoutModeKind = 'tokenize' | 'redirect';
|
|
478
|
-
/**
|
|
508
|
+
/**
|
|
509
|
+
* Provider-agnostic normalized checkout session. Backend may attach multiple
|
|
510
|
+
* gateways per session — read each from `data.<gatewayCode>`.
|
|
511
|
+
*/
|
|
479
512
|
interface NormalizedCheckoutSession {
|
|
480
|
-
|
|
513
|
+
/** Gateway codes advertised by the backend for this session, for diagnostics. */
|
|
514
|
+
providers: BillingProvider[];
|
|
481
515
|
mode: CheckoutModeKind;
|
|
482
516
|
autoProcessingError?: CheckoutProcessError;
|
|
483
517
|
autoProcessingAttempted?: boolean;
|
|
@@ -486,17 +520,25 @@ interface NormalizedCheckoutSession {
|
|
|
486
520
|
hostedUrl?: string;
|
|
487
521
|
clientToken?: string;
|
|
488
522
|
session?: CheckoutSession;
|
|
489
|
-
chargebee?: {
|
|
490
|
-
site?: string;
|
|
491
|
-
publishableKey?: string;
|
|
492
|
-
dropInToken?: string;
|
|
493
|
-
sessionId?: string;
|
|
494
|
-
};
|
|
495
523
|
stripe?: {
|
|
496
524
|
clientSecret?: string;
|
|
497
525
|
publishableKey?: string;
|
|
498
|
-
/**
|
|
526
|
+
/**
|
|
527
|
+
* Optional dedicated Stripe sub-account publishable key for rendering
|
|
528
|
+
* PayPal via Stripe Elements. When present and distinct, the saved-PM
|
|
529
|
+
* resume flow loads a separate FloPay instance for the PayPal PI.
|
|
530
|
+
*/
|
|
499
531
|
paypalPublishableKey?: string;
|
|
532
|
+
environment?: GatewayEnvironment;
|
|
533
|
+
};
|
|
534
|
+
/**
|
|
535
|
+
* Direct PayPal gateway configuration. Present only when the backend has
|
|
536
|
+
* configured a dedicated PayPal gateway for the consumer; absent means the
|
|
537
|
+
* Stripe-rendered PayPal fallback should be used (if Stripe is configured).
|
|
538
|
+
*/
|
|
539
|
+
paypal?: {
|
|
540
|
+
publishableKey?: string;
|
|
541
|
+
environment?: GatewayEnvironment;
|
|
500
542
|
};
|
|
501
543
|
};
|
|
502
544
|
raw?: unknown;
|
|
@@ -532,6 +574,42 @@ interface CheckoutItem {
|
|
|
532
574
|
/** Arbitrary key/value metadata forwarded to the backend. */
|
|
533
575
|
metadata?: Record<string, unknown> | null;
|
|
534
576
|
}
|
|
577
|
+
/**
|
|
578
|
+
* Unified product input for checkout session creation. Mirrors the backend's
|
|
579
|
+
* `CreateCheckoutProductBodyDto` introduced in #760 — the SDK accepts this
|
|
580
|
+
* shape on `CreateSessionParams.products`. Callers using the legacy
|
|
581
|
+
* {@link CheckoutItem} / {@link CheckoutSubscription} shapes do not need to
|
|
582
|
+
* migrate; the SDK folds them into this shape internally.
|
|
583
|
+
*/
|
|
584
|
+
interface CheckoutProduct {
|
|
585
|
+
/** Whether this product is a one-time item or a recurring subscription. */
|
|
586
|
+
type: CheckoutProductType;
|
|
587
|
+
/** Catalog code — preferred identifier. */
|
|
588
|
+
code?: string;
|
|
589
|
+
/** @deprecated Falls back to {@link CheckoutProduct.code} for back-compat. */
|
|
590
|
+
providerItemId?: string;
|
|
591
|
+
/** @deprecated Falls back to {@link CheckoutProduct.code} for back-compat. */
|
|
592
|
+
providerPlanId?: string;
|
|
593
|
+
/** Display-only name for the product. */
|
|
594
|
+
name?: string | null;
|
|
595
|
+
/** @deprecated Use {@link CheckoutProduct.name}. */
|
|
596
|
+
itemName?: string | null;
|
|
597
|
+
/** @deprecated Use {@link CheckoutProduct.name}. */
|
|
598
|
+
providerItemName?: string | null;
|
|
599
|
+
/** @deprecated Use {@link CheckoutProduct.name}. */
|
|
600
|
+
subscriptionName?: string | null;
|
|
601
|
+
/** @deprecated Use {@link CheckoutProduct.name}. */
|
|
602
|
+
providerPlanName?: string | null;
|
|
603
|
+
/** Defaults to 1. */
|
|
604
|
+
quantity?: number;
|
|
605
|
+
/** Display-only. Backend resolves prices from the catalog. */
|
|
606
|
+
totalAmount?: number;
|
|
607
|
+
/** Display-only discount override. Backend ignores this entirely. */
|
|
608
|
+
overrideAmount?: number | null;
|
|
609
|
+
/** @deprecated Prefer the session-level `currency`. */
|
|
610
|
+
currency?: string;
|
|
611
|
+
metadata?: Record<string, unknown> | null;
|
|
612
|
+
}
|
|
535
613
|
/** A recurring subscription plan for checkout session creation. */
|
|
536
614
|
interface CheckoutSubscription {
|
|
537
615
|
/**
|
|
@@ -597,14 +675,23 @@ interface CreateSessionParams {
|
|
|
597
675
|
/** The client ID for the checkout session. */
|
|
598
676
|
clientId: string;
|
|
599
677
|
/**
|
|
600
|
-
* Session-level ISO 4217 currency code.
|
|
601
|
-
*
|
|
602
|
-
*
|
|
678
|
+
* Session-level ISO 4217 currency code. **Required** by post-#760
|
|
679
|
+
* backends (`@IsNotEmpty`). The SDK resolves it from this field first,
|
|
680
|
+
* then `items[0].currency`, then `subscriptions[0].currency`, then
|
|
681
|
+
* `products[0].currency`. When none resolve, the SDK throws
|
|
682
|
+
* `FloPayError('validation_error')` before issuing the HTTP request.
|
|
603
683
|
*/
|
|
604
684
|
currency?: string;
|
|
605
|
-
/**
|
|
685
|
+
/**
|
|
686
|
+
* Unified products array. When supplied, it is sent verbatim and
|
|
687
|
+
* {@link CreateSessionParams.items} / {@link CreateSessionParams.subscriptions}
|
|
688
|
+
* are ignored. Otherwise the SDK folds the legacy fields into this shape
|
|
689
|
+
* before POSTing to the backend.
|
|
690
|
+
*/
|
|
691
|
+
products?: CheckoutProduct[];
|
|
692
|
+
/** One-time purchase items. Folded into `products[]` before send. */
|
|
606
693
|
items?: CheckoutItem[];
|
|
607
|
-
/** Recurring subscription plans. */
|
|
694
|
+
/** Recurring subscription plans. Folded into `products[]` before send. */
|
|
608
695
|
subscriptions?: CheckoutSubscription[];
|
|
609
696
|
/** Buyer's account information. */
|
|
610
697
|
account: CheckoutAccount;
|
|
@@ -641,14 +728,23 @@ interface InlineSessionParams {
|
|
|
641
728
|
/** The client ID for the checkout session. */
|
|
642
729
|
clientId: string;
|
|
643
730
|
/**
|
|
644
|
-
* Session-level ISO 4217 currency code.
|
|
645
|
-
*
|
|
646
|
-
*
|
|
731
|
+
* Session-level ISO 4217 currency code. **Required** by post-#760
|
|
732
|
+
* backends (`@IsNotEmpty`). The SDK resolves it from this field first,
|
|
733
|
+
* then `items[0].currency`, then `subscriptions[0].currency`, then
|
|
734
|
+
* `products[0].currency`. When none resolve, the SDK throws
|
|
735
|
+
* `FloPayError('validation_error')` before issuing the HTTP request.
|
|
647
736
|
*/
|
|
648
737
|
currency?: string;
|
|
649
|
-
/**
|
|
738
|
+
/**
|
|
739
|
+
* Unified products array. When supplied, it is sent verbatim and
|
|
740
|
+
* {@link InlineSessionParams.items} / {@link InlineSessionParams.subscriptions}
|
|
741
|
+
* are ignored. Otherwise the SDK folds the legacy fields into this shape
|
|
742
|
+
* before POSTing to the backend.
|
|
743
|
+
*/
|
|
744
|
+
products?: CheckoutProduct[];
|
|
745
|
+
/** One-time purchase items. Folded into `products[]` before send. */
|
|
650
746
|
items?: CheckoutItem[];
|
|
651
|
-
/** Recurring subscription plans. */
|
|
747
|
+
/** Recurring subscription plans. Folded into `products[]` before send. */
|
|
652
748
|
subscriptions?: CheckoutSubscription[];
|
|
653
749
|
/** Buyer's account information. */
|
|
654
750
|
account: CheckoutAccount;
|
|
@@ -817,7 +913,7 @@ declare function getConfiguredBillingApiUrl(): string;
|
|
|
817
913
|
declare function getFloPayEnvironment(): FloPayEnvironment;
|
|
818
914
|
|
|
819
915
|
/** Current SDK version. */
|
|
820
|
-
declare const SDK_VERSION = "1.
|
|
916
|
+
declare const SDK_VERSION = "1.1.3";
|
|
821
917
|
/** Billing API URL for staging environment. */
|
|
822
918
|
declare const BILLING_API_URL_STAGING = "https://api.stage.flopay.com";
|
|
823
919
|
/** Billing API URL for production environment. */
|
|
@@ -951,6 +1047,13 @@ interface CheckoutDisplayData {
|
|
|
951
1047
|
totalSave: number;
|
|
952
1048
|
/** Discount percentage (0–100). */
|
|
953
1049
|
discountPercent: number;
|
|
1050
|
+
/**
|
|
1051
|
+
* Coupon discount reported by the backend (cart-currency major units),
|
|
1052
|
+
* when available. Populated from `session.discountAmount` (billing
|
|
1053
|
+
* API ≥ v1.1.2); `undefined` on older backends. Use this to render an
|
|
1054
|
+
* explicit "coupon" line without recomputing per-item math.
|
|
1055
|
+
*/
|
|
1056
|
+
couponDiscount?: number;
|
|
954
1057
|
}
|
|
955
1058
|
/** Options for {@link buildCheckoutDisplayData}. */
|
|
956
1059
|
interface BuildCheckoutDisplayDataOptions {
|
|
@@ -987,31 +1090,51 @@ declare function buildCheckoutDisplayData(session: CheckoutSession, options?: Bu
|
|
|
987
1090
|
|
|
988
1091
|
/**
|
|
989
1092
|
* Resolve the session-level currency, honoring the documented fallback:
|
|
990
|
-
* `session.currency ?? items[*].currency ?? subscriptions[*].currency`.
|
|
1093
|
+
* `session.currency ?? items[*].currency ?? subscriptions[*].currency ?? products[*].currency`.
|
|
991
1094
|
*
|
|
992
|
-
* Returns the first non-blank currency found, or
|
|
1095
|
+
* Returns the first non-blank currency found, or `null` when nothing is set.
|
|
993
1096
|
* Empty and whitespace-only strings are treated as unset so they do not
|
|
994
1097
|
* bypass the fallback chain.
|
|
1098
|
+
*
|
|
1099
|
+
* Post-#760 backends reject session-create requests without a session-level
|
|
1100
|
+
* currency (`@IsNotEmpty`); callers should throw a validation error when
|
|
1101
|
+
* this returns `null` rather than silently defaulting.
|
|
995
1102
|
*/
|
|
996
|
-
declare function resolveSessionCurrency(sessionCurrency: string | undefined, items
|
|
1103
|
+
declare function resolveSessionCurrency(sessionCurrency: string | undefined, items?: ReadonlyArray<{
|
|
1104
|
+
currency?: string;
|
|
1105
|
+
}> | undefined, subscriptions?: ReadonlyArray<{
|
|
997
1106
|
currency?: string;
|
|
998
|
-
}> | undefined,
|
|
1107
|
+
}> | undefined, products?: ReadonlyArray<{
|
|
999
1108
|
currency?: string;
|
|
1000
|
-
}> | undefined): string;
|
|
1109
|
+
}> | undefined): string | null;
|
|
1110
|
+
/**
|
|
1111
|
+
* Fold legacy `items` + `subscriptions` arrays into the unified `products[]`
|
|
1112
|
+
* shape introduced by backend #760. Items become `type: 'item'`,
|
|
1113
|
+
* subscriptions become `type: 'subscription'`. The relative order is
|
|
1114
|
+
* subscriptions-first then items, matching the order the previous payload
|
|
1115
|
+
* builders emitted on the wire.
|
|
1116
|
+
*/
|
|
1117
|
+
declare function foldIntoProducts(items: readonly CheckoutItem[] | undefined, subscriptions: readonly CheckoutSubscription[] | undefined): CheckoutProduct[];
|
|
1118
|
+
/**
|
|
1119
|
+
* Build the request payload for a single product in the unified shape
|
|
1120
|
+
* introduced by backend #760. Emits `type`, `code`, `name`, `quantity`,
|
|
1121
|
+
* `totalAmount`, `overrideAmount`, `currency`, and optional `metadata`.
|
|
1122
|
+
*/
|
|
1123
|
+
declare function buildProductPayload(product: CheckoutProduct, sessionCurrency: string): Record<string, unknown>;
|
|
1001
1124
|
/**
|
|
1002
1125
|
* Build the request payload for a single item.
|
|
1003
1126
|
*
|
|
1004
|
-
*
|
|
1005
|
-
*
|
|
1006
|
-
*
|
|
1127
|
+
* @deprecated Use {@link buildProductPayload} with {@link foldIntoProducts}.
|
|
1128
|
+
* Retained until the next major so external callers building the legacy
|
|
1129
|
+
* `items[]` payload manually keep working.
|
|
1007
1130
|
*/
|
|
1008
1131
|
declare function buildItemPayload(item: CheckoutItem, sessionCurrency: string): Record<string, unknown>;
|
|
1009
1132
|
/**
|
|
1010
1133
|
* Build the request payload for a single subscription.
|
|
1011
1134
|
*
|
|
1012
|
-
*
|
|
1013
|
-
*
|
|
1014
|
-
*
|
|
1135
|
+
* @deprecated Use {@link buildProductPayload} with {@link foldIntoProducts}.
|
|
1136
|
+
* Retained until the next major so external callers building the legacy
|
|
1137
|
+
* `subscriptions[]` payload manually keep working.
|
|
1015
1138
|
*/
|
|
1016
1139
|
declare function buildSubscriptionPayload(subscription: CheckoutSubscription, sessionCurrency: string): Record<string, unknown>;
|
|
1017
1140
|
|
|
@@ -1025,4 +1148,4 @@ declare function isValidPublishableKey(key: string): boolean;
|
|
|
1025
1148
|
/** Returns `true` if the string looks like a Stripe secret key. */
|
|
1026
1149
|
declare function isValidSecretKey(key: string): boolean;
|
|
1027
1150
|
|
|
1028
|
-
export { type AVSFieldConfig, BILLING_API_URL, BILLING_API_URL_PRODUCTION, BILLING_API_URL_STAGING, BUTTONS_LAYOUT_DARK, BUTTONS_LAYOUT_DEFAULT, BUTTONS_LAYOUT_MINIMAL, BUTTONS_LAYOUT_ROUNDED, type BeforeButtonClickEvent, type BillingDetails, type BillingProvider, type BuildCheckoutDisplayDataOptions, type ButtonsLayoutStyles, type ButtonsLayoutTheme, CA_PROVINCES, COUNTRY_OPTIONS, CURRENCY_MAP, type CheckoutAccount, type CheckoutButtonMethod, type CheckoutDisplayData, type CheckoutItem, type CheckoutMode, type CheckoutModeKind, type CheckoutProcessError, type CheckoutProcessingPending, type
|
|
1151
|
+
export { type AVSFieldConfig, BILLING_API_URL, BILLING_API_URL_PRODUCTION, BILLING_API_URL_STAGING, BUTTONS_LAYOUT_DARK, BUTTONS_LAYOUT_DEFAULT, BUTTONS_LAYOUT_MINIMAL, BUTTONS_LAYOUT_ROUNDED, type BeforeButtonClickEvent, type BillingDetails, type BillingProvider, type BuildCheckoutDisplayDataOptions, type ButtonsLayoutStyles, type ButtonsLayoutTheme, CA_PROVINCES, COUNTRY_OPTIONS, CURRENCY_MAP, type CheckoutAccount, type CheckoutButtonMethod, type CheckoutDisplayData, type CheckoutGateway, type CheckoutGateways, type CheckoutItem, type CheckoutMode, type CheckoutModeKind, type CheckoutProcessError, type CheckoutProcessingPending, type CheckoutProduct, type CheckoutProductType, type CheckoutSession, type CheckoutSessionProduct, type CheckoutSessionResult, type CheckoutSubscription, type ConfirmCardPaymentParams, type ConfirmCardPaymentResult, type ConfirmPaymentParams, type CountryOption, type CreateCustomerParams, type CreatePaymentMethodResult, type CreateSessionParams, type CurrencyInfo, type Customer, DEFAULT_API_BASE_URL, DEFAULT_API_VERSION, DEFAULT_APPEARANCE, DEFAULT_CURRENCY, type DeclineEvent, type DisplayLineItem, ELEMENT_TYPES, type ElementChangeEvent, type ElementOptions, type ElementType, FLAT_APPEARANCE, type FloPayAppearance, type FloPayConfig, type FloPayEnvironment, FloPayError, type FloPayErrorType, type FloPayThemeVariables, type GatewayEnvironment, type InlineSessionDraft, type InlineSessionParams, type InlineSessionPatch, type LineItem, type MountedElement, NIGHT_APPEARANCE, type NormalizedCheckoutSession, type NormalizedGatewayEnvironment, type PaymentProviderAdapter, type PaymentResult, type PriceData, type ProcessPaymentParams, type RecurringInterval, SDK_VERSION, SUPPORTED_CARD_BRANDS, type StateOption, type TagsData, type TokenizedBody, US_STATES, type UpdateCustomerParams, type WebhookEvent, apiError, authenticationError, buildCheckoutDisplayData, buildItemPayload, buildProductPayload, buildSubscriptionPayload, configureFlopay, foldIntoProducts, getConfiguredBillingApiUrl, getCountryByCode, getCurrencyByCountry, getFloPayEnvironment, getPostalCodeLabel, getStateFromPostalCode, getStateLabel, getStateOptions, isAVSEnabled, isAVSFieldVisible, isValidPublishableKey, isValidSecretKey, networkError, normalizeGatewayEnvironment, rateLimitError, resolveAVSConfig, resolveBillingApiUrl, resolveButtonsLayoutTheme, resolveSessionCurrency, validationError };
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
function normalizeGatewayEnvironment(env) {
|
|
3
|
+
if (env == null) return void 0;
|
|
4
|
+
switch (env) {
|
|
5
|
+
case "sandbox":
|
|
6
|
+
case "stage":
|
|
7
|
+
return "sandbox";
|
|
8
|
+
case "live":
|
|
9
|
+
case "production":
|
|
10
|
+
return "live";
|
|
11
|
+
default:
|
|
12
|
+
console.warn(
|
|
13
|
+
`[FloPay] Unrecognized gateway environment "${env}". Expected one of: sandbox, live, stage, production. Falling back to undefined.`
|
|
14
|
+
);
|
|
15
|
+
return void 0;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
1
19
|
// src/errors.ts
|
|
2
20
|
var FloPayError = class extends Error {
|
|
3
21
|
constructor(message, type, options) {
|
|
@@ -45,7 +63,7 @@ function getFloPayEnvironment() {
|
|
|
45
63
|
}
|
|
46
64
|
|
|
47
65
|
// src/constants.ts
|
|
48
|
-
var SDK_VERSION = "1.
|
|
66
|
+
var SDK_VERSION = "1.1.3";
|
|
49
67
|
var BILLING_API_URL_STAGING = "https://api.stage.flopay.com";
|
|
50
68
|
var BILLING_API_URL_PRODUCTION = "https://api.flopay.com";
|
|
51
69
|
var DEFAULT_API_BASE_URL = BILLING_API_URL_STAGING;
|
|
@@ -704,7 +722,7 @@ function nonBlank(value) {
|
|
|
704
722
|
const trimmed = value.trim();
|
|
705
723
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
706
724
|
}
|
|
707
|
-
function resolveSessionCurrency(sessionCurrency, items, subscriptions) {
|
|
725
|
+
function resolveSessionCurrency(sessionCurrency, items, subscriptions, products) {
|
|
708
726
|
const session = nonBlank(sessionCurrency);
|
|
709
727
|
if (session) return session;
|
|
710
728
|
for (const item of items ?? []) {
|
|
@@ -715,7 +733,67 @@ function resolveSessionCurrency(sessionCurrency, items, subscriptions) {
|
|
|
715
733
|
const c = nonBlank(sub.currency);
|
|
716
734
|
if (c) return c;
|
|
717
735
|
}
|
|
718
|
-
|
|
736
|
+
for (const product of products ?? []) {
|
|
737
|
+
const c = nonBlank(product.currency);
|
|
738
|
+
if (c) return c;
|
|
739
|
+
}
|
|
740
|
+
return null;
|
|
741
|
+
}
|
|
742
|
+
function foldIntoProducts(items, subscriptions) {
|
|
743
|
+
const products = [];
|
|
744
|
+
for (const sub of subscriptions ?? []) {
|
|
745
|
+
products.push({
|
|
746
|
+
type: "subscription",
|
|
747
|
+
code: nonBlank(sub.code) ?? nonBlank(sub.providerPlanId),
|
|
748
|
+
providerPlanId: sub.providerPlanId,
|
|
749
|
+
name: nonBlank(sub.subscriptionName) ?? nonBlank(sub.providerPlanName) ?? null,
|
|
750
|
+
subscriptionName: sub.subscriptionName ?? null,
|
|
751
|
+
providerPlanName: sub.providerPlanName ?? null,
|
|
752
|
+
quantity: sub.quantity,
|
|
753
|
+
totalAmount: sub.totalAmount,
|
|
754
|
+
overrideAmount: sub.overrideAmount,
|
|
755
|
+
currency: sub.currency,
|
|
756
|
+
metadata: sub.metadata
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
for (const item of items ?? []) {
|
|
760
|
+
products.push({
|
|
761
|
+
type: "item",
|
|
762
|
+
code: nonBlank(item.code) ?? nonBlank(item.providerItemId),
|
|
763
|
+
providerItemId: item.providerItemId,
|
|
764
|
+
name: nonBlank(item.itemName) ?? nonBlank(item.providerItemName) ?? null,
|
|
765
|
+
itemName: item.itemName ?? null,
|
|
766
|
+
providerItemName: item.providerItemName ?? null,
|
|
767
|
+
quantity: item.quantity,
|
|
768
|
+
totalAmount: item.totalAmount,
|
|
769
|
+
overrideAmount: item.overrideAmount,
|
|
770
|
+
currency: item.currency,
|
|
771
|
+
metadata: item.metadata
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
return products;
|
|
775
|
+
}
|
|
776
|
+
function buildProductPayload(product, sessionCurrency) {
|
|
777
|
+
const code = nonBlank(product.code) ?? nonBlank(product.providerItemId) ?? nonBlank(product.providerPlanId);
|
|
778
|
+
if (!code) {
|
|
779
|
+
throw new Error(
|
|
780
|
+
"CheckoutProduct requires `code` (or the deprecated `providerItemId` / `providerPlanId`)."
|
|
781
|
+
);
|
|
782
|
+
}
|
|
783
|
+
const name = nonBlank(product.name) ?? nonBlank(product.itemName) ?? nonBlank(product.providerItemName) ?? nonBlank(product.subscriptionName) ?? nonBlank(product.providerPlanName) ?? null;
|
|
784
|
+
const payload = {
|
|
785
|
+
type: product.type,
|
|
786
|
+
code,
|
|
787
|
+
name,
|
|
788
|
+
quantity: product.quantity ?? 1,
|
|
789
|
+
totalAmount: product.totalAmount,
|
|
790
|
+
overrideAmount: product.overrideAmount ?? null,
|
|
791
|
+
currency: nonBlank(product.currency) ?? sessionCurrency
|
|
792
|
+
};
|
|
793
|
+
if (product.metadata) {
|
|
794
|
+
payload["metadata"] = product.metadata;
|
|
795
|
+
}
|
|
796
|
+
return payload;
|
|
719
797
|
}
|
|
720
798
|
function buildItemPayload(item, sessionCurrency) {
|
|
721
799
|
const code = nonBlank(item.code) ?? nonBlank(item.providerItemId);
|
|
@@ -765,13 +843,15 @@ function buildSubscriptionPayload(subscription, sessionCurrency) {
|
|
|
765
843
|
// src/display.ts
|
|
766
844
|
function buildCheckoutDisplayData(session, options = {}) {
|
|
767
845
|
const itemsList = [];
|
|
768
|
-
const
|
|
769
|
-
const
|
|
770
|
-
const
|
|
846
|
+
const products = session.products ?? [];
|
|
847
|
+
const subscriptions = products.filter((p) => p.type === "subscription");
|
|
848
|
+
const items = products.filter((p) => p.type === "item");
|
|
849
|
+
const resolvedCurrency = resolveSessionCurrency(session.currency, void 0, void 0, products);
|
|
850
|
+
const currency = (resolvedCurrency ?? "USD").toUpperCase();
|
|
771
851
|
for (const sub of subscriptions) {
|
|
772
852
|
const originalPrice = sub.totalAmount ?? 0;
|
|
773
853
|
const discountedPrice = sub.overrideAmount ?? originalPrice;
|
|
774
|
-
let name = sub.
|
|
854
|
+
let name = sub.name || sub.code || "Subscription";
|
|
775
855
|
if (name === "4-WEEK PLAN" && discountedPrice <= 1) {
|
|
776
856
|
name = "7-DAY TRIAL: FULL ACCESS";
|
|
777
857
|
}
|
|
@@ -788,7 +868,7 @@ function buildCheckoutDisplayData(session, options = {}) {
|
|
|
788
868
|
const originalPrice = item.totalAmount ?? 0;
|
|
789
869
|
const discountedPrice = item.overrideAmount ?? originalPrice;
|
|
790
870
|
itemsList.push({
|
|
791
|
-
name: item.
|
|
871
|
+
name: item.name || item.code || "Item",
|
|
792
872
|
quantity: item.quantity,
|
|
793
873
|
price: discountedPrice,
|
|
794
874
|
originalPrice
|
|
@@ -803,8 +883,13 @@ function buildCheckoutDisplayData(session, options = {}) {
|
|
|
803
883
|
originalPrice: session.amount / 100
|
|
804
884
|
});
|
|
805
885
|
}
|
|
806
|
-
const
|
|
807
|
-
const
|
|
886
|
+
const lineOriginalTotal = itemsList.reduce((sum, i) => sum + i.originalPrice * i.quantity, 0);
|
|
887
|
+
const lineTotal = itemsList.reduce((sum, i) => sum + i.price * i.quantity, 0);
|
|
888
|
+
const hasBackendTotals = typeof session.totalAmount === "number" && Number.isFinite(session.totalAmount);
|
|
889
|
+
const hasBackendSubtotal = typeof session.subtotalAmount === "number" && Number.isFinite(session.subtotalAmount);
|
|
890
|
+
const hasBackendDiscount = typeof session.discountAmount === "number" && Number.isFinite(session.discountAmount);
|
|
891
|
+
const total = hasBackendTotals ? session.totalAmount : lineTotal;
|
|
892
|
+
const originalTotal = hasBackendSubtotal ? session.subtotalAmount : lineOriginalTotal;
|
|
808
893
|
const totalSave = Math.max(0, originalTotal - total);
|
|
809
894
|
const discountPercent = originalTotal > 0 ? Math.round(totalSave / originalTotal * 100) : 0;
|
|
810
895
|
return {
|
|
@@ -813,7 +898,8 @@ function buildCheckoutDisplayData(session, options = {}) {
|
|
|
813
898
|
total,
|
|
814
899
|
originalTotal,
|
|
815
900
|
totalSave,
|
|
816
|
-
discountPercent
|
|
901
|
+
discountPercent,
|
|
902
|
+
...hasBackendDiscount ? { couponDiscount: session.discountAmount } : {}
|
|
817
903
|
};
|
|
818
904
|
}
|
|
819
905
|
|
|
@@ -853,8 +939,10 @@ export {
|
|
|
853
939
|
authenticationError,
|
|
854
940
|
buildCheckoutDisplayData,
|
|
855
941
|
buildItemPayload,
|
|
942
|
+
buildProductPayload,
|
|
856
943
|
buildSubscriptionPayload,
|
|
857
944
|
configureFlopay,
|
|
945
|
+
foldIntoProducts,
|
|
858
946
|
getConfiguredBillingApiUrl,
|
|
859
947
|
getCountryByCode,
|
|
860
948
|
getCurrencyByCountry,
|
|
@@ -868,6 +956,7 @@ export {
|
|
|
868
956
|
isValidPublishableKey,
|
|
869
957
|
isValidSecretKey,
|
|
870
958
|
networkError,
|
|
959
|
+
normalizeGatewayEnvironment,
|
|
871
960
|
rateLimitError,
|
|
872
961
|
resolveAVSConfig,
|
|
873
962
|
resolveBillingApiUrl,
|