@flopay/js 1.4.0 → 1.4.1
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 -2
- package/dist/index.cjs +112 -125
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +111 -114
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -24,7 +24,13 @@ const flopay = await loadFloPay('pk_test_...', {
|
|
|
24
24
|
});
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
`loadFloPay` caches
|
|
27
|
+
`loadFloPay` caches by publishable key and behavior-affecting options. Concurrent
|
|
28
|
+
calls with the same key and options share one in-flight provider initialization
|
|
29
|
+
and resolve to the same `FloPay` instance. A failed initialization is evicted so
|
|
30
|
+
a later call can retry. The optional second argument accepts
|
|
31
|
+
`Omit<FloPayConfig, 'publishableKey'>`, including `billingApiUrl`, `locale`,
|
|
32
|
+
`appearance`, and `telemetry`; set `telemetry: false` to opt out of privacy-safe
|
|
33
|
+
operational telemetry.
|
|
28
34
|
|
|
29
35
|
### Create and Mount Elements
|
|
30
36
|
|
|
@@ -267,7 +273,7 @@ The same default-on behavior and boolean opt-out apply to direct `FloPay`,
|
|
|
267
273
|
|
|
268
274
|
| Export | Description |
|
|
269
275
|
|--------|-------------|
|
|
270
|
-
| `loadFloPay(publishableKey, options?)` | Initializes the SDK. Returns a `Promise<FloPay>`.
|
|
276
|
+
| `loadFloPay(publishableKey, options?)` | Initializes the SDK. Returns a `Promise<FloPay>`. Shares successful and in-flight work by key; failed work remains retryable. |
|
|
271
277
|
| `FloPay` | Main SDK class. Methods: `elements()`, `submitElements()`, `createPaymentMethod()`, `confirmCardPayment()`, `cardCapture()`, `confirmPayment()`, `confirmPayPalPayment()`, `resumePayPalPayment()`, `retrieveSession()`, `retrieveUnifiedSession()`, `getRawProvider()`, `destroy()` |
|
|
272
278
|
| `FloPayElements` | Element group manager. Methods: `create(type, options?)`, `getElement(type)`, `submit()`, `destroy()` |
|
|
273
279
|
| `StripeAdapter` | `PaymentProviderAdapter` implementation for Stripe |
|
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// src/index.ts
|
|
@@ -48,7 +38,14 @@ module.exports = __toCommonJS(index_exports);
|
|
|
48
38
|
var import_shared7 = require("@flopay/shared");
|
|
49
39
|
|
|
50
40
|
// src/stripe-adapter.ts
|
|
41
|
+
var import_stripe_js = require("@stripe/stripe-js");
|
|
51
42
|
var import_shared = require("@flopay/shared");
|
|
43
|
+
|
|
44
|
+
// src/card-three-ds.ts
|
|
45
|
+
var CARD_THREE_DS_ATTEMPT_TTL_MS = 15 * 6e4;
|
|
46
|
+
var MAX_CARD_THREE_DS_ATTEMPTS = 32;
|
|
47
|
+
|
|
48
|
+
// src/stripe-adapter.ts
|
|
52
49
|
function toStripeElementType(type) {
|
|
53
50
|
const map = {
|
|
54
51
|
payment: "payment",
|
|
@@ -71,8 +68,6 @@ function toStripeAppearanceTheme(theme) {
|
|
|
71
68
|
return "stripe";
|
|
72
69
|
}
|
|
73
70
|
}
|
|
74
|
-
var CARD_THREE_DS_ATTEMPT_TTL_MS = 15 * 6e4;
|
|
75
|
-
var MAX_CARD_THREE_DS_ATTEMPTS = 32;
|
|
76
71
|
function cardThreeDsNow() {
|
|
77
72
|
return globalThis.performance?.now() ?? Date.now();
|
|
78
73
|
}
|
|
@@ -99,6 +94,24 @@ function wrapStripeElement(stripeElement) {
|
|
|
99
94
|
}
|
|
100
95
|
};
|
|
101
96
|
}
|
|
97
|
+
function toStripeBillingDetails(billing) {
|
|
98
|
+
return {
|
|
99
|
+
billing_details: {
|
|
100
|
+
...billing.email ? { email: billing.email } : {},
|
|
101
|
+
...billing.name ? { name: billing.name } : {},
|
|
102
|
+
...billing.address ? {
|
|
103
|
+
address: {
|
|
104
|
+
...billing.address.country ? { country: billing.address.country } : {},
|
|
105
|
+
...billing.address.postal_code ? { postal_code: billing.address.postal_code } : {},
|
|
106
|
+
...billing.address.city ? { city: billing.address.city } : {},
|
|
107
|
+
...billing.address.line1 ? { line1: billing.address.line1 } : {},
|
|
108
|
+
...billing.address.line2 ? { line2: billing.address.line2 } : {},
|
|
109
|
+
...billing.address.state ? { state: billing.address.state } : {}
|
|
110
|
+
}
|
|
111
|
+
} : {}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
102
115
|
var StripeAdapter = class {
|
|
103
116
|
constructor() {
|
|
104
117
|
this.name = "stripe";
|
|
@@ -116,17 +129,7 @@ var StripeAdapter = class {
|
|
|
116
129
|
if (typeof window === "undefined") {
|
|
117
130
|
return;
|
|
118
131
|
}
|
|
119
|
-
|
|
120
|
-
try {
|
|
121
|
-
({ loadStripe } = await import("@stripe/stripe-js"));
|
|
122
|
-
} catch {
|
|
123
|
-
throw new import_shared.FloPayError(
|
|
124
|
-
"Failed to load @stripe/stripe-js. Reinstall @flopay/js.",
|
|
125
|
-
"api_error",
|
|
126
|
-
{ code: "StripeJsLoadFailed" }
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
const stripe = await loadStripe(config.publishableKey, {
|
|
132
|
+
const stripe = await (0, import_stripe_js.loadStripe)(config.publishableKey, {
|
|
130
133
|
locale: config.locale ?? "auto"
|
|
131
134
|
});
|
|
132
135
|
if (!stripe) {
|
|
@@ -237,22 +240,7 @@ var StripeAdapter = class {
|
|
|
237
240
|
};
|
|
238
241
|
}
|
|
239
242
|
const cardNumberEl = this.elements.getElement("cardNumber");
|
|
240
|
-
const stripeBilling = billingDetails ? {
|
|
241
|
-
billing_details: {
|
|
242
|
-
...billingDetails.email ? { email: billingDetails.email } : {},
|
|
243
|
-
...billingDetails.name ? { name: billingDetails.name } : {},
|
|
244
|
-
...billingDetails.address ? {
|
|
245
|
-
address: {
|
|
246
|
-
...billingDetails.address.country ? { country: billingDetails.address.country } : {},
|
|
247
|
-
...billingDetails.address.postal_code ? { postal_code: billingDetails.address.postal_code } : {},
|
|
248
|
-
...billingDetails.address.city ? { city: billingDetails.address.city } : {},
|
|
249
|
-
...billingDetails.address.line1 ? { line1: billingDetails.address.line1 } : {},
|
|
250
|
-
...billingDetails.address.line2 ? { line2: billingDetails.address.line2 } : {},
|
|
251
|
-
...billingDetails.address.state ? { state: billingDetails.address.state } : {}
|
|
252
|
-
}
|
|
253
|
-
} : {}
|
|
254
|
-
}
|
|
255
|
-
} : {};
|
|
243
|
+
const stripeBilling = billingDetails ? toStripeBillingDetails(billingDetails) : {};
|
|
256
244
|
const { error, paymentMethod } = cardNumberEl ? await this.stripe.createPaymentMethod({
|
|
257
245
|
type: "card",
|
|
258
246
|
card: cardNumberEl,
|
|
@@ -372,22 +360,7 @@ var StripeAdapter = class {
|
|
|
372
360
|
);
|
|
373
361
|
}
|
|
374
362
|
const billing = params.billingDetails;
|
|
375
|
-
const paymentMethodData = billing ?
|
|
376
|
-
billing_details: {
|
|
377
|
-
...billing.email ? { email: billing.email } : {},
|
|
378
|
-
...billing.name ? { name: billing.name } : {},
|
|
379
|
-
...billing.address ? {
|
|
380
|
-
address: {
|
|
381
|
-
...billing.address.country ? { country: billing.address.country } : {},
|
|
382
|
-
...billing.address.postal_code ? { postal_code: billing.address.postal_code } : {},
|
|
383
|
-
...billing.address.city ? { city: billing.address.city } : {},
|
|
384
|
-
...billing.address.line1 ? { line1: billing.address.line1 } : {},
|
|
385
|
-
...billing.address.line2 ? { line2: billing.address.line2 } : {},
|
|
386
|
-
...billing.address.state ? { state: billing.address.state } : {}
|
|
387
|
-
}
|
|
388
|
-
} : {}
|
|
389
|
-
}
|
|
390
|
-
} : void 0;
|
|
363
|
+
const paymentMethodData = billing ? toStripeBillingDetails(billing) : void 0;
|
|
391
364
|
const { error, paymentIntent } = await this.stripe.confirmPayment({
|
|
392
365
|
elements: this.elements,
|
|
393
366
|
clientSecret: params.clientSecret,
|
|
@@ -612,6 +585,19 @@ var FloPayElements = class {
|
|
|
612
585
|
// src/payment-api.ts
|
|
613
586
|
var import_shared4 = require("@flopay/shared");
|
|
614
587
|
|
|
588
|
+
// src/api-error.ts
|
|
589
|
+
function readErrorString(value) {
|
|
590
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
591
|
+
}
|
|
592
|
+
function readErrorMessage(value) {
|
|
593
|
+
if (typeof value === "string") return value.trim() ? value : void 0;
|
|
594
|
+
if (Array.isArray(value)) {
|
|
595
|
+
const joined = value.filter((entry) => typeof entry === "string" && entry.trim().length > 0).join("; ");
|
|
596
|
+
return joined || void 0;
|
|
597
|
+
}
|
|
598
|
+
return void 0;
|
|
599
|
+
}
|
|
600
|
+
|
|
615
601
|
// src/session-display-cache.ts
|
|
616
602
|
var STORAGE_KEY_PREFIX = "flopay_session_display:";
|
|
617
603
|
var DEFAULT_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -1035,17 +1021,10 @@ function telemetryFailure(error, fallbackCode) {
|
|
|
1035
1021
|
};
|
|
1036
1022
|
}
|
|
1037
1023
|
function readString(payload, key) {
|
|
1038
|
-
|
|
1039
|
-
return typeof value === "string" && value.trim() ? value : void 0;
|
|
1024
|
+
return readErrorString(payload?.[key]);
|
|
1040
1025
|
}
|
|
1041
1026
|
function readMessage(payload, key) {
|
|
1042
|
-
|
|
1043
|
-
if (typeof value === "string") return value.trim() ? value : void 0;
|
|
1044
|
-
if (Array.isArray(value)) {
|
|
1045
|
-
const joined = value.filter((entry) => typeof entry === "string" && entry.trim().length > 0).join("; ");
|
|
1046
|
-
return joined || void 0;
|
|
1047
|
-
}
|
|
1048
|
-
return void 0;
|
|
1027
|
+
return readErrorMessage(payload?.[key]);
|
|
1049
1028
|
}
|
|
1050
1029
|
function readNumber(payload, key) {
|
|
1051
1030
|
const value = payload?.[key];
|
|
@@ -2877,8 +2856,6 @@ function telemetryProvider(name) {
|
|
|
2877
2856
|
if (name === "stripe" || name === "paypal" || name === "pcivault") return name;
|
|
2878
2857
|
return "other";
|
|
2879
2858
|
}
|
|
2880
|
-
var CARD_THREE_DS_ATTEMPT_TTL_MS2 = 15 * 6e4;
|
|
2881
|
-
var MAX_CARD_THREE_DS_ATTEMPTS2 = 32;
|
|
2882
2859
|
var FloPay = class {
|
|
2883
2860
|
constructor(provider, config, telemetryReporter) {
|
|
2884
2861
|
this.currentElements = null;
|
|
@@ -3060,7 +3037,7 @@ var FloPay = class {
|
|
|
3060
3037
|
trackCardThreeDsAttempt(attemptId, startedAt) {
|
|
3061
3038
|
this.pruneExpiredCardThreeDsAttempts(startedAt);
|
|
3062
3039
|
if (this.cardThreeDsStartedAt.has(attemptId)) return false;
|
|
3063
|
-
while (this.cardThreeDsStartedAt.size >=
|
|
3040
|
+
while (this.cardThreeDsStartedAt.size >= MAX_CARD_THREE_DS_ATTEMPTS) {
|
|
3064
3041
|
const oldestAttemptId = this.cardThreeDsStartedAt.keys().next().value;
|
|
3065
3042
|
if (oldestAttemptId === void 0) break;
|
|
3066
3043
|
this.cardThreeDsStartedAt.delete(oldestAttemptId);
|
|
@@ -3076,7 +3053,7 @@ var FloPay = class {
|
|
|
3076
3053
|
}
|
|
3077
3054
|
pruneExpiredCardThreeDsAttempts(now) {
|
|
3078
3055
|
for (const [attemptId, startedAt] of this.cardThreeDsStartedAt) {
|
|
3079
|
-
if (now - startedAt >=
|
|
3056
|
+
if (now - startedAt >= CARD_THREE_DS_ATTEMPT_TTL_MS) {
|
|
3080
3057
|
this.cardThreeDsStartedAt.delete(attemptId);
|
|
3081
3058
|
}
|
|
3082
3059
|
}
|
|
@@ -3516,20 +3493,21 @@ function instanceCacheKey(publishableKey, options) {
|
|
|
3516
3493
|
stableCacheValue(options?.appearance ?? null)
|
|
3517
3494
|
]);
|
|
3518
3495
|
}
|
|
3496
|
+
var initializationCache = /* @__PURE__ */ new Map();
|
|
3519
3497
|
async function loadFloPay(publishableKey, options) {
|
|
3520
3498
|
if (!publishableKey) {
|
|
3521
|
-
const
|
|
3499
|
+
const reporter = new TelemetryReporter({
|
|
3522
3500
|
billingApiUrl: (0, import_shared7.resolveBillingApiUrl)(options?.billingApiUrl),
|
|
3523
3501
|
sdkVersion: import_shared7.SDK_VERSION,
|
|
3524
3502
|
enabled: options?.telemetry !== false
|
|
3525
3503
|
});
|
|
3526
|
-
|
|
3504
|
+
reporter.error({
|
|
3527
3505
|
errorCode: "CONFIGURATION_INVALID",
|
|
3528
3506
|
stage: "sdk_initialize",
|
|
3529
3507
|
paymentMethodCategory: "unknown"
|
|
3530
3508
|
});
|
|
3531
|
-
void
|
|
3532
|
-
}).finally(() =>
|
|
3509
|
+
void reporter.flush().catch(() => {
|
|
3510
|
+
}).finally(() => reporter.destroy());
|
|
3533
3511
|
throw new import_shared7.FloPayError(
|
|
3534
3512
|
"A publishable key is required to initialize FloPay.",
|
|
3535
3513
|
"validation_error",
|
|
@@ -3547,71 +3525,80 @@ async function loadFloPay(publishableKey, options) {
|
|
|
3547
3525
|
}
|
|
3548
3526
|
return cached;
|
|
3549
3527
|
}
|
|
3528
|
+
const initializing = initializationCache.get(cacheKey);
|
|
3529
|
+
if (initializing) return initializing;
|
|
3550
3530
|
const config = {
|
|
3551
|
-
|
|
3552
|
-
|
|
3531
|
+
...options,
|
|
3532
|
+
publishableKey
|
|
3553
3533
|
};
|
|
3554
|
-
const
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3534
|
+
const initialization = (async () => {
|
|
3535
|
+
const reporter = new TelemetryReporter({
|
|
3536
|
+
billingApiUrl: (0, import_shared7.resolveBillingApiUrl)(config.billingApiUrl),
|
|
3537
|
+
sdkVersion: import_shared7.SDK_VERSION,
|
|
3538
|
+
enabled: config.telemetry !== false
|
|
3539
|
+
});
|
|
3540
|
+
const initializationStarted = reporter.now();
|
|
3541
|
+
reporter.log({ name: "sdk.initialize.started", stage: "sdk_initialize" });
|
|
3542
|
+
reporter.log({ name: "sdk.cache.miss", stage: "sdk_initialize" });
|
|
3543
|
+
reporter.log({
|
|
3544
|
+
name: "provider.load.started",
|
|
3545
|
+
stage: "provider_load",
|
|
3546
|
+
provider: "stripe"
|
|
3547
|
+
});
|
|
3548
|
+
const adapter = new StripeAdapter();
|
|
3549
|
+
try {
|
|
3550
|
+
await adapter.initialize(config);
|
|
3551
|
+
} catch (error) {
|
|
3552
|
+
reporter.error({
|
|
3553
|
+
errorCode: "SDK_INITIALIZATION_FAILED",
|
|
3554
|
+
stage: "sdk_initialize",
|
|
3555
|
+
provider: "stripe",
|
|
3556
|
+
paymentMethodCategory: "unknown"
|
|
3557
|
+
});
|
|
3558
|
+
reporter.destroy();
|
|
3559
|
+
throw error;
|
|
3560
|
+
}
|
|
3561
|
+
reporter.log({ name: "provider.ready", stage: "provider_ready", provider: "stripe" });
|
|
3562
|
+
reporter.log({
|
|
3563
|
+
name: "provider.availability.checked",
|
|
3564
|
+
stage: "provider_ready",
|
|
3565
|
+
provider: "stripe"
|
|
3566
|
+
});
|
|
3567
|
+
reporter.log({ name: "sdk.initialize.ready", stage: "sdk_initialize" });
|
|
3568
|
+
const initializationDuration = reporter.now() - initializationStarted;
|
|
3569
|
+
reporter.performance({
|
|
3573
3570
|
stage: "sdk_initialize",
|
|
3574
|
-
|
|
3575
|
-
|
|
3571
|
+
durationMs: initializationDuration,
|
|
3572
|
+
durationMode: "machine",
|
|
3573
|
+
provider: "stripe"
|
|
3576
3574
|
});
|
|
3577
|
-
reporter.
|
|
3578
|
-
|
|
3575
|
+
reporter.performance({
|
|
3576
|
+
stage: "provider_ready",
|
|
3577
|
+
durationMs: initializationDuration,
|
|
3578
|
+
durationMode: "machine",
|
|
3579
|
+
provider: "stripe"
|
|
3580
|
+
});
|
|
3581
|
+
const instance = createInstrumentedFloPay(adapter, config, reporter);
|
|
3582
|
+
instanceCache.set(cacheKey, instance);
|
|
3583
|
+
return instance;
|
|
3584
|
+
})();
|
|
3585
|
+
initializationCache.set(cacheKey, initialization);
|
|
3586
|
+
try {
|
|
3587
|
+
return await initialization;
|
|
3588
|
+
} finally {
|
|
3589
|
+
if (initializationCache.get(cacheKey) === initialization) {
|
|
3590
|
+
initializationCache.delete(cacheKey);
|
|
3591
|
+
}
|
|
3579
3592
|
}
|
|
3580
|
-
reporter.log({ name: "provider.ready", stage: "provider_ready", provider: "stripe" });
|
|
3581
|
-
reporter.log({
|
|
3582
|
-
name: "provider.availability.checked",
|
|
3583
|
-
stage: "provider_ready",
|
|
3584
|
-
provider: "stripe"
|
|
3585
|
-
});
|
|
3586
|
-
reporter.log({ name: "sdk.initialize.ready", stage: "sdk_initialize" });
|
|
3587
|
-
const initializationDuration = reporter.now() - initializationStarted;
|
|
3588
|
-
reporter.performance({
|
|
3589
|
-
stage: "sdk_initialize",
|
|
3590
|
-
durationMs: initializationDuration,
|
|
3591
|
-
durationMode: "machine",
|
|
3592
|
-
provider: "stripe"
|
|
3593
|
-
});
|
|
3594
|
-
reporter.performance({
|
|
3595
|
-
stage: "provider_ready",
|
|
3596
|
-
durationMs: initializationDuration,
|
|
3597
|
-
durationMode: "machine",
|
|
3598
|
-
provider: "stripe"
|
|
3599
|
-
});
|
|
3600
|
-
const instance = createInstrumentedFloPay(adapter, config, reporter);
|
|
3601
|
-
instanceCache.set(cacheKey, instance);
|
|
3602
|
-
return instance;
|
|
3603
3593
|
}
|
|
3604
3594
|
|
|
3605
3595
|
// src/create-checkout-session.ts
|
|
3606
3596
|
var import_shared8 = require("@flopay/shared");
|
|
3607
3597
|
var MAX_COUPON_CODES = 5;
|
|
3608
|
-
function readString2(value) {
|
|
3609
|
-
return typeof value === "string" && value.trim() ? value : void 0;
|
|
3610
|
-
}
|
|
3611
3598
|
function buildCheckoutSessionError(status, payload) {
|
|
3612
3599
|
const nested = payload?.error;
|
|
3613
|
-
const code =
|
|
3614
|
-
const message =
|
|
3600
|
+
const code = readErrorString(payload?.code) ?? readErrorString(nested?.code) ?? `http_${status}`;
|
|
3601
|
+
const message = readErrorString(payload?.message) ?? readErrorString(nested?.message) ?? defaultMessageForCode(code, status);
|
|
3615
3602
|
return new import_shared8.FloPayError(message, "api_error", { code, statusCode: status });
|
|
3616
3603
|
}
|
|
3617
3604
|
function defaultMessageForCode(code, status) {
|