@agent-cards/sdk 0.23.19 → 0.23.21
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/CHANGELOG.md +61 -2
- package/PREFLIGHT.md +4 -0
- package/README.md +175 -7
- package/dist/amadeus.d.ts +4 -2
- package/dist/amadeus.js +16 -3
- package/dist/buy.d.ts +84 -2
- package/dist/buy.js +16 -1
- package/dist/card-endpoint-facts.d.ts +2 -1
- package/dist/card-endpoint-facts.js +18 -9
- package/dist/card-endpoint.d.ts +20 -4
- package/dist/card-endpoint.js +38 -4
- package/dist/card-fields.generated.js +1444 -51
- package/dist/cdp.d.ts +29 -0
- package/dist/cdp.js +444 -24
- package/dist/client.d.ts +134 -7
- package/dist/client.js +350 -25
- package/dist/comgate.d.ts +50 -0
- package/dist/comgate.js +80 -0
- package/dist/cybersource-secure-acceptance.generated.d.ts +1 -1
- package/dist/eprotect.generated.d.ts +1 -1
- package/dist/gmo.generated.js +7 -3
- package/dist/hipay.generated.d.ts +56 -0
- package/dist/hipay.generated.js +392 -0
- package/dist/hold.d.ts +180 -0
- package/dist/hold.js +270 -0
- package/dist/hosted-entry.d.ts +4 -0
- package/dist/hosted-entry.js +32 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1 -0
- package/dist/lifecycle.d.ts +10 -0
- package/dist/lifecycle.js +21 -0
- package/dist/merchant-card-endpoints.generated.js +102 -11
- package/dist/paddle-tokenex.generated.js +7 -3
- package/dist/paddle-vgs.generated.d.ts +3 -2
- package/dist/paddle-vgs.generated.js +9 -5
- package/dist/payrails.generated.js +7 -3
- package/dist/pre-claim.d.ts +20 -0
- package/dist/pre-claim.js +202 -22
- package/dist/preflight-catalog.json +58 -0
- package/dist/preflight-schemas.json +4 -0
- package/dist/preflight.generated.js +26 -2
- package/dist/prepared-processor.d.ts +6 -2
- package/dist/prepared-processor.js +18 -2
- package/dist/primer.generated.js +1487 -94
- package/dist/przelewy24.d.ts +47 -0
- package/dist/przelewy24.js +88 -0
- package/dist/quickpay.d.ts +44 -0
- package/dist/quickpay.js +65 -0
- package/dist/registry.d.ts +6 -5
- package/dist/registry.js +27 -7
- package/dist/shiji-sts.generated.js +7 -3
- package/dist/stripe-checkout.generated.js +744 -13
- package/dist/tokenex-iframe.d.ts +93 -0
- package/dist/tokenex-iframe.generated.d.ts +81 -0
- package/dist/tokenex-iframe.generated.js +403 -0
- package/dist/tokenex-iframe.js +195 -0
- package/dist/transbank.d.ts +45 -0
- package/dist/transbank.js +73 -0
- package/dist/twoc2p.d.ts +54 -0
- package/dist/twoc2p.generated.d.ts +33 -0
- package/dist/twoc2p.generated.js +1149 -0
- package/dist/twoc2p.js +85 -0
- package/dist/voice.d.ts +16 -13
- package/dist/voice.js +13 -10
- package/examples/preflight/kernel-native/inventory.json +1 -1
- package/package.json +3 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
// Generated from @agent-cards/payment-core. Do not edit.
|
|
3
|
-
// artifact-sha256:
|
|
3
|
+
// artifact-sha256: f313f792b559132984a5fefb5678f9f2416a3f93adbf526b8345bc29649581df
|
|
4
4
|
// src/card-number-key.js
|
|
5
5
|
var CARD_NUMBER_KEY = /^(number|card_number|cardnumber|cardNum|card_num|pan)$/i;
|
|
6
6
|
// src/json-path.js
|
|
@@ -101,8 +101,8 @@ function parseConvergeBody(body) {
|
|
|
101
101
|
return parsed;
|
|
102
102
|
}
|
|
103
103
|
function convergeAmountCents(value) {
|
|
104
|
-
const
|
|
105
|
-
const m = typeof
|
|
104
|
+
const text6 = typeof value === "number" && Number.isFinite(value) ? String(value) : value;
|
|
105
|
+
const m = typeof text6 === "string" ? AMOUNT.exec(text6) : null;
|
|
106
106
|
if (!m)
|
|
107
107
|
return null;
|
|
108
108
|
const cents = Number(m[1]) * 100 + Number(((m[2] ?? "") + "00").slice(0, 2));
|
|
@@ -357,8 +357,8 @@ var CONTROL = /[\u0000-\u001f\u007f]/;
|
|
|
357
357
|
var cardLikeName = (name) => (name.match(/[0-9]/g) ?? []).length >= 12;
|
|
358
358
|
var record3 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
359
359
|
var sameKeys = (value, keys) => {
|
|
360
|
-
const
|
|
361
|
-
return
|
|
360
|
+
const own6 = Object.keys(value);
|
|
361
|
+
return own6.length === keys.length && own6.every((key, at) => key === keys[at]);
|
|
362
362
|
};
|
|
363
363
|
var refuse4 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
364
364
|
var CARD4 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
@@ -582,9 +582,9 @@ var K = /* @__PURE__ */ new Uint32Array([
|
|
|
582
582
|
3329325298
|
|
583
583
|
]);
|
|
584
584
|
var rotr = (x, n) => x >>> n | x << 32 - n;
|
|
585
|
-
function utf8(
|
|
585
|
+
function utf8(text6) {
|
|
586
586
|
const out = [];
|
|
587
|
-
for (const char of
|
|
587
|
+
for (const char of text6) {
|
|
588
588
|
let cp = char.codePointAt(0);
|
|
589
589
|
if (cp >= 55296 && cp <= 57343)
|
|
590
590
|
cp = 65533;
|
|
@@ -663,10 +663,13 @@ var TYPED_ARRAY = Object.getPrototypeOf(Uint8Array.prototype);
|
|
|
663
663
|
var typedArrayName = Object.getOwnPropertyDescriptor(TYPED_ARRAY, Symbol.toStringTag).get;
|
|
664
664
|
function parseRsaPublicKey(key) {
|
|
665
665
|
const spki = key && typeof key === "object" ? key.spki : void 0;
|
|
666
|
-
const
|
|
666
|
+
const pin8 = key && typeof key === "object" ? key.sha256 : void 0;
|
|
667
|
+
const named = key && typeof key === "object" && Object.prototype.hasOwnProperty.call(key, "exponent") ? key.exponent : void 0;
|
|
668
|
+
if (named !== void 0 && named !== 17)
|
|
669
|
+
throw refuse6("key");
|
|
667
670
|
if (typeof spki !== "string" || spki.length > 1024 || spki.length % 4 !== 0 || !BASE64.test(spki))
|
|
668
671
|
throw refuse6("key");
|
|
669
|
-
if (typeof
|
|
672
|
+
if (typeof pin8 !== "string" || !SHA256_HEX.test(pin8))
|
|
670
673
|
throw refuse6("key");
|
|
671
674
|
let binary;
|
|
672
675
|
try {
|
|
@@ -678,7 +681,7 @@ function parseRsaPublicKey(key) {
|
|
|
678
681
|
if (btoa(binary) !== spki)
|
|
679
682
|
throw refuse6("key");
|
|
680
683
|
const der = Uint8Array.from(binary, (c) => c.charCodeAt(0));
|
|
681
|
-
if (sha256Hex(der) !==
|
|
684
|
+
if (sha256Hex(der) !== pin8)
|
|
682
685
|
throw refuse6("key");
|
|
683
686
|
const outer = readElement(der, 0, 48);
|
|
684
687
|
if (outer.end !== der.length || outer.start + RSA_ALGORITHM.length > der.length)
|
|
@@ -699,9 +702,10 @@ function parseRsaPublicKey(key) {
|
|
|
699
702
|
if (!MODULUS_BYTES.includes(n.length) || !(n[0] & 128) || !(n[n.length - 1] & 1))
|
|
700
703
|
throw refuse6("key");
|
|
701
704
|
const e = exponent.bytes;
|
|
702
|
-
|
|
705
|
+
const expected = named === 17 ? [17] : [1, 0, 1];
|
|
706
|
+
if (e.length !== expected.length || !expected.every((byte, i) => e[i] === byte))
|
|
703
707
|
throw refuse6("key");
|
|
704
|
-
return Object.freeze({ n: toBigInt(n), e: 65537n, size: n.length });
|
|
708
|
+
return Object.freeze({ n: toBigInt(n), e: named === 17 ? 17n : 65537n, size: n.length });
|
|
705
709
|
}
|
|
706
710
|
function readElement(der, at, tag) {
|
|
707
711
|
if (at + 2 > der.length || der[at] !== tag)
|
|
@@ -767,8 +771,8 @@ var PADDLE_TOKENEX_PSP = "paddle_tokenex";
|
|
|
767
771
|
var PADDLE_TOKENEX_FACT_KEYS = /* @__PURE__ */ Object.freeze(["card_first_six", "card_last_four", "expiry_month", "expiry_year", "card_brand"]);
|
|
768
772
|
var record4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
769
773
|
var sameKeys2 = (value, keys) => {
|
|
770
|
-
const
|
|
771
|
-
return
|
|
774
|
+
const own6 = Object.keys(value);
|
|
775
|
+
return own6.length === keys.length && own6.every((key, at) => key === keys[at]);
|
|
772
776
|
};
|
|
773
777
|
var refuse7 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
774
778
|
var CARD6 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
@@ -1257,8 +1261,8 @@ var TEXT_LIMIT = 256;
|
|
|
1257
1261
|
var CONTROL4 = /[\u0000-\u001f\u007f]/;
|
|
1258
1262
|
var record6 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1259
1263
|
var sameKeys3 = (value, keys) => {
|
|
1260
|
-
const
|
|
1261
|
-
return
|
|
1264
|
+
const own6 = Object.keys(value);
|
|
1265
|
+
return own6.length === keys.length && own6.every((key, at) => key === keys[at]);
|
|
1262
1266
|
};
|
|
1263
1267
|
var plainText = (value) => typeof value === "string" && value.length <= TEXT_LIMIT && !CONTROL4.test(value) && (value.match(/[0-9]/g) ?? []).length < 12;
|
|
1264
1268
|
var refuse9 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
@@ -1368,14 +1372,14 @@ function readJson2(body) {
|
|
|
1368
1372
|
catch {
|
|
1369
1373
|
return { parsed: null, exact: false };
|
|
1370
1374
|
}
|
|
1371
|
-
let
|
|
1375
|
+
let exact3 = false;
|
|
1372
1376
|
try {
|
|
1373
|
-
|
|
1377
|
+
exact3 = body.length <= BODY_LIMIT6 && JSON.stringify(parsed) === body;
|
|
1374
1378
|
}
|
|
1375
1379
|
catch {
|
|
1376
|
-
|
|
1380
|
+
exact3 = false;
|
|
1377
1381
|
}
|
|
1378
|
-
return { parsed, exact };
|
|
1382
|
+
return { parsed, exact: exact3 };
|
|
1379
1383
|
}
|
|
1380
1384
|
function billingValue(value) {
|
|
1381
1385
|
if (value === UNDEFINED)
|
|
@@ -1430,14 +1434,14 @@ function attachType(parsed) {
|
|
|
1430
1434
|
return typeof type === "string" ? type : null;
|
|
1431
1435
|
}
|
|
1432
1436
|
function paymongoBodyVerdict(body, session) {
|
|
1433
|
-
const { parsed, exact } = readJson2(body);
|
|
1437
|
+
const { parsed, exact: exact3 } = readJson2(body);
|
|
1434
1438
|
const type = parsed === null ? null : attachType(parsed);
|
|
1435
1439
|
if (type !== "card") {
|
|
1436
1440
|
if (parsed === null)
|
|
1437
1441
|
return body === void 0 || body === null || body === "" ? CONTINUE4 : refuse10("paymongo_body_unsupported");
|
|
1438
1442
|
return namesCardValue(parsed) ? refuse10("paymongo_body_unsupported") : CONTINUE4;
|
|
1439
1443
|
}
|
|
1440
|
-
if (!
|
|
1444
|
+
if (!exact3)
|
|
1441
1445
|
return refuse10("paymongo_body_unsupported");
|
|
1442
1446
|
const code = judgeCardAttach(parsed, session);
|
|
1443
1447
|
return code === null ? CARD9 : refuse10(code);
|
|
@@ -1460,15 +1464,15 @@ var EXPIRATION = /^[0-9]{2}(?:0[1-9]|1[0-2])$/;
|
|
|
1460
1464
|
var CARD_PAYMENT = "PAYMENT_CARD";
|
|
1461
1465
|
var record8 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1462
1466
|
var sameKeys4 = (value, keys) => {
|
|
1463
|
-
const
|
|
1464
|
-
return
|
|
1467
|
+
const own6 = Object.keys(value);
|
|
1468
|
+
return own6.length === keys.length && own6.every((key, at) => key === keys[at]);
|
|
1465
1469
|
};
|
|
1466
1470
|
var refuse11 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
1467
1471
|
var CARD10 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
1468
|
-
function luhn(
|
|
1472
|
+
function luhn(digits2) {
|
|
1469
1473
|
let sum = 0;
|
|
1470
|
-
for (let at = 0; at <
|
|
1471
|
-
let digit = Number(
|
|
1474
|
+
for (let at = 0; at < digits2.length; at += 1) {
|
|
1475
|
+
let digit = Number(digits2[digits2.length - 1 - at]);
|
|
1472
1476
|
if (at % 2 === 1) {
|
|
1473
1477
|
digit *= 2;
|
|
1474
1478
|
if (digit > 9)
|
|
@@ -1476,7 +1480,7 @@ function luhn(digits) {
|
|
|
1476
1480
|
}
|
|
1477
1481
|
sum += digit;
|
|
1478
1482
|
}
|
|
1479
|
-
return sum % 10 === 0;
|
|
1483
|
+
return sum > 0 && sum % 10 === 0;
|
|
1480
1484
|
}
|
|
1481
1485
|
function gopayCardFormUrl(url) {
|
|
1482
1486
|
if (typeof url !== "string" || url.length > 2048 || url.includes("#"))
|
|
@@ -1540,6 +1544,9 @@ function gopayBodyVerdict(body, url) {
|
|
|
1540
1544
|
return refuse11("gopay_signature_mismatch");
|
|
1541
1545
|
return CARD10;
|
|
1542
1546
|
}
|
|
1547
|
+
var GOPAY_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
1548
|
+
Object.freeze({ id: "caramilla", merchant: "Caramilla.cz", origins: Object.freeze(["https://www.caramilla.cz"]) })
|
|
1549
|
+
]);
|
|
1543
1550
|
// src/payrexx.js
|
|
1544
1551
|
var PAYREXX_PSP = "payrexx";
|
|
1545
1552
|
var PAYREXX_FRAME_HOST = "checkout.payrexx.com";
|
|
@@ -1612,10 +1619,10 @@ function readForm2(body) {
|
|
|
1612
1619
|
return null;
|
|
1613
1620
|
}
|
|
1614
1621
|
}
|
|
1615
|
-
function cardNetwork2(
|
|
1616
|
-
if (VISA2.test(
|
|
1622
|
+
function cardNetwork2(digits2) {
|
|
1623
|
+
if (VISA2.test(digits2))
|
|
1617
1624
|
return "visa";
|
|
1618
|
-
return MASTERCARD2.test(
|
|
1625
|
+
return MASTERCARD2.test(digits2) ? "mastercard" : null;
|
|
1619
1626
|
}
|
|
1620
1627
|
function judgeBody2(body) {
|
|
1621
1628
|
const pairs = readForm2(body);
|
|
@@ -1658,6 +1665,9 @@ function payrexxGateVerdict(url, body) {
|
|
|
1658
1665
|
const verdict = payrexxBodyVerdict(body);
|
|
1659
1666
|
return verdict.verdict === "card" && target.pspId !== PAYREXX_PAY_PSP_ID ? refuse12("payrexx_other_provider") : verdict;
|
|
1660
1667
|
}
|
|
1668
|
+
var PAYREXX_FOLLOW_UP_WINDOW_MS = 15 * 60 * 1e3;
|
|
1669
|
+
var PAYREXX_FOLLOW_UP_IDLE_MS = 60 * 1e3;
|
|
1670
|
+
var PAYREXX_FOLLOW_UP_CHALLENGE_MS = 11 * 60 * 1e3;
|
|
1661
1671
|
// src/komoju.js
|
|
1662
1672
|
var KOMOJU_PSP = "komoju";
|
|
1663
1673
|
var KOMOJU_HOST = "komoju.com";
|
|
@@ -1685,8 +1695,8 @@ var LOCALE = /^[a-z]{2}(?:-[A-Za-z]{2,4})?$/;
|
|
|
1685
1695
|
var PAN_LIKE3 = /(?:[0-9][ _.:-]*){12,}/;
|
|
1686
1696
|
var record9 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1687
1697
|
var sameKeys5 = (value, keys) => {
|
|
1688
|
-
const
|
|
1689
|
-
return
|
|
1698
|
+
const own6 = Object.keys(value);
|
|
1699
|
+
return own6.length === keys.length && own6.every((key, at) => key === keys[at]);
|
|
1690
1700
|
};
|
|
1691
1701
|
var refuse13 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
1692
1702
|
var CARD12 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
@@ -1971,7 +1981,7 @@ var HOLDER3 = /^\p{L}+(?: \p{L}+)*$/u;
|
|
|
1971
1981
|
var HOLDER_LIMIT2 = 256;
|
|
1972
1982
|
var SECURITY_CODE10 = /^[0-9]{3,4}$/;
|
|
1973
1983
|
var MONTH6 = /^(?:0[1-9]|1[0-2])$/;
|
|
1974
|
-
var YEAR6 = /^[0-9]{2}$/;
|
|
1984
|
+
var YEAR6 = /^(?:[0-9]{2}|20[0-9]{2})$/;
|
|
1975
1985
|
var refuse15 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
1976
1986
|
var CARD14 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
1977
1987
|
function isPayNlTokenUrl(url) {
|
|
@@ -2077,10 +2087,10 @@ var wellFormed = (value) => {
|
|
|
2077
2087
|
var plainText2 = (value) => typeof value === "string" && value.length >= 1 && value.length <= TEXT_LIMIT2 && !CONTROL5.test(value) && (value.match(/[0-9]/g) ?? []).length < 12 && wellFormed(value);
|
|
2078
2088
|
var between = (value, min, max) => Number.isSafeInteger(value) && value >= min && value <= max;
|
|
2079
2089
|
var NETWORK = /^(?:4[0-9]{15}|4[0-9]{12}|5[1-5][0-9]{14}|2(?:2(?:2[1-9]|[3-9][0-9])|[3-6][0-9]{2}|7(?:[01][0-9]|20))[0-9]{12}|3[47][0-9]{13})$/;
|
|
2080
|
-
var luhn2 = (
|
|
2090
|
+
var luhn2 = (digits2) => {
|
|
2081
2091
|
let sum = 0;
|
|
2082
|
-
for (let at = 0; at <
|
|
2083
|
-
let d =
|
|
2092
|
+
for (let at = 0; at < digits2.length; at += 1) {
|
|
2093
|
+
let d = digits2.charCodeAt(digits2.length - 1 - at) - 48;
|
|
2084
2094
|
if (at % 2 === 1) {
|
|
2085
2095
|
d *= 2;
|
|
2086
2096
|
if (d > 9)
|
|
@@ -2091,7 +2101,7 @@ var luhn2 = (digits) => {
|
|
|
2091
2101
|
return sum % 10 === 0;
|
|
2092
2102
|
};
|
|
2093
2103
|
var ANY_NETWORK = /^[2-6][0-9]{12,18}$/;
|
|
2094
|
-
var holdsCardShape = (
|
|
2104
|
+
var holdsCardShape = (text6, shape = NETWORK) => (text6.match(/[0-9]{13,}/g) ?? []).some((run) => run.length > 19 || shape.test(run) && luhn2(run));
|
|
2095
2105
|
var phone = (value) => typeof value === "string" && PHONE.test(value) && (value.match(/[0-9]/g) ?? []).length >= 6 && (value.match(/[0-9]/g) ?? []).length <= 15;
|
|
2096
2106
|
var refuse16 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
2097
2107
|
var CARD15 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
@@ -2302,10 +2312,10 @@ function orderedSubset(value, keys) {
|
|
|
2302
2312
|
}
|
|
2303
2313
|
return true;
|
|
2304
2314
|
}
|
|
2305
|
-
function luhn3(
|
|
2315
|
+
function luhn3(digits2) {
|
|
2306
2316
|
let sum = 0;
|
|
2307
|
-
for (let at = 0; at <
|
|
2308
|
-
let digit = Number(
|
|
2317
|
+
for (let at = 0; at < digits2.length; at += 1) {
|
|
2318
|
+
let digit = Number(digits2[digits2.length - 1 - at]);
|
|
2309
2319
|
if (at % 2 === 1) {
|
|
2310
2320
|
digit *= 2;
|
|
2311
2321
|
if (digit > 9)
|
|
@@ -2319,13 +2329,13 @@ var printable = (value) => [...value].every((ch) => ch.charCodeAt(0) >= 32 && ch
|
|
|
2319
2329
|
function typed(value, limit = 256) {
|
|
2320
2330
|
return typeof value === "string" && value.length >= 1 && value.length <= limit && !PAN_LIKE4.test(value) && printable(value);
|
|
2321
2331
|
}
|
|
2322
|
-
function decodeBase64(
|
|
2323
|
-
if (typeof
|
|
2332
|
+
function decodeBase64(text6) {
|
|
2333
|
+
if (typeof text6 !== "string" || !BASE643.test(text6) || text6.length % 4 !== 0)
|
|
2324
2334
|
return null;
|
|
2325
2335
|
let bits = 0;
|
|
2326
2336
|
let value = 0;
|
|
2327
2337
|
let out = "";
|
|
2328
|
-
for (const ch of
|
|
2338
|
+
for (const ch of text6.replace(/=+$/, "")) {
|
|
2329
2339
|
value = (value << 6 | BASE64_ALPHABET.indexOf(ch)) & 16777215;
|
|
2330
2340
|
bits += 6;
|
|
2331
2341
|
if (bits >= 8) {
|
|
@@ -2335,8 +2345,8 @@ function decodeBase64(text2) {
|
|
|
2335
2345
|
}
|
|
2336
2346
|
return out;
|
|
2337
2347
|
}
|
|
2338
|
-
function soundDevice(
|
|
2339
|
-
const json = decodeBase64(
|
|
2348
|
+
function soundDevice(text6) {
|
|
2349
|
+
const json = decodeBase64(text6);
|
|
2340
2350
|
if (json === null)
|
|
2341
2351
|
return false;
|
|
2342
2352
|
let value;
|
|
@@ -2450,6 +2460,1348 @@ function sumupBodyVerdict(body, url) {
|
|
|
2450
2460
|
return refuse17("sumup_card_saving_refused");
|
|
2451
2461
|
return CARD16;
|
|
2452
2462
|
}
|
|
2463
|
+
// src/twoc2p-secure-pay.js
|
|
2464
|
+
var SALTED = /* @__PURE__ */ Object.freeze([83, 97, 108, 116, 101, 100, 95, 95]);
|
|
2465
|
+
var B64 = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
2466
|
+
var FIELD_LIMIT = 1024;
|
|
2467
|
+
function decodeCanonical(text6) {
|
|
2468
|
+
if (typeof text6 !== "string" || text6.length === 0 || text6.length % 4 !== 0 || !B64.test(text6))
|
|
2469
|
+
return null;
|
|
2470
|
+
let binary;
|
|
2471
|
+
try {
|
|
2472
|
+
binary = atob(text6);
|
|
2473
|
+
}
|
|
2474
|
+
catch {
|
|
2475
|
+
return null;
|
|
2476
|
+
}
|
|
2477
|
+
if (btoa(binary) !== text6)
|
|
2478
|
+
return null;
|
|
2479
|
+
return Uint8Array.from(binary, (char) => char.charCodeAt(0));
|
|
2480
|
+
}
|
|
2481
|
+
function twoC2pSecurePayParts(value) {
|
|
2482
|
+
if (typeof value !== "string" || value.length > FIELD_LIMIT || !/^[0-9a-f]{4}/.test(value))
|
|
2483
|
+
return null;
|
|
2484
|
+
const length = parseInt(value.slice(0, 4), 16);
|
|
2485
|
+
if (length < 4 || 4 + length >= value.length)
|
|
2486
|
+
return null;
|
|
2487
|
+
const rsaText = value.slice(4, 4 + length);
|
|
2488
|
+
const rsa = decodeCanonical(rsaText);
|
|
2489
|
+
const cipher = decodeCanonical(value.slice(4 + length));
|
|
2490
|
+
if (!rsa || !cipher || cipher.length < 32 || cipher.length > 80 || cipher.length % 16 !== 0)
|
|
2491
|
+
return null;
|
|
2492
|
+
if (!SALTED.every((byte, at) => cipher[at] === byte))
|
|
2493
|
+
return null;
|
|
2494
|
+
return { rsaText, rsa, salt: cipher.slice(8, 16), blocks: (cipher.length - 16) / 16 };
|
|
2495
|
+
}
|
|
2496
|
+
function isTwoC2pPageField(value, keyBytes) {
|
|
2497
|
+
const parts = twoC2pSecurePayParts(value);
|
|
2498
|
+
if (!parts || !Number.isInteger(keyBytes) || keyBytes < 128)
|
|
2499
|
+
return false;
|
|
2500
|
+
const expected = Math.ceil(keyBytes / 3) * 4;
|
|
2501
|
+
return parts.rsaText.length === expected && (parts.rsa.length === keyBytes || parts.rsa.length === keyBytes - 1);
|
|
2502
|
+
}
|
|
2503
|
+
// src/twoc2p-keys.js
|
|
2504
|
+
var TWOC2P_KEYS = /* @__PURE__ */ Object.freeze({
|
|
2505
|
+
production: Object.freeze({
|
|
2506
|
+
spki: "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/1ljsxI+r6qQraTFrHfWNrV41vxumBF+4ILAG3WsN6HEBQU2wSUv/IyQmZkiys1ilOb+OOuQTH8OXMnqQg9E4epyePW3L7IeOieSbIIDeSX6UpTWmT/Fs7moWZkN8RpuCV0u87n3AY2tQbtcSqwEKi2sxzWLFwscoGn6N5yVIpQIDAQAB",
|
|
2507
|
+
sha256: "bb8f27929ce140c6ef0ec9c4a20d7ca0b83376bc35a501985dc40d16669384fe",
|
|
2508
|
+
script: Object.freeze({ url: "https://t.2c2p.com/SecurePayment/api/my2c2p.1.7.6.min.js", sha256: "4a745a37765a2e28e299d64f6ea5811aab27b176da61db6f840fa85d6a47e763" })
|
|
2509
|
+
}),
|
|
2510
|
+
sandbox: Object.freeze({
|
|
2511
|
+
spki: "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKakJC+2MSZikKoPzlNqXvJCuWNLhejg3gMRePSetYNNgnhyqFwwAR7t7i/B2QFZoixSYc2/23cJz0jA5O+q+Cu3fycqKlf1L9966+X3B9nyHe2eKQZr8KrcS/8+sEKcd0pLATY4AleW1iktuN+2oghrDKuv+aDNztWcOy+PTofwIDAQAB",
|
|
2512
|
+
sha256: "7f80c07f1d72db28ede10dae942940657c72dfa789836c9fdf283cba6feff2e6",
|
|
2513
|
+
script: Object.freeze({ url: "https://demo2.2c2p.com/2C2PFrontEnd/SecurePayment/api/my2c2p.1.7.6.min.js", sha256: "435723d92bfefb00607a56851967e0b745d52b8d49443de5f0000f0583fde5cc" })
|
|
2514
|
+
})
|
|
2515
|
+
});
|
|
2516
|
+
function twoC2pKey(environment2) {
|
|
2517
|
+
if (environment2 !== "production" && environment2 !== "sandbox")
|
|
2518
|
+
return null;
|
|
2519
|
+
return TWOC2P_KEYS[environment2] ?? null;
|
|
2520
|
+
}
|
|
2521
|
+
function twoC2pKeyBytes(environment2) {
|
|
2522
|
+
const key = twoC2pKey(environment2);
|
|
2523
|
+
if (!key)
|
|
2524
|
+
return null;
|
|
2525
|
+
try {
|
|
2526
|
+
return parseRsaPublicKey(key).size;
|
|
2527
|
+
}
|
|
2528
|
+
catch {
|
|
2529
|
+
return null;
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
// src/twoc2p.js
|
|
2533
|
+
var TWOC2P_PSP = "twoc2p";
|
|
2534
|
+
var TWOC2P_FIELD = "securePayToken";
|
|
2535
|
+
var TWOC2P_REVIEWED_BUILDS = /* @__PURE__ */ Object.freeze(["4.1", "4.2", "4.3", "4.4", "4.5"]);
|
|
2536
|
+
var record12 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2537
|
+
var refuse18 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
2538
|
+
var CARD17 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
2539
|
+
var CONTINUE8 = /* @__PURE__ */ Object.freeze({ verdict: "continue" });
|
|
2540
|
+
var PAYMENT_URL = /^https:\/\/(sandbox-)?pgwv4\.2c2p\.com\/payment\/(4\.[0-9]{1,2})\/Payment$/;
|
|
2541
|
+
function twoC2pPaymentTarget(url) {
|
|
2542
|
+
const match = typeof url === "string" ? PAYMENT_URL.exec(url) : null;
|
|
2543
|
+
if (!match)
|
|
2544
|
+
return null;
|
|
2545
|
+
return Object.freeze({ environment: match[1] ? "sandbox" : "production", version: match[2], reviewed: TWOC2P_REVIEWED_BUILDS.includes(match[2]) });
|
|
2546
|
+
}
|
|
2547
|
+
function twoC2pPaymentCarriesCard(body) {
|
|
2548
|
+
if (typeof body !== "string")
|
|
2549
|
+
return true;
|
|
2550
|
+
try {
|
|
2551
|
+
return JSON.stringify(JSON.parse(body)).includes(`"${TWOC2P_FIELD}"`);
|
|
2552
|
+
}
|
|
2553
|
+
catch {
|
|
2554
|
+
return true;
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
var ROOT_KEYS6 = /* @__PURE__ */ Object.freeze(["paymentToken", "clientIP", "locale", "responseReturnUrl", "clientID", "payment"]);
|
|
2558
|
+
var CODE_KEYS = /* @__PURE__ */ Object.freeze(["channelCode", "agentCode", "agentChannelCode"]);
|
|
2559
|
+
var DATA_KEYS2 = /* @__PURE__ */ Object.freeze([
|
|
2560
|
+
"name",
|
|
2561
|
+
"isIppChosen",
|
|
2562
|
+
"cardDetails",
|
|
2563
|
+
"loyaltyPoints",
|
|
2564
|
+
"fxRateID",
|
|
2565
|
+
"email",
|
|
2566
|
+
"mobileNo",
|
|
2567
|
+
"mobileNoPrefix",
|
|
2568
|
+
"customerNote",
|
|
2569
|
+
"paymentExpiry",
|
|
2570
|
+
"securePayToken",
|
|
2571
|
+
"cardTokenize",
|
|
2572
|
+
"accountTokenization",
|
|
2573
|
+
"token",
|
|
2574
|
+
"customerToken",
|
|
2575
|
+
"accountNo",
|
|
2576
|
+
"installmentPeriod",
|
|
2577
|
+
"interestType",
|
|
2578
|
+
"payLaterPeriod",
|
|
2579
|
+
"billingAddress1",
|
|
2580
|
+
"billingAddress2",
|
|
2581
|
+
"billingCity",
|
|
2582
|
+
"billingState",
|
|
2583
|
+
"billingCountryCode",
|
|
2584
|
+
"billingPostalCode",
|
|
2585
|
+
"riskInfo"
|
|
2586
|
+
]);
|
|
2587
|
+
var RISK_KEYS = /* @__PURE__ */ Object.freeze(["customer_id", "shipping_method", "deviceSessionId", "customData"]);
|
|
2588
|
+
var BODY_LIMIT14 = 16384;
|
|
2589
|
+
var CONTROL6 = /[\u0000-\u001f\u007f]/;
|
|
2590
|
+
var CARD_LIKE = /(?:[0-9][ _.:/-]*){12,}/;
|
|
2591
|
+
var PAYMENT_TOKEN = /^[A-Za-z0-9+/]{16,1000}={0,2}$/;
|
|
2592
|
+
var UUID2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2593
|
+
var IP = /^[0-9A-Fa-f.:]{2,45}$/;
|
|
2594
|
+
var LOCALE2 = /^[A-Za-z]{2,3}(?:[-_][A-Za-z0-9]{2,8})?$/;
|
|
2595
|
+
var AGENT = /^[A-Za-z0-9_]{1,32}$/;
|
|
2596
|
+
var RISK_TOKEN2 = /^[\x21-\x7e]{1,512}$/;
|
|
2597
|
+
var RETURN_URL = /^https:\/\/((?:sandbox-)?pgw-ui\.2c2p\.com)\/payment\/4\.[0-9]{1,2}(?:\/|\/index\.html)?#\/(?:info|mobile\/process)\/([A-Za-z0-9+/]{16,1000}={0,2})?$/;
|
|
2598
|
+
var PAGE_HOSTS = /* @__PURE__ */ Object.freeze({ production: "pgw-ui.2c2p.com", sandbox: "sandbox-pgw-ui.2c2p.com" });
|
|
2599
|
+
var returnUrlTaken = (value, paymentToken, environment2) => {
|
|
2600
|
+
if (value === void 0)
|
|
2601
|
+
return true;
|
|
2602
|
+
const match = typeof value === "string" ? RETURN_URL.exec(value) : null;
|
|
2603
|
+
return !!match && (match[2] === void 0 || match[2] === paymentToken) && (environment2 === void 0 || match[1] === PAGE_HOSTS[environment2]);
|
|
2604
|
+
};
|
|
2605
|
+
var inOrder2 = (value, order) => {
|
|
2606
|
+
let at = -1;
|
|
2607
|
+
for (const key of Object.keys(value)) {
|
|
2608
|
+
const next = order.indexOf(key);
|
|
2609
|
+
if (next <= at)
|
|
2610
|
+
return false;
|
|
2611
|
+
at = next;
|
|
2612
|
+
}
|
|
2613
|
+
return true;
|
|
2614
|
+
};
|
|
2615
|
+
var text2 = (value, limit) => typeof value === "string" && value.length <= limit && !CONTROL6.test(value) && !CARD_LIKE.test(value);
|
|
2616
|
+
var optionalText = (value, limit) => value === void 0 || text2(value, limit);
|
|
2617
|
+
function twoC2pBodyVerdict(body, keyBytes = 128, environment2 = void 0) {
|
|
2618
|
+
if (!twoC2pPaymentCarriesCard(body))
|
|
2619
|
+
return CONTINUE8;
|
|
2620
|
+
if (typeof body !== "string" || body.length > BODY_LIMIT14)
|
|
2621
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2622
|
+
let value;
|
|
2623
|
+
try {
|
|
2624
|
+
value = JSON.parse(body);
|
|
2625
|
+
}
|
|
2626
|
+
catch {
|
|
2627
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2628
|
+
}
|
|
2629
|
+
if (!record12(value) || JSON.stringify(value) !== body || !inOrder2(value, ROOT_KEYS6))
|
|
2630
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2631
|
+
if (typeof value.paymentToken !== "string" || !PAYMENT_TOKEN.test(value.paymentToken) || value.clientIP !== void 0 && !(typeof value.clientIP === "string" && IP.test(value.clientIP)) || value.locale !== void 0 && !(typeof value.locale === "string" && LOCALE2.test(value.locale)) || !returnUrlTaken(value.responseReturnUrl, value.paymentToken, environment2) || value.clientID !== void 0 && !(typeof value.clientID === "string" && UUID2.test(value.clientID)))
|
|
2632
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2633
|
+
const payment = value.payment;
|
|
2634
|
+
if (!record12(payment) || Object.keys(payment).join(",") !== "code,data")
|
|
2635
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2636
|
+
const code = payment.code;
|
|
2637
|
+
const data = payment.data;
|
|
2638
|
+
if (!record12(code) || !record12(data))
|
|
2639
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2640
|
+
if (Object.prototype.hasOwnProperty.call(code, "subChannelCode"))
|
|
2641
|
+
return refuse18("twoc2p_stored_card");
|
|
2642
|
+
if (code.channelCode === "IPP" || code.channelCode === "LIPP")
|
|
2643
|
+
return refuse18("twoc2p_installments");
|
|
2644
|
+
if (!inOrder2(code, CODE_KEYS) || code.channelCode === void 0)
|
|
2645
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2646
|
+
if (code.channelCode !== "CC")
|
|
2647
|
+
return refuse18("twoc2p_channel_unsupported");
|
|
2648
|
+
if ([code.agentCode, code.agentChannelCode].some((part) => part !== void 0 && !(typeof part === "string" && AGENT.test(part))))
|
|
2649
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2650
|
+
return dataVerdict(data, keyBytes, body);
|
|
2651
|
+
}
|
|
2652
|
+
function dataVerdict(data, keyBytes, body) {
|
|
2653
|
+
if (data.cardTokenize !== void 0 || data.accountTokenization !== void 0)
|
|
2654
|
+
return refuse18("twoc2p_keeps_card");
|
|
2655
|
+
if (data.token !== void 0 || data.customerToken !== void 0)
|
|
2656
|
+
return refuse18("twoc2p_stored_card");
|
|
2657
|
+
if (data.accountNo !== void 0)
|
|
2658
|
+
return refuse18("twoc2p_card_in_clear");
|
|
2659
|
+
const details = data.cardDetails;
|
|
2660
|
+
if (record12(details) && (details.cardNo !== void 0 || details.accountNo !== void 0))
|
|
2661
|
+
return refuse18("twoc2p_card_in_clear");
|
|
2662
|
+
if (record12(details) && Object.keys(details).some((key) => key !== "email"))
|
|
2663
|
+
return refuse18("twoc2p_stored_card");
|
|
2664
|
+
if (data.isIppChosen === true || data.installmentPeriod !== void 0 || data.interestType !== void 0 || data.payLaterPeriod !== void 0) {
|
|
2665
|
+
return refuse18("twoc2p_installments");
|
|
2666
|
+
}
|
|
2667
|
+
if (data.fxRateID !== void 0)
|
|
2668
|
+
return refuse18("twoc2p_currency_conversion");
|
|
2669
|
+
if (data.loyaltyPoints !== void 0 && !(Array.isArray(data.loyaltyPoints) && data.loyaltyPoints.length === 0)) {
|
|
2670
|
+
return refuse18("twoc2p_loyalty_redemption");
|
|
2671
|
+
}
|
|
2672
|
+
if (!inOrder2(data, DATA_KEYS2) || data.paymentExpiry !== void 0)
|
|
2673
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2674
|
+
if (typeof data.securePayToken !== "string" || !isTwoC2pPageField(data.securePayToken, keyBytes))
|
|
2675
|
+
return refuse18("twoc2p_field_unreviewed");
|
|
2676
|
+
if (body.split(data.securePayToken).length !== 2)
|
|
2677
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2678
|
+
if (data.isIppChosen !== void 0 && data.isIppChosen !== false)
|
|
2679
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2680
|
+
if (details !== void 0 && !(record12(details) && (details.email === void 0 || text2(details.email, 254))))
|
|
2681
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2682
|
+
if (!optionalText(data.name, 128) || !optionalText(data.email, 254) || !optionalText(data.customerNote, 255) || !(data.mobileNo === void 0 || typeof data.mobileNo === "string" && /^[0-9]{4,11}$/.test(data.mobileNo)) || !(data.mobileNoPrefix === void 0 || typeof data.mobileNoPrefix === "string" && /^\+?[0-9]{1,4}$/.test(data.mobileNoPrefix))) {
|
|
2683
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2684
|
+
}
|
|
2685
|
+
for (const key of ["billingAddress1", "billingAddress2", "billingCity", "billingState", "billingPostalCode"]) {
|
|
2686
|
+
if (!optionalText(data[key], 128))
|
|
2687
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2688
|
+
}
|
|
2689
|
+
if (data.billingCountryCode !== void 0 && !(typeof data.billingCountryCode === "string" && /^[A-Za-z]{2}$/.test(data.billingCountryCode))) {
|
|
2690
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2691
|
+
}
|
|
2692
|
+
const risk = data.riskInfo;
|
|
2693
|
+
if (risk !== void 0 && risk !== null && !(record12(risk) && Object.keys(risk).join(",") === RISK_KEYS.join(",") && risk.customer_id === "" && risk.shipping_method === "" && typeof risk.deviceSessionId === "string" && RISK_TOKEN2.test(risk.deviceSessionId) && record12(risk.customData) && Object.keys(risk.customData).length === 0)) {
|
|
2694
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2695
|
+
}
|
|
2696
|
+
return CARD17;
|
|
2697
|
+
}
|
|
2698
|
+
// src/hipay.js
|
|
2699
|
+
var HIPAY_PSP = "hipay";
|
|
2700
|
+
var HIPAY_TOKEN_URLS = /* @__PURE__ */ Object.freeze({
|
|
2701
|
+
production: "https://secure2-vault.hipay-tpp.com/rest/v2/token",
|
|
2702
|
+
sandbox: "https://stage-secure2-vault.hipay-tpp.com/rest/v2/token"
|
|
2703
|
+
});
|
|
2704
|
+
var BODY_LIMIT15 = 2048;
|
|
2705
|
+
var HOSTED_KEYS = /* @__PURE__ */ Object.freeze(["multi_use", "card_expiry_month", "card_expiry_year", "card_number", "card_holder", "cvc"]);
|
|
2706
|
+
var HOSTED_KEYS_NO_HOLDER = /* @__PURE__ */ Object.freeze(["multi_use", "card_expiry_month", "card_expiry_year", "card_number", "cvc"]);
|
|
2707
|
+
var DIRECT_KEYS = /* @__PURE__ */ Object.freeze(["card_expiry_month", "card_expiry_year", "card_number", "card_holder", "cvc", "multi_use"]);
|
|
2708
|
+
var DIRECT_KEYS_NO_HOLDER = /* @__PURE__ */ Object.freeze(["card_expiry_month", "card_expiry_year", "card_number", "cvc", "multi_use"]);
|
|
2709
|
+
var CARD_SHAPES = /* @__PURE__ */ Object.freeze([HOSTED_KEYS, HOSTED_KEYS_NO_HOLDER, DIRECT_KEYS, DIRECT_KEYS_NO_HOLDER]);
|
|
2710
|
+
var NUMBER_ONLY_KEYS = /* @__PURE__ */ Object.freeze(["multi_use", "card_expiry_month", "card_expiry_year", "card_number"]);
|
|
2711
|
+
var CARD_NUMBER10 = /^[0-9]{12,19}$/;
|
|
2712
|
+
var SECURITY_CODE12 = /^[0-9]{3,4}$/;
|
|
2713
|
+
var MONTH8 = /^(?:0[1-9]|1[0-2])$/;
|
|
2714
|
+
var YEAR8 = /^20[0-9]{2}$/;
|
|
2715
|
+
var TEXT_LIMIT3 = 256;
|
|
2716
|
+
var CONTROL7 = /[\u0000-\u001f\u007f]/;
|
|
2717
|
+
var record13 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2718
|
+
var sameKeys7 = (value, keys) => {
|
|
2719
|
+
const own6 = Object.keys(value);
|
|
2720
|
+
return own6.length === keys.length && own6.every((key, at) => key === keys[at]);
|
|
2721
|
+
};
|
|
2722
|
+
var plainText3 = (value) => typeof value === "string" && value.length <= TEXT_LIMIT3 && !CONTROL7.test(value) && (value.match(/[0-9]/g) ?? []).length < 12;
|
|
2723
|
+
var refuse19 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
2724
|
+
var CARD18 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
2725
|
+
function hipayTokenEnvironment(url) {
|
|
2726
|
+
if (url === HIPAY_TOKEN_URLS.production)
|
|
2727
|
+
return "production";
|
|
2728
|
+
if (url === HIPAY_TOKEN_URLS.sandbox)
|
|
2729
|
+
return "sandbox";
|
|
2730
|
+
return null;
|
|
2731
|
+
}
|
|
2732
|
+
function isHipayTokenUrl(url) {
|
|
2733
|
+
return hipayTokenEnvironment(url) !== null;
|
|
2734
|
+
}
|
|
2735
|
+
function readBody9(body) {
|
|
2736
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT15)
|
|
2737
|
+
return null;
|
|
2738
|
+
let value;
|
|
2739
|
+
try {
|
|
2740
|
+
value = JSON.parse(body);
|
|
2741
|
+
if (!record13(value) || JSON.stringify(value) !== body)
|
|
2742
|
+
return null;
|
|
2743
|
+
}
|
|
2744
|
+
catch {
|
|
2745
|
+
return null;
|
|
2746
|
+
}
|
|
2747
|
+
return value;
|
|
2748
|
+
}
|
|
2749
|
+
function hipayBodyVerdict(body) {
|
|
2750
|
+
const value = readBody9(body);
|
|
2751
|
+
if (value === null)
|
|
2752
|
+
return refuse19("hipay_body_unsupported");
|
|
2753
|
+
if (sameKeys7(value, NUMBER_ONLY_KEYS))
|
|
2754
|
+
return refuse19("hipay_number_only");
|
|
2755
|
+
if (!CARD_SHAPES.some((keys) => sameKeys7(value, keys)))
|
|
2756
|
+
return refuse19("hipay_body_unsupported");
|
|
2757
|
+
if (typeof value.card_number !== "string" || !CARD_NUMBER10.test(value.card_number) || typeof value.cvc !== "string" || !SECURITY_CODE12.test(value.cvc) || typeof value.card_expiry_month !== "string" || !MONTH8.test(value.card_expiry_month) || typeof value.card_expiry_year !== "string" || !YEAR8.test(value.card_expiry_year) || "card_holder" in value && !plainText3(value.card_holder)) {
|
|
2758
|
+
return refuse19("hipay_body_unsupported");
|
|
2759
|
+
}
|
|
2760
|
+
if (value.multi_use === 1)
|
|
2761
|
+
return refuse19("hipay_keeps_card");
|
|
2762
|
+
return value.multi_use === 0 ? CARD18 : refuse19("hipay_body_unsupported");
|
|
2763
|
+
}
|
|
2764
|
+
var pin5 = (fields) => Object.freeze({ ...fields, origins: Object.freeze([...fields.origins]), usernames: Object.freeze([...fields.usernames]) });
|
|
2765
|
+
var HIPAY_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
2766
|
+
pin5({ id: "happybulle", merchant: "HappyBulle", origins: ["https://www.happybulle.com"], usernames: ["94683309.secure-gateway.hipay-tpp.com"] })
|
|
2767
|
+
]);
|
|
2768
|
+
// src/amazon-payment-services.js
|
|
2769
|
+
var APS_PSP = "amazon_payment_services";
|
|
2770
|
+
var APS_HOSTS = /* @__PURE__ */ Object.freeze({ "checkout.payfort.com": "production", "sbcheckout.payfort.com": "sandbox" });
|
|
2771
|
+
var APS_TOKENIZATION_PATH = "/FortAPI/paymentPage";
|
|
2772
|
+
var APS_SIGNED_FIELDS = /* @__PURE__ */ Object.freeze([
|
|
2773
|
+
"service_command",
|
|
2774
|
+
"access_code",
|
|
2775
|
+
"merchant_identifier",
|
|
2776
|
+
"merchant_reference",
|
|
2777
|
+
"language",
|
|
2778
|
+
"return_url",
|
|
2779
|
+
"signature"
|
|
2780
|
+
]);
|
|
2781
|
+
var APS_CARD_FIELDS = /* @__PURE__ */ Object.freeze(["card_number", "expiry_date", "card_security_code"]);
|
|
2782
|
+
var APS_OPTIONAL_FIELDS = /* @__PURE__ */ Object.freeze(["card_holder_name", "remember_me"]);
|
|
2783
|
+
var URL_LIMIT7 = 2048;
|
|
2784
|
+
var BODY_LIMIT16 = 32 * 1024;
|
|
2785
|
+
var exact = (pattern, value) => typeof value === "string" && pattern.exec(value)?.[0] === value;
|
|
2786
|
+
var controlFree = (value, max) => typeof value === "string" && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
|
|
2787
|
+
var SHAPES = /* @__PURE__ */ new Map([
|
|
2788
|
+
["service_command", (v) => v === "TOKENIZATION"],
|
|
2789
|
+
["access_code", (v) => exact(/^[A-Za-z0-9]{1,20}$/, v)],
|
|
2790
|
+
["merchant_identifier", (v) => exact(/^[A-Za-z0-9]{1,20}$/, v)],
|
|
2791
|
+
["merchant_reference", (v) => exact(/^[A-Za-z0-9._-]{1,40}$/, v)],
|
|
2792
|
+
["language", (v) => v === "en" || v === "ar"],
|
|
2793
|
+
// Hex SHA-256 (APS's default), SHA-512, or the 40 characters of the SHA-1 APS calls SHA-128.
|
|
2794
|
+
["signature", (v) => exact(/^(?:[0-9A-Fa-f]{40}|[0-9A-Fa-f]{64}|[0-9A-Fa-f]{128})$/, v)],
|
|
2795
|
+
["card_number", (v) => exact(/^[0-9]{12,19}$/, v)],
|
|
2796
|
+
["expiry_date", (v) => exact(/^[0-9]{2}(?:0[1-9]|1[0-2])$/, v)],
|
|
2797
|
+
["card_security_code", (v) => exact(/^[0-9]{3,4}$/, v)],
|
|
2798
|
+
["card_holder_name", (v) => controlFree(v, 255)],
|
|
2799
|
+
["remember_me", (v) => v === "YES" || v === "NO"]
|
|
2800
|
+
]);
|
|
2801
|
+
function apsTokenizationUrl(url) {
|
|
2802
|
+
if (typeof url !== "string" || url.length > URL_LIMIT7 || url.includes("?") || url.includes("#"))
|
|
2803
|
+
return null;
|
|
2804
|
+
let parsed;
|
|
2805
|
+
try {
|
|
2806
|
+
parsed = new URL(url);
|
|
2807
|
+
}
|
|
2808
|
+
catch {
|
|
2809
|
+
return null;
|
|
2810
|
+
}
|
|
2811
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || parsed.pathname !== APS_TOKENIZATION_PATH || !Object.prototype.hasOwnProperty.call(APS_HOSTS, parsed.hostname))
|
|
2812
|
+
return null;
|
|
2813
|
+
return Object.freeze({ host: parsed.hostname, environment: APS_HOSTS[parsed.hostname] });
|
|
2814
|
+
}
|
|
2815
|
+
function formEncode2(value) {
|
|
2816
|
+
let encoded;
|
|
2817
|
+
try {
|
|
2818
|
+
encoded = encodeURIComponent(value);
|
|
2819
|
+
}
|
|
2820
|
+
catch {
|
|
2821
|
+
return null;
|
|
2822
|
+
}
|
|
2823
|
+
return encoded.replace(/[!'()~]/g, (ch) => `%${ch.charCodeAt(0).toString(16).toUpperCase()}`).replace(/%20/g, "+");
|
|
2824
|
+
}
|
|
2825
|
+
function formDecode(raw) {
|
|
2826
|
+
if (!/^(?:[A-Za-z0-9*._+-]|%[0-9A-F]{2})*$/.test(raw))
|
|
2827
|
+
return null;
|
|
2828
|
+
let value;
|
|
2829
|
+
try {
|
|
2830
|
+
value = decodeURIComponent(raw.replace(/\+/g, "%20"));
|
|
2831
|
+
}
|
|
2832
|
+
catch {
|
|
2833
|
+
return null;
|
|
2834
|
+
}
|
|
2835
|
+
return formEncode2(value) === raw ? value : null;
|
|
2836
|
+
}
|
|
2837
|
+
function parseForm(body) {
|
|
2838
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT16)
|
|
2839
|
+
return null;
|
|
2840
|
+
const pairs = [];
|
|
2841
|
+
const values = /* @__PURE__ */ new Map();
|
|
2842
|
+
for (const chunk of body.split("&")) {
|
|
2843
|
+
const separator = chunk.indexOf("=");
|
|
2844
|
+
if (separator < 1)
|
|
2845
|
+
return null;
|
|
2846
|
+
const rawName = chunk.slice(0, separator), raw = chunk.slice(separator + 1);
|
|
2847
|
+
const name = formDecode(rawName), value = formDecode(raw);
|
|
2848
|
+
if (name === null || value === null || values.has(name))
|
|
2849
|
+
return null;
|
|
2850
|
+
pairs.push({ name, rawName, raw, value });
|
|
2851
|
+
values.set(name, value);
|
|
2852
|
+
}
|
|
2853
|
+
return { pairs, values };
|
|
2854
|
+
}
|
|
2855
|
+
function returnUrlAdmitted(value) {
|
|
2856
|
+
if (typeof value !== "string" || value.length > 400 || value.includes("#") || /[\u0000- \u007f]/.test(value))
|
|
2857
|
+
return false;
|
|
2858
|
+
let parsed;
|
|
2859
|
+
try {
|
|
2860
|
+
parsed = new URL(value);
|
|
2861
|
+
}
|
|
2862
|
+
catch {
|
|
2863
|
+
return false;
|
|
2864
|
+
}
|
|
2865
|
+
return parsed.protocol === "https:" && !parsed.username && !parsed.password && parsed.href === value;
|
|
2866
|
+
}
|
|
2867
|
+
function apsBodyRefusal(body) {
|
|
2868
|
+
const form = parseForm(body);
|
|
2869
|
+
if (!form)
|
|
2870
|
+
return "aps_body_unsupported";
|
|
2871
|
+
const has = (name) => form.values.has(name);
|
|
2872
|
+
if (has("token_name"))
|
|
2873
|
+
return "aps_saved_card_refused";
|
|
2874
|
+
if ([...form.values.keys()].some((name) => /^merchant_extra[1-5]?$|^agreement_id$|^recurring_/.test(name)))
|
|
2875
|
+
return "aps_recurring_refused";
|
|
2876
|
+
if (has("service_command") && form.values.get("service_command") !== "TOKENIZATION")
|
|
2877
|
+
return "aps_service_command_refused";
|
|
2878
|
+
const allowed = /* @__PURE__ */ new Set([...APS_SIGNED_FIELDS, ...APS_CARD_FIELDS, ...APS_OPTIONAL_FIELDS]);
|
|
2879
|
+
if (form.pairs.some(({ name }) => !allowed.has(name)))
|
|
2880
|
+
return "aps_body_unsupported";
|
|
2881
|
+
if (!returnUrlAdmitted(form.values.get("return_url")))
|
|
2882
|
+
return "aps_return_url_refused";
|
|
2883
|
+
for (const name of [...APS_SIGNED_FIELDS, ...APS_CARD_FIELDS]) {
|
|
2884
|
+
if (name !== "return_url" && !SHAPES.get(name)(form.values.get(name)))
|
|
2885
|
+
return "aps_body_unsupported";
|
|
2886
|
+
}
|
|
2887
|
+
for (const name of APS_OPTIONAL_FIELDS) {
|
|
2888
|
+
if (has(name) && !SHAPES.get(name)(form.values.get(name)))
|
|
2889
|
+
return "aps_body_unsupported";
|
|
2890
|
+
}
|
|
2891
|
+
return null;
|
|
2892
|
+
}
|
|
2893
|
+
function apsBodyVerdict(body, url) {
|
|
2894
|
+
if (url !== void 0 && !apsTokenizationUrl(url))
|
|
2895
|
+
return { verdict: "refuse", code: "aps_url_refused" };
|
|
2896
|
+
const form = parseForm(body);
|
|
2897
|
+
const names = form ? [...form.values.keys()] : typeof body === "string" ? body.split("&").map((chunk) => {
|
|
2898
|
+
try {
|
|
2899
|
+
return decodeURIComponent(chunk.split("=")[0].replace(/\+/g, " "));
|
|
2900
|
+
}
|
|
2901
|
+
catch {
|
|
2902
|
+
return APS_CARD_FIELDS[0];
|
|
2903
|
+
}
|
|
2904
|
+
}) : [APS_CARD_FIELDS[0]];
|
|
2905
|
+
const mentionsCard = !form && typeof body === "string" && APS_CARD_FIELDS.some((name) => body.toLowerCase().includes(name) || body.replace(/%([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16))).toLowerCase().includes(name));
|
|
2906
|
+
if (!mentionsCard && !names.some((name) => APS_CARD_FIELDS.includes(name.trim().toLowerCase())))
|
|
2907
|
+
return { verdict: "continue" };
|
|
2908
|
+
const code = apsBodyRefusal(body);
|
|
2909
|
+
return code ? { verdict: "refuse", code } : { verdict: "card" };
|
|
2910
|
+
}
|
|
2911
|
+
var ANSWER_LIMIT = 64 * 1024;
|
|
2912
|
+
// src/paypal.js
|
|
2913
|
+
var PAYPAL_PSP = "paypal";
|
|
2914
|
+
var PAYPAL_CONFIRM_HOSTS = /* @__PURE__ */ Object.freeze(["www.paypal.com", "www.sandbox.paypal.com", "api-m.paypal.com", "api-m.sandbox.paypal.com"]);
|
|
2915
|
+
var CONFIRM_PATH = /^\/v2\/checkout\/orders\/([A-Z0-9]{1,36})\/confirm-payment-source$/;
|
|
2916
|
+
var BODY_LIMIT17 = 8192;
|
|
2917
|
+
var CARD_KEYS8 = /* @__PURE__ */ Object.freeze(["number", "expiry", "security_code", "name", "billing_address", "attributes", "brand_preference"]);
|
|
2918
|
+
var ADDRESS_KEYS3 = /* @__PURE__ */ Object.freeze([
|
|
2919
|
+
"address_line_1",
|
|
2920
|
+
"address_line_2",
|
|
2921
|
+
"address_line_3",
|
|
2922
|
+
"admin_area_1",
|
|
2923
|
+
"admin_area_2",
|
|
2924
|
+
"admin_area_3",
|
|
2925
|
+
"admin_area_4",
|
|
2926
|
+
"postal_code",
|
|
2927
|
+
"country_code"
|
|
2928
|
+
]);
|
|
2929
|
+
var CONTROL8 = /[\u0000-\u001f\u007f]/;
|
|
2930
|
+
var TEXT_LIMIT4 = 300;
|
|
2931
|
+
var cardLike = (value) => (value.match(/[0-9]/g) ?? []).length >= 12;
|
|
2932
|
+
var text3 = (value) => typeof value === "string" && value.length <= TEXT_LIMIT4 && !CONTROL8.test(value) && !cardLike(value);
|
|
2933
|
+
var record14 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2934
|
+
var own3 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
2935
|
+
var keysWithin2 = (value, allowed) => record14(value) && Object.keys(value).every((key) => allowed.includes(key));
|
|
2936
|
+
var refuse20 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
2937
|
+
var CARD19 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
2938
|
+
var CONTINUE9 = /* @__PURE__ */ Object.freeze({ verdict: "continue" });
|
|
2939
|
+
function paypalConfirmOrderId(url) {
|
|
2940
|
+
if (typeof url !== "string" || url.length > 256 || url.includes("?") || url.includes("#"))
|
|
2941
|
+
return null;
|
|
2942
|
+
let parsed;
|
|
2943
|
+
try {
|
|
2944
|
+
parsed = new URL(url);
|
|
2945
|
+
}
|
|
2946
|
+
catch {
|
|
2947
|
+
return null;
|
|
2948
|
+
}
|
|
2949
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !PAYPAL_CONFIRM_HOSTS.includes(parsed.hostname))
|
|
2950
|
+
return null;
|
|
2951
|
+
return CONFIRM_PATH.exec(parsed.pathname)?.[1] ?? null;
|
|
2952
|
+
}
|
|
2953
|
+
function isPaypalConfirmUrl(url) {
|
|
2954
|
+
return paypalConfirmOrderId(url) !== null;
|
|
2955
|
+
}
|
|
2956
|
+
function readBody10(body) {
|
|
2957
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT17)
|
|
2958
|
+
return null;
|
|
2959
|
+
let value;
|
|
2960
|
+
try {
|
|
2961
|
+
value = JSON.parse(body);
|
|
2962
|
+
if (!record14(value) || JSON.stringify(value) !== body)
|
|
2963
|
+
return null;
|
|
2964
|
+
}
|
|
2965
|
+
catch {
|
|
2966
|
+
return null;
|
|
2967
|
+
}
|
|
2968
|
+
return value;
|
|
2969
|
+
}
|
|
2970
|
+
var typedNumber = (value) => typeof value === "string" && value.length <= 23 && /^[0-9]+(?: [0-9]+)*$/.test(value) && value.replace(/ /g, "").length >= 12 && value.replace(/ /g, "").length <= 19;
|
|
2971
|
+
function installmentsOk(value) {
|
|
2972
|
+
if (!keysWithin2(value, ["term", "interval_duration"]) || Object.keys(value).length === 0)
|
|
2973
|
+
return false;
|
|
2974
|
+
if (own3(value, "term") && !(Number.isSafeInteger(value.term) && value.term >= 1 && value.term <= 99))
|
|
2975
|
+
return false;
|
|
2976
|
+
return !own3(value, "interval_duration") || typeof value.interval_duration === "string" && /^P[0-9]{1,3}[DWMY]$/.test(value.interval_duration);
|
|
2977
|
+
}
|
|
2978
|
+
function paypalBodyVerdict(body) {
|
|
2979
|
+
const value = readBody10(body);
|
|
2980
|
+
if (value === null)
|
|
2981
|
+
return refuse20("paypal_body_unsupported");
|
|
2982
|
+
const source = value.payment_source;
|
|
2983
|
+
const card = record14(source) ? source.card : void 0;
|
|
2984
|
+
const number = record14(card) ? card.number : void 0;
|
|
2985
|
+
if (number === void 0 || number === null || number === "")
|
|
2986
|
+
return CONTINUE9;
|
|
2987
|
+
const context = value.application_context;
|
|
2988
|
+
const attributes = record14(card.attributes) ? card.attributes : null;
|
|
2989
|
+
if (record14(context) && context.vault === true || own3(card, "stored_credential") || attributes && (own3(attributes, "vault") || own3(attributes, "customer")))
|
|
2990
|
+
return refuse20("paypal_card_on_file");
|
|
2991
|
+
if (attributes && record14(attributes.verification) && attributes.verification.method === "SCA_ALWAYS")
|
|
2992
|
+
return refuse20("paypal_three_ds");
|
|
2993
|
+
if (!keysWithin2(value, ["payment_source"]) || !keysWithin2(source, ["card"]) || !keysWithin2(card, CARD_KEYS8) || !typedNumber(card.number) || typeof card.expiry !== "string" || !/^[0-9]{4}-(?:0[1-9]|1[0-2])$/.test(card.expiry))
|
|
2994
|
+
return refuse20("paypal_body_unsupported");
|
|
2995
|
+
if (own3(card, "security_code") && !(typeof card.security_code === "string" && /^[0-9]{3,4}$/.test(card.security_code)))
|
|
2996
|
+
return refuse20("paypal_body_unsupported");
|
|
2997
|
+
if (own3(card, "name") && !(text3(card.name) && card.name.trim() !== ""))
|
|
2998
|
+
return refuse20("paypal_body_unsupported");
|
|
2999
|
+
if (own3(card, "brand_preference") && !(typeof card.brand_preference === "string" && /^[A-Z][A-Z_]{1,31}$/.test(card.brand_preference))) {
|
|
3000
|
+
return refuse20("paypal_body_unsupported");
|
|
3001
|
+
}
|
|
3002
|
+
if (own3(card, "billing_address") && !(keysWithin2(card.billing_address, ADDRESS_KEYS3) && Object.values(card.billing_address).every(text3))) {
|
|
3003
|
+
return refuse20("paypal_body_unsupported");
|
|
3004
|
+
}
|
|
3005
|
+
if (own3(card, "attributes") && !(keysWithin2(attributes, ["installments"]) && installmentsOk(attributes.installments))) {
|
|
3006
|
+
return refuse20("paypal_body_unsupported");
|
|
3007
|
+
}
|
|
3008
|
+
return CARD19;
|
|
3009
|
+
}
|
|
3010
|
+
// src/clover.js
|
|
3011
|
+
var CLOVER_PSP = "clover";
|
|
3012
|
+
var CLOVER_TOKEN_HOSTS = /* @__PURE__ */ Object.freeze({ "token.clover.com": "production", "token-sandbox.dev.clover.com": "test" });
|
|
3013
|
+
var CLOVER_TOKEN_PATH = "/v1/tokens";
|
|
3014
|
+
var BODY_LIMIT18 = 4096;
|
|
3015
|
+
var REQUIRED_KEYS = /* @__PURE__ */ Object.freeze(["encrypted_pan", "exp_month", "exp_year", "cvv", "first6", "last4", "brand"]);
|
|
3016
|
+
var OPTIONAL_KEYS = /* @__PURE__ */ Object.freeze(["address_line1", "phone_numbers", "email_address", "name", "address_zip"]);
|
|
3017
|
+
var CARD_ORDER = /* @__PURE__ */ Object.freeze([...REQUIRED_KEYS, ...OPTIONAL_KEYS]);
|
|
3018
|
+
var ENCRYPTED_PAN = /^[A-Za-z0-9+/]{341}[AQgw]==$/;
|
|
3019
|
+
var MONTH9 = /^(?:[1-9]|1[0-2])$/;
|
|
3020
|
+
var YEAR9 = /^(?:[0-9]|[1-9][0-9])$/;
|
|
3021
|
+
var CODE3 = /^[0-9]{3,4}$/;
|
|
3022
|
+
var FIRST6 = /^[0-9]{6}$/;
|
|
3023
|
+
var LAST4 = /^[0-9]{4}$/;
|
|
3024
|
+
var BRANDS = /* @__PURE__ */ new Set(["VISA", "MC", "AMEX", "DISCOVER", "DINERS_CLUB", "JCB"]);
|
|
3025
|
+
var PHONE_TYPES = /* @__PURE__ */ new Set(["home_number", "mobile_number", "work_number"]);
|
|
3026
|
+
var COUNTRY_CODE2 = /^[0-9]{1,4}$/;
|
|
3027
|
+
var SUBSCRIBER = /^[0-9]{1,11}$/;
|
|
3028
|
+
var POSTAL_CODE2 = /^[A-Za-z0-9]{1,10}$/;
|
|
3029
|
+
var TEXT_LIMIT5 = 256;
|
|
3030
|
+
var EMAIL_LIMIT = 254;
|
|
3031
|
+
var CARD_LIKE_RUN = /[0-9]{12,}/;
|
|
3032
|
+
var record15 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3033
|
+
var own4 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
3034
|
+
var refuse21 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
3035
|
+
var CARD20 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
3036
|
+
function cloverTokenUrl(url) {
|
|
3037
|
+
if (typeof url !== "string" || url.length > 256 || url.includes("?") || url.includes("#"))
|
|
3038
|
+
return null;
|
|
3039
|
+
let parsed;
|
|
3040
|
+
try {
|
|
3041
|
+
parsed = new URL(url);
|
|
3042
|
+
}
|
|
3043
|
+
catch {
|
|
3044
|
+
return null;
|
|
3045
|
+
}
|
|
3046
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password)
|
|
3047
|
+
return null;
|
|
3048
|
+
if (!own4(CLOVER_TOKEN_HOSTS, parsed.hostname) || parsed.pathname !== CLOVER_TOKEN_PATH)
|
|
3049
|
+
return null;
|
|
3050
|
+
return Object.freeze({ host: parsed.hostname, environment: CLOVER_TOKEN_HOSTS[parsed.hostname] });
|
|
3051
|
+
}
|
|
3052
|
+
function cloverBrand(digits2) {
|
|
3053
|
+
if (typeof digits2 !== "string" || !/^[0-9]{6,19}$/.test(digits2))
|
|
3054
|
+
return null;
|
|
3055
|
+
const two = Number(digits2.slice(0, 2));
|
|
3056
|
+
const three = Number(digits2.slice(0, 3));
|
|
3057
|
+
const four = Number(digits2.slice(0, 4));
|
|
3058
|
+
const six = Number(digits2.slice(0, 6));
|
|
3059
|
+
if (digits2.startsWith("4"))
|
|
3060
|
+
return "VISA";
|
|
3061
|
+
if (two === 34 || two === 37)
|
|
3062
|
+
return "AMEX";
|
|
3063
|
+
if (two >= 51 && two <= 55 || four >= 2221 && four < 2721)
|
|
3064
|
+
return "MC";
|
|
3065
|
+
if (four >= 3528 && four <= 3589)
|
|
3066
|
+
return "JCB";
|
|
3067
|
+
if (two === 64 || three >= 644 && three <= 659 || four === 6011 || six >= 622129 && six <= 622925)
|
|
3068
|
+
return "DISCOVER";
|
|
3069
|
+
if (two === 36 || two === 38 || two === 39 || three === 309 || three >= 300 && three <= 305)
|
|
3070
|
+
return "DINERS_CLUB";
|
|
3071
|
+
if ([5018, 5020, 5038, 5893, 6e3, 6304, 6759, 6761, 6762, 6763, 6799].includes(four))
|
|
3072
|
+
return "MAESTRO";
|
|
3073
|
+
return "UNKNOWN";
|
|
3074
|
+
}
|
|
3075
|
+
var isCiphertext = (value) => typeof value === "string" && ENCRYPTED_PAN.test(value);
|
|
3076
|
+
function readBody11(body) {
|
|
3077
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT18)
|
|
3078
|
+
return null;
|
|
3079
|
+
let value;
|
|
3080
|
+
try {
|
|
3081
|
+
value = JSON.parse(body);
|
|
3082
|
+
if (!record15(value) || JSON.stringify(value) !== body)
|
|
3083
|
+
return null;
|
|
3084
|
+
}
|
|
3085
|
+
catch {
|
|
3086
|
+
return null;
|
|
3087
|
+
}
|
|
3088
|
+
return value;
|
|
3089
|
+
}
|
|
3090
|
+
function inFrameOrder(keys) {
|
|
3091
|
+
let last = -1;
|
|
3092
|
+
for (const key of keys) {
|
|
3093
|
+
const at = CARD_ORDER.indexOf(key);
|
|
3094
|
+
if (at <= last)
|
|
3095
|
+
return false;
|
|
3096
|
+
last = at;
|
|
3097
|
+
}
|
|
3098
|
+
return REQUIRED_KEYS.every((key) => keys.includes(key));
|
|
3099
|
+
}
|
|
3100
|
+
var sideText = (value, limit = TEXT_LIMIT5) => typeof value === "string" && value.length <= limit && !CARD_LIKE_RUN.test(value);
|
|
3101
|
+
function isPhoneNumbers(value) {
|
|
3102
|
+
if (!record15(value))
|
|
3103
|
+
return false;
|
|
3104
|
+
const types = Object.keys(value);
|
|
3105
|
+
if (types.length !== 1 || !PHONE_TYPES.has(types[0]))
|
|
3106
|
+
return false;
|
|
3107
|
+
const phone2 = value[types[0]];
|
|
3108
|
+
if (!record15(phone2))
|
|
3109
|
+
return false;
|
|
3110
|
+
const keys = Object.keys(phone2);
|
|
3111
|
+
return keys.length === 2 && keys[0] === "country_code" && keys[1] === "subscriber" && typeof phone2.country_code === "string" && COUNTRY_CODE2.test(phone2.country_code) && typeof phone2.subscriber === "string" && SUBSCRIBER.test(phone2.subscriber);
|
|
3112
|
+
}
|
|
3113
|
+
function isCardMember(card) {
|
|
3114
|
+
if (!record15(card) || !inFrameOrder(Object.keys(card)))
|
|
3115
|
+
return false;
|
|
3116
|
+
if (!isCiphertext(card.encrypted_pan))
|
|
3117
|
+
return false;
|
|
3118
|
+
if (typeof card.exp_month !== "string" || !MONTH9.test(card.exp_month))
|
|
3119
|
+
return false;
|
|
3120
|
+
if (typeof card.exp_year !== "string" || !YEAR9.test(card.exp_year))
|
|
3121
|
+
return false;
|
|
3122
|
+
if (typeof card.cvv !== "string" || !CODE3.test(card.cvv))
|
|
3123
|
+
return false;
|
|
3124
|
+
if (typeof card.first6 !== "string" || !FIRST6.test(card.first6))
|
|
3125
|
+
return false;
|
|
3126
|
+
if (typeof card.last4 !== "string" || !LAST4.test(card.last4))
|
|
3127
|
+
return false;
|
|
3128
|
+
if (typeof card.brand !== "string" || !BRANDS.has(card.brand) || cloverBrand(card.first6) !== card.brand)
|
|
3129
|
+
return false;
|
|
3130
|
+
if (own4(card, "address_line1") && !sideText(card.address_line1))
|
|
3131
|
+
return false;
|
|
3132
|
+
if (own4(card, "phone_numbers") && !isPhoneNumbers(card.phone_numbers))
|
|
3133
|
+
return false;
|
|
3134
|
+
if (own4(card, "email_address") && !(sideText(card.email_address, EMAIL_LIMIT) && /^[^\s@]+@[^\s@]+$/.test(card.email_address)))
|
|
3135
|
+
return false;
|
|
3136
|
+
if (own4(card, "name") && !(sideText(card.name) && card.name !== "" && card.name === card.name.trim()))
|
|
3137
|
+
return false;
|
|
3138
|
+
if (own4(card, "address_zip") && !(typeof card.address_zip === "string" && POSTAL_CODE2.test(card.address_zip)))
|
|
3139
|
+
return false;
|
|
3140
|
+
return true;
|
|
3141
|
+
}
|
|
3142
|
+
function cloverBodyVerdict(body, url) {
|
|
3143
|
+
if (url !== void 0 && cloverTokenUrl(url) === null)
|
|
3144
|
+
return refuse21("clover_url_refused");
|
|
3145
|
+
const value = readBody11(body);
|
|
3146
|
+
if (value === null)
|
|
3147
|
+
return refuse21("clover_body_unsupported");
|
|
3148
|
+
const keys = Object.keys(value);
|
|
3149
|
+
if (keys.length !== 1 || keys[0] !== "card" || !isCardMember(value.card))
|
|
3150
|
+
return refuse21("clover_body_unsupported");
|
|
3151
|
+
return CARD20;
|
|
3152
|
+
}
|
|
3153
|
+
// src/tap-payments.js
|
|
3154
|
+
var TAP_PAYMENTS_PSP = "tap_payments";
|
|
3155
|
+
var TAP_PAYMENTS_TOKEN_URL = "https://sdk.tap.company/v2/card/token";
|
|
3156
|
+
var TAP_PAYMENTS_PURPOSES = /* @__PURE__ */ Object.freeze(["CHARGE", "AUTHORIZE"]);
|
|
3157
|
+
var record16 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3158
|
+
function isTapPaymentsTokenUrl(url) {
|
|
3159
|
+
return url === TAP_PAYMENTS_TOKEN_URL;
|
|
3160
|
+
}
|
|
3161
|
+
var pin6 = (fields) => Object.freeze({
|
|
3162
|
+
...fields,
|
|
3163
|
+
origins: Object.freeze([...fields.origins]),
|
|
3164
|
+
sessions: Object.freeze({ ...fields.sessions }),
|
|
3165
|
+
key: Object.freeze({ ...fields.key })
|
|
3166
|
+
});
|
|
3167
|
+
var TAP_PAYMENTS_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
3168
|
+
pin6({
|
|
3169
|
+
id: "casefilegame",
|
|
3170
|
+
merchant: "Casefilegame",
|
|
3171
|
+
tapMerchantId: "67977048",
|
|
3172
|
+
publishableKey: "pk_live_ydlRjrWcLXaVvpsSBQKOie86",
|
|
3173
|
+
environment: "production",
|
|
3174
|
+
origins: ["https://checkout.tap.company"],
|
|
3175
|
+
// The WooCommerce plugin's redirect (Plugin-WooCommerce-All-in-one tap.php 567-586, read 2026-10-17)
|
|
3176
|
+
// creates the src_all charge with save_card false and names no agreement, subscription or destinations.
|
|
3177
|
+
sessions: { saveCard: false, agreement: false, subscription: false, destinations: false },
|
|
3178
|
+
key: {
|
|
3179
|
+
spki: "MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAzja2vB+Iyafj2Mm3pFg65z7Yvj9ZeoFLdMBgWFyyjF020r5HSPKVhuZ39uJkjs0U/kWgEpKDzHZAKdtGv36dS33NjMAzYpgFkD8j+9/YWqpvAGRj5nv1b/q7NaiZk3b1wm7aXHJOx5L6rPQf2qDQxhcSNHocU+Uy8wGmGxRRu6QRKN3khaz4o4jJDzqxns4h/ShzHjdZeWIVfpCAyVoED0IESBYrvGEhJeyKnga5XdHdBU2yP8P1huO4RbSKcZv00ZgxVHAQQ9CqArW3TE8SyLLnJPkSpSHHBnIPSQS1z3ld1mImy/zqTd4ltkV6XHpYqVvoPmys2EuZX3pMvCcPGwIBEQ==",
|
|
3180
|
+
sha256: "6eb4e89a1e05a06a39d631f6fb450c052a9cad9935edc1921e84e80207470552",
|
|
3181
|
+
// The shared parser takes exponent 17 only under a pin that names it (rsa-pkcs1v15.js).
|
|
3182
|
+
exponent: 17
|
|
3183
|
+
}
|
|
3184
|
+
})
|
|
3185
|
+
]);
|
|
3186
|
+
var BODY_LIMIT19 = 16384;
|
|
3187
|
+
var ROOT_KEYS7 = /* @__PURE__ */ Object.freeze([
|
|
3188
|
+
"encryptedData",
|
|
3189
|
+
"purpose",
|
|
3190
|
+
"customer",
|
|
3191
|
+
"consent",
|
|
3192
|
+
"merchant",
|
|
3193
|
+
"order",
|
|
3194
|
+
"payment_agreement",
|
|
3195
|
+
"client_ip",
|
|
3196
|
+
"device",
|
|
3197
|
+
"browser",
|
|
3198
|
+
"app"
|
|
3199
|
+
]);
|
|
3200
|
+
var REQUIRED_KEYS2 = /* @__PURE__ */ Object.freeze(["encryptedData", "purpose", "order", "device", "browser", "app"]);
|
|
3201
|
+
var SAVE_PURPOSES = /* @__PURE__ */ Object.freeze(["SAVE_TOKEN", "SAVE_AUTHENTICATED_TOKEN"]);
|
|
3202
|
+
var ORDER_KEYS = /* @__PURE__ */ Object.freeze(["amount", "currency", "id", "description", "metadata", "reference"]);
|
|
3203
|
+
var DEVICE_KEYS3 = /* @__PURE__ */ Object.freeze(["source", "ip"]);
|
|
3204
|
+
var BROWSER_KEYS = /* @__PURE__ */ Object.freeze(["name", "id"]);
|
|
3205
|
+
var APP_KEYS = /* @__PURE__ */ Object.freeze(["identifier", "name", "version", "iframe_version", "sdk_version"]);
|
|
3206
|
+
var CIPHERTEXT_BYTES = /* @__PURE__ */ Object.freeze([128, 256, 384, 512]);
|
|
3207
|
+
var BASE644 = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
3208
|
+
var CURRENCY3 = /^[A-Z]{3}$/;
|
|
3209
|
+
var TEXT_LIMIT6 = 512;
|
|
3210
|
+
var CONTROL9 = /[\u0000-\u001f\u007f]/;
|
|
3211
|
+
var CARD_LONG_DIGITS = /(?:\p{Nd}[\s-]?){12}\p{Nd}/u;
|
|
3212
|
+
var NESTING_LIMIT = 4;
|
|
3213
|
+
var MEMBERS_LIMIT = 64;
|
|
3214
|
+
var refuse22 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
3215
|
+
var CARD21 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
3216
|
+
function decodedBytes(value) {
|
|
3217
|
+
if (typeof value !== "string" || value.length % 4 !== 0 || !BASE644.test(value))
|
|
3218
|
+
return -1;
|
|
3219
|
+
try {
|
|
3220
|
+
if (btoa(atob(value)) !== value)
|
|
3221
|
+
return -1;
|
|
3222
|
+
}
|
|
3223
|
+
catch {
|
|
3224
|
+
return -1;
|
|
3225
|
+
}
|
|
3226
|
+
const pad = value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0;
|
|
3227
|
+
return value.length / 4 * 3 - pad;
|
|
3228
|
+
}
|
|
3229
|
+
function isTapPaymentsCiphertext(value) {
|
|
3230
|
+
return CIPHERTEXT_BYTES.includes(decodedBytes(value));
|
|
3231
|
+
}
|
|
3232
|
+
function readBody12(body) {
|
|
3233
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT19)
|
|
3234
|
+
return null;
|
|
3235
|
+
try {
|
|
3236
|
+
const value = JSON.parse(body);
|
|
3237
|
+
return record16(value) && JSON.stringify(value) === body ? value : null;
|
|
3238
|
+
}
|
|
3239
|
+
catch {
|
|
3240
|
+
return null;
|
|
3241
|
+
}
|
|
3242
|
+
}
|
|
3243
|
+
var inOrder3 = (keys, order) => {
|
|
3244
|
+
let at = -1;
|
|
3245
|
+
for (const key of keys) {
|
|
3246
|
+
const next = order.indexOf(key);
|
|
3247
|
+
if (next <= at)
|
|
3248
|
+
return false;
|
|
3249
|
+
at = next;
|
|
3250
|
+
}
|
|
3251
|
+
return true;
|
|
3252
|
+
};
|
|
3253
|
+
var onlyKeys = (value, allowed) => record16(value) && Object.keys(value).every((key) => allowed.includes(key));
|
|
3254
|
+
var plainText4 = (value) => typeof value === "string" && value.length <= TEXT_LIMIT6 && !CONTROL9.test(value) && !CARD_LONG_DIGITS.test(value);
|
|
3255
|
+
var plainScalar = (value) => value === null || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value) && !CARD_LONG_DIGITS.test(String(value)) || plainText4(value);
|
|
3256
|
+
function plainJson(value, depth = 0, budget = { members: 0 }) {
|
|
3257
|
+
if (depth > NESTING_LIMIT)
|
|
3258
|
+
return false;
|
|
3259
|
+
if (Array.isArray(value)) {
|
|
3260
|
+
budget.members += value.length;
|
|
3261
|
+
return budget.members <= MEMBERS_LIMIT && value.every((item) => plainJson(item, depth + 1, budget));
|
|
3262
|
+
}
|
|
3263
|
+
if (record16(value)) {
|
|
3264
|
+
const keys = Object.keys(value);
|
|
3265
|
+
budget.members += keys.length;
|
|
3266
|
+
return budget.members <= MEMBERS_LIMIT && keys.every((key) => plainText4(key) && plainJson(value[key], depth + 1, budget));
|
|
3267
|
+
}
|
|
3268
|
+
return plainScalar(value);
|
|
3269
|
+
}
|
|
3270
|
+
function soundOrder(order) {
|
|
3271
|
+
if (!onlyKeys(order, ORDER_KEYS) || !inOrder3(Object.keys(order), ORDER_KEYS))
|
|
3272
|
+
return false;
|
|
3273
|
+
if ("amount" in order && !(typeof order.amount === "number" && Number.isFinite(order.amount) && order.amount >= 0 && !CARD_LONG_DIGITS.test(String(order.amount))))
|
|
3274
|
+
return false;
|
|
3275
|
+
if ("currency" in order && !(typeof order.currency === "string" && CURRENCY3.test(order.currency)))
|
|
3276
|
+
return false;
|
|
3277
|
+
if ("id" in order && !plainText4(order.id))
|
|
3278
|
+
return false;
|
|
3279
|
+
if ("description" in order && !plainText4(order.description))
|
|
3280
|
+
return false;
|
|
3281
|
+
if ("metadata" in order && !plainJson(order.metadata))
|
|
3282
|
+
return false;
|
|
3283
|
+
return !("reference" in order) || plainJson(order.reference);
|
|
3284
|
+
}
|
|
3285
|
+
var soundDevice2 = (device) => onlyKeys(device, DEVICE_KEYS3) && inOrder3(Object.keys(device), DEVICE_KEYS3) && (device.source === "web" || device.source === "app") && (!("ip" in device) || plainText4(device.ip));
|
|
3286
|
+
var soundBrowser = (browser) => onlyKeys(browser, BROWSER_KEYS) && inOrder3(Object.keys(browser), BROWSER_KEYS) && (!("name" in browser) || plainText4(browser.name)) && plainText4(browser.id);
|
|
3287
|
+
var versionValue = (value) => plainText4(value) || typeof value === "number" && Number.isFinite(value) && !CARD_LONG_DIGITS.test(String(value));
|
|
3288
|
+
var soundApp = (app) => onlyKeys(app, APP_KEYS) && inOrder3(Object.keys(app), APP_KEYS) && app.identifier === "card_sdk" && app.name === "card_sdk" && ["version", "iframe_version", "sdk_version"].every((key) => !(key in app) || versionValue(app[key]));
|
|
3289
|
+
function tapPaymentsBodyVerdict(body) {
|
|
3290
|
+
const value = readBody12(body);
|
|
3291
|
+
if (value === null)
|
|
3292
|
+
return refuse22("tap_payments_body_unsupported");
|
|
3293
|
+
const keys = Object.keys(value);
|
|
3294
|
+
if (!keys.every((key) => ROOT_KEYS7.includes(key)) || !inOrder3(keys, ROOT_KEYS7) || !REQUIRED_KEYS2.every((key) => keys.includes(key))) {
|
|
3295
|
+
return refuse22("tap_payments_body_unsupported");
|
|
3296
|
+
}
|
|
3297
|
+
if (!isTapPaymentsCiphertext(value.encryptedData))
|
|
3298
|
+
return refuse22("tap_payments_body_unsupported");
|
|
3299
|
+
if (typeof value.purpose !== "string")
|
|
3300
|
+
return refuse22("tap_payments_body_unsupported");
|
|
3301
|
+
if (SAVE_PURPOSES.includes(value.purpose))
|
|
3302
|
+
return refuse22("tap_payments_keep_on_file");
|
|
3303
|
+
if (!TAP_PAYMENTS_PURPOSES.includes(value.purpose))
|
|
3304
|
+
return refuse22("tap_payments_body_unsupported");
|
|
3305
|
+
if ("payment_agreement" in value && value.payment_agreement !== null)
|
|
3306
|
+
return refuse22("tap_payments_keep_on_file");
|
|
3307
|
+
if ("consent" in value) {
|
|
3308
|
+
const consent = value.consent;
|
|
3309
|
+
if (!record16(consent) || Object.keys(consent).length !== 1 || typeof consent.acknowledge !== "boolean")
|
|
3310
|
+
return refuse22("tap_payments_body_unsupported");
|
|
3311
|
+
if (consent.acknowledge)
|
|
3312
|
+
return refuse22("tap_payments_keep_on_file");
|
|
3313
|
+
}
|
|
3314
|
+
if ("customer" in value && !(record16(value.customer) && plainJson(value.customer)) || "merchant" in value && !(record16(value.merchant) && plainJson(value.merchant)) || "client_ip" in value && value.client_ip !== null && !plainText4(value.client_ip) || !soundOrder(value.order) || !soundDevice2(value.device) || !soundBrowser(value.browser) || !soundApp(value.app)) {
|
|
3315
|
+
return refuse22("tap_payments_body_unsupported");
|
|
3316
|
+
}
|
|
3317
|
+
return CARD21;
|
|
3318
|
+
}
|
|
3319
|
+
// src/conekta.js
|
|
3320
|
+
var CONEKTA_PSP = "conekta";
|
|
3321
|
+
var CONEKTA_TOKENS_URL = "https://api.conekta.io/tokens";
|
|
3322
|
+
var CONEKTA_COMPONENT_TOKEN_URLS = /* @__PURE__ */ Object.freeze(["https://pay.conekta.com/api/tokens", "https://pay.conekta.com/api/tokens/"]);
|
|
3323
|
+
var CONEKTA_CARD_KEYS = /* @__PURE__ */ Object.freeze(["number", "name", "cvc", "exp_month", "exp_year", "exp", "address", "device_fingerprint"]);
|
|
3324
|
+
var CONEKTA_ADDRESS_KEYS = /* @__PURE__ */ Object.freeze(["street1", "street2", "street3", "city", "state", "zip", "country"]);
|
|
3325
|
+
var BODY_LIMIT20 = 4096;
|
|
3326
|
+
var URL_LIMIT8 = 64;
|
|
3327
|
+
var NUMBER5 = /^[0-9]{12,19}$/;
|
|
3328
|
+
var SECURITY_CODE13 = /^[0-9]{3,4}$/;
|
|
3329
|
+
var MONTH10 = /^(?:0?[1-9]|1[0-2])$/;
|
|
3330
|
+
var YEAR10 = /^(?:[0-9]{2}|20[0-9]{2})$/;
|
|
3331
|
+
var EXPIRY2 = /^(?:0[1-9]|1[0-2])\/(?:[0-9]{2}|20[0-9]{2})$/;
|
|
3332
|
+
var FINGERPRINT = /^(?:[a-z0-9]{31,32})?$/;
|
|
3333
|
+
var LETTERS = "A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u017F";
|
|
3334
|
+
var PAGE_NAME2 = new RegExp(`^[${LETTERS} .'-]{1,64}$`);
|
|
3335
|
+
var HAS_LETTER = new RegExp(`[${LETTERS}]`);
|
|
3336
|
+
var ADDRESS_VALUE = new RegExp(`^[\\x20-\\x7e\\u00a0-\\u017f]{0,128}$`);
|
|
3337
|
+
var PAN_LIKE5 = new RegExp(`(?:[0-9][^0-9${LETTERS}]*){12,}`);
|
|
3338
|
+
var record17 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3339
|
+
var refuse23 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
3340
|
+
var CARD22 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
3341
|
+
function conektaTarget(url) {
|
|
3342
|
+
if (typeof url !== "string" || url.length > URL_LIMIT8)
|
|
3343
|
+
return null;
|
|
3344
|
+
if (url === CONEKTA_TOKENS_URL)
|
|
3345
|
+
return Object.freeze({ kind: "tokens" });
|
|
3346
|
+
return CONEKTA_COMPONENT_TOKEN_URLS.includes(url) ? Object.freeze({ kind: "component" }) : null;
|
|
3347
|
+
}
|
|
3348
|
+
function readJson4(body) {
|
|
3349
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT20)
|
|
3350
|
+
return null;
|
|
3351
|
+
try {
|
|
3352
|
+
const value = JSON.parse(body);
|
|
3353
|
+
return record17(value) && JSON.stringify(value) === body ? value : null;
|
|
3354
|
+
}
|
|
3355
|
+
catch {
|
|
3356
|
+
return null;
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
function componentBody(value) {
|
|
3360
|
+
const keys = Object.keys(value);
|
|
3361
|
+
return keys.length === 2 && keys[0] === "data" && keys[1] === "key" && typeof value.data === "string" && typeof value.key === "string";
|
|
3362
|
+
}
|
|
3363
|
+
function soundAddress(address2) {
|
|
3364
|
+
if (!record17(address2))
|
|
3365
|
+
return false;
|
|
3366
|
+
const keys = Object.keys(address2);
|
|
3367
|
+
return keys.length > 0 && keys.every((key) => CONEKTA_ADDRESS_KEYS.includes(key) && typeof address2[key] === "string" && ADDRESS_VALUE.test(address2[key]) && !PAN_LIKE5.test(address2[key])) && keys.some((key) => address2[key] !== "");
|
|
3368
|
+
}
|
|
3369
|
+
function judgeCard(card) {
|
|
3370
|
+
if (!record17(card))
|
|
3371
|
+
return "conekta_body_unsupported";
|
|
3372
|
+
const keys = Object.keys(card);
|
|
3373
|
+
if (!keys.every((key) => CONEKTA_CARD_KEYS.includes(key)) || keys[keys.length - 1] !== "device_fingerprint" || !["number", "name", "cvc", "exp_month", "exp_year"].every((key) => keys.includes(key)))
|
|
3374
|
+
return "conekta_body_unsupported";
|
|
3375
|
+
if (typeof card.number !== "string" || !NUMBER5.test(card.number) || typeof card.cvc !== "string" || !SECURITY_CODE13.test(card.cvc) || typeof card.exp_month !== "string" || !MONTH10.test(card.exp_month) || typeof card.exp_year !== "string" || !YEAR10.test(card.exp_year) || typeof card.name !== "string" || !PAGE_NAME2.test(card.name) || !HAS_LETTER.test(card.name) || typeof card.device_fingerprint !== "string" || !FINGERPRINT.test(card.device_fingerprint))
|
|
3376
|
+
return "conekta_body_unsupported";
|
|
3377
|
+
if (keys.includes("exp") && (typeof card.exp !== "string" || !EXPIRY2.test(card.exp) || card.exp !== `${card.exp_month}/${card.exp_year}`)) {
|
|
3378
|
+
return "conekta_body_unsupported";
|
|
3379
|
+
}
|
|
3380
|
+
if (keys.includes("address") && !soundAddress(card.address))
|
|
3381
|
+
return "conekta_body_unsupported";
|
|
3382
|
+
return null;
|
|
3383
|
+
}
|
|
3384
|
+
function conektaBodyVerdict(body, url) {
|
|
3385
|
+
if (url !== void 0) {
|
|
3386
|
+
const target = conektaTarget(url);
|
|
3387
|
+
if (target === null)
|
|
3388
|
+
return refuse23("conekta_url_refused");
|
|
3389
|
+
if (target.kind === "component")
|
|
3390
|
+
return refuse23("conekta_component_unsupported");
|
|
3391
|
+
}
|
|
3392
|
+
const value = readJson4(body);
|
|
3393
|
+
if (value === null)
|
|
3394
|
+
return refuse23("conekta_body_unsupported");
|
|
3395
|
+
if (componentBody(value))
|
|
3396
|
+
return refuse23("conekta_component_unsupported");
|
|
3397
|
+
const keys = Object.keys(value);
|
|
3398
|
+
if (keys.length !== 1 || keys[0] !== "card")
|
|
3399
|
+
return refuse23("conekta_body_unsupported");
|
|
3400
|
+
const code = judgeCard(value.card);
|
|
3401
|
+
return code === null ? CARD22 : refuse23(code);
|
|
3402
|
+
}
|
|
3403
|
+
var HOLDER4 = new RegExp(`^[${LETTERS}](?:[${LETTERS} .'-]{0,62}[${LETTERS}.])?$`);
|
|
3404
|
+
var ERROR_TYPE_STATUS = /* @__PURE__ */ Object.freeze({
|
|
3405
|
+
malformed_request_error: 400,
|
|
3406
|
+
authentication_error: 401,
|
|
3407
|
+
processing_error: 402,
|
|
3408
|
+
resource_not_found_error: 404,
|
|
3409
|
+
conflict_error: 409,
|
|
3410
|
+
precondition_required_error: 412,
|
|
3411
|
+
parameter_validation_error: 422
|
|
3412
|
+
});
|
|
3413
|
+
var CONEKTA_ANSWER_ERROR_TYPES = /* @__PURE__ */ Object.freeze(Object.keys(ERROR_TYPE_STATUS));
|
|
3414
|
+
// src/makecommerce.js
|
|
3415
|
+
var MAKECOMMERCE_PSP = "makecommerce";
|
|
3416
|
+
var MAKECOMMERCE_CARD_HOSTS = /* @__PURE__ */ Object.freeze({ "cc.maksekeskus.ee": "production", "cc-test.maksekeskus.ee": "test" });
|
|
3417
|
+
var MAKECOMMERCE_CARD_PATH = "/card-payment";
|
|
3418
|
+
var MAKECOMMERCE_FRAME_VERSIONS = /* @__PURE__ */ Object.freeze(["cde.31", "cde.35"]);
|
|
3419
|
+
var BODY_LIMIT21 = 4096;
|
|
3420
|
+
var HEAD_KEYS = /* @__PURE__ */ Object.freeze(["transaction", "customer", "ocp", "checkout"]);
|
|
3421
|
+
var TAIL_KEYS = /* @__PURE__ */ Object.freeze(["card", "tokenizer", "shop_id", "client_data", "hostname", "public_key"]);
|
|
3422
|
+
var CARD_KEYS9 = /* @__PURE__ */ Object.freeze(["name", "number", "exp_month", "exp_year", "cvc"]);
|
|
3423
|
+
var CLIENT_KEYS = /* @__PURE__ */ Object.freeze(["client_fingerprint", "client_tz_offset", "client_time"]);
|
|
3424
|
+
var UUID3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
3425
|
+
var EMAIL4 = /^(?!.*\.\.)(?!.*-$)(?!^-)[A-Za-z0-9._%+-]+@[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*(?:\.[A-Za-z]{2,})+$/;
|
|
3426
|
+
var CARD_NUMBER11 = /^[0-9]{13,19}$/;
|
|
3427
|
+
var MONTH11 = /^(?:0[1-9]|1[0-2])$/;
|
|
3428
|
+
var YEAR11 = /^[0-9]{2}$/;
|
|
3429
|
+
var CODE4 = /^[0-9]{3}$/;
|
|
3430
|
+
var NAME_LIMIT3 = 100;
|
|
3431
|
+
var NAME_WORD = /[a-z]+/gi;
|
|
3432
|
+
var printable2 = (text6) => [...text6].every((character) => {
|
|
3433
|
+
const point = character.codePointAt(0);
|
|
3434
|
+
return point >= 32 && !(point >= 127 && point <= 159) && point !== 8232 && point !== 8233;
|
|
3435
|
+
});
|
|
3436
|
+
var FINGERPRINT2 = /^[0-9a-f]{40}$/i;
|
|
3437
|
+
var HOSTNAME = /^(?=.{1,253}$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)+$/;
|
|
3438
|
+
var PUBLISHABLE_KEY = /^[A-Za-z0-9]{16,64}$/;
|
|
3439
|
+
var record18 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3440
|
+
var sameKeys8 = (value, keys) => {
|
|
3441
|
+
const own6 = Object.keys(value);
|
|
3442
|
+
return own6.length === keys.length && own6.every((key, at) => key === keys[at]);
|
|
3443
|
+
};
|
|
3444
|
+
var refuse24 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
3445
|
+
var CARD23 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
3446
|
+
function luhn4(digits2) {
|
|
3447
|
+
let sum = 0;
|
|
3448
|
+
for (let at = 0; at < digits2.length; at += 1) {
|
|
3449
|
+
let digit = Number(digits2[digits2.length - 1 - at]);
|
|
3450
|
+
if (at % 2 === 1) {
|
|
3451
|
+
digit *= 2;
|
|
3452
|
+
if (digit > 9)
|
|
3453
|
+
digit -= 9;
|
|
3454
|
+
}
|
|
3455
|
+
sum += digit;
|
|
3456
|
+
}
|
|
3457
|
+
return sum % 10 === 0;
|
|
3458
|
+
}
|
|
3459
|
+
function makecommerceCardUrl(url) {
|
|
3460
|
+
if (typeof url !== "string" || url.length > 256 || url.includes("?") || url.includes("#"))
|
|
3461
|
+
return null;
|
|
3462
|
+
let parsed;
|
|
3463
|
+
try {
|
|
3464
|
+
parsed = new URL(url);
|
|
3465
|
+
}
|
|
3466
|
+
catch {
|
|
3467
|
+
return null;
|
|
3468
|
+
}
|
|
3469
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || parsed.search || parsed.hash || parsed.pathname !== MAKECOMMERCE_CARD_PATH)
|
|
3470
|
+
return null;
|
|
3471
|
+
if (!Object.prototype.hasOwnProperty.call(MAKECOMMERCE_CARD_HOSTS, parsed.hostname))
|
|
3472
|
+
return null;
|
|
3473
|
+
return Object.freeze({ host: parsed.hostname, environment: MAKECOMMERCE_CARD_HOSTS[parsed.hostname] });
|
|
3474
|
+
}
|
|
3475
|
+
function isMakecommerceCardUrl(url) {
|
|
3476
|
+
return makecommerceCardUrl(url) !== null;
|
|
3477
|
+
}
|
|
3478
|
+
function readBody13(body) {
|
|
3479
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT21)
|
|
3480
|
+
return null;
|
|
3481
|
+
let value;
|
|
3482
|
+
try {
|
|
3483
|
+
value = JSON.parse(body);
|
|
3484
|
+
if (!record18(value) || JSON.stringify(value) !== body)
|
|
3485
|
+
return null;
|
|
3486
|
+
}
|
|
3487
|
+
catch {
|
|
3488
|
+
return null;
|
|
3489
|
+
}
|
|
3490
|
+
return value;
|
|
3491
|
+
}
|
|
3492
|
+
var box = (value) => record18(value) && sameKeys8(value, ["requested"]) && typeof value.requested === "boolean";
|
|
3493
|
+
var holderName = (name) => typeof name === "string" && name.length <= NAME_LIMIT3 && printable2(name) && (name.match(NAME_WORD) ?? []).length > 1;
|
|
3494
|
+
function frameCardValues(card) {
|
|
3495
|
+
return record18(card) && sameKeys8(card, CARD_KEYS9) && holderName(card.name) && typeof card.number === "string" && CARD_NUMBER11.test(card.number) && luhn4(card.number) && typeof card.exp_month === "string" && MONTH11.test(card.exp_month) && typeof card.exp_year === "string" && YEAR11.test(card.exp_year) && typeof card.cvc === "string" && CODE4.test(card.cvc);
|
|
3496
|
+
}
|
|
3497
|
+
function clientData(value) {
|
|
3498
|
+
return record18(value) && sameKeys8(value, CLIENT_KEYS) && typeof value.client_fingerprint === "string" && FINGERPRINT2.test(value.client_fingerprint) && Number.isFinite(value.client_tz_offset) && Math.abs(value.client_tz_offset) <= 14 && Number.isSafeInteger(value.client_time) && value.client_time > 0;
|
|
3499
|
+
}
|
|
3500
|
+
function makecommerceBodyVerdict(body, url) {
|
|
3501
|
+
if (url !== void 0 && !isMakecommerceCardUrl(url))
|
|
3502
|
+
return refuse24("makecommerce_url_refused");
|
|
3503
|
+
const value = readBody13(body);
|
|
3504
|
+
if (value === null)
|
|
3505
|
+
return refuse24("makecommerce_body_unsupported");
|
|
3506
|
+
const recurring = Object.prototype.hasOwnProperty.call(value, "recurring");
|
|
3507
|
+
if (!sameKeys8(value, [...HEAD_KEYS, ...recurring ? ["recurring"] : [], ...TAIL_KEYS]))
|
|
3508
|
+
return refuse24("makecommerce_body_unsupported");
|
|
3509
|
+
if (!record18(value.transaction) || !sameKeys8(value.transaction, ["id"]) || typeof value.transaction.id !== "string" || !UUID3.test(value.transaction.id) || !record18(value.customer) || !sameKeys8(value.customer, ["email"]) || typeof value.customer.email !== "string" || value.customer.email.length > 254 || !EMAIL4.test(value.customer.email) || !box(value.ocp) || recurring && !box(value.recurring) || !MAKECOMMERCE_FRAME_VERSIONS.includes(value.checkout) || value.tokenizer !== value.checkout || !frameCardValues(value.card) || typeof value.shop_id !== "string" || !UUID3.test(value.shop_id) || !clientData(value.client_data) || typeof value.hostname !== "string" || !HOSTNAME.test(value.hostname) || typeof value.public_key !== "string" || !PUBLISHABLE_KEY.test(value.public_key))
|
|
3510
|
+
return refuse24("makecommerce_body_unsupported");
|
|
3511
|
+
if (value.ocp.requested || recurring && value.recurring.requested)
|
|
3512
|
+
return refuse24("makecommerce_card_saving_refused");
|
|
3513
|
+
return CARD23;
|
|
3514
|
+
}
|
|
3515
|
+
// src/tokenex-iframe.js
|
|
3516
|
+
var TOKENEX_IFRAME_PSP = "tokenex_iframe";
|
|
3517
|
+
var TOKENEX_IFRAME_HOSTS = Object.freeze(["htp.tokenex.com", "test-htp.tokenex.com"]);
|
|
3518
|
+
var TOKENEX_IFRAME_PATH = "/iframe/v3";
|
|
3519
|
+
var TOKENEX_IFRAME_REFUSAL_REASONS = Object.freeze(["unsupported", "brand_mismatch", "unreviewed_account"]);
|
|
3520
|
+
var TOKENEX_IFRAME_BODY_KEYS = Object.freeze([
|
|
3521
|
+
"TokenExID",
|
|
3522
|
+
"Origin",
|
|
3523
|
+
"AuthenticationKey",
|
|
3524
|
+
"Timestamp",
|
|
3525
|
+
"Data",
|
|
3526
|
+
"CvvValue",
|
|
3527
|
+
"TokenScheme",
|
|
3528
|
+
"CvvOnly",
|
|
3529
|
+
"PCI",
|
|
3530
|
+
"ReturnHash",
|
|
3531
|
+
"use3DS",
|
|
3532
|
+
"ThreeDSMethodNotificationUrl",
|
|
3533
|
+
"kountSessionId",
|
|
3534
|
+
"fraudMerchantId",
|
|
3535
|
+
"UseKount",
|
|
3536
|
+
"kountMode",
|
|
3537
|
+
"kountAnId",
|
|
3538
|
+
"FraudServicesRiskRequestModel",
|
|
3539
|
+
"EnforceLuhnCompliance",
|
|
3540
|
+
"CustomDataLuhnCheck"
|
|
3541
|
+
]);
|
|
3542
|
+
var TOKENEX_IFRAME_TOKEN_SCHEMES = Object.freeze(["sixTOKENfour"]);
|
|
3543
|
+
var TOKENEX_IFRAME_REVIEWED_ACCOUNTS = Object.freeze({
|
|
3544
|
+
"htp.tokenex.com": Object.freeze({}),
|
|
3545
|
+
"test-htp.tokenex.com": Object.freeze({})
|
|
3546
|
+
});
|
|
3547
|
+
var TOKENEX_IFRAME_ACCOUNT_NAMES = Object.freeze({
|
|
3548
|
+
"htp.tokenex.com": Object.freeze({}),
|
|
3549
|
+
"test-htp.tokenex.com": Object.freeze({})
|
|
3550
|
+
});
|
|
3551
|
+
var BODY_LIMIT22 = 8192;
|
|
3552
|
+
var URL_LIMIT9 = 2048;
|
|
3553
|
+
var record19 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3554
|
+
var owns5 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
3555
|
+
var exact2 = (pattern, value) => typeof value === "string" && pattern.exec(value)?.[0] === value;
|
|
3556
|
+
var text4 = (value, max) => typeof value === "string" && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
|
|
3557
|
+
var digits = (value, min, max) => typeof value === "string" && value.length >= min && value.length <= max && !/[^0-9]/.test(value);
|
|
3558
|
+
var panLike = (value) => (value.match(/\p{Nd}/gu) ?? []).length >= 12;
|
|
3559
|
+
var plain = (value, max) => text4(value, max) && !panLike(value);
|
|
3560
|
+
var TOKENEX_ID = /^[0-9]{16}$/;
|
|
3561
|
+
var AUTHENTICATION_KEY = /^[A-Za-z0-9+/]{43}=$/;
|
|
3562
|
+
var TIMESTAMP = /^20[0-9]{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12][0-9]|3[01])(?:[01][0-9]|2[0-3])[0-5][0-9][0-5][0-9]$/;
|
|
3563
|
+
function isOrigin(value) {
|
|
3564
|
+
if (typeof value !== "string" || value.length > 255 || !value.startsWith("https://"))
|
|
3565
|
+
return false;
|
|
3566
|
+
try {
|
|
3567
|
+
return new URL(value).origin === value;
|
|
3568
|
+
}
|
|
3569
|
+
catch {
|
|
3570
|
+
return false;
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
var BOUND = {
|
|
3574
|
+
TokenExID: (value) => exact2(TOKENEX_ID, value),
|
|
3575
|
+
Origin: isOrigin,
|
|
3576
|
+
AuthenticationKey: (value) => exact2(AUTHENTICATION_KEY, value),
|
|
3577
|
+
Timestamp: (value) => exact2(TIMESTAMP, value),
|
|
3578
|
+
TokenScheme: (value) => TOKENEX_IFRAME_TOKEN_SCHEMES.includes(value)
|
|
3579
|
+
};
|
|
3580
|
+
var BOUND_KEYS = Object.keys(BOUND);
|
|
3581
|
+
var BOOLEAN = /^(?:true|false)$/i;
|
|
3582
|
+
var QUERY_RULES = {
|
|
3583
|
+
...BOUND,
|
|
3584
|
+
Mode: (value) => value === "Data",
|
|
3585
|
+
PCI: (value) => exact2(/^true$/i, value),
|
|
3586
|
+
CVV: (value) => exact2(/^true$/i, value),
|
|
3587
|
+
Container: (value) => exact2(/^[A-Za-z][A-Za-z0-9_-]{0,63}$/, value),
|
|
3588
|
+
CvvContainer: (value) => exact2(/^[A-Za-z][A-Za-z0-9_-]{0,63}$/, value),
|
|
3589
|
+
EnforceLuhnCompliance: (value) => exact2(BOOLEAN, value),
|
|
3590
|
+
CustomDataLabel: (value) => plain(value, 64),
|
|
3591
|
+
CustomCvvDataLabel: (value) => plain(value, 64),
|
|
3592
|
+
ExpiresInSeconds: (value) => exact2(/^[1-9][0-9]{0,3}$/, value),
|
|
3593
|
+
ReturnAutoCompleteValues: (value) => exact2(BOOLEAN, value)
|
|
3594
|
+
};
|
|
3595
|
+
var QUERY_REQUIRED = [...BOUND_KEYS, "Mode", "PCI", "CVV"];
|
|
3596
|
+
function readQuery(search) {
|
|
3597
|
+
if (typeof search !== "string" || !search.startsWith("?") || search.length < 2)
|
|
3598
|
+
return null;
|
|
3599
|
+
const query = /* @__PURE__ */ new Map();
|
|
3600
|
+
for (const chunk of search.slice(1).split("&")) {
|
|
3601
|
+
const eq = chunk.indexOf("=");
|
|
3602
|
+
if (eq < 1)
|
|
3603
|
+
return null;
|
|
3604
|
+
let key, value;
|
|
3605
|
+
try {
|
|
3606
|
+
key = decodeURIComponent(chunk.slice(0, eq));
|
|
3607
|
+
value = decodeURIComponent(chunk.slice(eq + 1));
|
|
3608
|
+
}
|
|
3609
|
+
catch {
|
|
3610
|
+
return null;
|
|
3611
|
+
}
|
|
3612
|
+
if (query.has(key) || !owns5(QUERY_RULES, key) || !QUERY_RULES[key](value))
|
|
3613
|
+
return null;
|
|
3614
|
+
query.set(key, value);
|
|
3615
|
+
}
|
|
3616
|
+
return QUERY_REQUIRED.every((key) => query.has(key)) ? query : null;
|
|
3617
|
+
}
|
|
3618
|
+
function tokenexIframeTarget(url) {
|
|
3619
|
+
if (typeof url !== "string" || url.length > URL_LIMIT9 || url.includes("#"))
|
|
3620
|
+
return null;
|
|
3621
|
+
let parsed;
|
|
3622
|
+
try {
|
|
3623
|
+
parsed = new URL(url);
|
|
3624
|
+
}
|
|
3625
|
+
catch {
|
|
3626
|
+
return null;
|
|
3627
|
+
}
|
|
3628
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password)
|
|
3629
|
+
return null;
|
|
3630
|
+
if (!TOKENEX_IFRAME_HOSTS.includes(parsed.hostname) || parsed.pathname !== TOKENEX_IFRAME_PATH)
|
|
3631
|
+
return null;
|
|
3632
|
+
const query = readQuery(parsed.search);
|
|
3633
|
+
return query ? { host: parsed.hostname, query } : null;
|
|
3634
|
+
}
|
|
3635
|
+
var PLACEHOLDER = /^[0-9]{1,19}(?: [0-9]{1,19}){0,5}$/;
|
|
3636
|
+
var placeholderDigits = (value) => exact2(PLACEHOLDER, value) && value.length <= 23 ? value.replace(/ /g, "") : null;
|
|
3637
|
+
var RULES = {
|
|
3638
|
+
...BOUND,
|
|
3639
|
+
Data: (value) => {
|
|
3640
|
+
const pan = placeholderDigits(value);
|
|
3641
|
+
return pan !== null && pan.length >= 13 && pan.length <= 19;
|
|
3642
|
+
},
|
|
3643
|
+
CvvValue: (value) => digits(value, 3, 4),
|
|
3644
|
+
CvvOnly: (value) => value === "False",
|
|
3645
|
+
PCI: (value) => value === "True",
|
|
3646
|
+
ReturnHash: (value) => value === null,
|
|
3647
|
+
use3DS: (value) => value === "False",
|
|
3648
|
+
ThreeDSMethodNotificationUrl: (value) => value === "",
|
|
3649
|
+
kountSessionId: (value) => value === "",
|
|
3650
|
+
fraudMerchantId: (value) => value === "",
|
|
3651
|
+
UseKount: (value) => value === "False",
|
|
3652
|
+
kountMode: (value) => value === "",
|
|
3653
|
+
kountAnId: (value) => value === "",
|
|
3654
|
+
FraudServicesRiskRequestModel: (value) => value === "",
|
|
3655
|
+
EnforceLuhnCompliance: (value) => value === "true" || value === "false",
|
|
3656
|
+
CustomDataLuhnCheck: (value) => value === true
|
|
3657
|
+
};
|
|
3658
|
+
function readJson5(body, limit) {
|
|
3659
|
+
if (typeof body !== "string" || body === "" || body.length > limit)
|
|
3660
|
+
return null;
|
|
3661
|
+
try {
|
|
3662
|
+
const value = JSON.parse(body);
|
|
3663
|
+
return record19(value) ? value : null;
|
|
3664
|
+
}
|
|
3665
|
+
catch {
|
|
3666
|
+
return null;
|
|
3667
|
+
}
|
|
3668
|
+
}
|
|
3669
|
+
function judgeBody4(body) {
|
|
3670
|
+
const value = readJson5(body, BODY_LIMIT22);
|
|
3671
|
+
if (!value || JSON.stringify(value) !== body)
|
|
3672
|
+
return null;
|
|
3673
|
+
const keys = Object.keys(value);
|
|
3674
|
+
if (keys.length !== TOKENEX_IFRAME_BODY_KEYS.length || keys.some((key, index) => key !== TOKENEX_IFRAME_BODY_KEYS[index]))
|
|
3675
|
+
return null;
|
|
3676
|
+
return keys.every((key) => RULES[key](value[key])) ? value : null;
|
|
3677
|
+
}
|
|
3678
|
+
function carriesCard2(body) {
|
|
3679
|
+
const value = readJson5(body, BODY_LIMIT22 * 4);
|
|
3680
|
+
return value !== null && typeof value.Data === "string" && value.Data !== "";
|
|
3681
|
+
}
|
|
3682
|
+
function bindingRefusal(target, value) {
|
|
3683
|
+
return BOUND_KEYS.every((key) => target.query.get(key) === value[key]) ? null : "unsupported";
|
|
3684
|
+
}
|
|
3685
|
+
var TOKENEX_IFRAME_GATE_CODES = Object.freeze(["tokenex_iframe_url_refused", "tokenex_iframe_body_unsupported", "tokenex_iframe_query_mismatch"]);
|
|
3686
|
+
function tokenexIframeBodyVerdict(body, url) {
|
|
3687
|
+
if (!carriesCard2(body))
|
|
3688
|
+
return { verdict: "continue" };
|
|
3689
|
+
const target = url !== void 0 ? tokenexIframeTarget(url) : null;
|
|
3690
|
+
if (url !== void 0 && !target)
|
|
3691
|
+
return { verdict: "refuse", code: "tokenex_iframe_url_refused" };
|
|
3692
|
+
const value = judgeBody4(body);
|
|
3693
|
+
if (!value)
|
|
3694
|
+
return { verdict: "refuse", code: "tokenex_iframe_body_unsupported" };
|
|
3695
|
+
if (target && bindingRefusal(target, value))
|
|
3696
|
+
return { verdict: "refuse", code: "tokenex_iframe_query_mismatch" };
|
|
3697
|
+
return { verdict: "card" };
|
|
3698
|
+
}
|
|
3699
|
+
var SUCCESS_RULES = {
|
|
3700
|
+
token: (value) => digits(value, 13, 19),
|
|
3701
|
+
firstSix: (value) => digits(value, 6, 6),
|
|
3702
|
+
lastFour: (value) => digits(value, 4, 4),
|
|
3703
|
+
referenceNumber: (value) => exact2(/^[A-Za-z0-9-]{1,64}$/, value),
|
|
3704
|
+
tokenHMAC: (value) => exact2(/^[A-Za-z0-9+/]{1,128}={0,2}$/, value),
|
|
3705
|
+
cvvIncluded: (value) => typeof value === "boolean"
|
|
3706
|
+
};
|
|
3707
|
+
var SUCCESS_KEYS = Object.keys(SUCCESS_RULES);
|
|
3708
|
+
// src/poynt.js
|
|
3709
|
+
var POYNT_PSP = "poynt";
|
|
3710
|
+
var UUID4 = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
|
|
3711
|
+
var NONCE_URL = new RegExp(`^https://services\\.poynt\\.net/v1/commerce/stores/(${UUID4})/payment-tokens/generate-nonce$`);
|
|
3712
|
+
var STORE_ID = new RegExp(`^${UUID4}$`);
|
|
3713
|
+
var BODY_LIMIT23 = 8192;
|
|
3714
|
+
var ROOT_KEYS8 = /* @__PURE__ */ Object.freeze(["applicationId", "channelId", "card", "verificationData"]);
|
|
3715
|
+
var CARD_KEYS10 = /* @__PURE__ */ Object.freeze(["number", "expirationMonth", "expirationYear", "type", "cardHolderFirstName", "cardHolderLastName", "cardHolderFullName"]);
|
|
3716
|
+
var ADDRESS_KEYS4 = /* @__PURE__ */ Object.freeze(["postalCode", "line1", "line2", "city", "territory", "countryCode", "postalCodeExtension"]);
|
|
3717
|
+
var REQUIRED_ROOT = /* @__PURE__ */ Object.freeze(["applicationId", "card", "verificationData"]);
|
|
3718
|
+
var REQUIRED_CARD = /* @__PURE__ */ Object.freeze(["number", "expirationMonth", "expirationYear", "type", "cardHolderFullName"]);
|
|
3719
|
+
var CARD_ON_FILE_KEYS = /* @__PURE__ */ Object.freeze(["saveFinancialInstrumentOnFile", "financialInstrumentAgreement"]);
|
|
3720
|
+
var CARD_TYPES = /* @__PURE__ */ Object.freeze(["VISA", "MASTERCARD", "AMERICAN_EXPRESS", "DINERS_CLUB", "DISCOVER", "JCB", "UNIONPAY", "MAESTRO", "ELO", "HIPERCARD", "TROY", ""]);
|
|
3721
|
+
var CARD_NUMBER12 = /^[0-9]{12,19}$/;
|
|
3722
|
+
var MONTH12 = /^(?:0[1-9]|1[0-2])$/;
|
|
3723
|
+
var YEAR12 = /^20[0-9]{2}$/;
|
|
3724
|
+
var SECURITY_CODE14 = /^[0-9]{3,4}$/;
|
|
3725
|
+
var IDENTIFIER = /^[A-Za-z0-9:._-]{1,128}$/;
|
|
3726
|
+
var APPLICATION_ID = new RegExp(`^urn:aid:${UUID4}$`);
|
|
3727
|
+
var POSTAL_CODE3 = /^[A-Za-z0-9_]{0,16}$/;
|
|
3728
|
+
var COUNTRY3 = /^[A-Z]{2}$/;
|
|
3729
|
+
var TEXT_LIMIT7 = 256;
|
|
3730
|
+
var CONTROL10 = /[\u0000-\u001f\u007f]/;
|
|
3731
|
+
var cardLike2 = (text6) => (text6.match(/[0-9]/g) ?? []).length >= 12;
|
|
3732
|
+
var text5 = (value) => typeof value === "string" && value.length <= TEXT_LIMIT7 && !CONTROL10.test(value) && !cardLike2(value);
|
|
3733
|
+
var record20 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3734
|
+
var own5 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
3735
|
+
var inOrder4 = (value, order, required) => {
|
|
3736
|
+
const keys = Object.keys(value);
|
|
3737
|
+
let at = -1;
|
|
3738
|
+
for (const key of keys) {
|
|
3739
|
+
const next = order.indexOf(key);
|
|
3740
|
+
if (next <= at)
|
|
3741
|
+
return false;
|
|
3742
|
+
at = next;
|
|
3743
|
+
}
|
|
3744
|
+
return required.every((key) => keys.includes(key));
|
|
3745
|
+
};
|
|
3746
|
+
var refuse25 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
3747
|
+
var CARD24 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
3748
|
+
function poyntStoreId(url) {
|
|
3749
|
+
const match = typeof url === "string" ? NONCE_URL.exec(url) : null;
|
|
3750
|
+
return match ? match[1] : null;
|
|
3751
|
+
}
|
|
3752
|
+
function isPoyntNonceUrl(url) {
|
|
3753
|
+
return poyntStoreId(url) !== null;
|
|
3754
|
+
}
|
|
3755
|
+
function readBody14(body) {
|
|
3756
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT23)
|
|
3757
|
+
return null;
|
|
3758
|
+
let value;
|
|
3759
|
+
try {
|
|
3760
|
+
value = JSON.parse(body);
|
|
3761
|
+
if (!record20(value) || JSON.stringify(value) !== body)
|
|
3762
|
+
return null;
|
|
3763
|
+
}
|
|
3764
|
+
catch {
|
|
3765
|
+
return null;
|
|
3766
|
+
}
|
|
3767
|
+
return value;
|
|
3768
|
+
}
|
|
3769
|
+
function poyntBodyVerdict(body) {
|
|
3770
|
+
const value = readBody14(body);
|
|
3771
|
+
if (value === null)
|
|
3772
|
+
return refuse25("poynt_body_unsupported");
|
|
3773
|
+
if (CARD_ON_FILE_KEYS.some((key) => own5(value, key)))
|
|
3774
|
+
return refuse25("poynt_card_on_file");
|
|
3775
|
+
if (!inOrder4(value, ROOT_KEYS8, REQUIRED_ROOT) || typeof value.applicationId !== "string" || !APPLICATION_ID.test(value.applicationId) || own5(value, "channelId") && (typeof value.channelId !== "string" || !IDENTIFIER.test(value.channelId))) {
|
|
3776
|
+
return refuse25("poynt_body_unsupported");
|
|
3777
|
+
}
|
|
3778
|
+
const { card, verificationData: verification } = value;
|
|
3779
|
+
if (!record20(card) || !inOrder4(card, CARD_KEYS10, REQUIRED_CARD) || typeof card.number !== "string" || !CARD_NUMBER12.test(card.number) || typeof card.expirationMonth !== "string" || !MONTH12.test(card.expirationMonth) || typeof card.expirationYear !== "string" || !YEAR12.test(card.expirationYear) || !CARD_TYPES.includes(card.type) || !["cardHolderFirstName", "cardHolderLastName", "cardHolderFullName"].every((key) => !own5(card, key) || text5(card[key]))) {
|
|
3780
|
+
return refuse25("poynt_body_unsupported");
|
|
3781
|
+
}
|
|
3782
|
+
if (!record20(verification) || Object.keys(verification).join() !== "cardHolderBillingAddress,cvData" || typeof verification.cvData !== "string" || !SECURITY_CODE14.test(verification.cvData))
|
|
3783
|
+
return refuse25("poynt_body_unsupported");
|
|
3784
|
+
const address2 = verification.cardHolderBillingAddress;
|
|
3785
|
+
if (!record20(address2) || !inOrder4(address2, ADDRESS_KEYS4, []) || !Object.values(address2).every(text5) || own5(address2, "postalCode") && !POSTAL_CODE3.test(address2.postalCode) || own5(address2, "postalCodeExtension") && !POSTAL_CODE3.test(address2.postalCodeExtension) || own5(address2, "countryCode") && !COUNTRY3.test(address2.countryCode))
|
|
3786
|
+
return refuse25("poynt_body_unsupported");
|
|
3787
|
+
return CARD24;
|
|
3788
|
+
}
|
|
3789
|
+
var pin7 = (fields) => Object.freeze({ ...fields, origins: Object.freeze([...fields.origins]), storeIds: Object.freeze([...fields.storeIds]) });
|
|
3790
|
+
var POYNT_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
3791
|
+
pin7({
|
|
3792
|
+
id: "yearning_for_learning",
|
|
3793
|
+
merchant: "Yearning for Learning Publishing & Coaching",
|
|
3794
|
+
origins: ["https://ff305485-ba6c-423a-87b0-cebe3f83ffe9.mysimplestore.com"],
|
|
3795
|
+
storeIds: ["71ac12ed-e61f-4318-95db-db0e7c649d6f"]
|
|
3796
|
+
}),
|
|
3797
|
+
pin7({
|
|
3798
|
+
id: "timber_ridge_bookkeeping",
|
|
3799
|
+
merchant: "Timber Ridge Bookkeeping",
|
|
3800
|
+
origins: ["https://d7d64ac3-0352-4e53-af9a-f6d8e7b5fb71.mysimplestore.com"],
|
|
3801
|
+
storeIds: ["27be984a-0a03-4a54-8675-e64bbbe1c43e"]
|
|
3802
|
+
})
|
|
3803
|
+
]);
|
|
3804
|
+
var MAX_ANSWER_CHARS = 16 * 1024;
|
|
2453
3805
|
// src/card-fields.js
|
|
2454
3806
|
function processorGate(recognizer, url, body) {
|
|
2455
3807
|
if (recognizer && recognizer.psp === LYRA_PSP)
|
|
@@ -2461,6 +3813,23 @@ function processorGate(recognizer, url, body) {
|
|
|
2461
3813
|
}
|
|
2462
3814
|
if (recognizer && recognizer.psp === KOMOJU_PSP)
|
|
2463
3815
|
return komojuBodyVerdict(body, url);
|
|
3816
|
+
if (recognizer && recognizer.psp === HIPAY_PSP) {
|
|
3817
|
+
if (url !== void 0 && !isHipayTokenUrl(url))
|
|
3818
|
+
return { verdict: "refuse", code: "hipay_url_refused" };
|
|
3819
|
+
return hipayBodyVerdict(body);
|
|
3820
|
+
}
|
|
3821
|
+
if (recognizer && recognizer.psp === PAYPAL_PSP) {
|
|
3822
|
+
if (url !== void 0 && !isPaypalConfirmUrl(url))
|
|
3823
|
+
return { verdict: "refuse", code: "paypal_url_refused" };
|
|
3824
|
+
return paypalBodyVerdict(body);
|
|
3825
|
+
}
|
|
3826
|
+
if (recognizer && recognizer.psp === MAKECOMMERCE_PSP)
|
|
3827
|
+
return makecommerceBodyVerdict(body, url);
|
|
3828
|
+
if (recognizer && recognizer.psp === POYNT_PSP) {
|
|
3829
|
+
if (url !== void 0 && !isPoyntNonceUrl(url))
|
|
3830
|
+
return { verdict: "refuse", code: "poynt_url_refused" };
|
|
3831
|
+
return poyntBodyVerdict(body);
|
|
3832
|
+
}
|
|
2464
3833
|
if (recognizer && recognizer.psp === PADDLE_VGS_PSP) {
|
|
2465
3834
|
if (url !== void 0 && !isPaddleVgsCardsUrl(url))
|
|
2466
3835
|
return { verdict: "refuse", code: "paddle_vgs_url_refused" };
|
|
@@ -2482,6 +3851,21 @@ function processorGate(recognizer, url, body) {
|
|
|
2482
3851
|
return { verdict: "refuse", code: "pay_nl_url_refused" };
|
|
2483
3852
|
return payNlBodyVerdict(body);
|
|
2484
3853
|
}
|
|
3854
|
+
if (recognizer && recognizer.psp === TWOC2P_PSP) {
|
|
3855
|
+
if (url === void 0)
|
|
3856
|
+
return twoC2pBodyVerdict(body);
|
|
3857
|
+
const target = twoC2pPaymentTarget(url);
|
|
3858
|
+
if (target === null)
|
|
3859
|
+
return { verdict: "refuse", code: "twoc2p_url_refused" };
|
|
3860
|
+
if (!target.reviewed)
|
|
3861
|
+
return twoC2pPaymentCarriesCard(body) ? { verdict: "refuse", code: "twoc2p_build_unreviewed" } : { verdict: "continue" };
|
|
3862
|
+
const keyBytes = twoC2pKeyBytes(target.environment);
|
|
3863
|
+
return keyBytes === null ? { verdict: "refuse", code: "twoc2p_field_unreviewed" } : twoC2pBodyVerdict(body, keyBytes, target.environment);
|
|
3864
|
+
}
|
|
3865
|
+
if (recognizer && recognizer.psp === APS_PSP)
|
|
3866
|
+
return apsBodyVerdict(body, url);
|
|
3867
|
+
if (recognizer && recognizer.psp === CONEKTA_PSP)
|
|
3868
|
+
return conektaBodyVerdict(body, url);
|
|
2485
3869
|
if (recognizer && recognizer.psp === PADDLE_TOKENEX_PSP) {
|
|
2486
3870
|
const target = url !== void 0 ? paddleTokenexPayTarget(url) : null;
|
|
2487
3871
|
if (url !== void 0 && target === null)
|
|
@@ -2503,6 +3887,15 @@ function processorGate(recognizer, url, body) {
|
|
|
2503
3887
|
}
|
|
2504
3888
|
if (recognizer && recognizer.psp === SUMUP_PSP)
|
|
2505
3889
|
return sumupBodyVerdict(body, url);
|
|
3890
|
+
if (recognizer && recognizer.psp === CLOVER_PSP)
|
|
3891
|
+
return cloverBodyVerdict(body, url);
|
|
3892
|
+
if (recognizer && recognizer.psp === TAP_PAYMENTS_PSP) {
|
|
3893
|
+
if (url !== void 0 && !isTapPaymentsTokenUrl(url))
|
|
3894
|
+
return { verdict: "refuse", code: "tap_payments_url_refused" };
|
|
3895
|
+
return tapPaymentsBodyVerdict(body);
|
|
3896
|
+
}
|
|
3897
|
+
if (recognizer && recognizer.psp === TOKENEX_IFRAME_PSP)
|
|
3898
|
+
return tokenexIframeBodyVerdict(body, url);
|
|
2506
3899
|
if (recognizer && recognizer.psp === GRAVY_PSP)
|
|
2507
3900
|
return gravyBodyVerdict(body);
|
|
2508
3901
|
if (recognizer && recognizer.psp === MONERIS_PSP) {
|
|
@@ -2620,7 +4013,7 @@ function splitCardLeg(recognizer, body) {
|
|
|
2620
4013
|
const absorb = list(split.absorb);
|
|
2621
4014
|
const pass = list(split.pass);
|
|
2622
4015
|
const sibling = list(split.siblingKeys);
|
|
2623
|
-
const
|
|
4016
|
+
const own6 = [];
|
|
2624
4017
|
const seen = /* @__PURE__ */ new Set();
|
|
2625
4018
|
for (const chunk of body.split("&")) {
|
|
2626
4019
|
const eq = chunk.indexOf("=");
|
|
@@ -2637,13 +4030,13 @@ function splitCardLeg(recognizer, body) {
|
|
|
2637
4030
|
return null;
|
|
2638
4031
|
seen.add(key);
|
|
2639
4032
|
if (!sibling.includes(key))
|
|
2640
|
-
|
|
4033
|
+
own6.push(key);
|
|
2641
4034
|
}
|
|
2642
|
-
if (
|
|
4035
|
+
if (own6.length === 0)
|
|
2643
4036
|
return null;
|
|
2644
|
-
if (
|
|
4037
|
+
if (own6.every((key) => absorb.includes(key)))
|
|
2645
4038
|
return "absorb";
|
|
2646
|
-
if (
|
|
4039
|
+
if (own6.every((key) => pass.includes(key)))
|
|
2647
4040
|
return "pass";
|
|
2648
4041
|
return null;
|
|
2649
4042
|
}
|