@flopay/react 0.5.3 → 0.5.5
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.cjs +148 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +148 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -559,6 +559,27 @@ function buildDeclineEvent(method, input, overrides) {
|
|
|
559
559
|
...declineCode ? { declineCode } : {}
|
|
560
560
|
};
|
|
561
561
|
}
|
|
562
|
+
function isRecord(value) {
|
|
563
|
+
return typeof value === "object" && value !== null;
|
|
564
|
+
}
|
|
565
|
+
function readString(payload, key) {
|
|
566
|
+
const value = payload?.[key];
|
|
567
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
568
|
+
}
|
|
569
|
+
function buildFloPayApiError(payload, fallbackMessage) {
|
|
570
|
+
const nestedError = isRecord(payload?.error) ? payload.error : null;
|
|
571
|
+
const message = readString(payload, "message") ?? readString(nestedError, "message") ?? fallbackMessage;
|
|
572
|
+
const code = readString(payload, "code") ?? readString(payload, "gatewayErrorCode") ?? readString(nestedError, "code");
|
|
573
|
+
const declineCode = readString(payload, "declineCode") ?? readString(payload, "gatewayDeclineReason") ?? readString(payload, "decline_code") ?? readString(nestedError, "decline_code");
|
|
574
|
+
return new import_shared3.FloPayError(message, "api_error", {
|
|
575
|
+
...code ? { code } : {},
|
|
576
|
+
...declineCode ? { declineCode } : {}
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
async function buildFloPayApiErrorFromResponse(response, fallbackMessage) {
|
|
580
|
+
const payload = await response.json().catch(() => null);
|
|
581
|
+
return buildFloPayApiError(payload, fallbackMessage);
|
|
582
|
+
}
|
|
562
583
|
function mapPayPalIntentStatusToPaymentResult(status) {
|
|
563
584
|
if (status === "succeeded") {
|
|
564
585
|
return "succeeded";
|
|
@@ -568,6 +589,29 @@ function mapPayPalIntentStatusToPaymentResult(status) {
|
|
|
568
589
|
}
|
|
569
590
|
return "failed";
|
|
570
591
|
}
|
|
592
|
+
function resolvePaymentIntentPaymentMethodId(paymentIntent) {
|
|
593
|
+
const paymentMethod = paymentIntent?.payment_method;
|
|
594
|
+
if (typeof paymentMethod === "string" && paymentMethod.startsWith("pm_")) {
|
|
595
|
+
return paymentMethod;
|
|
596
|
+
}
|
|
597
|
+
if (paymentMethod && typeof paymentMethod === "object" && typeof paymentMethod.id === "string") {
|
|
598
|
+
return paymentMethod.id;
|
|
599
|
+
}
|
|
600
|
+
return void 0;
|
|
601
|
+
}
|
|
602
|
+
async function retrievePaymentIntentFromProvider(provider, clientSecret) {
|
|
603
|
+
const retriever = provider;
|
|
604
|
+
if (!retriever?.retrievePaymentIntent) {
|
|
605
|
+
return null;
|
|
606
|
+
}
|
|
607
|
+
const { paymentIntent, error } = await retriever.retrievePaymentIntent(clientSecret);
|
|
608
|
+
if (error) {
|
|
609
|
+
throw new import_shared3.FloPayError(error.message ?? "Failed to retrieve payment intent.", "api_error", {
|
|
610
|
+
...error.code ? { code: error.code } : {}
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
return paymentIntent ?? null;
|
|
614
|
+
}
|
|
571
615
|
function resolveTokenizedPaymentMethodId(tokenizedBody) {
|
|
572
616
|
const candidates = [
|
|
573
617
|
tokenizedBody?.id,
|
|
@@ -812,7 +856,16 @@ function PayPalButtonInner({
|
|
|
812
856
|
setup_future_usage: "off_session"
|
|
813
857
|
})
|
|
814
858
|
});
|
|
815
|
-
if (!intentResponse.ok)
|
|
859
|
+
if (!intentResponse.ok) {
|
|
860
|
+
const intentError = await buildFloPayApiErrorFromResponse(
|
|
861
|
+
intentResponse,
|
|
862
|
+
"Failed to create payment intent"
|
|
863
|
+
);
|
|
864
|
+
onErrorChange?.(intentError.message);
|
|
865
|
+
onDecline?.(buildDeclineEvent("paypal", intentError));
|
|
866
|
+
event.paymentFailed({ reason: "fail", message: intentError.message });
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
816
869
|
const intentJson = await intentResponse.json();
|
|
817
870
|
const intentClientSecret = intentJson.data?.id;
|
|
818
871
|
if (!intentClientSecret) throw new Error("No client_secret in payment intent response");
|
|
@@ -949,7 +1002,16 @@ function WalletButtonInner({
|
|
|
949
1002
|
isPaypal: false
|
|
950
1003
|
})
|
|
951
1004
|
});
|
|
952
|
-
if (!intentResponse.ok)
|
|
1005
|
+
if (!intentResponse.ok) {
|
|
1006
|
+
const intentError = await buildFloPayApiErrorFromResponse(
|
|
1007
|
+
intentResponse,
|
|
1008
|
+
"Failed to create payment intent"
|
|
1009
|
+
);
|
|
1010
|
+
onErrorChange?.(intentError.message);
|
|
1011
|
+
onDecline?.(buildDeclineEvent(method, intentError));
|
|
1012
|
+
event.paymentFailed({ reason: "fail", message: intentError.message });
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
953
1015
|
const intentJson = await intentResponse.json();
|
|
954
1016
|
const intentClientSecret = intentJson.data?.id;
|
|
955
1017
|
if (!intentClientSecret) throw new Error("No client_secret in payment intent response");
|
|
@@ -1564,7 +1626,18 @@ function SplitCardFormInner({
|
|
|
1564
1626
|
isPaypal: false
|
|
1565
1627
|
})
|
|
1566
1628
|
});
|
|
1567
|
-
if (!intentResponse.ok)
|
|
1629
|
+
if (!intentResponse.ok) {
|
|
1630
|
+
const intentError = await buildFloPayApiErrorFromResponse(
|
|
1631
|
+
intentResponse,
|
|
1632
|
+
"Failed to create payment intent"
|
|
1633
|
+
);
|
|
1634
|
+
setOverlayStatus("error");
|
|
1635
|
+
updateError(intentError.message);
|
|
1636
|
+
onError?.(intentError);
|
|
1637
|
+
emitDecline("card", intentError);
|
|
1638
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1568
1641
|
const intentJson = await intentResponse.json();
|
|
1569
1642
|
const intentClientSecret = intentJson.data?.id;
|
|
1570
1643
|
if (!intentClientSecret) throw new import_shared5.FloPayError("No client_secret in payment intent response", "api_error");
|
|
@@ -1580,11 +1653,26 @@ function SplitCardFormInner({
|
|
|
1580
1653
|
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
1581
1654
|
return;
|
|
1582
1655
|
}
|
|
1656
|
+
const rawProvider = typeof flopay.getRawProvider === "function" ? flopay.getRawProvider() : null;
|
|
1657
|
+
const confirmedPaymentIntent = await retrievePaymentIntentFromProvider(
|
|
1658
|
+
rawProvider,
|
|
1659
|
+
intentClientSecret
|
|
1660
|
+
);
|
|
1661
|
+
const paymentIntentId = confirmResult.paymentIntentId ?? confirmedPaymentIntent?.id;
|
|
1662
|
+
const paymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? pmResult.paymentMethodId;
|
|
1663
|
+
if (!paymentIntentId) {
|
|
1664
|
+
const error2 = new import_shared5.FloPayError("No payment intent returned after confirmation.", "api_error");
|
|
1665
|
+
setOverlayStatus("error");
|
|
1666
|
+
updateError(error2.message);
|
|
1667
|
+
onError?.(error2);
|
|
1668
|
+
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_ERROR_DELAY_MS));
|
|
1669
|
+
return;
|
|
1670
|
+
}
|
|
1583
1671
|
handedOff = isSelfContained;
|
|
1584
1672
|
dispatchTokenizedBody({
|
|
1585
|
-
id:
|
|
1673
|
+
id: paymentMethodId,
|
|
1586
1674
|
type: "card",
|
|
1587
|
-
threeDSecureActionResultTokenId:
|
|
1675
|
+
threeDSecureActionResultTokenId: paymentIntentId,
|
|
1588
1676
|
originalPaymentMethodId: pmResult.paymentMethodId
|
|
1589
1677
|
});
|
|
1590
1678
|
} catch (err) {
|
|
@@ -2405,12 +2493,12 @@ async function processSavedPaymentWithIntent({
|
|
|
2405
2493
|
));
|
|
2406
2494
|
const intentJson = await intentResponse.json().catch(() => null);
|
|
2407
2495
|
if (!intentResponse.ok) {
|
|
2496
|
+
const intentError = buildFloPayApiError(
|
|
2497
|
+
intentJson,
|
|
2498
|
+
"Failed to create payment intent."
|
|
2499
|
+
);
|
|
2408
2500
|
throw Object.assign(
|
|
2409
|
-
|
|
2410
|
-
intentJson?.message ?? "Failed to create payment intent.",
|
|
2411
|
-
"api_error",
|
|
2412
|
-
{ code: intentJson?.code ?? intentJson?.gatewayErrorCode }
|
|
2413
|
-
),
|
|
2501
|
+
intentError,
|
|
2414
2502
|
{ checkoutMethod: "card" }
|
|
2415
2503
|
);
|
|
2416
2504
|
}
|
|
@@ -2433,7 +2521,14 @@ async function processSavedPaymentWithIntent({
|
|
|
2433
2521
|
{ checkoutMethod: "card" }
|
|
2434
2522
|
);
|
|
2435
2523
|
}
|
|
2436
|
-
|
|
2524
|
+
const rawProvider = typeof flopay.getRawProvider === "function" ? flopay.getRawProvider() : null;
|
|
2525
|
+
const confirmedPaymentIntent = await retrievePaymentIntentFromProvider(
|
|
2526
|
+
rawProvider,
|
|
2527
|
+
intentClientSecret
|
|
2528
|
+
);
|
|
2529
|
+
const confirmedPaymentIntentId = confirmResult.paymentIntentId ?? confirmedPaymentIntent?.id;
|
|
2530
|
+
const confirmedPaymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? paymentMethodId;
|
|
2531
|
+
if (!confirmedPaymentIntentId || confirmResult.status !== "succeeded" && confirmResult.status !== "processing" && confirmResult.status !== "requires_capture") {
|
|
2437
2532
|
throw Object.assign(
|
|
2438
2533
|
new import_shared6.FloPayError(
|
|
2439
2534
|
`Unfortunately, your payment could not be processed. Please try again using a different payment method or contact your bank for assistance. If the issue persists, feel free to reach out to us for support.`,
|
|
@@ -2450,9 +2545,9 @@ async function processSavedPaymentWithIntent({
|
|
|
2450
2545
|
sessionId,
|
|
2451
2546
|
session,
|
|
2452
2547
|
tokenizedData: {
|
|
2453
|
-
id:
|
|
2548
|
+
id: confirmedPaymentMethodId,
|
|
2454
2549
|
type: "card",
|
|
2455
|
-
threeDSecureActionResultTokenId:
|
|
2550
|
+
threeDSecureActionResultTokenId: confirmedPaymentIntentId
|
|
2456
2551
|
},
|
|
2457
2552
|
returnUrl
|
|
2458
2553
|
});
|
|
@@ -2467,8 +2562,8 @@ async function processSavedPaymentWithIntent({
|
|
|
2467
2562
|
});
|
|
2468
2563
|
return {
|
|
2469
2564
|
...finalResult,
|
|
2470
|
-
paymentIntentId: finalResult.paymentIntentId ??
|
|
2471
|
-
paymentMethodId: finalResult.paymentMethodId ??
|
|
2565
|
+
paymentIntentId: finalResult.paymentIntentId ?? confirmedPaymentIntentId,
|
|
2566
|
+
paymentMethodId: finalResult.paymentMethodId ?? confirmedPaymentMethodId,
|
|
2472
2567
|
checkoutMethod: finalResult.checkoutMethod ?? "card"
|
|
2473
2568
|
};
|
|
2474
2569
|
}
|
|
@@ -3053,6 +3148,11 @@ function FloPayCheckout({
|
|
|
3053
3148
|
function hashCreateParams(params) {
|
|
3054
3149
|
const key = JSON.stringify({
|
|
3055
3150
|
c: params?.clientId,
|
|
3151
|
+
a: {
|
|
3152
|
+
u: params?.account?.userId ?? "",
|
|
3153
|
+
e: params?.account?.email?.trim().toLowerCase() ?? "",
|
|
3154
|
+
country: params?.account?.country ?? ""
|
|
3155
|
+
},
|
|
3056
3156
|
successUrl: params?.successUrl,
|
|
3057
3157
|
cancelUrl: params?.cancelUrl,
|
|
3058
3158
|
i: params?.items?.map((x) => `${x.providerItemId}:${x.totalAmount}:${x.overrideAmount ?? ""}:${x.quantity ?? 1}`).sort(),
|
|
@@ -3060,6 +3160,7 @@ function FloPayCheckout({
|
|
|
3060
3160
|
couponCodes: params?.couponCodes,
|
|
3061
3161
|
tagsData: params?.tagsData,
|
|
3062
3162
|
utmMetadata: params?.utmMetadata,
|
|
3163
|
+
tokenizedData: params?.tokenizedData,
|
|
3063
3164
|
m: params?.checkoutMode ?? "full"
|
|
3064
3165
|
});
|
|
3065
3166
|
let h = 0;
|
|
@@ -4062,6 +4163,7 @@ function CheckoutFormInner({
|
|
|
4062
4163
|
if (!flopay || !elements || isSubmitting) return;
|
|
4063
4164
|
setProcessing(true);
|
|
4064
4165
|
updateError(null);
|
|
4166
|
+
let handedOff = false;
|
|
4065
4167
|
try {
|
|
4066
4168
|
const submitResult = await flopay.submitElements();
|
|
4067
4169
|
if (submitResult.error) {
|
|
@@ -4091,7 +4193,16 @@ function CheckoutFormInner({
|
|
|
4091
4193
|
isPaypal: false
|
|
4092
4194
|
})
|
|
4093
4195
|
});
|
|
4094
|
-
if (!intentResponse.ok)
|
|
4196
|
+
if (!intentResponse.ok) {
|
|
4197
|
+
const intentError = await buildFloPayApiErrorFromResponse(
|
|
4198
|
+
intentResponse,
|
|
4199
|
+
"Failed to create payment intent"
|
|
4200
|
+
);
|
|
4201
|
+
updateError(intentError.message);
|
|
4202
|
+
onError?.(intentError);
|
|
4203
|
+
emitDecline(intentError);
|
|
4204
|
+
return;
|
|
4205
|
+
}
|
|
4095
4206
|
const intentJson = await intentResponse.json();
|
|
4096
4207
|
const intentClientSecret = intentJson.data?.id;
|
|
4097
4208
|
if (!intentClientSecret) throw new import_shared8.FloPayError("No client_secret in payment intent response", "api_error");
|
|
@@ -4105,17 +4216,30 @@ function CheckoutFormInner({
|
|
|
4105
4216
|
emitDecline(confirmResult.error);
|
|
4106
4217
|
return;
|
|
4107
4218
|
}
|
|
4219
|
+
const rawProvider = typeof flopay.getRawProvider === "function" ? flopay.getRawProvider() : null;
|
|
4220
|
+
const confirmedPaymentIntent = await retrievePaymentIntentFromProvider(
|
|
4221
|
+
rawProvider,
|
|
4222
|
+
intentClientSecret
|
|
4223
|
+
);
|
|
4224
|
+
const paymentIntentId = confirmResult.paymentIntentId ?? confirmedPaymentIntent?.id;
|
|
4225
|
+
const paymentMethodId = confirmResult.paymentMethodId ?? resolvePaymentIntentPaymentMethodId(confirmedPaymentIntent) ?? pmResult.paymentMethodId;
|
|
4226
|
+
if (!paymentIntentId) {
|
|
4227
|
+
const error2 = new import_shared8.FloPayError("No payment intent returned after confirmation.", "api_error");
|
|
4228
|
+
updateError(error2.message);
|
|
4229
|
+
onError?.(error2);
|
|
4230
|
+
return;
|
|
4231
|
+
}
|
|
4232
|
+
handedOff = isSelfContained;
|
|
4108
4233
|
dispatchTokenizedBody({
|
|
4109
|
-
id:
|
|
4234
|
+
id: paymentMethodId,
|
|
4110
4235
|
type: "card",
|
|
4111
|
-
threeDSecureActionResultTokenId:
|
|
4236
|
+
threeDSecureActionResultTokenId: paymentIntentId,
|
|
4112
4237
|
originalPaymentMethodId: pmResult.paymentMethodId
|
|
4113
4238
|
});
|
|
4114
4239
|
} catch (err) {
|
|
4115
4240
|
updateError(err instanceof Error ? err.message : "An unexpected error occurred");
|
|
4116
4241
|
} finally {
|
|
4117
|
-
if (
|
|
4118
|
-
} else {
|
|
4242
|
+
if (!handedOff) {
|
|
4119
4243
|
setProcessing(false);
|
|
4120
4244
|
}
|
|
4121
4245
|
}
|
|
@@ -4793,7 +4917,10 @@ function FloPayAutomaticPaymentButton({
|
|
|
4793
4917
|
return;
|
|
4794
4918
|
}
|
|
4795
4919
|
try {
|
|
4796
|
-
const result = await api.createAndFetchSession(
|
|
4920
|
+
const result = await api.createAndFetchSession({
|
|
4921
|
+
...createSessionDraft,
|
|
4922
|
+
...automaticPaymentToken ? { tokenizedData: automaticPaymentToken } : {}
|
|
4923
|
+
});
|
|
4797
4924
|
await processResolvedSession(result, result.data.session?.id ?? null, {
|
|
4798
4925
|
fromCreateSession: true
|
|
4799
4926
|
});
|