@reevit/react 0.6.0 → 0.8.0
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 +14 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +112 -25
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +112 -25
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +457 -237
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -509,8 +509,9 @@ function mapToPaymentIntent(response, config) {
|
|
|
509
509
|
status: response.status,
|
|
510
510
|
recommendedPsp: mapProviderToPsp(response.provider),
|
|
511
511
|
availableMethods: config.paymentMethods || ["card", "mobile_money"],
|
|
512
|
-
|
|
513
|
-
|
|
512
|
+
providerRefId: response.provider_ref_id,
|
|
513
|
+
reference: response.reference || response.provider_ref_id || response.id,
|
|
514
|
+
// Use backend reference or fallback to provider ref then ID
|
|
514
515
|
orgId: response.org_id,
|
|
515
516
|
connectionId: response.connection_id,
|
|
516
517
|
provider: response.provider,
|
|
@@ -811,30 +812,47 @@ function detectCountryFromCurrency(currency) {
|
|
|
811
812
|
};
|
|
812
813
|
return currencyToCountry[currency.toUpperCase()] || "GH";
|
|
813
814
|
}
|
|
815
|
+
var MethodIcons = {
|
|
816
|
+
card: () => /* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
817
|
+
/* @__PURE__ */ jsx("rect", { x: "1", y: "4", width: "22", height: "16", rx: "3" }),
|
|
818
|
+
/* @__PURE__ */ jsx("line", { x1: "1", y1: "10", x2: "23", y2: "10" }),
|
|
819
|
+
/* @__PURE__ */ jsx("line", { x1: "5", y1: "15", x2: "9", y2: "15" })
|
|
820
|
+
] }),
|
|
821
|
+
mobile_money: () => /* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
822
|
+
/* @__PURE__ */ jsx("rect", { x: "5", y: "2", width: "14", height: "20", rx: "3" }),
|
|
823
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "18", x2: "12", y2: "18.01", strokeWidth: "2", strokeLinecap: "round" })
|
|
824
|
+
] }),
|
|
825
|
+
bank_transfer: () => /* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
826
|
+
/* @__PURE__ */ jsx("path", { d: "M3 21h18" }),
|
|
827
|
+
/* @__PURE__ */ jsx("path", { d: "M3 10h18" }),
|
|
828
|
+
/* @__PURE__ */ jsx("path", { d: "M12 3l9 7H3l9-7z" }),
|
|
829
|
+
/* @__PURE__ */ jsx("path", { d: "M6 10v8" }),
|
|
830
|
+
/* @__PURE__ */ jsx("path", { d: "M10 10v8" }),
|
|
831
|
+
/* @__PURE__ */ jsx("path", { d: "M14 10v8" }),
|
|
832
|
+
/* @__PURE__ */ jsx("path", { d: "M18 10v8" })
|
|
833
|
+
] }),
|
|
834
|
+
apple_pay: () => /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M17.05 20.28c-.98.95-2.05.88-3.08.4-1.09-.5-2.08-.48-3.24 0-1.44.62-2.2.44-3.06-.4C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.53 4.09zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z" }) }),
|
|
835
|
+
google_pay: () => /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M12.24 10.285V14.4h6.806c-.275 1.765-2.056 5.174-6.806 5.174-4.095 0-7.439-3.389-7.439-7.574s3.345-7.574 7.439-7.574c2.33 0 3.891.989 4.785 1.849l3.254-3.138C18.189 1.186 15.479 0 12.24 0c-6.635 0-12 5.365-12 12s5.365 12 12 12c6.926 0 11.52-4.869 11.52-11.726 0-.788-.085-1.39-.189-1.989H12.24z", fill: "currentColor" }) })
|
|
836
|
+
};
|
|
814
837
|
var methodConfig = {
|
|
815
838
|
card: {
|
|
816
839
|
label: "Card",
|
|
817
|
-
icon: "\u{1F4B3}",
|
|
818
840
|
description: "Pay with Visa, Mastercard, or other cards"
|
|
819
841
|
},
|
|
820
842
|
mobile_money: {
|
|
821
843
|
label: "Mobile Money",
|
|
822
|
-
icon: "\u{1F4F1}",
|
|
823
844
|
description: "MTN, Telecel, AirtelTigo Money"
|
|
824
845
|
},
|
|
825
846
|
bank_transfer: {
|
|
826
847
|
label: "Bank Transfer",
|
|
827
|
-
icon: "\u{1F3E6}",
|
|
828
848
|
description: "Pay directly from your bank account"
|
|
829
849
|
},
|
|
830
850
|
apple_pay: {
|
|
831
851
|
label: "Apple Pay",
|
|
832
|
-
icon: "\u{1F34E}",
|
|
833
852
|
description: "Pay with Apple Pay"
|
|
834
853
|
},
|
|
835
854
|
google_pay: {
|
|
836
855
|
label: "Google Pay",
|
|
837
|
-
icon: "\u{1F916}",
|
|
838
856
|
description: "Pay with Google Pay"
|
|
839
857
|
}
|
|
840
858
|
};
|
|
@@ -884,7 +902,6 @@ function PaymentMethodSelector({
|
|
|
884
902
|
),
|
|
885
903
|
style: selectedTheme?.backgroundColor ? { backgroundColor: selectedTheme.backgroundColor } : void 0,
|
|
886
904
|
children: methods.map((method, index) => {
|
|
887
|
-
const config = methodConfig[method];
|
|
888
905
|
const isSelected = selectedMethod === method;
|
|
889
906
|
const methodLabel = getMethodLabel(method);
|
|
890
907
|
const methodDescription = getMethodDescription(method);
|
|
@@ -915,7 +932,7 @@ function PaymentMethodSelector({
|
|
|
915
932
|
className: "reevit-method-option__logo-img"
|
|
916
933
|
},
|
|
917
934
|
i
|
|
918
|
-
)) }) : /* @__PURE__ */ jsx("span", { className: "reevit-method-option__icon", children:
|
|
935
|
+
)) }) : /* @__PURE__ */ jsx("span", { className: "reevit-method-option__icon", children: MethodIcons[method]() }) }),
|
|
919
936
|
/* @__PURE__ */ jsxs("div", { className: "reevit-method-option__content", children: [
|
|
920
937
|
/* @__PURE__ */ jsx("span", { className: "reevit-method-option__label", style: selectedTheme?.textColor ? { color: selectedTheme.textColor } : void 0, children: methodLabel }),
|
|
921
938
|
!isGrid && /* @__PURE__ */ jsx("span", { className: "reevit-method-option__description", style: selectedTheme?.descriptionColor ? { color: selectedTheme.descriptionColor } : void 0, children: methodDescription })
|
|
@@ -1315,6 +1332,38 @@ function PaystackBridge({
|
|
|
1315
1332
|
/* @__PURE__ */ jsx("p", { children: "Connecting to Paystack..." })
|
|
1316
1333
|
] }) });
|
|
1317
1334
|
}
|
|
1335
|
+
var DEFAULT_REEVIT_API_BASE_URL = "https://api.reevit.io";
|
|
1336
|
+
function getHubtelCallbackURL(apiBaseUrl) {
|
|
1337
|
+
return `${apiBaseUrl || DEFAULT_REEVIT_API_BASE_URL}/v1/webhooks/incoming/hubtel`;
|
|
1338
|
+
}
|
|
1339
|
+
function parseHubtelCallbackPayload(input) {
|
|
1340
|
+
if (!input || typeof input !== "object") {
|
|
1341
|
+
return {};
|
|
1342
|
+
}
|
|
1343
|
+
const raw = input;
|
|
1344
|
+
const nested = raw.data;
|
|
1345
|
+
if (typeof nested === "string") {
|
|
1346
|
+
try {
|
|
1347
|
+
const parsed = JSON.parse(nested);
|
|
1348
|
+
if (parsed && typeof parsed === "object") {
|
|
1349
|
+
return { ...raw, ...parsed };
|
|
1350
|
+
}
|
|
1351
|
+
} catch {
|
|
1352
|
+
}
|
|
1353
|
+
} else if (nested && typeof nested === "object") {
|
|
1354
|
+
return { ...raw, ...nested };
|
|
1355
|
+
}
|
|
1356
|
+
return raw;
|
|
1357
|
+
}
|
|
1358
|
+
function readHubtelField(payload, keys) {
|
|
1359
|
+
for (const key of keys) {
|
|
1360
|
+
const value = payload[key];
|
|
1361
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
1362
|
+
return value.trim();
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
return "";
|
|
1366
|
+
}
|
|
1318
1367
|
function HubtelBridge({
|
|
1319
1368
|
paymentId,
|
|
1320
1369
|
publicKey,
|
|
@@ -1391,12 +1440,12 @@ function HubtelBridge({
|
|
|
1391
1440
|
purchaseDescription: description,
|
|
1392
1441
|
customerPhoneNumber: phone || "",
|
|
1393
1442
|
...email ? { customerEmail: email } : {},
|
|
1394
|
-
clientReference: reference || `hubtel_${Date.now()}`,
|
|
1443
|
+
clientReference: reference || paymentId || `hubtel_${Date.now()}`,
|
|
1395
1444
|
...methodPreference ? { paymentMethod: methodPreference } : {}
|
|
1396
1445
|
};
|
|
1397
1446
|
const config = {
|
|
1398
1447
|
branding: "enabled",
|
|
1399
|
-
callbackUrl: callbackUrl ||
|
|
1448
|
+
callbackUrl: callbackUrl || getHubtelCallbackURL(apiBaseUrl),
|
|
1400
1449
|
merchantAccount: typeof resolvedMerchantAccount === "string" ? parseInt(resolvedMerchantAccount, 10) : resolvedMerchantAccount,
|
|
1401
1450
|
basicAuth: authValue || "",
|
|
1402
1451
|
...methodPreference ? { paymentMethod: methodPreference } : {}
|
|
@@ -1407,24 +1456,41 @@ function HubtelBridge({
|
|
|
1407
1456
|
callBacks: {
|
|
1408
1457
|
onInit: () => console.log("Hubtel checkout initialized"),
|
|
1409
1458
|
onPaymentSuccess: (data) => {
|
|
1459
|
+
const payload = parseHubtelCallbackPayload(data);
|
|
1460
|
+
const transactionReference = readHubtelField(payload, [
|
|
1461
|
+
"transactionId",
|
|
1462
|
+
"transaction_id",
|
|
1463
|
+
"transactionReference",
|
|
1464
|
+
"paymentReference",
|
|
1465
|
+
"checkoutId"
|
|
1466
|
+
]);
|
|
1467
|
+
const clientReference = readHubtelField(payload, ["clientReference", "client_reference"]);
|
|
1410
1468
|
const result = {
|
|
1411
|
-
paymentId
|
|
1412
|
-
reference:
|
|
1469
|
+
paymentId,
|
|
1470
|
+
reference: clientReference || reference || paymentId,
|
|
1413
1471
|
amount,
|
|
1414
1472
|
currency: currency || "GHS",
|
|
1415
1473
|
paymentMethod: preferredMethod || "mobile_money",
|
|
1416
1474
|
psp: "hubtel",
|
|
1417
|
-
pspReference:
|
|
1418
|
-
status: "success"
|
|
1475
|
+
pspReference: transactionReference || paymentId,
|
|
1476
|
+
status: "success",
|
|
1477
|
+
metadata: {
|
|
1478
|
+
hubtel_payload: payload,
|
|
1479
|
+
hubtel_raw: data
|
|
1480
|
+
}
|
|
1419
1481
|
};
|
|
1420
1482
|
onSuccess(result);
|
|
1421
1483
|
checkout.closePopUp();
|
|
1422
1484
|
},
|
|
1423
1485
|
onPaymentFailure: (data) => {
|
|
1486
|
+
const payload = parseHubtelCallbackPayload(data);
|
|
1424
1487
|
const error = {
|
|
1425
1488
|
code: "PAYMENT_FAILED",
|
|
1426
|
-
message:
|
|
1427
|
-
recoverable: true
|
|
1489
|
+
message: readHubtelField(payload, ["message", "error", "reason"]) || "Payment failed",
|
|
1490
|
+
recoverable: true,
|
|
1491
|
+
details: {
|
|
1492
|
+
hubtel_payload: payload
|
|
1493
|
+
}
|
|
1428
1494
|
};
|
|
1429
1495
|
onError(error);
|
|
1430
1496
|
},
|
|
@@ -1449,6 +1515,8 @@ function HubtelBridge({
|
|
|
1449
1515
|
phone,
|
|
1450
1516
|
description,
|
|
1451
1517
|
callbackUrl,
|
|
1518
|
+
paymentId,
|
|
1519
|
+
apiBaseUrl,
|
|
1452
1520
|
authValue,
|
|
1453
1521
|
isLoading,
|
|
1454
1522
|
preferredMethod,
|
|
@@ -1481,7 +1549,7 @@ function openHubtelPopup(config) {
|
|
|
1481
1549
|
};
|
|
1482
1550
|
const checkoutConfig = {
|
|
1483
1551
|
branding: "enabled",
|
|
1484
|
-
callbackUrl: config.callbackUrl ||
|
|
1552
|
+
callbackUrl: config.callbackUrl || getHubtelCallbackURL(config.apiBaseUrl),
|
|
1485
1553
|
merchantAccount: typeof config.merchantAccount === "string" ? parseInt(config.merchantAccount, 10) : config.merchantAccount,
|
|
1486
1554
|
basicAuth: config.basicAuth || "",
|
|
1487
1555
|
...methodPreference ? { paymentMethod: methodPreference } : {}
|
|
@@ -1491,11 +1559,11 @@ function openHubtelPopup(config) {
|
|
|
1491
1559
|
config: checkoutConfig,
|
|
1492
1560
|
callBacks: {
|
|
1493
1561
|
onPaymentSuccess: (data) => {
|
|
1494
|
-
config.onSuccess?.(data);
|
|
1562
|
+
config.onSuccess?.(parseHubtelCallbackPayload(data));
|
|
1495
1563
|
checkout.closePopUp();
|
|
1496
1564
|
},
|
|
1497
1565
|
onPaymentFailure: (data) => {
|
|
1498
|
-
config.onError?.(data);
|
|
1566
|
+
config.onError?.(parseHubtelCallbackPayload(data));
|
|
1499
1567
|
},
|
|
1500
1568
|
onClose: () => {
|
|
1501
1569
|
config.onClose?.();
|
|
@@ -2475,7 +2543,11 @@ function ReevitCheckout({
|
|
|
2475
2543
|
const renderContent = () => {
|
|
2476
2544
|
if (status === "loading" || status === "processing") {
|
|
2477
2545
|
return /* @__PURE__ */ jsxs("div", { className: "reevit-loading reevit-animate-fade-in", children: [
|
|
2478
|
-
/* @__PURE__ */
|
|
2546
|
+
/* @__PURE__ */ jsxs("div", { className: "reevit-dot-pulse", children: [
|
|
2547
|
+
/* @__PURE__ */ jsx("span", { className: "reevit-dot-pulse__dot" }),
|
|
2548
|
+
/* @__PURE__ */ jsx("span", { className: "reevit-dot-pulse__dot" }),
|
|
2549
|
+
/* @__PURE__ */ jsx("span", { className: "reevit-dot-pulse__dot" })
|
|
2550
|
+
] }),
|
|
2479
2551
|
/* @__PURE__ */ jsx("p", { children: status === "loading" ? "Preparing checkout..." : "Processing payment..." })
|
|
2480
2552
|
] });
|
|
2481
2553
|
}
|
|
@@ -2491,12 +2563,22 @@ function ReevitCheckout({
|
|
|
2491
2563
|
"Reference: ",
|
|
2492
2564
|
result.reference
|
|
2493
2565
|
] }),
|
|
2494
|
-
/* @__PURE__ */ jsx("p", { className: "reevit-success__redirect", children: "Redirecting in a moment..." })
|
|
2566
|
+
/* @__PURE__ */ jsx("p", { className: "reevit-success__redirect", children: "Redirecting in a moment..." }),
|
|
2567
|
+
/* @__PURE__ */ jsx(
|
|
2568
|
+
"div",
|
|
2569
|
+
{
|
|
2570
|
+
className: "reevit-success__countdown",
|
|
2571
|
+
style: { animationDuration: `${successDelayMs}ms` }
|
|
2572
|
+
}
|
|
2573
|
+
)
|
|
2495
2574
|
] });
|
|
2496
2575
|
}
|
|
2497
2576
|
if (status === "failed" && error && !error.recoverable) {
|
|
2498
2577
|
return /* @__PURE__ */ jsxs("div", { className: "reevit-error reevit-animate-fade-in", children: [
|
|
2499
|
-
/* @__PURE__ */ jsx("div", { className: "reevit-error__icon", children: "
|
|
2578
|
+
/* @__PURE__ */ jsx("div", { className: "reevit-error__icon", children: /* @__PURE__ */ jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2579
|
+
/* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
2580
|
+
/* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
2581
|
+
] }) }),
|
|
2500
2582
|
/* @__PURE__ */ jsx("h3", { children: "Payment Failed" }),
|
|
2501
2583
|
/* @__PURE__ */ jsx("p", { children: error.message }),
|
|
2502
2584
|
/* @__PURE__ */ jsx("button", { className: "reevit-btn reevit-btn--primary", onClick: handleBack, children: "Try Again" })
|
|
@@ -2541,10 +2623,11 @@ function ReevitCheckout({
|
|
|
2541
2623
|
merchantAccount: paymentIntent?.pspCredentials?.merchantAccount || "",
|
|
2542
2624
|
amount: paymentIntent?.amount ?? amount,
|
|
2543
2625
|
currency: paymentIntent?.currency ?? currency,
|
|
2544
|
-
reference: paymentIntent?.reference || reference,
|
|
2626
|
+
reference: paymentIntent?.providerRefId || paymentIntent?.reference || reference,
|
|
2545
2627
|
email,
|
|
2546
2628
|
phone: momoData?.phone || phone,
|
|
2547
2629
|
description: `Payment ${paymentIntent?.reference || reference || ""}`,
|
|
2630
|
+
callbackUrl: `${apiBaseUrl || "https://api.reevit.io"}/v1/webhooks/incoming/hubtel`,
|
|
2548
2631
|
hubtelSessionToken: paymentIntent?.id ? paymentIntent.id : void 0,
|
|
2549
2632
|
clientSecret: paymentIntent?.clientSecret,
|
|
2550
2633
|
apiBaseUrl,
|
|
@@ -2618,7 +2701,11 @@ function ReevitCheckout({
|
|
|
2618
2701
|
);
|
|
2619
2702
|
default:
|
|
2620
2703
|
return /* @__PURE__ */ jsxs("div", { className: "reevit-error", children: [
|
|
2621
|
-
/* @__PURE__ */ jsx("div", { className: "reevit-error__icon", children: "
|
|
2704
|
+
/* @__PURE__ */ jsx("div", { className: "reevit-error__icon", children: /* @__PURE__ */ jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2705
|
+
/* @__PURE__ */ jsx("path", { d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }),
|
|
2706
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "9", x2: "12", y2: "13" }),
|
|
2707
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
|
|
2708
|
+
] }) }),
|
|
2622
2709
|
/* @__PURE__ */ jsx("h3", { children: "Provider Not Supported" }),
|
|
2623
2710
|
/* @__PURE__ */ jsxs("p", { children: [
|
|
2624
2711
|
"Provider (",
|