@agent-cards/sdk 0.23.19 → 0.23.20
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 +20 -0
- package/PREFLIGHT.md +2 -0
- package/README.md +34 -4
- 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 +483 -17
- package/dist/cdp.d.ts +29 -0
- package/dist/cdp.js +302 -18
- package/dist/client.d.ts +30 -4
- package/dist/client.js +128 -13
- package/dist/hipay.generated.d.ts +56 -0
- package/dist/hipay.generated.js +389 -0
- package/dist/hold.d.ts +180 -0
- package/dist/hold.js +264 -0
- package/dist/index.d.ts +3 -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-vgs.generated.d.ts +3 -2
- package/dist/paddle-vgs.generated.js +9 -5
- package/dist/pre-claim.d.ts +14 -0
- package/dist/pre-claim.js +76 -3
- package/dist/prepared-processor.d.ts +6 -2
- package/dist/prepared-processor.js +18 -2
- package/dist/primer.generated.js +510 -44
- package/dist/quickpay.d.ts +44 -0
- package/dist/quickpay.js +65 -0
- package/dist/stripe-checkout.generated.js +124 -2
- package/dist/twoc2p.d.ts +54 -0
- package/dist/twoc2p.generated.d.ts +33 -0
- package/dist/twoc2p.generated.js +1145 -0
- package/dist/twoc2p.js +85 -0
- package/dist/voice.d.ts +16 -13
- package/dist/voice.js +13 -10
- package/package.json +3 -3
package/dist/primer.generated.js
CHANGED
|
@@ -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: 04a99605d111c45486d6e77e4e9f55e04217690d33f5ddbfcffa4950c6754c17
|
|
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
|
|
@@ -109,8 +109,8 @@ function parseConvergeBody(body) {
|
|
|
109
109
|
return parsed;
|
|
110
110
|
}
|
|
111
111
|
function convergeAmountCents(value) {
|
|
112
|
-
const
|
|
113
|
-
const m = typeof
|
|
112
|
+
const text4 = typeof value === "number" && Number.isFinite(value) ? String(value) : value;
|
|
113
|
+
const m = typeof text4 === "string" ? AMOUNT.exec(text4) : null;
|
|
114
114
|
if (!m)
|
|
115
115
|
return null;
|
|
116
116
|
const cents = Number(m[1]) * 100 + Number(((m[2] ?? "") + "00").slice(0, 2));
|
|
@@ -590,9 +590,9 @@ var K = /* @__PURE__ */ new Uint32Array([
|
|
|
590
590
|
3329325298
|
|
591
591
|
]);
|
|
592
592
|
var rotr = (x, n) => x >>> n | x << 32 - n;
|
|
593
|
-
function utf8(
|
|
593
|
+
function utf8(text4) {
|
|
594
594
|
const out = [];
|
|
595
|
-
for (const char of
|
|
595
|
+
for (const char of text4) {
|
|
596
596
|
let cp = char.codePointAt(0);
|
|
597
597
|
if (cp >= 55296 && cp <= 57343)
|
|
598
598
|
cp = 65533;
|
|
@@ -1376,14 +1376,14 @@ function readJson2(body) {
|
|
|
1376
1376
|
catch {
|
|
1377
1377
|
return { parsed: null, exact: false };
|
|
1378
1378
|
}
|
|
1379
|
-
let
|
|
1379
|
+
let exact3 = false;
|
|
1380
1380
|
try {
|
|
1381
|
-
|
|
1381
|
+
exact3 = body.length <= BODY_LIMIT6 && JSON.stringify(parsed) === body;
|
|
1382
1382
|
}
|
|
1383
1383
|
catch {
|
|
1384
|
-
|
|
1384
|
+
exact3 = false;
|
|
1385
1385
|
}
|
|
1386
|
-
return { parsed, exact:
|
|
1386
|
+
return { parsed, exact: exact3 };
|
|
1387
1387
|
}
|
|
1388
1388
|
function billingValue(value) {
|
|
1389
1389
|
if (value === UNDEFINED)
|
|
@@ -1438,14 +1438,14 @@ function attachType(parsed) {
|
|
|
1438
1438
|
return typeof type === "string" ? type : null;
|
|
1439
1439
|
}
|
|
1440
1440
|
function paymongoBodyVerdict(body, session) {
|
|
1441
|
-
const { parsed, exact:
|
|
1441
|
+
const { parsed, exact: exact3 } = readJson2(body);
|
|
1442
1442
|
const type = parsed === null ? null : attachType(parsed);
|
|
1443
1443
|
if (type !== "card") {
|
|
1444
1444
|
if (parsed === null)
|
|
1445
1445
|
return body === void 0 || body === null || body === "" ? CONTINUE4 : refuse10("paymongo_body_unsupported");
|
|
1446
1446
|
return namesCardValue(parsed) ? refuse10("paymongo_body_unsupported") : CONTINUE4;
|
|
1447
1447
|
}
|
|
1448
|
-
if (!
|
|
1448
|
+
if (!exact3)
|
|
1449
1449
|
return refuse10("paymongo_body_unsupported");
|
|
1450
1450
|
const code = judgeCardAttach(parsed, session);
|
|
1451
1451
|
return code === null ? CARD9 : refuse10(code);
|
|
@@ -1666,6 +1666,9 @@ function payrexxGateVerdict(url, body) {
|
|
|
1666
1666
|
const verdict = payrexxBodyVerdict(body);
|
|
1667
1667
|
return verdict.verdict === "card" && target.pspId !== PAYREXX_PAY_PSP_ID ? refuse12("payrexx_other_provider") : verdict;
|
|
1668
1668
|
}
|
|
1669
|
+
var PAYREXX_FOLLOW_UP_WINDOW_MS = 15 * 60 * 1e3;
|
|
1670
|
+
var PAYREXX_FOLLOW_UP_IDLE_MS = 60 * 1e3;
|
|
1671
|
+
var PAYREXX_FOLLOW_UP_CHALLENGE_MS = 11 * 60 * 1e3;
|
|
1669
1672
|
// src/komoju.js
|
|
1670
1673
|
var KOMOJU_PSP = "komoju";
|
|
1671
1674
|
var KOMOJU_HOST = "komoju.com";
|
|
@@ -2099,7 +2102,7 @@ var luhn2 = (digits2) => {
|
|
|
2099
2102
|
return sum % 10 === 0;
|
|
2100
2103
|
};
|
|
2101
2104
|
var ANY_NETWORK = /^[2-6][0-9]{12,18}$/;
|
|
2102
|
-
var holdsCardShape = (
|
|
2105
|
+
var holdsCardShape = (text4, shape = NETWORK) => (text4.match(/[0-9]{13,}/g) ?? []).some((run) => run.length > 19 || shape.test(run) && luhn2(run));
|
|
2103
2106
|
var phone = (value) => typeof value === "string" && PHONE.test(value) && (value.match(/[0-9]/g) ?? []).length >= 6 && (value.match(/[0-9]/g) ?? []).length <= 15;
|
|
2104
2107
|
var refuse16 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
2105
2108
|
var CARD15 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
@@ -2327,13 +2330,13 @@ var printable = (value) => [...value].every((ch) => ch.charCodeAt(0) >= 32 && ch
|
|
|
2327
2330
|
function typed(value, limit = 256) {
|
|
2328
2331
|
return typeof value === "string" && value.length >= 1 && value.length <= limit && !PAN_LIKE4.test(value) && printable(value);
|
|
2329
2332
|
}
|
|
2330
|
-
function decodeBase64(
|
|
2331
|
-
if (typeof
|
|
2333
|
+
function decodeBase64(text4) {
|
|
2334
|
+
if (typeof text4 !== "string" || !BASE643.test(text4) || text4.length % 4 !== 0)
|
|
2332
2335
|
return null;
|
|
2333
2336
|
let bits = 0;
|
|
2334
2337
|
let value = 0;
|
|
2335
2338
|
let out = "";
|
|
2336
|
-
for (const ch of
|
|
2339
|
+
for (const ch of text4.replace(/=+$/, "")) {
|
|
2337
2340
|
value = (value << 6 | BASE64_ALPHABET.indexOf(ch)) & 16777215;
|
|
2338
2341
|
bits += 6;
|
|
2339
2342
|
if (bits >= 8) {
|
|
@@ -2343,8 +2346,8 @@ function decodeBase64(text3) {
|
|
|
2343
2346
|
}
|
|
2344
2347
|
return out;
|
|
2345
2348
|
}
|
|
2346
|
-
function soundDevice(
|
|
2347
|
-
const json = decodeBase64(
|
|
2349
|
+
function soundDevice(text4) {
|
|
2350
|
+
const json = decodeBase64(text4);
|
|
2348
2351
|
if (json === null)
|
|
2349
2352
|
return false;
|
|
2350
2353
|
let value;
|
|
@@ -2458,6 +2461,451 @@ function sumupBodyVerdict(body, url) {
|
|
|
2458
2461
|
return refuse17("sumup_card_saving_refused");
|
|
2459
2462
|
return CARD16;
|
|
2460
2463
|
}
|
|
2464
|
+
// src/twoc2p-secure-pay.js
|
|
2465
|
+
var SALTED = /* @__PURE__ */ Object.freeze([83, 97, 108, 116, 101, 100, 95, 95]);
|
|
2466
|
+
var B64 = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
2467
|
+
var FIELD_LIMIT = 1024;
|
|
2468
|
+
function decodeCanonical(text4) {
|
|
2469
|
+
if (typeof text4 !== "string" || text4.length === 0 || text4.length % 4 !== 0 || !B64.test(text4))
|
|
2470
|
+
return null;
|
|
2471
|
+
let binary;
|
|
2472
|
+
try {
|
|
2473
|
+
binary = atob(text4);
|
|
2474
|
+
}
|
|
2475
|
+
catch {
|
|
2476
|
+
return null;
|
|
2477
|
+
}
|
|
2478
|
+
if (btoa(binary) !== text4)
|
|
2479
|
+
return null;
|
|
2480
|
+
return Uint8Array.from(binary, (char) => char.charCodeAt(0));
|
|
2481
|
+
}
|
|
2482
|
+
function twoC2pSecurePayParts(value) {
|
|
2483
|
+
if (typeof value !== "string" || value.length > FIELD_LIMIT || !/^[0-9a-f]{4}/.test(value))
|
|
2484
|
+
return null;
|
|
2485
|
+
const length = parseInt(value.slice(0, 4), 16);
|
|
2486
|
+
if (length < 4 || 4 + length >= value.length)
|
|
2487
|
+
return null;
|
|
2488
|
+
const rsaText = value.slice(4, 4 + length);
|
|
2489
|
+
const rsa = decodeCanonical(rsaText);
|
|
2490
|
+
const cipher = decodeCanonical(value.slice(4 + length));
|
|
2491
|
+
if (!rsa || !cipher || cipher.length < 32 || cipher.length > 80 || cipher.length % 16 !== 0)
|
|
2492
|
+
return null;
|
|
2493
|
+
if (!SALTED.every((byte, at) => cipher[at] === byte))
|
|
2494
|
+
return null;
|
|
2495
|
+
return { rsaText, rsa, salt: cipher.slice(8, 16), blocks: (cipher.length - 16) / 16 };
|
|
2496
|
+
}
|
|
2497
|
+
function isTwoC2pPageField(value, keyBytes) {
|
|
2498
|
+
const parts = twoC2pSecurePayParts(value);
|
|
2499
|
+
if (!parts || !Number.isInteger(keyBytes) || keyBytes < 128)
|
|
2500
|
+
return false;
|
|
2501
|
+
const expected = Math.ceil(keyBytes / 3) * 4;
|
|
2502
|
+
return parts.rsaText.length === expected && (parts.rsa.length === keyBytes || parts.rsa.length === keyBytes - 1);
|
|
2503
|
+
}
|
|
2504
|
+
// src/twoc2p-keys.js
|
|
2505
|
+
var TWOC2P_KEYS = /* @__PURE__ */ Object.freeze({
|
|
2506
|
+
production: Object.freeze({
|
|
2507
|
+
spki: "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/1ljsxI+r6qQraTFrHfWNrV41vxumBF+4ILAG3WsN6HEBQU2wSUv/IyQmZkiys1ilOb+OOuQTH8OXMnqQg9E4epyePW3L7IeOieSbIIDeSX6UpTWmT/Fs7moWZkN8RpuCV0u87n3AY2tQbtcSqwEKi2sxzWLFwscoGn6N5yVIpQIDAQAB",
|
|
2508
|
+
sha256: "bb8f27929ce140c6ef0ec9c4a20d7ca0b83376bc35a501985dc40d16669384fe",
|
|
2509
|
+
script: Object.freeze({ url: "https://t.2c2p.com/SecurePayment/api/my2c2p.1.7.6.min.js", sha256: "4a745a37765a2e28e299d64f6ea5811aab27b176da61db6f840fa85d6a47e763" })
|
|
2510
|
+
}),
|
|
2511
|
+
sandbox: Object.freeze({
|
|
2512
|
+
spki: "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKakJC+2MSZikKoPzlNqXvJCuWNLhejg3gMRePSetYNNgnhyqFwwAR7t7i/B2QFZoixSYc2/23cJz0jA5O+q+Cu3fycqKlf1L9966+X3B9nyHe2eKQZr8KrcS/8+sEKcd0pLATY4AleW1iktuN+2oghrDKuv+aDNztWcOy+PTofwIDAQAB",
|
|
2513
|
+
sha256: "7f80c07f1d72db28ede10dae942940657c72dfa789836c9fdf283cba6feff2e6",
|
|
2514
|
+
script: Object.freeze({ url: "https://demo2.2c2p.com/2C2PFrontEnd/SecurePayment/api/my2c2p.1.7.6.min.js", sha256: "435723d92bfefb00607a56851967e0b745d52b8d49443de5f0000f0583fde5cc" })
|
|
2515
|
+
})
|
|
2516
|
+
});
|
|
2517
|
+
function twoC2pKey(environment2) {
|
|
2518
|
+
if (environment2 !== "production" && environment2 !== "sandbox")
|
|
2519
|
+
return null;
|
|
2520
|
+
return TWOC2P_KEYS[environment2] ?? null;
|
|
2521
|
+
}
|
|
2522
|
+
function twoC2pKeyBytes(environment2) {
|
|
2523
|
+
const key = twoC2pKey(environment2);
|
|
2524
|
+
if (!key)
|
|
2525
|
+
return null;
|
|
2526
|
+
try {
|
|
2527
|
+
return parseRsaPublicKey(key).size;
|
|
2528
|
+
}
|
|
2529
|
+
catch {
|
|
2530
|
+
return null;
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
// src/twoc2p.js
|
|
2534
|
+
var TWOC2P_PSP = "twoc2p";
|
|
2535
|
+
var TWOC2P_FIELD = "securePayToken";
|
|
2536
|
+
var TWOC2P_REVIEWED_BUILDS = /* @__PURE__ */ Object.freeze(["4.1", "4.2", "4.3", "4.4", "4.5"]);
|
|
2537
|
+
var record12 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2538
|
+
var refuse18 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
2539
|
+
var CARD17 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
2540
|
+
var CONTINUE8 = /* @__PURE__ */ Object.freeze({ verdict: "continue" });
|
|
2541
|
+
var PAYMENT_URL = /^https:\/\/(sandbox-)?pgwv4\.2c2p\.com\/payment\/(4\.[0-9]{1,2})\/Payment$/;
|
|
2542
|
+
function twoC2pPaymentTarget(url) {
|
|
2543
|
+
const match = typeof url === "string" ? PAYMENT_URL.exec(url) : null;
|
|
2544
|
+
if (!match)
|
|
2545
|
+
return null;
|
|
2546
|
+
return Object.freeze({ environment: match[1] ? "sandbox" : "production", version: match[2], reviewed: TWOC2P_REVIEWED_BUILDS.includes(match[2]) });
|
|
2547
|
+
}
|
|
2548
|
+
function twoC2pPaymentCarriesCard(body) {
|
|
2549
|
+
if (typeof body !== "string")
|
|
2550
|
+
return true;
|
|
2551
|
+
try {
|
|
2552
|
+
return JSON.stringify(JSON.parse(body)).includes(`"${TWOC2P_FIELD}"`);
|
|
2553
|
+
}
|
|
2554
|
+
catch {
|
|
2555
|
+
return true;
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
var ROOT_KEYS6 = /* @__PURE__ */ Object.freeze(["paymentToken", "clientIP", "locale", "responseReturnUrl", "clientID", "payment"]);
|
|
2559
|
+
var CODE_KEYS = /* @__PURE__ */ Object.freeze(["channelCode", "agentCode", "agentChannelCode"]);
|
|
2560
|
+
var DATA_KEYS2 = /* @__PURE__ */ Object.freeze([
|
|
2561
|
+
"name",
|
|
2562
|
+
"isIppChosen",
|
|
2563
|
+
"cardDetails",
|
|
2564
|
+
"loyaltyPoints",
|
|
2565
|
+
"fxRateID",
|
|
2566
|
+
"email",
|
|
2567
|
+
"mobileNo",
|
|
2568
|
+
"mobileNoPrefix",
|
|
2569
|
+
"customerNote",
|
|
2570
|
+
"paymentExpiry",
|
|
2571
|
+
"securePayToken",
|
|
2572
|
+
"cardTokenize",
|
|
2573
|
+
"accountTokenization",
|
|
2574
|
+
"token",
|
|
2575
|
+
"customerToken",
|
|
2576
|
+
"accountNo",
|
|
2577
|
+
"installmentPeriod",
|
|
2578
|
+
"interestType",
|
|
2579
|
+
"payLaterPeriod",
|
|
2580
|
+
"billingAddress1",
|
|
2581
|
+
"billingAddress2",
|
|
2582
|
+
"billingCity",
|
|
2583
|
+
"billingState",
|
|
2584
|
+
"billingCountryCode",
|
|
2585
|
+
"billingPostalCode",
|
|
2586
|
+
"riskInfo"
|
|
2587
|
+
]);
|
|
2588
|
+
var RISK_KEYS = /* @__PURE__ */ Object.freeze(["customer_id", "shipping_method", "deviceSessionId", "customData"]);
|
|
2589
|
+
var BODY_LIMIT14 = 16384;
|
|
2590
|
+
var CONTROL6 = /[\u0000-\u001f\u007f]/;
|
|
2591
|
+
var CARD_LIKE = /(?:[0-9][ _.:/-]*){12,}/;
|
|
2592
|
+
var PAYMENT_TOKEN = /^[A-Za-z0-9+/]{16,1000}={0,2}$/;
|
|
2593
|
+
var UUID2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2594
|
+
var IP = /^[0-9A-Fa-f.:]{2,45}$/;
|
|
2595
|
+
var LOCALE2 = /^[A-Za-z]{2,3}(?:[-_][A-Za-z0-9]{2,8})?$/;
|
|
2596
|
+
var AGENT = /^[A-Za-z0-9_]{1,32}$/;
|
|
2597
|
+
var RISK_TOKEN2 = /^[\x21-\x7e]{1,512}$/;
|
|
2598
|
+
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})?$/;
|
|
2599
|
+
var PAGE_HOSTS = /* @__PURE__ */ Object.freeze({ production: "pgw-ui.2c2p.com", sandbox: "sandbox-pgw-ui.2c2p.com" });
|
|
2600
|
+
var returnUrlTaken = (value, paymentToken, environment2) => {
|
|
2601
|
+
if (value === void 0)
|
|
2602
|
+
return true;
|
|
2603
|
+
const match = typeof value === "string" ? RETURN_URL.exec(value) : null;
|
|
2604
|
+
return !!match && (match[2] === void 0 || match[2] === paymentToken) && (environment2 === void 0 || match[1] === PAGE_HOSTS[environment2]);
|
|
2605
|
+
};
|
|
2606
|
+
var inOrder2 = (value, order) => {
|
|
2607
|
+
let at = -1;
|
|
2608
|
+
for (const key of Object.keys(value)) {
|
|
2609
|
+
const next = order.indexOf(key);
|
|
2610
|
+
if (next <= at)
|
|
2611
|
+
return false;
|
|
2612
|
+
at = next;
|
|
2613
|
+
}
|
|
2614
|
+
return true;
|
|
2615
|
+
};
|
|
2616
|
+
var text2 = (value, limit) => typeof value === "string" && value.length <= limit && !CONTROL6.test(value) && !CARD_LIKE.test(value);
|
|
2617
|
+
var optionalText = (value, limit) => value === void 0 || text2(value, limit);
|
|
2618
|
+
function twoC2pBodyVerdict(body, keyBytes = 128, environment2 = void 0) {
|
|
2619
|
+
if (!twoC2pPaymentCarriesCard(body))
|
|
2620
|
+
return CONTINUE8;
|
|
2621
|
+
if (typeof body !== "string" || body.length > BODY_LIMIT14)
|
|
2622
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2623
|
+
let value;
|
|
2624
|
+
try {
|
|
2625
|
+
value = JSON.parse(body);
|
|
2626
|
+
}
|
|
2627
|
+
catch {
|
|
2628
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2629
|
+
}
|
|
2630
|
+
if (!record12(value) || JSON.stringify(value) !== body || !inOrder2(value, ROOT_KEYS6))
|
|
2631
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2632
|
+
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)))
|
|
2633
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2634
|
+
const payment = value.payment;
|
|
2635
|
+
if (!record12(payment) || Object.keys(payment).join(",") !== "code,data")
|
|
2636
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2637
|
+
const code = payment.code;
|
|
2638
|
+
const data = payment.data;
|
|
2639
|
+
if (!record12(code) || !record12(data))
|
|
2640
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2641
|
+
if (Object.prototype.hasOwnProperty.call(code, "subChannelCode"))
|
|
2642
|
+
return refuse18("twoc2p_stored_card");
|
|
2643
|
+
if (code.channelCode === "IPP" || code.channelCode === "LIPP")
|
|
2644
|
+
return refuse18("twoc2p_installments");
|
|
2645
|
+
if (!inOrder2(code, CODE_KEYS) || code.channelCode === void 0)
|
|
2646
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2647
|
+
if (code.channelCode !== "CC")
|
|
2648
|
+
return refuse18("twoc2p_channel_unsupported");
|
|
2649
|
+
if ([code.agentCode, code.agentChannelCode].some((part) => part !== void 0 && !(typeof part === "string" && AGENT.test(part))))
|
|
2650
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2651
|
+
return dataVerdict(data, keyBytes, body);
|
|
2652
|
+
}
|
|
2653
|
+
function dataVerdict(data, keyBytes, body) {
|
|
2654
|
+
if (data.cardTokenize !== void 0 || data.accountTokenization !== void 0)
|
|
2655
|
+
return refuse18("twoc2p_keeps_card");
|
|
2656
|
+
if (data.token !== void 0 || data.customerToken !== void 0)
|
|
2657
|
+
return refuse18("twoc2p_stored_card");
|
|
2658
|
+
if (data.accountNo !== void 0)
|
|
2659
|
+
return refuse18("twoc2p_card_in_clear");
|
|
2660
|
+
const details = data.cardDetails;
|
|
2661
|
+
if (record12(details) && (details.cardNo !== void 0 || details.accountNo !== void 0))
|
|
2662
|
+
return refuse18("twoc2p_card_in_clear");
|
|
2663
|
+
if (record12(details) && Object.keys(details).some((key) => key !== "email"))
|
|
2664
|
+
return refuse18("twoc2p_stored_card");
|
|
2665
|
+
if (data.isIppChosen === true || data.installmentPeriod !== void 0 || data.interestType !== void 0 || data.payLaterPeriod !== void 0) {
|
|
2666
|
+
return refuse18("twoc2p_installments");
|
|
2667
|
+
}
|
|
2668
|
+
if (data.fxRateID !== void 0)
|
|
2669
|
+
return refuse18("twoc2p_currency_conversion");
|
|
2670
|
+
if (data.loyaltyPoints !== void 0 && !(Array.isArray(data.loyaltyPoints) && data.loyaltyPoints.length === 0)) {
|
|
2671
|
+
return refuse18("twoc2p_loyalty_redemption");
|
|
2672
|
+
}
|
|
2673
|
+
if (!inOrder2(data, DATA_KEYS2) || data.paymentExpiry !== void 0)
|
|
2674
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2675
|
+
if (typeof data.securePayToken !== "string" || !isTwoC2pPageField(data.securePayToken, keyBytes))
|
|
2676
|
+
return refuse18("twoc2p_field_unreviewed");
|
|
2677
|
+
if (body.split(data.securePayToken).length !== 2)
|
|
2678
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2679
|
+
if (data.isIppChosen !== void 0 && data.isIppChosen !== false)
|
|
2680
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2681
|
+
if (details !== void 0 && !(record12(details) && (details.email === void 0 || text2(details.email, 254))))
|
|
2682
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2683
|
+
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))) {
|
|
2684
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2685
|
+
}
|
|
2686
|
+
for (const key of ["billingAddress1", "billingAddress2", "billingCity", "billingState", "billingPostalCode"]) {
|
|
2687
|
+
if (!optionalText(data[key], 128))
|
|
2688
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2689
|
+
}
|
|
2690
|
+
if (data.billingCountryCode !== void 0 && !(typeof data.billingCountryCode === "string" && /^[A-Za-z]{2}$/.test(data.billingCountryCode))) {
|
|
2691
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2692
|
+
}
|
|
2693
|
+
const risk = data.riskInfo;
|
|
2694
|
+
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)) {
|
|
2695
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2696
|
+
}
|
|
2697
|
+
return CARD17;
|
|
2698
|
+
}
|
|
2699
|
+
// src/hipay.js
|
|
2700
|
+
var HIPAY_PSP = "hipay";
|
|
2701
|
+
var HIPAY_TOKEN_URLS = /* @__PURE__ */ Object.freeze({
|
|
2702
|
+
production: "https://secure2-vault.hipay-tpp.com/rest/v2/token",
|
|
2703
|
+
sandbox: "https://stage-secure2-vault.hipay-tpp.com/rest/v2/token"
|
|
2704
|
+
});
|
|
2705
|
+
var BODY_LIMIT15 = 2048;
|
|
2706
|
+
var HOSTED_KEYS = /* @__PURE__ */ Object.freeze(["multi_use", "card_expiry_month", "card_expiry_year", "card_number", "card_holder", "cvc"]);
|
|
2707
|
+
var HOSTED_KEYS_NO_HOLDER = /* @__PURE__ */ Object.freeze(["multi_use", "card_expiry_month", "card_expiry_year", "card_number", "cvc"]);
|
|
2708
|
+
var DIRECT_KEYS = /* @__PURE__ */ Object.freeze(["card_expiry_month", "card_expiry_year", "card_number", "card_holder", "cvc", "multi_use"]);
|
|
2709
|
+
var DIRECT_KEYS_NO_HOLDER = /* @__PURE__ */ Object.freeze(["card_expiry_month", "card_expiry_year", "card_number", "cvc", "multi_use"]);
|
|
2710
|
+
var CARD_SHAPES = /* @__PURE__ */ Object.freeze([HOSTED_KEYS, HOSTED_KEYS_NO_HOLDER, DIRECT_KEYS, DIRECT_KEYS_NO_HOLDER]);
|
|
2711
|
+
var NUMBER_ONLY_KEYS = /* @__PURE__ */ Object.freeze(["multi_use", "card_expiry_month", "card_expiry_year", "card_number"]);
|
|
2712
|
+
var CARD_NUMBER10 = /^[0-9]{12,19}$/;
|
|
2713
|
+
var SECURITY_CODE12 = /^[0-9]{3,4}$/;
|
|
2714
|
+
var MONTH8 = /^(?:0[1-9]|1[0-2])$/;
|
|
2715
|
+
var YEAR8 = /^20[0-9]{2}$/;
|
|
2716
|
+
var TEXT_LIMIT3 = 256;
|
|
2717
|
+
var CONTROL7 = /[\u0000-\u001f\u007f]/;
|
|
2718
|
+
var record13 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2719
|
+
var sameKeys7 = (value, keys) => {
|
|
2720
|
+
const own3 = Object.keys(value);
|
|
2721
|
+
return own3.length === keys.length && own3.every((key, at) => key === keys[at]);
|
|
2722
|
+
};
|
|
2723
|
+
var plainText3 = (value) => typeof value === "string" && value.length <= TEXT_LIMIT3 && !CONTROL7.test(value) && (value.match(/[0-9]/g) ?? []).length < 12;
|
|
2724
|
+
var refuse19 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
2725
|
+
var CARD18 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
2726
|
+
function hipayTokenEnvironment(url) {
|
|
2727
|
+
if (url === HIPAY_TOKEN_URLS.production)
|
|
2728
|
+
return "production";
|
|
2729
|
+
if (url === HIPAY_TOKEN_URLS.sandbox)
|
|
2730
|
+
return "sandbox";
|
|
2731
|
+
return null;
|
|
2732
|
+
}
|
|
2733
|
+
function isHipayTokenUrl(url) {
|
|
2734
|
+
return hipayTokenEnvironment(url) !== null;
|
|
2735
|
+
}
|
|
2736
|
+
function readBody9(body) {
|
|
2737
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT15)
|
|
2738
|
+
return null;
|
|
2739
|
+
let value;
|
|
2740
|
+
try {
|
|
2741
|
+
value = JSON.parse(body);
|
|
2742
|
+
if (!record13(value) || JSON.stringify(value) !== body)
|
|
2743
|
+
return null;
|
|
2744
|
+
}
|
|
2745
|
+
catch {
|
|
2746
|
+
return null;
|
|
2747
|
+
}
|
|
2748
|
+
return value;
|
|
2749
|
+
}
|
|
2750
|
+
function hipayBodyVerdict(body) {
|
|
2751
|
+
const value = readBody9(body);
|
|
2752
|
+
if (value === null)
|
|
2753
|
+
return refuse19("hipay_body_unsupported");
|
|
2754
|
+
if (sameKeys7(value, NUMBER_ONLY_KEYS))
|
|
2755
|
+
return refuse19("hipay_number_only");
|
|
2756
|
+
if (!CARD_SHAPES.some((keys) => sameKeys7(value, keys)))
|
|
2757
|
+
return refuse19("hipay_body_unsupported");
|
|
2758
|
+
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)) {
|
|
2759
|
+
return refuse19("hipay_body_unsupported");
|
|
2760
|
+
}
|
|
2761
|
+
if (value.multi_use === 1)
|
|
2762
|
+
return refuse19("hipay_keeps_card");
|
|
2763
|
+
return value.multi_use === 0 ? CARD18 : refuse19("hipay_body_unsupported");
|
|
2764
|
+
}
|
|
2765
|
+
// src/amazon-payment-services.js
|
|
2766
|
+
var APS_PSP = "amazon_payment_services";
|
|
2767
|
+
var APS_HOSTS = /* @__PURE__ */ Object.freeze({ "checkout.payfort.com": "production", "sbcheckout.payfort.com": "sandbox" });
|
|
2768
|
+
var APS_TOKENIZATION_PATH = "/FortAPI/paymentPage";
|
|
2769
|
+
var APS_SIGNED_FIELDS = /* @__PURE__ */ Object.freeze([
|
|
2770
|
+
"service_command",
|
|
2771
|
+
"access_code",
|
|
2772
|
+
"merchant_identifier",
|
|
2773
|
+
"merchant_reference",
|
|
2774
|
+
"language",
|
|
2775
|
+
"return_url",
|
|
2776
|
+
"signature"
|
|
2777
|
+
]);
|
|
2778
|
+
var APS_CARD_FIELDS = /* @__PURE__ */ Object.freeze(["card_number", "expiry_date", "card_security_code"]);
|
|
2779
|
+
var APS_OPTIONAL_FIELDS = /* @__PURE__ */ Object.freeze(["card_holder_name", "remember_me"]);
|
|
2780
|
+
var URL_LIMIT7 = 2048;
|
|
2781
|
+
var BODY_LIMIT16 = 32 * 1024;
|
|
2782
|
+
var exact = (pattern, value) => typeof value === "string" && pattern.exec(value)?.[0] === value;
|
|
2783
|
+
var controlFree = (value, max) => typeof value === "string" && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
|
|
2784
|
+
var SHAPES = /* @__PURE__ */ new Map([
|
|
2785
|
+
["service_command", (v) => v === "TOKENIZATION"],
|
|
2786
|
+
["access_code", (v) => exact(/^[A-Za-z0-9]{1,20}$/, v)],
|
|
2787
|
+
["merchant_identifier", (v) => exact(/^[A-Za-z0-9]{1,20}$/, v)],
|
|
2788
|
+
["merchant_reference", (v) => exact(/^[A-Za-z0-9._-]{1,40}$/, v)],
|
|
2789
|
+
["language", (v) => v === "en" || v === "ar"],
|
|
2790
|
+
// Hex SHA-256 (APS's default), SHA-512, or the 40 characters of the SHA-1 APS calls SHA-128.
|
|
2791
|
+
["signature", (v) => exact(/^(?:[0-9A-Fa-f]{40}|[0-9A-Fa-f]{64}|[0-9A-Fa-f]{128})$/, v)],
|
|
2792
|
+
["card_number", (v) => exact(/^[0-9]{12,19}$/, v)],
|
|
2793
|
+
["expiry_date", (v) => exact(/^[0-9]{2}(?:0[1-9]|1[0-2])$/, v)],
|
|
2794
|
+
["card_security_code", (v) => exact(/^[0-9]{3,4}$/, v)],
|
|
2795
|
+
["card_holder_name", (v) => controlFree(v, 255)],
|
|
2796
|
+
["remember_me", (v) => v === "YES" || v === "NO"]
|
|
2797
|
+
]);
|
|
2798
|
+
function apsTokenizationUrl(url) {
|
|
2799
|
+
if (typeof url !== "string" || url.length > URL_LIMIT7 || url.includes("?") || url.includes("#"))
|
|
2800
|
+
return null;
|
|
2801
|
+
let parsed;
|
|
2802
|
+
try {
|
|
2803
|
+
parsed = new URL(url);
|
|
2804
|
+
}
|
|
2805
|
+
catch {
|
|
2806
|
+
return null;
|
|
2807
|
+
}
|
|
2808
|
+
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))
|
|
2809
|
+
return null;
|
|
2810
|
+
return Object.freeze({ host: parsed.hostname, environment: APS_HOSTS[parsed.hostname] });
|
|
2811
|
+
}
|
|
2812
|
+
function formEncode2(value) {
|
|
2813
|
+
let encoded;
|
|
2814
|
+
try {
|
|
2815
|
+
encoded = encodeURIComponent(value);
|
|
2816
|
+
}
|
|
2817
|
+
catch {
|
|
2818
|
+
return null;
|
|
2819
|
+
}
|
|
2820
|
+
return encoded.replace(/[!'()~]/g, (ch) => `%${ch.charCodeAt(0).toString(16).toUpperCase()}`).replace(/%20/g, "+");
|
|
2821
|
+
}
|
|
2822
|
+
function formDecode(raw) {
|
|
2823
|
+
if (!/^(?:[A-Za-z0-9*._+-]|%[0-9A-F]{2})*$/.test(raw))
|
|
2824
|
+
return null;
|
|
2825
|
+
let value;
|
|
2826
|
+
try {
|
|
2827
|
+
value = decodeURIComponent(raw.replace(/\+/g, "%20"));
|
|
2828
|
+
}
|
|
2829
|
+
catch {
|
|
2830
|
+
return null;
|
|
2831
|
+
}
|
|
2832
|
+
return formEncode2(value) === raw ? value : null;
|
|
2833
|
+
}
|
|
2834
|
+
function parseForm(body) {
|
|
2835
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT16)
|
|
2836
|
+
return null;
|
|
2837
|
+
const pairs = [];
|
|
2838
|
+
const values = /* @__PURE__ */ new Map();
|
|
2839
|
+
for (const chunk of body.split("&")) {
|
|
2840
|
+
const separator = chunk.indexOf("=");
|
|
2841
|
+
if (separator < 1)
|
|
2842
|
+
return null;
|
|
2843
|
+
const rawName = chunk.slice(0, separator), raw = chunk.slice(separator + 1);
|
|
2844
|
+
const name = formDecode(rawName), value = formDecode(raw);
|
|
2845
|
+
if (name === null || value === null || values.has(name))
|
|
2846
|
+
return null;
|
|
2847
|
+
pairs.push({ name, rawName, raw, value });
|
|
2848
|
+
values.set(name, value);
|
|
2849
|
+
}
|
|
2850
|
+
return { pairs, values };
|
|
2851
|
+
}
|
|
2852
|
+
function returnUrlAdmitted(value) {
|
|
2853
|
+
if (typeof value !== "string" || value.length > 400 || value.includes("#") || /[\u0000- \u007f]/.test(value))
|
|
2854
|
+
return false;
|
|
2855
|
+
let parsed;
|
|
2856
|
+
try {
|
|
2857
|
+
parsed = new URL(value);
|
|
2858
|
+
}
|
|
2859
|
+
catch {
|
|
2860
|
+
return false;
|
|
2861
|
+
}
|
|
2862
|
+
return parsed.protocol === "https:" && !parsed.username && !parsed.password && parsed.href === value;
|
|
2863
|
+
}
|
|
2864
|
+
function apsBodyRefusal(body) {
|
|
2865
|
+
const form = parseForm(body);
|
|
2866
|
+
if (!form)
|
|
2867
|
+
return "aps_body_unsupported";
|
|
2868
|
+
const has = (name) => form.values.has(name);
|
|
2869
|
+
if (has("token_name"))
|
|
2870
|
+
return "aps_saved_card_refused";
|
|
2871
|
+
if ([...form.values.keys()].some((name) => /^merchant_extra[1-5]?$|^agreement_id$|^recurring_/.test(name)))
|
|
2872
|
+
return "aps_recurring_refused";
|
|
2873
|
+
if (has("service_command") && form.values.get("service_command") !== "TOKENIZATION")
|
|
2874
|
+
return "aps_service_command_refused";
|
|
2875
|
+
const allowed = /* @__PURE__ */ new Set([...APS_SIGNED_FIELDS, ...APS_CARD_FIELDS, ...APS_OPTIONAL_FIELDS]);
|
|
2876
|
+
if (form.pairs.some(({ name }) => !allowed.has(name)))
|
|
2877
|
+
return "aps_body_unsupported";
|
|
2878
|
+
if (!returnUrlAdmitted(form.values.get("return_url")))
|
|
2879
|
+
return "aps_return_url_refused";
|
|
2880
|
+
for (const name of [...APS_SIGNED_FIELDS, ...APS_CARD_FIELDS]) {
|
|
2881
|
+
if (name !== "return_url" && !SHAPES.get(name)(form.values.get(name)))
|
|
2882
|
+
return "aps_body_unsupported";
|
|
2883
|
+
}
|
|
2884
|
+
for (const name of APS_OPTIONAL_FIELDS) {
|
|
2885
|
+
if (has(name) && !SHAPES.get(name)(form.values.get(name)))
|
|
2886
|
+
return "aps_body_unsupported";
|
|
2887
|
+
}
|
|
2888
|
+
return null;
|
|
2889
|
+
}
|
|
2890
|
+
function apsBodyVerdict(body, url) {
|
|
2891
|
+
if (url !== void 0 && !apsTokenizationUrl(url))
|
|
2892
|
+
return { verdict: "refuse", code: "aps_url_refused" };
|
|
2893
|
+
const form = parseForm(body);
|
|
2894
|
+
const names = form ? [...form.values.keys()] : typeof body === "string" ? body.split("&").map((chunk) => {
|
|
2895
|
+
try {
|
|
2896
|
+
return decodeURIComponent(chunk.split("=")[0].replace(/\+/g, " "));
|
|
2897
|
+
}
|
|
2898
|
+
catch {
|
|
2899
|
+
return APS_CARD_FIELDS[0];
|
|
2900
|
+
}
|
|
2901
|
+
}) : [APS_CARD_FIELDS[0]];
|
|
2902
|
+
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));
|
|
2903
|
+
if (!mentionsCard && !names.some((name) => APS_CARD_FIELDS.includes(name.trim().toLowerCase())))
|
|
2904
|
+
return { verdict: "continue" };
|
|
2905
|
+
const code = apsBodyRefusal(body);
|
|
2906
|
+
return code ? { verdict: "refuse", code } : { verdict: "card" };
|
|
2907
|
+
}
|
|
2908
|
+
var ANSWER_LIMIT = 64 * 1024;
|
|
2461
2909
|
// src/card-fields.js
|
|
2462
2910
|
function processorGate(recognizer, url, body) {
|
|
2463
2911
|
if (recognizer && recognizer.psp === LYRA_PSP)
|
|
@@ -2469,6 +2917,11 @@ function processorGate(recognizer, url, body) {
|
|
|
2469
2917
|
}
|
|
2470
2918
|
if (recognizer && recognizer.psp === KOMOJU_PSP)
|
|
2471
2919
|
return komojuBodyVerdict(body, url);
|
|
2920
|
+
if (recognizer && recognizer.psp === HIPAY_PSP) {
|
|
2921
|
+
if (url !== void 0 && !isHipayTokenUrl(url))
|
|
2922
|
+
return { verdict: "refuse", code: "hipay_url_refused" };
|
|
2923
|
+
return hipayBodyVerdict(body);
|
|
2924
|
+
}
|
|
2472
2925
|
if (recognizer && recognizer.psp === PADDLE_VGS_PSP) {
|
|
2473
2926
|
if (url !== void 0 && !isPaddleVgsCardsUrl(url))
|
|
2474
2927
|
return { verdict: "refuse", code: "paddle_vgs_url_refused" };
|
|
@@ -2490,6 +2943,19 @@ function processorGate(recognizer, url, body) {
|
|
|
2490
2943
|
return { verdict: "refuse", code: "pay_nl_url_refused" };
|
|
2491
2944
|
return payNlBodyVerdict(body);
|
|
2492
2945
|
}
|
|
2946
|
+
if (recognizer && recognizer.psp === TWOC2P_PSP) {
|
|
2947
|
+
if (url === void 0)
|
|
2948
|
+
return twoC2pBodyVerdict(body);
|
|
2949
|
+
const target = twoC2pPaymentTarget(url);
|
|
2950
|
+
if (target === null)
|
|
2951
|
+
return { verdict: "refuse", code: "twoc2p_url_refused" };
|
|
2952
|
+
if (!target.reviewed)
|
|
2953
|
+
return twoC2pPaymentCarriesCard(body) ? { verdict: "refuse", code: "twoc2p_build_unreviewed" } : { verdict: "continue" };
|
|
2954
|
+
const keyBytes = twoC2pKeyBytes(target.environment);
|
|
2955
|
+
return keyBytes === null ? { verdict: "refuse", code: "twoc2p_field_unreviewed" } : twoC2pBodyVerdict(body, keyBytes, target.environment);
|
|
2956
|
+
}
|
|
2957
|
+
if (recognizer && recognizer.psp === APS_PSP)
|
|
2958
|
+
return apsBodyVerdict(body, url);
|
|
2493
2959
|
if (recognizer && recognizer.psp === PADDLE_TOKENEX_PSP) {
|
|
2494
2960
|
const target = url !== void 0 ? paddleTokenexPayTarget(url) : null;
|
|
2495
2961
|
if (url !== void 0 && target === null)
|
|
@@ -2631,20 +3097,20 @@ var KEEP_ON_FILE_REFUSAL = "Refusing to pay: this Primer payment would keep the
|
|
|
2631
3097
|
var UNSUPPORTED_SDK_REFUSAL = "Refusing to pay: this checkout uses a Primer SDK Agentcard does not support yet. Nothing was sent.";
|
|
2632
3098
|
var NETWORK_MISMATCH_REFUSAL = "Refusing to pay: this Primer payment names a card network that is not your card's. Nothing was sent.";
|
|
2633
3099
|
var FILL_REFUSAL = "Could not fill the card fields for Primer. Nothing was sent.";
|
|
2634
|
-
var
|
|
3100
|
+
var BODY_LIMIT17 = 16384;
|
|
2635
3101
|
var RESPONSE_LIMIT = 32768;
|
|
2636
|
-
var
|
|
3102
|
+
var ROOT_KEYS7 = ["paymentInstrument", "userDescription", "tokenType", "paymentFlow"];
|
|
2637
3103
|
var INSTRUMENT_KEYS = ["number", "cvv", "expirationMonth", "expirationYear", "cardholderName", "preferredNetwork"];
|
|
2638
3104
|
var REQUIRED_INSTRUMENT_KEYS = ["number", "cvv", "expirationMonth", "expirationYear"];
|
|
2639
|
-
var
|
|
3105
|
+
var record14 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2640
3106
|
var owns5 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
2641
|
-
var
|
|
2642
|
-
var
|
|
3107
|
+
var exact2 = (pattern, value) => typeof value === "string" && pattern.exec(value)?.[0] === value;
|
|
3108
|
+
var text3 = (value, max) => typeof value === "string" && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
|
|
2643
3109
|
var digits = (value, min, max) => typeof value === "string" && value.length >= min && value.length <= max && !/[^0-9]/.test(value);
|
|
2644
3110
|
var panLike = (value) => /(?:[0-9][ _.:-]*){12,}/.test(value);
|
|
2645
|
-
var plain = (value, max) =>
|
|
2646
|
-
var
|
|
2647
|
-
var
|
|
3111
|
+
var plain = (value, max) => text3(value, max) && !panLike(value);
|
|
3112
|
+
var MONTH9 = /^(?:0[1-9]|1[0-2])$/;
|
|
3113
|
+
var YEAR9 = /^20[0-9]{2}$/;
|
|
2648
3114
|
var NETWORK2 = /^[A-Z][A-Z_]{1,31}$/;
|
|
2649
3115
|
function isPrimerTokenizeUrl(url, method = "POST") {
|
|
2650
3116
|
if (method !== "POST" || typeof url !== "string" || url.length > 256 || url.includes("?") || url.includes("#"))
|
|
@@ -2659,7 +3125,7 @@ function isPrimerTokenizeUrl(url, method = "POST") {
|
|
|
2659
3125
|
return parsed.href === url && parsed.protocol === "https:" && !parsed.port && !parsed.username && !parsed.password && !parsed.search && !parsed.hash && PRIMER_PCI_HOSTS.includes(parsed.hostname) && parsed.pathname === PRIMER_TOKENIZE_PATH;
|
|
2660
3126
|
}
|
|
2661
3127
|
function judgeBody4(body) {
|
|
2662
|
-
if (typeof body !== "string" || body === "" || body.length >
|
|
3128
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT17)
|
|
2663
3129
|
return null;
|
|
2664
3130
|
let value;
|
|
2665
3131
|
try {
|
|
@@ -2668,16 +3134,16 @@ function judgeBody4(body) {
|
|
|
2668
3134
|
catch {
|
|
2669
3135
|
return null;
|
|
2670
3136
|
}
|
|
2671
|
-
if (!
|
|
3137
|
+
if (!record14(value) || !roundTrips(value, body))
|
|
2672
3138
|
return null;
|
|
2673
|
-
if (!Object.keys(value).every((key) =>
|
|
3139
|
+
if (!Object.keys(value).every((key) => ROOT_KEYS7.includes(key)) || !owns5(value, "paymentInstrument"))
|
|
2674
3140
|
return null;
|
|
2675
3141
|
const instrument = value.paymentInstrument;
|
|
2676
|
-
if (!
|
|
3142
|
+
if (!record14(instrument) || !Object.keys(instrument).every((key) => INSTRUMENT_KEYS.includes(key)) || !REQUIRED_INSTRUMENT_KEYS.every((key) => owns5(instrument, key)))
|
|
2677
3143
|
return null;
|
|
2678
|
-
if (!digits(instrument.number, 12, 19) || !digits(instrument.cvv, 3, 4) || !
|
|
3144
|
+
if (!digits(instrument.number, 12, 19) || !digits(instrument.cvv, 3, 4) || !exact2(MONTH9, instrument.expirationMonth) || !exact2(YEAR9, instrument.expirationYear))
|
|
2679
3145
|
return null;
|
|
2680
|
-
if (owns5(instrument, "cardholderName") && instrument.cardholderName !== null && !plain(instrument.cardholderName, 256) || owns5(instrument, "preferredNetwork") && instrument.preferredNetwork !== null && !
|
|
3146
|
+
if (owns5(instrument, "cardholderName") && instrument.cardholderName !== null && !plain(instrument.cardholderName, 256) || owns5(instrument, "preferredNetwork") && instrument.preferredNetwork !== null && !exact2(NETWORK2, instrument.preferredNetwork) || owns5(value, "userDescription") && value.userDescription !== null && !plain(value.userDescription, 256) || owns5(value, "tokenType") && value.tokenType !== "MULTI_USE" || owns5(value, "paymentFlow") && value.paymentFlow !== "VAULT")
|
|
2681
3147
|
return null;
|
|
2682
3148
|
return { value, keepOnFile: owns5(value, "tokenType") || owns5(value, "paymentFlow") };
|
|
2683
3149
|
}
|
|
@@ -2701,7 +3167,7 @@ var CLIENT_TOKEN = /^[A-Za-z0-9._~+/=-]{16,4096}$/;
|
|
|
2701
3167
|
var REQUEST_ID = /^[A-Za-z0-9-]{1,64}$/;
|
|
2702
3168
|
var API_VERSION = /^2\.[0-9]{1,2}$/;
|
|
2703
3169
|
function readHeaders(headers) {
|
|
2704
|
-
if (!
|
|
3170
|
+
if (!record14(headers))
|
|
2705
3171
|
return null;
|
|
2706
3172
|
const folded = /* @__PURE__ */ new Map();
|
|
2707
3173
|
for (const [name, value] of Object.entries(headers)) {
|
|
@@ -2719,9 +3185,9 @@ function headersRefusal(headers) {
|
|
|
2719
3185
|
const version = folded.get("primer-sdk-version");
|
|
2720
3186
|
if (typeof version !== "string")
|
|
2721
3187
|
return "unsupported";
|
|
2722
|
-
if (!
|
|
3188
|
+
if (!exact2(LEGACY_SDK_VERSION, version))
|
|
2723
3189
|
return "unsupported_sdk";
|
|
2724
|
-
if (!
|
|
3190
|
+
if (!exact2(CONTENT_TYPE2, folded.get("content-type")) || !exact2(CLIENT_TOKEN, folded.get("primer-client-token")) || folded.has("primer-sdk-client") && folded.get("primer-sdk-client") !== "WEB" || folded.has("x-api-version") && !exact2(API_VERSION, folded.get("x-api-version")) || folded.has("primer-sdk-checkout-session-id") && !exact2(REQUEST_ID, folded.get("primer-sdk-checkout-session-id")) || folded.has("x-request-id") && !exact2(REQUEST_ID, folded.get("x-request-id")))
|
|
2725
3191
|
return "unsupported";
|
|
2726
3192
|
return null;
|
|
2727
3193
|
}
|
|
@@ -2748,7 +3214,7 @@ function onTokenizePath(url) {
|
|
|
2748
3214
|
}
|
|
2749
3215
|
}
|
|
2750
3216
|
function primerTokenizeRefusal(request) {
|
|
2751
|
-
if (!
|
|
3217
|
+
if (!record14(request) || request.method !== "POST" || !isPrimerTokenizeUrl(request.url))
|
|
2752
3218
|
return "unsupported";
|
|
2753
3219
|
return headersRefusal(request.headers) ?? primerBodyRefusal(request.body);
|
|
2754
3220
|
}
|
|
@@ -2763,7 +3229,7 @@ function primerCardOnFileRefusal(url, options, policy = PRIMER_SESSION_CARD_ON_F
|
|
|
2763
3229
|
return "unsupported";
|
|
2764
3230
|
if (new URL(url).hostname !== LIVE_PCI_HOST)
|
|
2765
3231
|
return null;
|
|
2766
|
-
return primerCardOnFileDisclosure(url, policy) &&
|
|
3232
|
+
return primerCardOnFileDisclosure(url, policy) && record14(options) && options.keepOnFile === true ? null : "keep_on_file";
|
|
2767
3233
|
}
|
|
2768
3234
|
function primerRefusalMessage(reason) {
|
|
2769
3235
|
if (reason === "keep_on_file")
|
|
@@ -2847,25 +3313,25 @@ function readAnswer(body) {
|
|
|
2847
3313
|
return null;
|
|
2848
3314
|
try {
|
|
2849
3315
|
const value = JSON.parse(body);
|
|
2850
|
-
return
|
|
3316
|
+
return record14(value) ? value : null;
|
|
2851
3317
|
}
|
|
2852
3318
|
catch {
|
|
2853
3319
|
return null;
|
|
2854
3320
|
}
|
|
2855
3321
|
}
|
|
2856
|
-
var tokenValue = (value) =>
|
|
3322
|
+
var tokenValue = (value) => exact2(TOKEN3, value) && !panLike(value);
|
|
2857
3323
|
var optional = (value, key, check) => !owns5(value, key) || value[key] === null || check(value[key]);
|
|
2858
3324
|
function cardDetails(data) {
|
|
2859
|
-
if (!
|
|
3325
|
+
if (!record14(data) || !exact2(/^[0-9]{4}$/, data.last4Digits))
|
|
2860
3326
|
return null;
|
|
2861
|
-
if (!optional(data, "first6Digits", (v) =>
|
|
3327
|
+
if (!optional(data, "first6Digits", (v) => exact2(/^[0-9]{6}$/, v)) || !optional(data, "expirationMonth", (v) => exact2(RESPONSE_MONTH, v)) || !optional(data, "expirationYear", (v) => exact2(RESPONSE_YEAR, v)) || !optional(data, "cardholderName", (v) => plain(v, 256)) || !optional(data, "network", (v) => exact2(NETWORK_NAME, v)) || !optional(data, "isNetworkTokenized", (v) => typeof v === "boolean") || !optional(data, "binData", record14))
|
|
2862
3328
|
return null;
|
|
2863
3329
|
const safe = { last4Digits: data.last4Digits };
|
|
2864
3330
|
for (const key of ["first6Digits", "expirationMonth", "expirationYear", "cardholderName", "network", "isNetworkTokenized"]) {
|
|
2865
3331
|
if (owns5(data, key) && data[key] !== null)
|
|
2866
3332
|
safe[key] = data[key];
|
|
2867
3333
|
}
|
|
2868
|
-
if (
|
|
3334
|
+
if (record14(data.binData)) {
|
|
2869
3335
|
const bin = {};
|
|
2870
3336
|
for (const key of BIN_KEYS) {
|
|
2871
3337
|
if (!owns5(data.binData, key) || data.binData[key] === null)
|
|
@@ -2881,7 +3347,7 @@ function cardDetails(data) {
|
|
|
2881
3347
|
function threeDsSummary(value) {
|
|
2882
3348
|
if (value === void 0 || value === null)
|
|
2883
3349
|
return null;
|
|
2884
|
-
if (!
|
|
3350
|
+
if (!record14(value) || !exact2(CODE3, value.responseCode) || !optional(value, "reasonCode", (v) => exact2(CODE3, v)) || !optional(value, "reasonText", (v) => plain(v, 256)) || !optional(value, "protocolVersion", (v) => v === "" || exact2(PROTOCOL, v)) || !optional(value, "challengeIssued", (v) => typeof v === "boolean"))
|
|
2885
3351
|
return void 0;
|
|
2886
3352
|
const safe = { responseCode: value.responseCode };
|
|
2887
3353
|
for (const key of ["reasonCode", "reasonText", "protocolVersion", "challengeIssued"]) {
|
|
@@ -2909,8 +3375,8 @@ function rebuildToken(value) {
|
|
|
2909
3375
|
}
|
|
2910
3376
|
function primerErrorId(body) {
|
|
2911
3377
|
const value = readAnswer(body);
|
|
2912
|
-
const id = value &&
|
|
2913
|
-
return
|
|
3378
|
+
const id = value && record14(value.error) ? value.error.errorId : null;
|
|
3379
|
+
return exact2(ERROR_ID, id) && !panLike(id) ? id : null;
|
|
2914
3380
|
}
|
|
2915
3381
|
function matchesCard(details, card) {
|
|
2916
3382
|
const number = card && typeof card.number === "string" ? card.number : "";
|