@agent-cards/sdk 0.23.27 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/PREFLIGHT.md +7 -1
- package/README.md +137 -99
- package/dist/aci.d.ts +52 -22
- package/dist/aci.js +79 -15
- package/dist/adyen-merchant-hosted.generated.d.ts +1 -1
- package/dist/adyen-merchant-hosted.generated.js +459 -21
- package/dist/agent-amount.generated.js +1 -1
- package/dist/agentcard.d.ts +4 -5
- package/dist/agentcard.js +4 -5
- package/dist/amadeus.d.ts +9 -3
- package/dist/amadeus.js +33 -4
- package/dist/api-module.d.ts +1 -7
- package/dist/api-module.js +3 -5
- package/dist/{voice-retry.js → api-retry.js} +1 -1
- package/dist/api-types.d.ts +53 -0
- package/dist/{voice-types.js → api-types.js} +7 -2
- package/dist/approvals.d.ts +166 -0
- package/dist/approvals.js +213 -0
- package/dist/buy.d.ts +20 -101
- package/dist/buy.js +19 -74
- package/dist/capabilities.generated.js +1 -1
- package/dist/card-fields.generated.js +1398 -106
- package/dist/cdp.d.ts +3 -13
- package/dist/cdp.js +231 -175
- package/dist/client.d.ts +104 -22
- package/dist/client.js +215 -40
- package/dist/creditguard.generated.d.ts +4 -4
- package/dist/datatrans.generated.js +22 -1
- package/dist/elavon-converge.generated.js +5 -3
- package/dist/hold.d.ts +8 -0
- package/dist/hold.js +43 -2
- package/dist/hosted-entry.js +2 -0
- package/dist/index.d.ts +9 -15
- package/dist/index.js +6 -10
- package/dist/juspay-gate.js +2 -2
- package/dist/juspay.generated.d.ts +2 -2
- package/dist/juspay.generated.js +174 -4
- package/dist/lifecycle.d.ts +9 -61
- package/dist/lifecycle.js +24 -10
- package/dist/merchant-card-endpoints.generated.d.ts +6 -1
- package/dist/merchant-card-endpoints.generated.js +344 -19
- package/dist/merchant-hosted.d.ts +8 -1
- package/dist/nike-order.d.ts +51 -0
- package/dist/nike-order.js +81 -0
- package/dist/oceanpayment.d.ts +38 -0
- package/dist/oceanpayment.js +70 -0
- package/dist/paddle-tokenex.generated.js +105 -10
- package/dist/payplug.d.ts +41 -0
- package/dist/payplug.js +71 -0
- package/dist/payrails.generated.js +27 -7
- package/dist/payrexx.generated.js +176 -2
- package/dist/pre-claim.d.ts +9 -0
- package/dist/pre-claim.js +86 -7
- package/dist/preflight-capabilities.generated.d.ts +0 -4
- package/dist/preflight-capabilities.generated.js +0 -5
- package/dist/preflight-catalog.json +46 -5
- package/dist/preflight-playwright.d.ts +2 -2
- package/dist/preflight-playwright.js +63 -14
- package/dist/preflight-schemas.json +4 -0
- package/dist/preflight.generated.d.ts +0 -4
- package/dist/preflight.generated.js +24 -1
- package/dist/prepared-processor.d.ts +18 -5
- package/dist/prepared-processor.js +48 -8
- package/dist/primer.generated.js +1418 -120
- package/dist/processout.generated.d.ts +61 -0
- package/dist/processout.generated.js +577 -0
- package/dist/requests.js +1 -1
- package/dist/shiji-sts.generated.js +105 -10
- package/dist/stripe-checkout.generated.js +1405 -234
- package/dist/substitutions.generated.js +460 -26
- package/dist/tap-payments.generated.js +105 -10
- package/dist/twoc2p.generated.js +105 -10
- package/dist/url-masks/bluesnap.d.ts +2 -0
- package/dist/url-masks/bluesnap.js +15 -0
- package/dist/url-masks/oceanpayment.d.ts +2 -0
- package/dist/url-masks/oceanpayment.js +13 -0
- package/dist/url-masks/payplug.d.ts +2 -0
- package/dist/url-masks/payplug.js +13 -0
- package/dist/url-masks/vtex_payments.d.ts +2 -0
- package/dist/url-masks/vtex_payments.js +12 -0
- package/dist/url-masks.generated.d.ts +1 -1
- package/dist/url-masks.generated.js +6 -2
- package/dist/verifone.generated.js +42 -2
- package/dist/vtex-payments.generated.d.ts +127 -0
- package/dist/vtex-payments.generated.js +544 -0
- package/dist/webhooks.d.ts +2 -2
- package/dist/webhooks.js +2 -2
- package/dist/wspay.generated.d.ts +1 -1
- package/dist/wspay.generated.js +175 -3
- package/examples/preflight/kernel-native/inventory.json +1 -1
- package/package.json +6 -8
- package/dist/languages.d.ts +0 -23
- package/dist/languages.js +0 -76
- package/dist/voice-pkce.d.ts +0 -49
- package/dist/voice-pkce.js +0 -147
- package/dist/voice-stream.generated.d.ts +0 -118
- package/dist/voice-stream.generated.js +0 -170
- package/dist/voice-types.d.ts +0 -735
- package/dist/voice.d.ts +0 -373
- package/dist/voice.js +0 -815
- package/readme.test.mjs +0 -53
- /package/dist/{voice-retry.d.ts → api-retry.d.ts} +0 -0
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: e27ad846d6a41b2ebe25fee25b50db7b41665063aa2b912c4bc63f8b2ed5b9c4
|
|
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
|
|
@@ -365,8 +365,8 @@ var CONTROL = /[\u0000-\u001f\u007f]/;
|
|
|
365
365
|
var cardLikeName = (name) => (name.match(/[0-9]/g) ?? []).length >= 12;
|
|
366
366
|
var record3 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
367
367
|
var sameKeys = (value, keys) => {
|
|
368
|
-
const
|
|
369
|
-
return
|
|
368
|
+
const own19 = Object.keys(value);
|
|
369
|
+
return own19.length === keys.length && own19.every((key, at) => key === keys[at]);
|
|
370
370
|
};
|
|
371
371
|
var refuse4 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
372
372
|
var CARD4 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
@@ -721,13 +721,13 @@ function readElement(der, at, tag) {
|
|
|
721
721
|
let length = der[at + 1];
|
|
722
722
|
let start = at + 2;
|
|
723
723
|
if (length & 128) {
|
|
724
|
-
const
|
|
725
|
-
if (
|
|
724
|
+
const count2 = length & 127;
|
|
725
|
+
if (count2 === 0 || count2 > 2 || start + count2 > der.length || der[start] === 0)
|
|
726
726
|
throw refuse6("key");
|
|
727
|
-
length =
|
|
727
|
+
length = count2 === 1 ? der[start] : der[start] * 256 + der[start + 1];
|
|
728
728
|
if (length < 128)
|
|
729
729
|
throw refuse6("key");
|
|
730
|
-
start +=
|
|
730
|
+
start += count2;
|
|
731
731
|
}
|
|
732
732
|
if (start + length > der.length)
|
|
733
733
|
throw refuse6("key");
|
|
@@ -779,8 +779,8 @@ var PADDLE_TOKENEX_PSP = "paddle_tokenex";
|
|
|
779
779
|
var PADDLE_TOKENEX_FACT_KEYS = /* @__PURE__ */ Object.freeze(["card_first_six", "card_last_four", "expiry_month", "expiry_year", "card_brand"]);
|
|
780
780
|
var record4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
781
781
|
var sameKeys2 = (value, keys) => {
|
|
782
|
-
const
|
|
783
|
-
return
|
|
782
|
+
const own19 = Object.keys(value);
|
|
783
|
+
return own19.length === keys.length && own19.every((key, at) => key === keys[at]);
|
|
784
784
|
};
|
|
785
785
|
var refuse7 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
786
786
|
var CARD6 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
@@ -850,8 +850,8 @@ function readPay(body, line, environment2) {
|
|
|
850
850
|
const card = record4(method) && sameKeys2(method, ["card"]) ? method.card : null;
|
|
851
851
|
if (!record4(card) || !(sameKeys2(card, PAY_CARD_KEYS) || sameKeys2(card, [...PAY_CARD_KEYS, "session_tracking"])))
|
|
852
852
|
return null;
|
|
853
|
-
const
|
|
854
|
-
if (!record4(
|
|
853
|
+
const metadata2 = card.metadata;
|
|
854
|
+
if (!record4(metadata2) || !sameKeys2(metadata2, METADATA_KEYS2) || typeof metadata2.cardholder_name !== "string" || metadata2.cardholder_name.length > NAME_LIMIT2 || CONTROL2.test(metadata2.cardholder_name) || cardLikeName2(metadata2.cardholder_name) || typeof metadata2.card_first_six !== "string" || !FIRST_SIX.test(metadata2.card_first_six) || typeof metadata2.card_last_four !== "string" || !LAST_FOUR.test(metadata2.card_last_four) || !expiryMonth(metadata2.expiry_month) || !expiryYear(metadata2.expiry_year) || !FRAME_BRANDS.includes(metadata2.card_brand))
|
|
855
855
|
return null;
|
|
856
856
|
const details = card.three_d_s;
|
|
857
857
|
if (!record4(details) || !sameKeys2(details, ["browser_info"]) || typeof details.browser_info !== "string" || !BROWSER_INFO.test(details.browser_info))
|
|
@@ -1269,8 +1269,8 @@ var TEXT_LIMIT = 256;
|
|
|
1269
1269
|
var CONTROL4 = /[\u0000-\u001f\u007f]/;
|
|
1270
1270
|
var record6 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1271
1271
|
var sameKeys3 = (value, keys) => {
|
|
1272
|
-
const
|
|
1273
|
-
return
|
|
1272
|
+
const own19 = Object.keys(value);
|
|
1273
|
+
return own19.length === keys.length && own19.every((key, at) => key === keys[at]);
|
|
1274
1274
|
};
|
|
1275
1275
|
var plainText = (value) => typeof value === "string" && value.length <= TEXT_LIMIT && !CONTROL4.test(value) && (value.match(/[0-9]/g) ?? []).length < 12;
|
|
1276
1276
|
var refuse9 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
@@ -1300,13 +1300,13 @@ function billingFields(value) {
|
|
|
1300
1300
|
if (names.length > MAX_FIELDS)
|
|
1301
1301
|
return false;
|
|
1302
1302
|
return names.every((name) => {
|
|
1303
|
-
const
|
|
1303
|
+
const field3 = value[name];
|
|
1304
1304
|
if (!FIELD_NAME.test(name))
|
|
1305
1305
|
return false;
|
|
1306
|
-
if (!record6(
|
|
1307
|
-
return billingText(
|
|
1308
|
-
const nested = Object.keys(
|
|
1309
|
-
return nested.length <= MAX_NESTED_FIELDS && nested.every((key) => FIELD_NAME.test(key) && billingText(
|
|
1306
|
+
if (!record6(field3))
|
|
1307
|
+
return billingText(field3);
|
|
1308
|
+
const nested = Object.keys(field3);
|
|
1309
|
+
return nested.length <= MAX_NESTED_FIELDS && nested.every((key) => FIELD_NAME.test(key) && billingText(field3[key]));
|
|
1310
1310
|
});
|
|
1311
1311
|
}
|
|
1312
1312
|
function wixPaymentsBodyVerdict(body) {
|
|
@@ -1380,14 +1380,14 @@ function readJson2(body) {
|
|
|
1380
1380
|
catch {
|
|
1381
1381
|
return { parsed: null, exact: false };
|
|
1382
1382
|
}
|
|
1383
|
-
let
|
|
1383
|
+
let exact6 = false;
|
|
1384
1384
|
try {
|
|
1385
|
-
|
|
1385
|
+
exact6 = body.length <= BODY_LIMIT6 && JSON.stringify(parsed) === body;
|
|
1386
1386
|
}
|
|
1387
1387
|
catch {
|
|
1388
|
-
|
|
1388
|
+
exact6 = false;
|
|
1389
1389
|
}
|
|
1390
|
-
return { parsed, exact:
|
|
1390
|
+
return { parsed, exact: exact6 };
|
|
1391
1391
|
}
|
|
1392
1392
|
function billingValue(value) {
|
|
1393
1393
|
if (value === UNDEFINED)
|
|
@@ -1401,15 +1401,15 @@ function judgeCardAttach(args, session) {
|
|
|
1401
1401
|
return "paymongo_body_unsupported";
|
|
1402
1402
|
}
|
|
1403
1403
|
const id = args[0].slice(3);
|
|
1404
|
-
const
|
|
1405
|
-
const details =
|
|
1404
|
+
const attributes2 = args[1].data.attributes;
|
|
1405
|
+
const details = attributes2.details;
|
|
1406
1406
|
if (record7(details) && CLICK_TO_PAY_KEYS.some((key) => own(details, key)))
|
|
1407
1407
|
return "paymongo_click_to_pay";
|
|
1408
|
-
if (!keysAre(args[1], ["data"]) || !keysAre(args[1].data, ["attributes"]) || !keysAre(
|
|
1408
|
+
if (!keysAre(args[1], ["data"]) || !keysAre(args[1].data, ["attributes"]) || !keysAre(attributes2, PAYMONGO_ATTRIBUTE_KEYS) || !record7(details) || !keysAre(details, PAYMONGO_CARD_KEYS))
|
|
1409
1409
|
return "paymongo_body_unsupported";
|
|
1410
1410
|
if (typeof details.card_number !== "string" || !NUMBER.test(details.card_number) || !Number.isSafeInteger(details.exp_month) || details.exp_month < 1 || details.exp_month > 12 || !Number.isSafeInteger(details.exp_year) || details.exp_year < 0 || details.exp_year > 99 || typeof details.cvc !== "string" || !SECURITY_CODE6.test(details.cvc))
|
|
1411
1411
|
return "paymongo_body_unsupported";
|
|
1412
|
-
const billing =
|
|
1412
|
+
const billing = attributes2.billing;
|
|
1413
1413
|
if (!record7(billing) || !keysAre(billing, PAYMONGO_BILLING_KEYS) || !record7(billing.address) || !keysAre(billing.address, PAYMONGO_ADDRESS_KEYS))
|
|
1414
1414
|
return "paymongo_body_unsupported";
|
|
1415
1415
|
if (billing.name === UNDEFINED || !billingValue(billing.name) || !billingValue(billing.email) || !billingValue(billing.phone) || !PAYMONGO_ADDRESS_KEYS.every((key) => billingValue(billing.address[key])))
|
|
@@ -1417,7 +1417,7 @@ function judgeCardAttach(args, session) {
|
|
|
1417
1417
|
const third = args[2];
|
|
1418
1418
|
if (!record7(third) || !keysAre(third, ["viewerAccept"]) || !billingValue(third.viewerAccept))
|
|
1419
1419
|
return "paymongo_body_unsupported";
|
|
1420
|
-
if (
|
|
1420
|
+
if (attributes2.return_url !== `${ORIGIN}${id}` || session !== void 0 && session !== id)
|
|
1421
1421
|
return "paymongo_session_mismatch";
|
|
1422
1422
|
return null;
|
|
1423
1423
|
}
|
|
@@ -1442,14 +1442,14 @@ function attachType(parsed) {
|
|
|
1442
1442
|
return typeof type === "string" ? type : null;
|
|
1443
1443
|
}
|
|
1444
1444
|
function paymongoBodyVerdict(body, session) {
|
|
1445
|
-
const { parsed, exact:
|
|
1445
|
+
const { parsed, exact: exact6 } = readJson2(body);
|
|
1446
1446
|
const type = parsed === null ? null : attachType(parsed);
|
|
1447
1447
|
if (type !== "card") {
|
|
1448
1448
|
if (parsed === null)
|
|
1449
1449
|
return body === void 0 || body === null || body === "" ? CONTINUE4 : refuse10("paymongo_body_unsupported");
|
|
1450
1450
|
return namesCardValue(parsed) ? refuse10("paymongo_body_unsupported") : CONTINUE4;
|
|
1451
1451
|
}
|
|
1452
|
-
if (!
|
|
1452
|
+
if (!exact6)
|
|
1453
1453
|
return refuse10("paymongo_body_unsupported");
|
|
1454
1454
|
const code = judgeCardAttach(parsed, session);
|
|
1455
1455
|
return code === null ? CARD9 : refuse10(code);
|
|
@@ -1472,8 +1472,8 @@ var EXPIRATION = /^[0-9]{2}(?:0[1-9]|1[0-2])$/;
|
|
|
1472
1472
|
var CARD_PAYMENT = "PAYMENT_CARD";
|
|
1473
1473
|
var record8 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1474
1474
|
var sameKeys4 = (value, keys) => {
|
|
1475
|
-
const
|
|
1476
|
-
return
|
|
1475
|
+
const own19 = Object.keys(value);
|
|
1476
|
+
return own19.length === keys.length && own19.every((key, at) => key === keys[at]);
|
|
1477
1477
|
};
|
|
1478
1478
|
var refuse11 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
1479
1479
|
var CARD10 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
@@ -1703,8 +1703,8 @@ var LOCALE = /^[a-z]{2}(?:-[A-Za-z]{2,4})?$/;
|
|
|
1703
1703
|
var PAN_LIKE3 = /(?:[0-9][ _.:-]*){12,}/;
|
|
1704
1704
|
var record9 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1705
1705
|
var sameKeys5 = (value, keys) => {
|
|
1706
|
-
const
|
|
1707
|
-
return
|
|
1706
|
+
const own19 = Object.keys(value);
|
|
1707
|
+
return own19.length === keys.length && own19.every((key, at) => key === keys[at]);
|
|
1708
1708
|
};
|
|
1709
1709
|
var refuse13 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
1710
1710
|
var CARD12 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
@@ -1956,10 +1956,10 @@ function judge(body, contentType, rule) {
|
|
|
1956
1956
|
if (read.parts.some((part) => !listed(rule.parts, part.name)))
|
|
1957
1957
|
return refusal("multipart_unknown_part");
|
|
1958
1958
|
for (const name of rule.card) {
|
|
1959
|
-
const
|
|
1960
|
-
if (
|
|
1959
|
+
const count2 = read.parts.filter((part) => part.name === name).length;
|
|
1960
|
+
if (count2 === 0)
|
|
1961
1961
|
return refusal("multipart_missing_card_part");
|
|
1962
|
-
if (
|
|
1962
|
+
if (count2 > 1)
|
|
1963
1963
|
return refusal("multipart_duplicate_card_part");
|
|
1964
1964
|
}
|
|
1965
1965
|
return read;
|
|
@@ -1968,6 +1968,25 @@ function multipartFormRefusal(body, contentType, rule) {
|
|
|
1968
1968
|
const read = judge(body, contentType, rule);
|
|
1969
1969
|
return read.refusal ?? null;
|
|
1970
1970
|
}
|
|
1971
|
+
// src/answer-card-leak.js
|
|
1972
|
+
var DECIMAL = /\p{Nd}/u;
|
|
1973
|
+
function digitValue(char) {
|
|
1974
|
+
const point = char.codePointAt(0);
|
|
1975
|
+
let first = point;
|
|
1976
|
+
while (DECIMAL.test(String.fromCodePoint(first - 1)))
|
|
1977
|
+
first -= 1;
|
|
1978
|
+
return String((point - first) % 10);
|
|
1979
|
+
}
|
|
1980
|
+
var ENCLOSED = /* @__PURE__ */ Object.freeze([[9451, 10, 11], [9461, 10, 1], [9471, 1, 0], [10102, 30, 1], [127243, 2, 0]]);
|
|
1981
|
+
var ENCLOSED_CHAR = /[\u24eb-\u24ff\u2776-\u2793\u{1f10b}\u{1f10c}]/gu;
|
|
1982
|
+
function enclosedValue(char) {
|
|
1983
|
+
const point = char.codePointAt(0);
|
|
1984
|
+
const [first, , start] = ENCLOSED.find(([from, size]) => point >= from && point < from + size);
|
|
1985
|
+
return String(first === 127243 ? 0 : first === 10102 ? (point - first) % 10 + 1 : start + point - first);
|
|
1986
|
+
}
|
|
1987
|
+
var asciiDigits = (text10) => (typeof text10.normalize === "function" ? text10.normalize("NFKC") : text10).replace(ENCLOSED_CHAR, enclosedValue).replace(/\p{Nd}/gu, (char) => char >= "0" && char <= "9" ? char : digitValue(char));
|
|
1988
|
+
var digitCount = (text10) => (asciiDigits(String(text10)).match(/\p{N}/gu) ?? []).length;
|
|
1989
|
+
var NAME_DIGITS = 3;
|
|
1971
1990
|
// src/pay-nl.js
|
|
1972
1991
|
var PAY_NL_PSP = "pay_nl";
|
|
1973
1992
|
var PAY_NL_TOKEN_URL = "https://payment.pay.nl/v1/Payment/getCardToken/json";
|
|
@@ -2735,8 +2754,8 @@ var TEXT_LIMIT3 = 256;
|
|
|
2735
2754
|
var CONTROL7 = /[\u0000-\u001f\u007f]/;
|
|
2736
2755
|
var record13 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2737
2756
|
var sameKeys7 = (value, keys) => {
|
|
2738
|
-
const
|
|
2739
|
-
return
|
|
2757
|
+
const own19 = Object.keys(value);
|
|
2758
|
+
return own19.length === keys.length && own19.every((key, at) => key === keys[at]);
|
|
2740
2759
|
};
|
|
2741
2760
|
var plainText3 = (value) => typeof value === "string" && value.length <= TEXT_LIMIT3 && !CONTROL7.test(value) && (value.match(/[0-9]/g) ?? []).length < 12;
|
|
2742
2761
|
var refuse19 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
@@ -3013,10 +3032,10 @@ function paypalBodyVerdict(body) {
|
|
|
3013
3032
|
if (number === void 0 || number === null || number === "")
|
|
3014
3033
|
return CONTINUE9;
|
|
3015
3034
|
const context = value.application_context;
|
|
3016
|
-
const
|
|
3017
|
-
if (record14(context) && context.vault === true || own3(card, "stored_credential") ||
|
|
3035
|
+
const attributes2 = record14(card.attributes) ? card.attributes : null;
|
|
3036
|
+
if (record14(context) && context.vault === true || own3(card, "stored_credential") || attributes2 && (own3(attributes2, "vault") || own3(attributes2, "customer")))
|
|
3018
3037
|
return refuse20("paypal_card_on_file");
|
|
3019
|
-
if (
|
|
3038
|
+
if (attributes2 && record14(attributes2.verification) && attributes2.verification.method === "SCA_ALWAYS")
|
|
3020
3039
|
return refuse20("paypal_three_ds");
|
|
3021
3040
|
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))
|
|
3022
3041
|
return refuse20("paypal_body_unsupported");
|
|
@@ -3030,7 +3049,7 @@ function paypalBodyVerdict(body) {
|
|
|
3030
3049
|
if (own3(card, "billing_address") && !(keysWithin2(card.billing_address, ADDRESS_KEYS3) && Object.values(card.billing_address).every(text3))) {
|
|
3031
3050
|
return refuse20("paypal_body_unsupported");
|
|
3032
3051
|
}
|
|
3033
|
-
if (own3(card, "attributes") && !(keysWithin2(
|
|
3052
|
+
if (own3(card, "attributes") && !(keysWithin2(attributes2, ["installments"]) && installmentsOk(attributes2.installments))) {
|
|
3034
3053
|
return refuse20("paypal_body_unsupported");
|
|
3035
3054
|
}
|
|
3036
3055
|
return CARD19;
|
|
@@ -3441,8 +3460,8 @@ var HOSTNAME = /^(?=.{1,253}$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](
|
|
|
3441
3460
|
var PUBLISHABLE_KEY = /^[A-Za-z0-9]{16,64}$/;
|
|
3442
3461
|
var record18 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3443
3462
|
var sameKeys8 = (value, keys) => {
|
|
3444
|
-
const
|
|
3445
|
-
return
|
|
3463
|
+
const own19 = Object.keys(value);
|
|
3464
|
+
return own19.length === keys.length && own19.every((key, at) => key === keys[at]);
|
|
3446
3465
|
};
|
|
3447
3466
|
var refuse24 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
3448
3467
|
var CARD23 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
@@ -4133,8 +4152,8 @@ var LONG_TEXT_LIMIT = BODY_LIMIT25;
|
|
|
4133
4152
|
var record22 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
4134
4153
|
var owns6 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
4135
4154
|
var sameKeys9 = (value, keys) => {
|
|
4136
|
-
const
|
|
4137
|
-
return
|
|
4155
|
+
const own19 = Object.keys(value);
|
|
4156
|
+
return own19.length === keys.length && own19.every((key, at) => key === keys[at]);
|
|
4138
4157
|
};
|
|
4139
4158
|
var exact3 = (pattern, value) => typeof value === "string" && pattern.test(value);
|
|
4140
4159
|
var printable3 = (text10) => [...text10].every((character) => {
|
|
@@ -4533,8 +4552,8 @@ var POSTAL_CODE4 = /^[A-Za-z0-9 -]{0,16}$/;
|
|
|
4533
4552
|
var CIPHERTEXT_B64 = /^[A-Za-z0-9+/]{341}[AQgw]==$/;
|
|
4534
4553
|
var record24 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
4535
4554
|
var sameKeys11 = (value, keys) => {
|
|
4536
|
-
const
|
|
4537
|
-
return
|
|
4555
|
+
const own19 = Object.keys(value);
|
|
4556
|
+
return own19.length === keys.length && own19.every((key, at) => key === keys[at]);
|
|
4538
4557
|
};
|
|
4539
4558
|
var refuse29 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
4540
4559
|
var failed = (code) => (
|
|
@@ -4685,14 +4704,14 @@ function readJson7(body) {
|
|
|
4685
4704
|
catch {
|
|
4686
4705
|
return { parsed: null, exact: false };
|
|
4687
4706
|
}
|
|
4688
|
-
let
|
|
4707
|
+
let exact6 = false;
|
|
4689
4708
|
try {
|
|
4690
|
-
|
|
4709
|
+
exact6 = JSON.stringify(parsed) === body;
|
|
4691
4710
|
}
|
|
4692
4711
|
catch {
|
|
4693
|
-
|
|
4712
|
+
exact6 = false;
|
|
4694
4713
|
}
|
|
4695
|
-
return { parsed, exact:
|
|
4714
|
+
return { parsed, exact: exact6 };
|
|
4696
4715
|
}
|
|
4697
4716
|
function numberDigits(number) {
|
|
4698
4717
|
if (typeof number !== "string")
|
|
@@ -4769,7 +4788,7 @@ function judgeCard2(parsed) {
|
|
|
4769
4788
|
return null;
|
|
4770
4789
|
}
|
|
4771
4790
|
function fastspringBodyVerdict(body) {
|
|
4772
|
-
const { parsed, exact:
|
|
4791
|
+
const { parsed, exact: exact6 } = readJson7(body);
|
|
4773
4792
|
if (!record25(parsed))
|
|
4774
4793
|
return body === void 0 || body === null || body === "" ? CONTINUE11 : refuse30("fastspring_body_unsupported");
|
|
4775
4794
|
if (parsed.paymentType !== "card") {
|
|
@@ -4777,7 +4796,7 @@ function fastspringBodyVerdict(body) {
|
|
|
4777
4796
|
return refuse30("fastspring_body_unsupported");
|
|
4778
4797
|
return typeof parsed.paymentType === "string" && parsed.paymentType !== "" ? CONTINUE11 : refuse30("fastspring_body_unsupported");
|
|
4779
4798
|
}
|
|
4780
|
-
if (!
|
|
4799
|
+
if (!exact6)
|
|
4781
4800
|
return refuse30("fastspring_body_unsupported");
|
|
4782
4801
|
const code = judgeCard2(parsed);
|
|
4783
4802
|
return code === null ? CARD29 : refuse30(code);
|
|
@@ -5013,10 +5032,10 @@ function billingDetails(value) {
|
|
|
5013
5032
|
if (!record27(value) || !inOrder5(value, BILLING_KEYS))
|
|
5014
5033
|
return false;
|
|
5015
5034
|
return Object.keys(value).every((key) => {
|
|
5016
|
-
const
|
|
5035
|
+
const field3 = value[key];
|
|
5017
5036
|
if (key !== "address")
|
|
5018
|
-
return key === "mobile_number" || key === "phone_number" ? typeof
|
|
5019
|
-
return record27(
|
|
5037
|
+
return key === "mobile_number" || key === "phone_number" ? typeof field3 === "string" && PHONE4.test(field3) : plainText6(field3);
|
|
5038
|
+
return record27(field3) && inOrder5(field3, ADDRESS_KEYS5) && Object.keys(field3).every((name) => plainText6(field3[name]));
|
|
5020
5039
|
});
|
|
5021
5040
|
}
|
|
5022
5041
|
function cardData(value) {
|
|
@@ -5046,8 +5065,8 @@ function xenditBodyVerdict(body) {
|
|
|
5046
5065
|
if (own9(value, "fp_session_id") && (typeof value.fp_session_id !== "string" || !FP_SESSION.test(value.fp_session_id)))
|
|
5047
5066
|
return refuse32("xendit_body_unsupported");
|
|
5048
5067
|
if (own9(value, "metadata")) {
|
|
5049
|
-
const
|
|
5050
|
-
if (!record27(
|
|
5068
|
+
const metadata2 = value.metadata;
|
|
5069
|
+
if (!record27(metadata2) || Object.keys(metadata2).length !== 1 || !record27(metadata2._forter) || Object.keys(metadata2._forter).length !== 1 || typeof metadata2._forter.token !== "string" || !FORTER_TOKEN.test(metadata2._forter.token))
|
|
5051
5070
|
return refuse32("xendit_body_unsupported");
|
|
5052
5071
|
}
|
|
5053
5072
|
if (own9(value, "mid_label") && (typeof value.mid_label !== "string" || !MID_LABEL.test(value.mid_label)))
|
|
@@ -5325,14 +5344,14 @@ function readJson8(body) {
|
|
|
5325
5344
|
catch {
|
|
5326
5345
|
return { parsed: null, exact: false };
|
|
5327
5346
|
}
|
|
5328
|
-
let
|
|
5347
|
+
let exact6 = false;
|
|
5329
5348
|
try {
|
|
5330
|
-
|
|
5349
|
+
exact6 = body.length <= BODY_LIMIT32 && JSON.stringify(parsed) === body;
|
|
5331
5350
|
}
|
|
5332
5351
|
catch {
|
|
5333
|
-
|
|
5352
|
+
exact6 = false;
|
|
5334
5353
|
}
|
|
5335
|
-
return { parsed, exact:
|
|
5354
|
+
return { parsed, exact: exact6 };
|
|
5336
5355
|
}
|
|
5337
5356
|
function namesCardValue3(parsed) {
|
|
5338
5357
|
const pending = parsed !== null && typeof parsed === "object" ? [parsed] : [];
|
|
@@ -5393,8 +5412,8 @@ function judgeCardPayment(parsed) {
|
|
|
5393
5412
|
function paymobBodyVerdict(body) {
|
|
5394
5413
|
if (body === void 0 || body === null || body === "")
|
|
5395
5414
|
return CONTINUE12;
|
|
5396
|
-
const { parsed, exact:
|
|
5397
|
-
if (!
|
|
5415
|
+
const { parsed, exact: exact6 } = readJson8(body);
|
|
5416
|
+
if (!exact6 || !record29(parsed) || !record29(parsed.source) || typeof parsed.source.subtype !== "string")
|
|
5398
5417
|
return refuse34("paymob_body_unsupported");
|
|
5399
5418
|
const subtype = parsed.source.subtype;
|
|
5400
5419
|
if (subtype === "CARD") {
|
|
@@ -5866,12 +5885,12 @@ function membersRefusal(root) {
|
|
|
5866
5885
|
const pending = [[root, ""]];
|
|
5867
5886
|
while (pending.length > 0) {
|
|
5868
5887
|
const [node, path] = pending.pop();
|
|
5869
|
-
const
|
|
5888
|
+
const own19 = path === "" ? TRANSACTION_MEMBERS : owns7(RECORD_MEMBERS, path) ? RECORD_MEMBERS[path] : null;
|
|
5870
5889
|
for (const [key, child] of Object.entries(node)) {
|
|
5871
5890
|
const at = Array.isArray(node) ? path : path === "" ? key : `${path}.${key}`;
|
|
5872
5891
|
if (at === "checkoutCreditCard")
|
|
5873
5892
|
continue;
|
|
5874
|
-
if (
|
|
5893
|
+
if (own19 !== null && !own19.includes(key))
|
|
5875
5894
|
return true;
|
|
5876
5895
|
if (TEXT_RECORDS.includes(path) && child !== null && typeof child !== "string")
|
|
5877
5896
|
return true;
|
|
@@ -6092,7 +6111,17 @@ var TOKEN_FACTS = /* @__PURE__ */ Object.freeze([
|
|
|
6092
6111
|
"primary"
|
|
6093
6112
|
]);
|
|
6094
6113
|
// src/registration.js
|
|
6095
|
-
var PARTS = {
|
|
6114
|
+
var PARTS = {
|
|
6115
|
+
psp: "id",
|
|
6116
|
+
definitions: "list",
|
|
6117
|
+
refusedOperations: "list",
|
|
6118
|
+
settlementReadback: "any",
|
|
6119
|
+
exactUrl: "rule",
|
|
6120
|
+
bodyGate: "rule",
|
|
6121
|
+
amount: "rule",
|
|
6122
|
+
hostedEntry: "rule",
|
|
6123
|
+
limitations: "sentences"
|
|
6124
|
+
};
|
|
6096
6125
|
var PSP_ID = /^[a-z][a-z0-9_]*$/;
|
|
6097
6126
|
var registrationProblems = (spec) => problemsOf(spec, PARTS);
|
|
6098
6127
|
function problemsOf(spec, parts) {
|
|
@@ -6108,9 +6137,14 @@ function problemsOf(spec, parts) {
|
|
|
6108
6137
|
continue;
|
|
6109
6138
|
if (kind === "rule" && typeof value !== "function")
|
|
6110
6139
|
problems2.push(`${psp}: ${key} is not a function`);
|
|
6140
|
+
if (kind === "flag" && value !== true)
|
|
6141
|
+
problems2.push(`${psp}: ${key} is not true`);
|
|
6111
6142
|
if (kind === "numbers" && !((Array.isArray(value) || value instanceof Set) && [...value].every((n) => typeof n === "string" && /^\d{12,19}$/.test(n)))) {
|
|
6112
6143
|
problems2.push(`${psp}: ${key} is not a list of card numbers`);
|
|
6113
6144
|
}
|
|
6145
|
+
if (kind === "sentences" && !(Array.isArray(value) && value.length > 0 && value.every((s) => typeof s === "string" && s.trim() !== ""))) {
|
|
6146
|
+
problems2.push(`${psp}: ${key} is not a list of sentences`);
|
|
6147
|
+
}
|
|
6114
6148
|
}
|
|
6115
6149
|
if ("definitions" in parts) {
|
|
6116
6150
|
if (!Array.isArray(spec.definitions) || spec.definitions.length === 0)
|
|
@@ -6121,6 +6155,10 @@ function problemsOf(spec, parts) {
|
|
|
6121
6155
|
if (typeof id !== "string" || !id.startsWith(`${psp}.`))
|
|
6122
6156
|
problems2.push(`${psp}: ${JSON.stringify(id)} is not one of its operations`);
|
|
6123
6157
|
}
|
|
6158
|
+
const pages = Array.isArray(spec.definitions) ? spec.definitions.filter((d) => d?.hostedForm?.cardIn === "processor_page") : [];
|
|
6159
|
+
if (spec.hostedEntry !== void 0 && (pages.length === 0 || pages.some((d) => d.hostedForm.policy !== void 0))) {
|
|
6160
|
+
problems2.push(`${psp}: hostedEntry needs a definition whose hosted form takes the card on the processor's page and names no policy`);
|
|
6161
|
+
}
|
|
6124
6162
|
}
|
|
6125
6163
|
return problems2;
|
|
6126
6164
|
}
|
|
@@ -6133,21 +6171,230 @@ function registered(spec, parts) {
|
|
|
6133
6171
|
function registerProcessor(spec) {
|
|
6134
6172
|
return registered(spec, PARTS);
|
|
6135
6173
|
}
|
|
6174
|
+
// src/processors/bluesnap.js
|
|
6175
|
+
var BLUESNAP_PSP = "bluesnap";
|
|
6176
|
+
var BLUESNAP_OPERATION = "bluesnap.card_request";
|
|
6177
|
+
var BLUESNAP_HOSTS = /* @__PURE__ */ Object.freeze({ 1: "ws1.bluesnap.com", 2: "ws2.bluesnap.com", _: "sandpay.bluesnap.com" });
|
|
6178
|
+
var BLUESNAP_SANDBOX_HOST = "sandpay.bluesnap.com";
|
|
6179
|
+
var BLUESNAP_CARD_KEYS = /* @__PURE__ */ Object.freeze(["cvv", "ccNumber", "expDate"]);
|
|
6180
|
+
var BLUESNAP_LEG_KEYS = /* @__PURE__ */ Object.freeze(["cvv", "expDate"]);
|
|
6181
|
+
var BODY_LIMIT35 = 1024;
|
|
6182
|
+
var TOKEN_URL2 = /^https:\/\/(ws1|ws2|sandpay)\.bluesnap\.com\/services\/2\/payment-fields-tokens\/([0-9a-f]{64}_[12]?)$/;
|
|
6183
|
+
var CARD_NUMBER18 = /^[0-9]{12,19}$/;
|
|
6184
|
+
var SECURITY_CODE22 = /^[0-9]{3,4}$/;
|
|
6185
|
+
var EXPIRY3 = /^(?:0[1-9]|1[0-2])\/20[0-9]{2}$/;
|
|
6186
|
+
var SAVED_CARD_KEYS2 = ["last4Digits", "lastFourDigits", "ccType"];
|
|
6187
|
+
var record32 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
6188
|
+
var own12 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
6189
|
+
var refuse37 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
6190
|
+
var CARD36 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
6191
|
+
var LEG = /* @__PURE__ */ Object.freeze({ verdict: "continue" });
|
|
6192
|
+
function bluesnapTokenUrl(url) {
|
|
6193
|
+
const match = typeof url === "string" ? TOKEN_URL2.exec(url) : null;
|
|
6194
|
+
if (!match || BLUESNAP_HOSTS[match[2].slice(-1)] !== `${match[1]}.bluesnap.com`)
|
|
6195
|
+
return null;
|
|
6196
|
+
const host = `${match[1]}.bluesnap.com`;
|
|
6197
|
+
return Object.freeze({ host, token: match[2], environment: host === BLUESNAP_SANDBOX_HOST ? "sandbox" : "production" });
|
|
6198
|
+
}
|
|
6199
|
+
function isBluesnapTokenUrl(url) {
|
|
6200
|
+
return bluesnapTokenUrl(url) !== null;
|
|
6201
|
+
}
|
|
6202
|
+
function readBody21(body) {
|
|
6203
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT35)
|
|
6204
|
+
return null;
|
|
6205
|
+
try {
|
|
6206
|
+
const value = JSON.parse(body);
|
|
6207
|
+
return record32(value) && JSON.stringify(value) === body ? value : null;
|
|
6208
|
+
}
|
|
6209
|
+
catch {
|
|
6210
|
+
return null;
|
|
6211
|
+
}
|
|
6212
|
+
}
|
|
6213
|
+
function bluesnapBodyVerdict(body) {
|
|
6214
|
+
const value = readBody21(body);
|
|
6215
|
+
if (value === null)
|
|
6216
|
+
return refuse37("bluesnap_body_unsupported");
|
|
6217
|
+
const keys = Object.keys(value);
|
|
6218
|
+
if (keys.some((key) => SAVED_CARD_KEYS2.includes(key)))
|
|
6219
|
+
return refuse37(own12(value, "ccNumber") ? "bluesnap_body_unsupported" : "bluesnap_saved_card");
|
|
6220
|
+
if (keys.length === 0 || keys.some((key, i) => !BLUESNAP_CARD_KEYS.includes(key) || i > 0 && BLUESNAP_CARD_KEYS.indexOf(keys[i - 1]) >= BLUESNAP_CARD_KEYS.indexOf(key))) {
|
|
6221
|
+
return refuse37("bluesnap_body_unsupported");
|
|
6222
|
+
}
|
|
6223
|
+
if (own12(value, "ccNumber") && !(typeof value.ccNumber === "string" && CARD_NUMBER18.test(value.ccNumber)) || own12(value, "cvv") && !(typeof value.cvv === "string" && SECURITY_CODE22.test(value.cvv)) || own12(value, "expDate") && !(typeof value.expDate === "string" && EXPIRY3.test(value.expDate)))
|
|
6224
|
+
return refuse37("bluesnap_body_unsupported");
|
|
6225
|
+
return own12(value, "ccNumber") ? CARD36 : LEG;
|
|
6226
|
+
}
|
|
6227
|
+
var bluesnap_default = /* @__PURE__ */ registerProcessor({
|
|
6228
|
+
psp: BLUESNAP_PSP,
|
|
6229
|
+
definitions: [
|
|
6230
|
+
{
|
|
6231
|
+
psp: "bluesnap",
|
|
6232
|
+
// The card fields' PUTs, as the header above reads them. The sandbox has its own server, so the device sends a
|
|
6233
|
+
// test-mode request only documented test cards (hostEnvironmentPinned, device-replay.js S7). `(?![\w/.%-])`
|
|
6234
|
+
// ends the token for a consumer that tests `match` unanchored; the exact-URL rule pins each server to its suffix.
|
|
6235
|
+
// Ships dark: served only to a client that declares `bluesnap_hosted_payment_fields`, and the backend's gate turns
|
|
6236
|
+
// it on for Agentcard's own company alone, in code.
|
|
6237
|
+
capability: "bluesnap_hosted_payment_fields",
|
|
6238
|
+
match: "(?:ws1|ws2|sandpay)\\.bluesnap\\.com/services/2/payment-fields-tokens/[0-9a-f]{64}_[12]?(?![\\w/.%-])",
|
|
6239
|
+
hosts: ["^ws1\\.bluesnap\\.com$", "^ws2\\.bluesnap\\.com$", "^sandpay\\.bluesnap\\.com$"],
|
|
6240
|
+
sandboxHosts: ["^sandpay\\.bluesnap\\.com$"],
|
|
6241
|
+
hostEnvironmentPinned: true,
|
|
6242
|
+
encoding: "json",
|
|
6243
|
+
// The frames' own headers, each held to its shape by bluesnapRequestRefusal. Origin, Referer and cookies never
|
|
6244
|
+
// ride (the frames send no cookie).
|
|
6245
|
+
passthroughHeaders: ["^authorization$", "^bluesnap_version_header$", "^bluesnap_origin_version_header$", "^bluesnap_origin_header$"],
|
|
6246
|
+
jsonCardFields: [["ccNumber"]],
|
|
6247
|
+
// The expiry and code frames' PUTs: held by the checkout SDK and answered with the card request's answer.
|
|
6248
|
+
splitCard: { absorb: [...BLUESNAP_LEG_KEYS], pass: [], siblingKeys: [] },
|
|
6249
|
+
request: { method: "PUT", cardIn: "body", response: "json" }
|
|
6250
|
+
}
|
|
6251
|
+
],
|
|
6252
|
+
// Only the cardholder's device sends the card, after a person approves; no reviewed list names bluesnap.
|
|
6253
|
+
refusedOperations: [BLUESNAP_OPERATION],
|
|
6254
|
+
// Not surveyed: the PUT moves no money, and the merchant's own charge is a server call Agentcard never sees.
|
|
6255
|
+
settlementReadback: "not_surveyed",
|
|
6256
|
+
exactUrl: isBluesnapTokenUrl,
|
|
6257
|
+
bodyGate: (url, body) => url !== void 0 && !isBluesnapTokenUrl(url) ? { verdict: "refuse", code: "bluesnap_url_refused" } : bluesnapBodyVerdict(body)
|
|
6258
|
+
});
|
|
6259
|
+
// src/processors/iyzico.js
|
|
6260
|
+
var IYZICO_PSP = "iyzico";
|
|
6261
|
+
var IYZICO_OPERATION = "iyzico.card_request";
|
|
6262
|
+
var PATHS = ["/payment/iyzipos/checkoutform/auth/ecom", "/payment/iyzipos/checkoutform/initialize3ds/ecom"];
|
|
6263
|
+
var IYZICO_CARD_URLS = /* @__PURE__ */ Object.freeze(["https://api.iyzipay.com", "https://sandbox-api.iyzipay.com"].flatMap((origin) => PATHS.map((path) => `${origin}${path}`)));
|
|
6264
|
+
var IYZICO_BODY_KEYS = /* @__PURE__ */ Object.freeze([
|
|
6265
|
+
"installment",
|
|
6266
|
+
"paidPrice",
|
|
6267
|
+
"paymentChannel",
|
|
6268
|
+
"paymentCard",
|
|
6269
|
+
"buyerProtected",
|
|
6270
|
+
"gsmNumber",
|
|
6271
|
+
"dccPayment",
|
|
6272
|
+
"dccQueryRrn",
|
|
6273
|
+
"pwiMetadata"
|
|
6274
|
+
]);
|
|
6275
|
+
var IYZICO_CARD_KEYS = /* @__PURE__ */ Object.freeze([
|
|
6276
|
+
"cardNumber",
|
|
6277
|
+
"cardHolderName",
|
|
6278
|
+
"expireYear",
|
|
6279
|
+
"expireMonth",
|
|
6280
|
+
"cvc",
|
|
6281
|
+
"registerConsumerCard",
|
|
6282
|
+
"registerCard"
|
|
6283
|
+
]);
|
|
6284
|
+
var BODY_LIMIT36 = 4096;
|
|
6285
|
+
var CARD_NUMBER19 = /^[0-9]{12,19}$/;
|
|
6286
|
+
var SECURITY_CODE23 = /^[0-9]{3,4}$/;
|
|
6287
|
+
var MONTH19 = /^(?:0?[1-9]|1[0-2])$/;
|
|
6288
|
+
var YEAR20 = /^(?:[0-9]{2}|20[0-9]{2})$/;
|
|
6289
|
+
var PRICE = /^([1-9][0-9]{0,8}|0)(?:\.([0-9]{1,2}))?$/;
|
|
6290
|
+
var CHANNELS = /* @__PURE__ */ Object.freeze(["WEB", "MOBILE_WEB", "MOBILE_IOS", "MOBILE_ANDROID", "MOBILE_WINDOWS"]);
|
|
6291
|
+
var METADATA_KEYS3 = /* @__PURE__ */ Object.freeze(["lightRedesign", "pwiGrowthActionDisabled"]);
|
|
6292
|
+
var FLAG = /^[A-Za-z_]{1,16}$/;
|
|
6293
|
+
var HOLDER5 = /^[^\x00-\x1f\x7f0-9]{3,100}$/u;
|
|
6294
|
+
var record33 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
6295
|
+
var own13 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
6296
|
+
var inOrder6 = (value, keys) => {
|
|
6297
|
+
let at = 0;
|
|
6298
|
+
for (const name of Object.keys(value)) {
|
|
6299
|
+
while (at < keys.length && keys[at] !== name)
|
|
6300
|
+
at += 1;
|
|
6301
|
+
if (at === keys.length)
|
|
6302
|
+
return false;
|
|
6303
|
+
at += 1;
|
|
6304
|
+
}
|
|
6305
|
+
return true;
|
|
6306
|
+
};
|
|
6307
|
+
var refuse38 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
6308
|
+
var CARD37 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
6309
|
+
function isIyzicoCardUrl(url) {
|
|
6310
|
+
return typeof url === "string" && IYZICO_CARD_URLS.includes(url);
|
|
6311
|
+
}
|
|
6312
|
+
function readBody22(body) {
|
|
6313
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT36)
|
|
6314
|
+
return null;
|
|
6315
|
+
try {
|
|
6316
|
+
const value = JSON.parse(body);
|
|
6317
|
+
return record33(value) && JSON.stringify(value) === body ? value : null;
|
|
6318
|
+
}
|
|
6319
|
+
catch {
|
|
6320
|
+
return null;
|
|
6321
|
+
}
|
|
6322
|
+
}
|
|
6323
|
+
function hundredths(price) {
|
|
6324
|
+
const match = typeof price === "number" && Number.isFinite(price) ? PRICE.exec(String(price)) : null;
|
|
6325
|
+
const value = match ? Number(match[1]) * 100 + Number((match[2] ?? "").padEnd(2, "0")) : 0;
|
|
6326
|
+
return value > 0 ? value : null;
|
|
6327
|
+
}
|
|
6328
|
+
var holderName2 = (name) => typeof name === "string" && HOLDER5.test(name) && name.trim().split(/\s+/).filter((word) => word.length > 1).length > 1;
|
|
6329
|
+
var metadata = (value) => record33(value) && inOrder6(value, METADATA_KEYS3) && Object.values(value).every((flag3) => Array.isArray(flag3) && flag3.length === 1 && typeof flag3[0] === "string" && FLAG.test(flag3[0]));
|
|
6330
|
+
function iyzicoBodyVerdict(body) {
|
|
6331
|
+
const value = readBody22(body);
|
|
6332
|
+
if (value === null)
|
|
6333
|
+
return refuse38("iyzico_body_unsupported");
|
|
6334
|
+
const card = value.paymentCard;
|
|
6335
|
+
if (record33(card) && (own13(card, "cardToken") || own13(card, "ucsToken") || own13(card, "consumerToken")) && !own13(card, "cardNumber"))
|
|
6336
|
+
return refuse38("iyzico_saved_card");
|
|
6337
|
+
if (own13(value, "dccPayment") || own13(value, "dccQueryRrn"))
|
|
6338
|
+
return refuse38("iyzico_dcc_refused");
|
|
6339
|
+
if (own13(value, "gsmNumber") || own13(value, "buyerProtected") && value.buyerProtected !== false || record33(card) && (own13(card, "registerCard") && card.registerCard !== 0 || own13(card, "registerConsumerCard") && card.registerConsumerCard !== false)) {
|
|
6340
|
+
return refuse38("iyzico_keeps_card");
|
|
6341
|
+
}
|
|
6342
|
+
if (Number.isSafeInteger(value.installment) && value.installment > 1)
|
|
6343
|
+
return refuse38("iyzico_installments_refused");
|
|
6344
|
+
if (!inOrder6(value, IYZICO_BODY_KEYS) || !["installment", "paidPrice", "paymentChannel", "paymentCard"].every((key) => own13(value, key)) || value.installment !== 1 || hundredths(value.paidPrice) === null || !CHANNELS.includes(value.paymentChannel) || own13(value, "pwiMetadata") && !metadata(value.pwiMetadata))
|
|
6345
|
+
return refuse38("iyzico_body_unsupported");
|
|
6346
|
+
if (!record33(card) || Object.keys(card).join() !== IYZICO_CARD_KEYS.join() || typeof card.cardNumber !== "string" || !CARD_NUMBER19.test(card.cardNumber) || !holderName2(card.cardHolderName) || typeof card.expireYear !== "string" || !YEAR20.test(card.expireYear) || typeof card.expireMonth !== "string" || !MONTH19.test(card.expireMonth) || typeof card.cvc !== "string" || !SECURITY_CODE23.test(card.cvc))
|
|
6347
|
+
return refuse38("iyzico_body_unsupported");
|
|
6348
|
+
return CARD37;
|
|
6349
|
+
}
|
|
6350
|
+
var iyzico_default = /* @__PURE__ */ registerProcessor({
|
|
6351
|
+
psp: IYZICO_PSP,
|
|
6352
|
+
definitions: [
|
|
6353
|
+
{
|
|
6354
|
+
psp: "iyzico",
|
|
6355
|
+
// The Checkout Form's card payment, as the header above reads it. Sandbox has its own host, so the device sends
|
|
6356
|
+
// a test-mode payment only iyzico's documented test cards (hostEnvironmentPinned, device-replay.js S7). Ships dark:
|
|
6357
|
+
// served only to a client that declares `iyzico_checkout_form`, for a company the backend's gate turns iyzico on
|
|
6358
|
+
// for, and autopilot never sends it.
|
|
6359
|
+
capability: "iyzico_checkout_form",
|
|
6360
|
+
match: "(?:sandbox-)?api\\.iyzipay\\.com/payment/iyzipos/checkoutform/(?:auth|initialize3ds)/ecom",
|
|
6361
|
+
hosts: ["^api\\.iyzipay\\.com$", "^sandbox-api\\.iyzipay\\.com$"],
|
|
6362
|
+
sandboxHosts: ["^sandbox-api\\.iyzipay\\.com$"],
|
|
6363
|
+
hostEnvironmentPinned: true,
|
|
6364
|
+
encoding: "json",
|
|
6365
|
+
// The form's session token and its Accept. Origin, Referer and cookies never ride, and neither does IYZI_LC,
|
|
6366
|
+
// which iyzico's preflight does not allow.
|
|
6367
|
+
passthroughHeaders: ["^x-iyzi-token$", "^accept$"],
|
|
6368
|
+
jsonCardFields: [["paymentCard", "cardNumber"]]
|
|
6369
|
+
}
|
|
6370
|
+
],
|
|
6371
|
+
// Only the cardholder's device sends it, after a person approves; 3-D Secure needs that person at the browser.
|
|
6372
|
+
refusedOperations: [IYZICO_OPERATION],
|
|
6373
|
+
// iyzico answers the form's result (CF retrieve) only to the merchant's API key and secret.
|
|
6374
|
+
settlementReadback: {
|
|
6375
|
+
answer: "none",
|
|
6376
|
+
reason: "merchant_credential_required",
|
|
6377
|
+
note: "The processor answers a payment result only to the server credentials of the shop; the intercepted request carries a checkout reference and no credential.",
|
|
6378
|
+
source: "https://docs.iyzico.com/en/payment-methods/checkoutform/cf-implementation/cf-retrieve"
|
|
6379
|
+
},
|
|
6380
|
+
exactUrl: isIyzicoCardUrl,
|
|
6381
|
+
bodyGate: (url, body) => url !== void 0 && !isIyzicoCardUrl(url) ? refuse38("iyzico_url_refused") : iyzicoBodyVerdict(body)
|
|
6382
|
+
});
|
|
6136
6383
|
// src/processors/midtrans.js
|
|
6137
6384
|
var MIDTRANS_PSP = "midtrans";
|
|
6138
6385
|
var MIDTRANS_OPERATION = "midtrans.card_request";
|
|
6139
6386
|
var MIDTRANS_TOKEN_URL = "https://api.midtrans.com/v2/token";
|
|
6140
6387
|
var MIDTRANS_SANDBOX_TOKEN_URL = "https://api.sandbox.midtrans.com/v2/token";
|
|
6141
6388
|
var MIDTRANS_TOKEN_KEYS = /* @__PURE__ */ Object.freeze(["card_cvv", "card_number", "card_exp_month", "card_exp_year", "installment_term"]);
|
|
6142
|
-
var
|
|
6143
|
-
var
|
|
6144
|
-
var
|
|
6145
|
-
var
|
|
6146
|
-
var
|
|
6389
|
+
var BODY_LIMIT37 = 4096;
|
|
6390
|
+
var CARD_NUMBER20 = /^[0-9]{12,19}$/;
|
|
6391
|
+
var SECURITY_CODE24 = /^[0-9]{3,4}$/;
|
|
6392
|
+
var MONTH20 = /^(?:0[1-9]|1[0-2])$/;
|
|
6393
|
+
var YEAR21 = /^20[0-9]{2}$/;
|
|
6147
6394
|
var TERM = /^[0-9]{1,3}$/;
|
|
6148
|
-
var
|
|
6149
|
-
var
|
|
6150
|
-
var
|
|
6395
|
+
var record34 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
6396
|
+
var own14 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
6397
|
+
var inOrder7 = (value, keys) => {
|
|
6151
6398
|
let at = 0;
|
|
6152
6399
|
for (const name of Object.keys(value)) {
|
|
6153
6400
|
while (at < keys.length && keys[at] !== name)
|
|
@@ -6158,18 +6405,18 @@ var inOrder6 = (value, keys) => {
|
|
|
6158
6405
|
}
|
|
6159
6406
|
return true;
|
|
6160
6407
|
};
|
|
6161
|
-
var
|
|
6162
|
-
var
|
|
6408
|
+
var refuse39 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
6409
|
+
var CARD38 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
6163
6410
|
function isMidtransTokenUrl(url) {
|
|
6164
6411
|
return url === MIDTRANS_TOKEN_URL || url === MIDTRANS_SANDBOX_TOKEN_URL;
|
|
6165
6412
|
}
|
|
6166
|
-
function
|
|
6167
|
-
if (typeof body !== "string" || body === "" || body.length >
|
|
6413
|
+
function readBody23(body) {
|
|
6414
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT37)
|
|
6168
6415
|
return null;
|
|
6169
6416
|
let value;
|
|
6170
6417
|
try {
|
|
6171
6418
|
value = JSON.parse(body);
|
|
6172
|
-
if (!
|
|
6419
|
+
if (!record34(value) || JSON.stringify(value) !== body)
|
|
6173
6420
|
return null;
|
|
6174
6421
|
}
|
|
6175
6422
|
catch {
|
|
@@ -6178,20 +6425,20 @@ function readBody21(body) {
|
|
|
6178
6425
|
return value;
|
|
6179
6426
|
}
|
|
6180
6427
|
function midtransBodyVerdict(body) {
|
|
6181
|
-
const value =
|
|
6182
|
-
if (value === null || !
|
|
6183
|
-
if (
|
|
6184
|
-
return
|
|
6185
|
-
return
|
|
6428
|
+
const value = readBody23(body);
|
|
6429
|
+
if (value === null || !inOrder7(value, MIDTRANS_TOKEN_KEYS)) {
|
|
6430
|
+
if (record34(value) && (own14(value, "token_id") || own14(value, "two_click")) && !own14(value, "card_number"))
|
|
6431
|
+
return refuse39("midtrans_saved_card");
|
|
6432
|
+
return refuse39("midtrans_body_unsupported");
|
|
6186
6433
|
}
|
|
6187
|
-
if (!
|
|
6188
|
-
return
|
|
6434
|
+
if (!own14(value, "card_cvv") || !own14(value, "card_number") || !own14(value, "card_exp_month") || !own14(value, "card_exp_year")) {
|
|
6435
|
+
return refuse39("midtrans_body_unsupported");
|
|
6189
6436
|
}
|
|
6190
|
-
if (typeof value.card_cvv !== "string" || !
|
|
6191
|
-
return
|
|
6192
|
-
if (
|
|
6193
|
-
return
|
|
6194
|
-
return
|
|
6437
|
+
if (typeof value.card_cvv !== "string" || !SECURITY_CODE24.test(value.card_cvv) || typeof value.card_number !== "string" || !CARD_NUMBER20.test(value.card_number) || typeof value.card_exp_month !== "string" || !MONTH20.test(value.card_exp_month) || typeof value.card_exp_year !== "string" || !YEAR21.test(value.card_exp_year))
|
|
6438
|
+
return refuse39("midtrans_body_unsupported");
|
|
6439
|
+
if (own14(value, "installment_term") && (typeof value.installment_term !== "string" || !TERM.test(value.installment_term)))
|
|
6440
|
+
return refuse39("midtrans_body_unsupported");
|
|
6441
|
+
return CARD38;
|
|
6195
6442
|
}
|
|
6196
6443
|
var midtrans_default = /* @__PURE__ */ registerProcessor({
|
|
6197
6444
|
psp: MIDTRANS_PSP,
|
|
@@ -6222,9 +6469,1058 @@ var midtrans_default = /* @__PURE__ */ registerProcessor({
|
|
|
6222
6469
|
exactUrl: isMidtransTokenUrl,
|
|
6223
6470
|
bodyGate: (url, body) => url !== void 0 && !isMidtransTokenUrl(url) ? { verdict: "refuse", code: "midtrans_url_refused" } : midtransBodyVerdict(body)
|
|
6224
6471
|
});
|
|
6472
|
+
// src/processors/oceanpayment.js
|
|
6473
|
+
var OCEANPAYMENT_PSP = "oceanpayment";
|
|
6474
|
+
var OCEANPAYMENT_OPERATION = "oceanpayment.card_request";
|
|
6475
|
+
var OCEANPAYMENT_HOSTS = /* @__PURE__ */ Object.freeze({ "secure.oceanpayment.com": "production", "test-secure.oceanpayment.com": "sandbox" });
|
|
6476
|
+
var OCEANPAYMENT_FORM_FIELDS = /* @__PURE__ */ Object.freeze([
|
|
6477
|
+
"card_number_three",
|
|
6478
|
+
"card_number_two",
|
|
6479
|
+
"card_number_temp",
|
|
6480
|
+
"card_number",
|
|
6481
|
+
"card_date",
|
|
6482
|
+
"card_year",
|
|
6483
|
+
"card_month",
|
|
6484
|
+
"card_secureCode",
|
|
6485
|
+
"copyCard",
|
|
6486
|
+
"closePage",
|
|
6487
|
+
"starttime",
|
|
6488
|
+
"endtime",
|
|
6489
|
+
"comloadpage",
|
|
6490
|
+
"timezone",
|
|
6491
|
+
"OSLang",
|
|
6492
|
+
"os",
|
|
6493
|
+
"brower",
|
|
6494
|
+
"BrowerLang",
|
|
6495
|
+
"resolution",
|
|
6496
|
+
"methods",
|
|
6497
|
+
"reference_id",
|
|
6498
|
+
"methods",
|
|
6499
|
+
"reference"
|
|
6500
|
+
]);
|
|
6501
|
+
var URL_LIMIT14 = 2048;
|
|
6502
|
+
var BODY_LIMIT38 = 8192;
|
|
6503
|
+
var SEND_PAY = /^\/gateway\/sendPay;jsessionid=[A-Za-z0-9._!-]{16,128}$/;
|
|
6504
|
+
var own15 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
6505
|
+
var exact4 = (pattern, value) => typeof value === "string" && pattern.test(value);
|
|
6506
|
+
var CARD_RUN = /[0-9]{12}/;
|
|
6507
|
+
var printable5 = (max) => (value) => typeof value === "string" && value.length <= max && /^[\x20-\x7e]*$/.test(value) && !CARD_RUN.test(value);
|
|
6508
|
+
var STAMP = /^(?:|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]\.[0-9]{3})$/;
|
|
6509
|
+
var LANGUAGE4 = /^(?:|[A-Za-z]{2,8}(?:[-_][A-Za-z0-9]{1,8}){0,3})$/;
|
|
6510
|
+
var SHAPES2 = /* @__PURE__ */ new Map([
|
|
6511
|
+
["customerCardType", (v) => v === ""],
|
|
6512
|
+
// The page's paste and typing markers: "0" until typed, the number's length when its key handler read it, or "N"
|
|
6513
|
+
// after a paste.
|
|
6514
|
+
["card_number_three", (v) => exact4(/^(?:0|N|[1-9]|1[0-9])$/, v)],
|
|
6515
|
+
["card_number_two", (v) => exact4(/^(?:0|[1-9]|1[0-9])$/, v)],
|
|
6516
|
+
["card_number_temp", (v) => exact4(/^[0-9]{4}(?: ?[0-9]{4}){3}$/, v)],
|
|
6517
|
+
["card_number", (v) => exact4(/^[0-9]{16}$/, v)],
|
|
6518
|
+
["card_date", (v) => exact4(/^(?:0[1-9]|1[0-2])\/[0-9]{2}$/, v)],
|
|
6519
|
+
["card_year", (v) => exact4(/^20[0-9]{2}$/, v)],
|
|
6520
|
+
["card_month", (v) => exact4(/^(?:0[1-9]|1[0-2])$/, v)],
|
|
6521
|
+
["card_secureCode", (v) => exact4(/^[0-9]{3,4}$/, v)],
|
|
6522
|
+
["copyCard", (v) => v === "" || v === "0" || v === "1"],
|
|
6523
|
+
// PAY NOW's handler sets it to 1 before the page submits.
|
|
6524
|
+
["closePage", (v) => v === "1"],
|
|
6525
|
+
["starttime", (v) => exact4(STAMP, v)],
|
|
6526
|
+
["endtime", (v) => exact4(STAMP, v)],
|
|
6527
|
+
["comloadpage", (v) => v === "0" || v === "1"],
|
|
6528
|
+
// getTimezoneOffset()/60*-1: whole or fractional hours.
|
|
6529
|
+
["timezone", (v) => exact4(/^(?:|-?(?:[0-9]|1[0-4])(?:\.[0-9]{1,2})?)$/, v)],
|
|
6530
|
+
["OSLang", (v) => exact4(LANGUAGE4, v)],
|
|
6531
|
+
["os", printable5(64)],
|
|
6532
|
+
["brower", printable5(128)],
|
|
6533
|
+
["BrowerLang", (v) => exact4(LANGUAGE4, v)],
|
|
6534
|
+
["resolution", printable5(32)],
|
|
6535
|
+
["methods", (v) => v === "1"],
|
|
6536
|
+
["reference_id", (v) => v === ""],
|
|
6537
|
+
// The page's own trade number.
|
|
6538
|
+
["reference", (v) => exact4(/^[0-9]{1,40}$/, v)],
|
|
6539
|
+
["button", (v) => v === ""]
|
|
6540
|
+
]);
|
|
6541
|
+
function oceanpaymentSendPayUrl(url) {
|
|
6542
|
+
if (typeof url !== "string" || url.length > URL_LIMIT14 || url.includes("?") || url.includes("#"))
|
|
6543
|
+
return null;
|
|
6544
|
+
let parsed;
|
|
6545
|
+
try {
|
|
6546
|
+
parsed = new URL(url);
|
|
6547
|
+
}
|
|
6548
|
+
catch {
|
|
6549
|
+
return null;
|
|
6550
|
+
}
|
|
6551
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !own15(OCEANPAYMENT_HOSTS, parsed.hostname) || !SEND_PAY.test(parsed.pathname))
|
|
6552
|
+
return null;
|
|
6553
|
+
return Object.freeze({ host: parsed.hostname, environment: OCEANPAYMENT_HOSTS[parsed.hostname] });
|
|
6554
|
+
}
|
|
6555
|
+
var isOceanpaymentSendPayUrl = (url) => oceanpaymentSendPayUrl(url) !== null;
|
|
6556
|
+
function formEncode3(value) {
|
|
6557
|
+
let encoded;
|
|
6558
|
+
try {
|
|
6559
|
+
encoded = encodeURIComponent(value);
|
|
6560
|
+
}
|
|
6561
|
+
catch {
|
|
6562
|
+
return null;
|
|
6563
|
+
}
|
|
6564
|
+
return encoded.replace(/[!'()~]/g, (ch) => `%${ch.charCodeAt(0).toString(16).toUpperCase()}`).replace(/%20/g, "+");
|
|
6565
|
+
}
|
|
6566
|
+
function formDecode2(raw) {
|
|
6567
|
+
if (!/^(?:[A-Za-z0-9*._+-]|%[0-9A-F]{2})*$/.test(raw))
|
|
6568
|
+
return null;
|
|
6569
|
+
let value;
|
|
6570
|
+
try {
|
|
6571
|
+
value = decodeURIComponent(raw.replace(/\+/g, "%20"));
|
|
6572
|
+
}
|
|
6573
|
+
catch {
|
|
6574
|
+
return null;
|
|
6575
|
+
}
|
|
6576
|
+
return formEncode3(value) === raw ? value : null;
|
|
6577
|
+
}
|
|
6578
|
+
function readPairs2(body) {
|
|
6579
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT38)
|
|
6580
|
+
return null;
|
|
6581
|
+
const pairs = [];
|
|
6582
|
+
for (const chunk of body.split("&")) {
|
|
6583
|
+
const separator = chunk.indexOf("=");
|
|
6584
|
+
if (separator < 1)
|
|
6585
|
+
return null;
|
|
6586
|
+
const rawName = chunk.slice(0, separator), raw = chunk.slice(separator + 1);
|
|
6587
|
+
const name = formDecode2(rawName), value = formDecode2(raw);
|
|
6588
|
+
if (name === null || value === null)
|
|
6589
|
+
return null;
|
|
6590
|
+
pairs.push({ name, rawName, raw, value });
|
|
6591
|
+
}
|
|
6592
|
+
return pairs;
|
|
6593
|
+
}
|
|
6594
|
+
function formPairs(body) {
|
|
6595
|
+
const pairs = readPairs2(body);
|
|
6596
|
+
if (!pairs)
|
|
6597
|
+
return null;
|
|
6598
|
+
const start = pairs[0].name === "customerCardType" ? 1 : 0;
|
|
6599
|
+
const end = pairs[pairs.length - 1].name === "button" ? pairs.length - 1 : pairs.length;
|
|
6600
|
+
if (end - start !== OCEANPAYMENT_FORM_FIELDS.length || OCEANPAYMENT_FORM_FIELDS.some((name, i) => pairs[start + i].name !== name))
|
|
6601
|
+
return null;
|
|
6602
|
+
return pairs;
|
|
6603
|
+
}
|
|
6604
|
+
var valueOf = (pairs, name) => pairs.find((pair) => pair.name === name)?.value;
|
|
6605
|
+
function bodyRefusal(body) {
|
|
6606
|
+
const pairs = formPairs(body);
|
|
6607
|
+
if (!pairs)
|
|
6608
|
+
return "oceanpayment_body_unsupported";
|
|
6609
|
+
if (pairs[0].name === "customerCardType" && pairs[0].value !== "")
|
|
6610
|
+
return "oceanpayment_card_brand_refused";
|
|
6611
|
+
if (valueOf(pairs, "reference_id") !== "")
|
|
6612
|
+
return "oceanpayment_device_data_refused";
|
|
6613
|
+
if (pairs.some(({ name, value }) => !SHAPES2.get(name)(value)))
|
|
6614
|
+
return "oceanpayment_body_unsupported";
|
|
6615
|
+
const number = valueOf(pairs, "card_number");
|
|
6616
|
+
const temp = valueOf(pairs, "card_number_temp");
|
|
6617
|
+
const [month, year] = valueOf(pairs, "card_date").split("/");
|
|
6618
|
+
if (temp.replace(/ /g, "") !== number || temp !== number && temp !== spaced(number))
|
|
6619
|
+
return "oceanpayment_body_unsupported";
|
|
6620
|
+
if (valueOf(pairs, "card_month") !== month || valueOf(pairs, "card_year") !== `20${year}`)
|
|
6621
|
+
return "oceanpayment_body_unsupported";
|
|
6622
|
+
return null;
|
|
6623
|
+
}
|
|
6624
|
+
var spaced = (number) => number.replace(/([0-9]{4})(?=[0-9])/g, "$1 ");
|
|
6625
|
+
function oceanpaymentBodyVerdict(body) {
|
|
6626
|
+
const code = bodyRefusal(body);
|
|
6627
|
+
return code ? Object.freeze({ verdict: "refuse", code }) : Object.freeze({ verdict: "card" });
|
|
6628
|
+
}
|
|
6629
|
+
var oceanpayment_default = /* @__PURE__ */ registerProcessor({
|
|
6630
|
+
psp: OCEANPAYMENT_PSP,
|
|
6631
|
+
definitions: [
|
|
6632
|
+
{
|
|
6633
|
+
psp: "oceanpayment",
|
|
6634
|
+
// The hosted page's card post, as the header above reads it. The sandbox has its own host, so a test row's device
|
|
6635
|
+
// sends only Oceanpayment's documented test cards (hostEnvironmentPinned, device-replay.js S7).
|
|
6636
|
+
// Ships dark: served only to a client that declares `oceanpayment_hosted_payment_page`, and only for a company the
|
|
6637
|
+
// backend's processor gate turns Oceanpayment on for. `(?![\w/.%;=!-])` ends the path for a consumer that tests
|
|
6638
|
+
// `match` unanchored.
|
|
6639
|
+
capability: "oceanpayment_hosted_payment_page",
|
|
6640
|
+
match: "(?:test-)?secure\\.oceanpayment\\.com/gateway/sendPay;jsessionid=[A-Za-z0-9._!-]{16,128}(?![\\w/.%;=!-])",
|
|
6641
|
+
hosts: ["^secure\\.oceanpayment\\.com$", "^test-secure\\.oceanpayment\\.com$"],
|
|
6642
|
+
sandboxHosts: ["^test-secure\\.oceanpayment\\.com$"],
|
|
6643
|
+
hostEnvironmentPinned: true,
|
|
6644
|
+
encoding: "form",
|
|
6645
|
+
// A form navigation: nothing but its type is replayed. Origin, Referer and cookies never ride.
|
|
6646
|
+
passthroughHeaders: [],
|
|
6647
|
+
cardFields: ["card_number"]
|
|
6648
|
+
}
|
|
6649
|
+
],
|
|
6650
|
+
// Only the cardholder's device sends this card, after a person approves; no reviewed list names oceanpayment.
|
|
6651
|
+
refusedOperations: [OCEANPAYMENT_OPERATION],
|
|
6652
|
+
// Not surveyed: Oceanpayment tells the merchant's server the result (its noticeUrl), and reading a payment back takes the
|
|
6653
|
+
// merchant's own secure code, which Agentcard never holds.
|
|
6654
|
+
settlementReadback: "not_surveyed",
|
|
6655
|
+
exactUrl: isOceanpaymentSendPayUrl,
|
|
6656
|
+
bodyGate: (url, body) => url !== void 0 && !isOceanpaymentSendPayUrl(url) ? Object.freeze({ verdict: "refuse", code: "oceanpayment_url_refused" }) : oceanpaymentBodyVerdict(body)
|
|
6657
|
+
// No amount reader: the post names none, so the agent's pair is the figure the cardholder approves.
|
|
6658
|
+
});
|
|
6659
|
+
// src/processors/paymentwall.js
|
|
6660
|
+
var PAYMENTWALL_PSP = "paymentwall";
|
|
6661
|
+
var PAYMENTWALL_OPERATION = "paymentwall.card_request";
|
|
6662
|
+
var PAYMENTWALL_TOKEN_URL = "https://pwgateway.com/api/token";
|
|
6663
|
+
var PAYMENTWALL_SANDBOX_TOKEN_URL = "https://api.paymentwall.com/api/brick/token";
|
|
6664
|
+
var BODY_LIMIT39 = 2048;
|
|
6665
|
+
var KEY3 = "public_key";
|
|
6666
|
+
var PUBLIC_KEY2 = /^(?:t_)?[A-Za-z0-9]{16,64}$/;
|
|
6667
|
+
var SHAPES3 = /* @__PURE__ */ Object.freeze({
|
|
6668
|
+
[KEY3]: PUBLIC_KEY2,
|
|
6669
|
+
"card[number]": /^[0-9]{12,19}$/,
|
|
6670
|
+
"card[exp_month]": /^(?:0?[1-9]|1[0-2])$/,
|
|
6671
|
+
"card[exp_year]": /^(?:[0-9]{2}|20[0-9]{2})$/,
|
|
6672
|
+
"card[cvv]": /^[0-9]{3,4}$/
|
|
6673
|
+
});
|
|
6674
|
+
var refuse40 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
6675
|
+
var CARD39 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
6676
|
+
function luhn9(digits4) {
|
|
6677
|
+
let sum = 0;
|
|
6678
|
+
for (let at = 0; at < digits4.length; at += 1) {
|
|
6679
|
+
let digit = Number(digits4[digits4.length - 1 - at]);
|
|
6680
|
+
if (at % 2 === 1) {
|
|
6681
|
+
digit *= 2;
|
|
6682
|
+
if (digit > 9)
|
|
6683
|
+
digit -= 9;
|
|
6684
|
+
}
|
|
6685
|
+
sum += digit;
|
|
6686
|
+
}
|
|
6687
|
+
return sum % 10 === 0;
|
|
6688
|
+
}
|
|
6689
|
+
function paymentwallUrlEnvironment(url) {
|
|
6690
|
+
if (url === PAYMENTWALL_TOKEN_URL)
|
|
6691
|
+
return "production";
|
|
6692
|
+
return url === PAYMENTWALL_SANDBOX_TOKEN_URL ? "sandbox" : null;
|
|
6693
|
+
}
|
|
6694
|
+
function isPaymentwallTokenUrl(url) {
|
|
6695
|
+
return paymentwallUrlEnvironment(url) !== null;
|
|
6696
|
+
}
|
|
6697
|
+
function paymentwallKeyEnvironment(publicKey) {
|
|
6698
|
+
if (typeof publicKey !== "string" || !PUBLIC_KEY2.test(publicKey))
|
|
6699
|
+
return null;
|
|
6700
|
+
return publicKey.startsWith("t_") ? "sandbox" : "production";
|
|
6701
|
+
}
|
|
6702
|
+
function readPairs3(body) {
|
|
6703
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT39 || !/^[A-Za-z0-9_[\]=&]+$/.test(body))
|
|
6704
|
+
return null;
|
|
6705
|
+
const pairs = /* @__PURE__ */ new Map();
|
|
6706
|
+
for (const chunk of body.split("&")) {
|
|
6707
|
+
const eq = chunk.indexOf("=");
|
|
6708
|
+
if (eq <= 0 || chunk.indexOf("=", eq + 1) !== -1)
|
|
6709
|
+
return null;
|
|
6710
|
+
const key = chunk.slice(0, eq);
|
|
6711
|
+
if (pairs.has(key))
|
|
6712
|
+
return null;
|
|
6713
|
+
pairs.set(key, chunk.slice(eq + 1));
|
|
6714
|
+
}
|
|
6715
|
+
return pairs;
|
|
6716
|
+
}
|
|
6717
|
+
function paymentwallBodyVerdict(body, url) {
|
|
6718
|
+
if (url !== void 0 && !isPaymentwallTokenUrl(url))
|
|
6719
|
+
return refuse40("paymentwall_url_refused");
|
|
6720
|
+
const pairs = readPairs3(body);
|
|
6721
|
+
if (pairs === null)
|
|
6722
|
+
return refuse40("paymentwall_body_unsupported");
|
|
6723
|
+
if (pairs.has("card[token]") && !pairs.has("card[number]"))
|
|
6724
|
+
return refuse40("paymentwall_saved_card");
|
|
6725
|
+
const keys = Object.keys(SHAPES3);
|
|
6726
|
+
if (pairs.size !== keys.length || !keys.every((key) => pairs.has(key) && SHAPES3[key].test(pairs.get(key)))) {
|
|
6727
|
+
return refuse40("paymentwall_body_unsupported");
|
|
6728
|
+
}
|
|
6729
|
+
if (!luhn9(pairs.get("card[number]")))
|
|
6730
|
+
return refuse40("paymentwall_body_unsupported");
|
|
6731
|
+
if (url !== void 0 && paymentwallKeyEnvironment(pairs.get(KEY3)) !== paymentwallUrlEnvironment(url))
|
|
6732
|
+
return refuse40("paymentwall_key_refused");
|
|
6733
|
+
return CARD39;
|
|
6734
|
+
}
|
|
6735
|
+
var paymentwall_default = /* @__PURE__ */ registerProcessor({
|
|
6736
|
+
psp: PAYMENTWALL_PSP,
|
|
6737
|
+
definitions: [
|
|
6738
|
+
{
|
|
6739
|
+
psp: "paymentwall",
|
|
6740
|
+
// Brick's token request, as the header above reads it. A test key's request has its own host, so the device sends
|
|
6741
|
+
// it only Paymentwall's documented test cards (hostEnvironmentPinned, device-replay.js S7). Ships dark: served only
|
|
6742
|
+
// to a client that declares `paymentwall_card_token`, for a company the backend's gate turns it on for
|
|
6743
|
+
// (checkout-processor-gate.ts), and the device sends a live card only under a key a reviewed pin names.
|
|
6744
|
+
capability: "paymentwall_card_token",
|
|
6745
|
+
match: "(?:pwgateway\\.com/api/token|api\\.paymentwall\\.com/api/brick/token)",
|
|
6746
|
+
hosts: ["^pwgateway\\.com$", "^api\\.paymentwall\\.com$"],
|
|
6747
|
+
sandboxHosts: ["^api\\.paymentwall\\.com$"],
|
|
6748
|
+
hostEnvironmentPinned: true,
|
|
6749
|
+
encoding: "form",
|
|
6750
|
+
// Brick's XHR sets the form Content-Type alone, and that always rides. Origin, Referer and cookies never do.
|
|
6751
|
+
passthroughHeaders: [],
|
|
6752
|
+
cardFields: ["card[number]"]
|
|
6753
|
+
}
|
|
6754
|
+
],
|
|
6755
|
+
// Only the cardholder's device sends a card request, after a person approves; no reviewed list names paymentwall.
|
|
6756
|
+
refusedOperations: [PAYMENTWALL_OPERATION],
|
|
6757
|
+
// Not surveyed: the token moves no money, and the charge that spends it happens out of this request.
|
|
6758
|
+
settlementReadback: "not_surveyed",
|
|
6759
|
+
exactUrl: isPaymentwallTokenUrl,
|
|
6760
|
+
bodyGate: (url, body) => paymentwallBodyVerdict(body, url)
|
|
6761
|
+
});
|
|
6762
|
+
// src/processors/ekashu.js
|
|
6763
|
+
var EKASHU_HOSTS = Object.freeze(["live.ekashu.com", "test.ekashu.com"]);
|
|
6764
|
+
var EKASHU_TEST_PANS = Object.freeze(["4100000000000100", "5100000000000107"]);
|
|
6765
|
+
var EKASHU_SIGNED_FIELDS = Object.freeze([
|
|
6766
|
+
"ekashu_3d_secure_verify",
|
|
6767
|
+
"ekashu_amount",
|
|
6768
|
+
"ekashu_amount_format",
|
|
6769
|
+
"ekashu_auto_confirm",
|
|
6770
|
+
"ekashu_callback_failure_url",
|
|
6771
|
+
"ekashu_callback_include_post",
|
|
6772
|
+
"ekashu_callback_success_url",
|
|
6773
|
+
"ekashu_card_address_editable",
|
|
6774
|
+
"ekashu_card_address_required",
|
|
6775
|
+
"ekashu_card_address_verify",
|
|
6776
|
+
"ekashu_card_email_address_mandatory",
|
|
6777
|
+
"ekashu_card_phone_number_mandatory",
|
|
6778
|
+
"ekashu_card_title_mandatory",
|
|
6779
|
+
"ekashu_card_zip_code_verify",
|
|
6780
|
+
"ekashu_currency",
|
|
6781
|
+
"ekashu_delivery_address_editable",
|
|
6782
|
+
"ekashu_delivery_address_required",
|
|
6783
|
+
"ekashu_delivery_email_address_mandatory",
|
|
6784
|
+
"ekashu_delivery_phone_number_mandatory",
|
|
6785
|
+
"ekashu_delivery_title_mandatory",
|
|
6786
|
+
"ekashu_description",
|
|
6787
|
+
"ekashu_device",
|
|
6788
|
+
"ekashu_duplicate_check",
|
|
6789
|
+
"ekashu_duplicate_minutes",
|
|
6790
|
+
"ekashu_failure_return_text",
|
|
6791
|
+
"ekashu_failure_url",
|
|
6792
|
+
"ekashu_hash_code_format",
|
|
6793
|
+
"ekashu_hash_code_type",
|
|
6794
|
+
"ekashu_hash_code_version",
|
|
6795
|
+
"ekashu_include_post",
|
|
6796
|
+
"ekashu_invoice_address_editable",
|
|
6797
|
+
"ekashu_invoice_address_required",
|
|
6798
|
+
"ekashu_invoice_email_address_mandatory",
|
|
6799
|
+
"ekashu_invoice_phone_number_mandatory",
|
|
6800
|
+
"ekashu_invoice_title_mandatory",
|
|
6801
|
+
"ekashu_locale",
|
|
6802
|
+
"ekashu_payment_methods",
|
|
6803
|
+
"ekashu_reference",
|
|
6804
|
+
"ekashu_request_type",
|
|
6805
|
+
"ekashu_return_text",
|
|
6806
|
+
"ekashu_seller_address",
|
|
6807
|
+
"ekashu_seller_email_address",
|
|
6808
|
+
"ekashu_seller_id",
|
|
6809
|
+
"ekashu_seller_key",
|
|
6810
|
+
"ekashu_seller_name",
|
|
6811
|
+
"ekashu_shortcut_icon",
|
|
6812
|
+
"ekashu_style_sheet",
|
|
6813
|
+
"ekashu_success_url",
|
|
6814
|
+
"ekashu_title",
|
|
6815
|
+
"ekashu_verification_value_mask",
|
|
6816
|
+
"ekashu_verification_value_verify",
|
|
6817
|
+
"ekashu_viewport"
|
|
6818
|
+
]);
|
|
6819
|
+
var REQUIRED = Object.freeze([
|
|
6820
|
+
"ekashu_seller_id",
|
|
6821
|
+
"ekashu_seller_key",
|
|
6822
|
+
"ekashu_amount",
|
|
6823
|
+
"ekashu_currency",
|
|
6824
|
+
"ekashu_reference",
|
|
6825
|
+
"ekashu_hash_code",
|
|
6826
|
+
"ekashu_hash_code_type",
|
|
6827
|
+
"ekashu_hash_code_version",
|
|
6828
|
+
"ekashu_success_url",
|
|
6829
|
+
"ekashu_failure_url",
|
|
6830
|
+
"ekashu_callback_success_url"
|
|
6831
|
+
]);
|
|
6832
|
+
var CARD_KEYS16 = Object.freeze([
|
|
6833
|
+
"ekashu_card_number",
|
|
6834
|
+
"ekashu_expires_end_month",
|
|
6835
|
+
"ekashu_expires_end_year",
|
|
6836
|
+
"ekashu_verification_value",
|
|
6837
|
+
"ekashu_valid_from_month",
|
|
6838
|
+
"ekashu_valid_from_year",
|
|
6839
|
+
"ekashu_issue_number"
|
|
6840
|
+
]);
|
|
6841
|
+
var PAGE_KEYS = Object.freeze(["ekashu_stage", "ekashu_context", "ekashu_submission_id"]);
|
|
6842
|
+
var STORED_KEYS = Object.freeze(["ekashu_card_hash", "ekashu_card_reference", "ekashu_cof_initiated_by", "ekashu_cof_reason", "ekashu_cof_id"]);
|
|
6843
|
+
var REDIRECT_KEYS = Object.freeze(["ekashu_success_url", "ekashu_failure_url", "ekashu_return_url"]);
|
|
6844
|
+
var CALLBACK_KEYS = Object.freeze(["ekashu_callback_success_url", "ekashu_callback_failure_url"]);
|
|
6845
|
+
var MAX_ENTRY = 16 * 1024;
|
|
6846
|
+
var MAX_PAGE = 256 * 1024;
|
|
6847
|
+
var EKASHU_SELLERS = Object.freeze([
|
|
6848
|
+
Object.freeze({ sellerId: "25060100", merchant: "Heathrow Drop-off", entryHost: "heathrowdropoff.apcoa.com", callbackHost: "incomingapi.apcoa.co.uk" })
|
|
6849
|
+
]);
|
|
6850
|
+
var CARD_FIELDS = Object.freeze({
|
|
6851
|
+
number: "ekashu_card_number",
|
|
6852
|
+
month: "ekashu_expires_end_month",
|
|
6853
|
+
year: "ekashu_expires_end_year",
|
|
6854
|
+
cvc: "ekashu_verification_value"
|
|
6855
|
+
});
|
|
6856
|
+
var NAME_FIELDS = Object.freeze({ first: "ekashu_card_first_name", last: "ekashu_card_last_name" });
|
|
6857
|
+
var LEFT_EMPTY = Object.freeze(["ekashu_card_title", "ekashu_valid_from_month", "ekashu_valid_from_year", "ekashu_issue_number"]);
|
|
6858
|
+
var VISIBLE = /* @__PURE__ */ new Set([...Object.values(CARD_FIELDS), ...Object.values(NAME_FIELDS), ...LEFT_EMPTY]);
|
|
6859
|
+
// src/processors/payplug.js
|
|
6860
|
+
var PAYPLUG_PSP = "payplug";
|
|
6861
|
+
var PAYPLUG_OPERATION = "payplug.hosted_sale";
|
|
6862
|
+
var PAYPLUG_HOST = "secure.payplug.com";
|
|
6863
|
+
var ENTRY_PATH = /^\/pay\/(?:(test)\/)?([A-Za-z0-9]{22})$/;
|
|
6864
|
+
var MAX_URL = 256;
|
|
6865
|
+
var field2 = (name, reason) => ({ ok: false, code: "hosted_form_field_refused", field: name, reason });
|
|
6866
|
+
function payplugEntry(raw) {
|
|
6867
|
+
if (typeof raw !== "string" || raw.length > MAX_URL || raw.includes("?") || raw.includes("#"))
|
|
6868
|
+
return null;
|
|
6869
|
+
let url;
|
|
6870
|
+
try {
|
|
6871
|
+
url = new URL(raw);
|
|
6872
|
+
}
|
|
6873
|
+
catch {
|
|
6874
|
+
return null;
|
|
6875
|
+
}
|
|
6876
|
+
if (url.href !== raw || url.protocol !== "https:" || url.hostname !== PAYPLUG_HOST || url.port || url.username || url.password)
|
|
6877
|
+
return null;
|
|
6878
|
+
const match = ENTRY_PATH.exec(url.pathname);
|
|
6879
|
+
return match ? Object.freeze({ id: match[2], test: match[1] === "test" }) : null;
|
|
6880
|
+
}
|
|
6881
|
+
function isPayplugEntryUrl(raw) {
|
|
6882
|
+
return payplugEntry(raw) !== null;
|
|
6883
|
+
}
|
|
6884
|
+
var PAYPLUG_MERCHANTS = Object.freeze([
|
|
6885
|
+
Object.freeze({ merchant: "Lazartigue", origins: Object.freeze(["https://lazartigue.com"]), payee: null, account: null })
|
|
6886
|
+
]);
|
|
6887
|
+
var ACCOUNT_ID = /^[A-Za-z0-9-]{1,64}$/;
|
|
6888
|
+
function payplugMerchant(checkoutOrigin, merchants = PAYPLUG_MERCHANTS) {
|
|
6889
|
+
if (typeof checkoutOrigin !== "string" || checkoutOrigin.length > MAX_URL || !Array.isArray(merchants))
|
|
6890
|
+
return null;
|
|
6891
|
+
let url;
|
|
6892
|
+
try {
|
|
6893
|
+
url = new URL(checkoutOrigin);
|
|
6894
|
+
}
|
|
6895
|
+
catch {
|
|
6896
|
+
return null;
|
|
6897
|
+
}
|
|
6898
|
+
if (url.protocol !== "https:" || url.origin !== checkoutOrigin || url.port)
|
|
6899
|
+
return null;
|
|
6900
|
+
const found = merchants.filter((row) => !!row && typeof row.merchant === "string" && row.merchant.trim() !== "" && typeof row.payee === "string" && row.payee.trim() !== "" && typeof row.account === "string" && ACCOUNT_ID.test(row.account) && Array.isArray(row.origins) && row.origins.includes(checkoutOrigin));
|
|
6901
|
+
return found.length === 1 ? found[0] : null;
|
|
6902
|
+
}
|
|
6903
|
+
function checkPayplugEntry(body, { url = null, checkoutOrigin = null, merchants = PAYPLUG_MERCHANTS } = {}) {
|
|
6904
|
+
if (body !== void 0 && body !== null && body !== "")
|
|
6905
|
+
return field2("(body)", "not_an_entry");
|
|
6906
|
+
const entry = payplugEntry(url);
|
|
6907
|
+
if (!entry)
|
|
6908
|
+
return field2("(url)", "malformed_field");
|
|
6909
|
+
const seller = payplugMerchant(checkoutOrigin, merchants);
|
|
6910
|
+
if (!seller)
|
|
6911
|
+
return field2("(checkout_origin)", "seller_unreviewed");
|
|
6912
|
+
return { ok: true, pairs: [], gated: false, dedupe: [entry.id], paymentId: entry.id, sandbox: entry.test, seller };
|
|
6913
|
+
}
|
|
6914
|
+
var MAX_PAGE2 = 512 * 1024;
|
|
6915
|
+
var PAYPLUG_REFUSALS = Object.freeze(["payplug_failed", "payplug_expired", "payplug_cancelled"]);
|
|
6916
|
+
var payplug_default = /* @__PURE__ */ registerProcessor({
|
|
6917
|
+
psp: PAYPLUG_PSP,
|
|
6918
|
+
definitions: [
|
|
6919
|
+
{
|
|
6920
|
+
psp: "payplug",
|
|
6921
|
+
// The merchant's redirect to PayPlug's payment page, as the header above reads it: a Document navigation that
|
|
6922
|
+
// carries no card. The cardholder's device repeats it over the end-to-end TLS relay and pays on the page PayPlug
|
|
6923
|
+
// returns to it, and the runtime resolves the paused navigation with the hosted_form notice. Only the entry is
|
|
6924
|
+
// matched (isPayplugEntryUrl): the page's card post and its 3-D Secure steps share the host, and none of them is
|
|
6925
|
+
// the entry. Test and live payments share the host, and the entry's path says which it is. Ships dark: served
|
|
6926
|
+
// only to a client that declares `payplug_hosted_payment_page`, and the backend's gate serves only Agentcard's
|
|
6927
|
+
// own company until a reviewed merchant pays.
|
|
6928
|
+
capability: "payplug_hosted_payment_page",
|
|
6929
|
+
match: "secure\\.payplug\\.com/pay/(?:test/)?[A-Za-z0-9]{22}",
|
|
6930
|
+
hosts: ["^secure\\.payplug\\.com$"],
|
|
6931
|
+
// `encoding` describes the page's own card post, which the device makes as the page does, since the entry has no
|
|
6932
|
+
// body. No captured header is ever replayed.
|
|
6933
|
+
encoding: "form",
|
|
6934
|
+
passthroughHeaders: [],
|
|
6935
|
+
request: { method: "GET", cardIn: "none", response: "html_page" },
|
|
6936
|
+
mode: "hosted_form",
|
|
6937
|
+
hostedForm: {
|
|
6938
|
+
// The card goes into PayPlug's page on the device, never into the entry, which carries no body at all. The
|
|
6939
|
+
// entry's own rules come with this registration (hostedEntry below), so no policy is named here.
|
|
6940
|
+
cardIn: "processor_page",
|
|
6941
|
+
required: [],
|
|
6942
|
+
// The page's card inputs, by the data-payplug role its script reads them by: they carry no name, and the
|
|
6943
|
+
// script posts the card only as its ciphertext, encryptedCard.
|
|
6944
|
+
card: { number: "card_number", expiry: "card_month_year", cvc: "card_cvv" },
|
|
6945
|
+
// The payment's id in the entry's URL names the one payment the merchant created; the entry's rules read it
|
|
6946
|
+
// there (checkPayplugEntry's dedupe), since no form field holds it.
|
|
6947
|
+
dedupe: ["(paymentId)"]
|
|
6948
|
+
}
|
|
6949
|
+
}
|
|
6950
|
+
],
|
|
6951
|
+
// Only the cardholder's device repeats an entry, after a person approves; no reviewed list names payplug.
|
|
6952
|
+
refusedOperations: [PAYPLUG_OPERATION],
|
|
6953
|
+
// Not surveyed: PayPlug tells only the merchant's server the result, and the browser returns whatever it was.
|
|
6954
|
+
settlementReadback: "not_surveyed",
|
|
6955
|
+
exactUrl: isPayplugEntryUrl,
|
|
6956
|
+
hostedEntry: checkPayplugEntry,
|
|
6957
|
+
limitations: [
|
|
6958
|
+
"The paused request is the merchant's redirect to PayPlug's payment page, a GET that carries only the payment's id and no card; the cardholder's device opens that page over the end-to-end TLS relay.",
|
|
6959
|
+
"The redirect names no merchant and no amount, so Agentcard takes one only from the checkout page of a merchant it reviewed, the approval names that merchant and the amount you send, and the cardholder's device pays only a PayPlug page that names that merchant and that amount.",
|
|
6960
|
+
"PayPlug runs 3-D Secure on the card. A challenge ends the payment on the device with nothing charged.",
|
|
6961
|
+
"PayPlug sends the buyer to the merchant's return page whether the payment succeeded or not, so the browser receives a submission notice, not the processor result."
|
|
6962
|
+
]
|
|
6963
|
+
});
|
|
6964
|
+
// src/processors/processout.js
|
|
6965
|
+
var PROCESSOUT_PSP = "processout";
|
|
6966
|
+
var PROCESSOUT_OPERATION = "processout.card_request";
|
|
6967
|
+
var URL_LIMIT15 = 512;
|
|
6968
|
+
var BODY_LIMIT40 = 4096;
|
|
6969
|
+
var CARD_URL2 = /^https:\/\/api\.processout\.com\/cards\?legacyrequest=true&project_id=((?:test-)?proj_[A-Za-z0-9]{16,64})&x-Content-Type=application\/json&x-API-Version=1\.3\.0\.0&x-Authorization=Basic%20([A-Za-z0-9+/]{4,256}={0,2})$/;
|
|
6970
|
+
var PAGE_KEYS2 = /* @__PURE__ */ Object.freeze(["name", "contact", "preferred_scheme"]);
|
|
6971
|
+
var CONTACT_KEYS = /* @__PURE__ */ Object.freeze(["address1", "address2", "city", "state", "country_code", "zip"]);
|
|
6972
|
+
var DEVICE_KEYS4 = /* @__PURE__ */ Object.freeze([
|
|
6973
|
+
"request_origin",
|
|
6974
|
+
"app_color_depth",
|
|
6975
|
+
"app_language",
|
|
6976
|
+
"app_screen_height",
|
|
6977
|
+
"app_screen_width",
|
|
6978
|
+
"app_timezone_offset",
|
|
6979
|
+
"app_java_enabled"
|
|
6980
|
+
]);
|
|
6981
|
+
var PROCESSOUT_CARD_KEYS = /* @__PURE__ */ Object.freeze(["number", "exp_month", "exp_year", "cvc2"]);
|
|
6982
|
+
var BODY_KEYS3 = /* @__PURE__ */ new Set([...PAGE_KEYS2, "device", ...DEVICE_KEYS4, ...PROCESSOUT_CARD_KEYS]);
|
|
6983
|
+
var NUMBER8 = /^[0-9]{12,19}$/;
|
|
6984
|
+
var MONTH21 = /^(?:[1-9]|1[0-2])$/;
|
|
6985
|
+
var YEAR22 = /^20[0-9]{2}$/;
|
|
6986
|
+
var CODE8 = /^[0-9]{3,4}$/;
|
|
6987
|
+
var TEXT_LIMIT14 = 256;
|
|
6988
|
+
var SCHEME = /^[A-Za-z][A-Za-z0-9 _-]{0,31}$/;
|
|
6989
|
+
var LANGUAGE5 = /^[A-Za-z]{1,8}(?:-[A-Za-z0-9]{1,8}){0,4}$/;
|
|
6990
|
+
var PAN_LIKE7 = /(?:[0-9][^0-9A-Za-z]*){12,}/;
|
|
6991
|
+
var record35 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
6992
|
+
var own16 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
6993
|
+
var refuse41 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
6994
|
+
var CARD40 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
6995
|
+
var BASE646 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
6996
|
+
function base64Of(text10) {
|
|
6997
|
+
let out = "";
|
|
6998
|
+
for (let at = 0; at < text10.length; at += 3) {
|
|
6999
|
+
const a = text10.charCodeAt(at);
|
|
7000
|
+
const b = at + 1 < text10.length ? text10.charCodeAt(at + 1) : NaN;
|
|
7001
|
+
const c = at + 2 < text10.length ? text10.charCodeAt(at + 2) : NaN;
|
|
7002
|
+
out += BASE646[a >> 2] + BASE646[(a & 3) << 4 | (Number.isNaN(b) ? 0 : b >> 4)] + (Number.isNaN(b) ? "=" : BASE646[(b & 15) << 2 | (Number.isNaN(c) ? 0 : c >> 6)]) + (Number.isNaN(c) ? "=" : BASE646[c & 63]);
|
|
7003
|
+
}
|
|
7004
|
+
return out;
|
|
7005
|
+
}
|
|
7006
|
+
var basicOf = (projectId) => base64Of(`${projectId}:`);
|
|
7007
|
+
function luhn10(digits4) {
|
|
7008
|
+
let sum = 0;
|
|
7009
|
+
for (let at = 0; at < digits4.length; at += 1) {
|
|
7010
|
+
let digit = Number(digits4[digits4.length - 1 - at]);
|
|
7011
|
+
if (at % 2 === 1) {
|
|
7012
|
+
digit *= 2;
|
|
7013
|
+
if (digit > 9)
|
|
7014
|
+
digit -= 9;
|
|
7015
|
+
}
|
|
7016
|
+
sum += digit;
|
|
7017
|
+
}
|
|
7018
|
+
return sum % 10 === 0;
|
|
7019
|
+
}
|
|
7020
|
+
function processoutCardTarget(url) {
|
|
7021
|
+
if (typeof url !== "string" || url.length > URL_LIMIT15)
|
|
7022
|
+
return null;
|
|
7023
|
+
const match = CARD_URL2.exec(url);
|
|
7024
|
+
if (!match || match[2] !== basicOf(match[1]))
|
|
7025
|
+
return null;
|
|
7026
|
+
return Object.freeze({ projectId: match[1], environment: match[1].startsWith("test-") ? "sandbox" : "production" });
|
|
7027
|
+
}
|
|
7028
|
+
function isProcessoutCardUrl(url) {
|
|
7029
|
+
return processoutCardTarget(url) !== null;
|
|
7030
|
+
}
|
|
7031
|
+
function readBody24(body) {
|
|
7032
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT40)
|
|
7033
|
+
return null;
|
|
7034
|
+
try {
|
|
7035
|
+
const value = JSON.parse(body);
|
|
7036
|
+
return record35(value) && JSON.stringify(value) === body ? value : null;
|
|
7037
|
+
}
|
|
7038
|
+
catch {
|
|
7039
|
+
return null;
|
|
7040
|
+
}
|
|
7041
|
+
}
|
|
7042
|
+
var pageText2 = (value) => value === null || typeof value === "string" && value.length <= TEXT_LIMIT14 && !PAN_LIKE7.test(value);
|
|
7043
|
+
var DEVICE_RULES = /* @__PURE__ */ Object.freeze({
|
|
7044
|
+
request_origin: (value) => value === "web",
|
|
7045
|
+
app_color_depth: (value) => Number.isSafeInteger(value) && value >= 1 && value <= 64,
|
|
7046
|
+
app_language: (value) => typeof value === "string" && value.length <= 64 && LANGUAGE5.test(value),
|
|
7047
|
+
app_screen_height: (value) => Number.isSafeInteger(value) && value >= 1 && value <= 1e5,
|
|
7048
|
+
app_screen_width: (value) => Number.isSafeInteger(value) && value >= 1 && value <= 1e5,
|
|
7049
|
+
app_timezone_offset: (value) => Number.isSafeInteger(value) && value >= -1440 && value <= 1440,
|
|
7050
|
+
app_java_enabled: (value) => typeof value === "boolean"
|
|
7051
|
+
});
|
|
7052
|
+
function soundDevice3(value) {
|
|
7053
|
+
const device = value.device;
|
|
7054
|
+
if (!record35(device) || !own16(device, "request_origin") || !own16(device, "app_timezone_offset"))
|
|
7055
|
+
return false;
|
|
7056
|
+
return DEVICE_KEYS4.every((key) => own16(device, key) ? DEVICE_RULES[key](device[key]) && own16(value, key) && value[key] === device[key] : !own16(value, key)) && Object.keys(device).every((key) => DEVICE_KEYS4.includes(key));
|
|
7057
|
+
}
|
|
7058
|
+
function soundPageData(value) {
|
|
7059
|
+
if (own16(value, "name") && !pageText2(value.name))
|
|
7060
|
+
return false;
|
|
7061
|
+
if (own16(value, "preferred_scheme") && !(value.preferred_scheme === null || typeof value.preferred_scheme === "string" && SCHEME.test(value.preferred_scheme)))
|
|
7062
|
+
return false;
|
|
7063
|
+
const contact = value.contact;
|
|
7064
|
+
return record35(contact) && Object.keys(contact).every((key) => CONTACT_KEYS.includes(key) && pageText2(contact[key]));
|
|
7065
|
+
}
|
|
7066
|
+
function processoutBodyVerdict(body, url) {
|
|
7067
|
+
if (url !== void 0 && processoutCardTarget(url) === null)
|
|
7068
|
+
return refuse41("processout_url_refused");
|
|
7069
|
+
const value = readBody24(body);
|
|
7070
|
+
if (value === null || !Object.keys(value).every((key) => BODY_KEYS3.has(key)))
|
|
7071
|
+
return refuse41("processout_body_unsupported");
|
|
7072
|
+
if (!PROCESSOUT_CARD_KEYS.every((key) => typeof value[key] === "string"))
|
|
7073
|
+
return refuse41("processout_body_unsupported");
|
|
7074
|
+
if (!NUMBER8.test(value.number) || !luhn10(value.number) || !MONTH21.test(value.exp_month) || !YEAR22.test(value.exp_year) || !CODE8.test(value.cvc2))
|
|
7075
|
+
return refuse41("processout_body_unsupported");
|
|
7076
|
+
if (!soundPageData(value) || !soundDevice3(value))
|
|
7077
|
+
return refuse41("processout_body_unsupported");
|
|
7078
|
+
return CARD40;
|
|
7079
|
+
}
|
|
7080
|
+
var processout_default = /* @__PURE__ */ registerProcessor({
|
|
7081
|
+
psp: PROCESSOUT_PSP,
|
|
7082
|
+
definitions: [
|
|
7083
|
+
{
|
|
7084
|
+
psp: "processout",
|
|
7085
|
+
// ProcessOut.js's card request, as the header above reads it. One host serves every project, live and sandbox
|
|
7086
|
+
// alike, so no sandbox host is marked: the project id names the environment, and the device sends a sandbox
|
|
7087
|
+
// project only ProcessOut's documented test cards (processoutDeviceRefusal). The page gives up 20 seconds after
|
|
7088
|
+
// its tokenize message, so the lane is prepared only (preparationRequired). The match reads the host and the path,
|
|
7089
|
+
// and ends where the path does, as Pin Payments' does: a card's own record under /cards/, where the code refresh
|
|
7090
|
+
// goes, is never paused. The exact-URL rule below holds the query, the project id and its Basic credential among it.
|
|
7091
|
+
// Ships dark: served only to a client that declares `processout_card_token`, and gated off for every org until
|
|
7092
|
+
// the backend's gate names one.
|
|
7093
|
+
capability: "processout_card_token",
|
|
7094
|
+
match: "api\\.processout\\.com/cards(?![\\w/.%-])",
|
|
7095
|
+
hosts: ["^api\\.processout\\.com$"],
|
|
7096
|
+
preparationRequired: true,
|
|
7097
|
+
encoding: "json",
|
|
7098
|
+
// ProcessOut.js's own headers: the project's Basic credential and the API version. Origin, Referer and cookies
|
|
7099
|
+
// never ride.
|
|
7100
|
+
passthroughHeaders: ["^authorization$", "^api-version$"],
|
|
7101
|
+
jsonCardFields: [["number"]]
|
|
7102
|
+
}
|
|
7103
|
+
],
|
|
7104
|
+
// Only the cardholder's device sends a card, after a person approves; no reviewed list names processout.
|
|
7105
|
+
refusedOperations: [PROCESSOUT_OPERATION],
|
|
7106
|
+
// Not surveyed: the card request mints a token and moves no money; the store's server charges it under its own
|
|
7107
|
+
// secret key, which Agentcard never holds.
|
|
7108
|
+
settlementReadback: "not_surveyed",
|
|
7109
|
+
exactUrl: isProcessoutCardUrl,
|
|
7110
|
+
bodyGate: (url, body) => processoutBodyVerdict(body, url)
|
|
7111
|
+
});
|
|
7112
|
+
// src/processors/usaepay.js
|
|
7113
|
+
var USAEPAY_PSP = "usaepay";
|
|
7114
|
+
var USAEPAY_OPERATION = "usaepay.card_request";
|
|
7115
|
+
var USAEPAY_HOSTS = /* @__PURE__ */ Object.freeze({
|
|
7116
|
+
"www.usaepay.com": "production",
|
|
7117
|
+
"secure.usaepay.com": "production",
|
|
7118
|
+
"sandbox.usaepay.com": "sandbox"
|
|
7119
|
+
});
|
|
7120
|
+
var USAEPAY_PAYMENT_KEYS_PATH = "/api/v2/pub/payment_keys";
|
|
7121
|
+
var BODY_LIMIT41 = 512;
|
|
7122
|
+
var URL_LIMIT16 = 256;
|
|
7123
|
+
var CARD_NUMBER21 = /^[0-9]{13,19}$/;
|
|
7124
|
+
var EXPIRATION2 = /^(?:0[1-9]|1[0-2])[0-9]{2}$/;
|
|
7125
|
+
var SECURITY_CODE25 = /^(?:[0-9]{3,4})?$/;
|
|
7126
|
+
var record36 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
7127
|
+
var own17 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
7128
|
+
var refuse42 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
7129
|
+
var CARD41 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
7130
|
+
function usaepayPaymentKeysUrl(url) {
|
|
7131
|
+
if (typeof url !== "string" || url.length > URL_LIMIT16 || url.includes("?") || url.includes("#"))
|
|
7132
|
+
return null;
|
|
7133
|
+
let parsed;
|
|
7134
|
+
try {
|
|
7135
|
+
parsed = new URL(url);
|
|
7136
|
+
}
|
|
7137
|
+
catch {
|
|
7138
|
+
return null;
|
|
7139
|
+
}
|
|
7140
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !own17(USAEPAY_HOSTS, parsed.hostname) || parsed.pathname !== USAEPAY_PAYMENT_KEYS_PATH)
|
|
7141
|
+
return null;
|
|
7142
|
+
return Object.freeze({ host: parsed.hostname, environment: USAEPAY_HOSTS[parsed.hostname] });
|
|
7143
|
+
}
|
|
7144
|
+
var isUsaepayPaymentKeysUrl = (url) => usaepayPaymentKeysUrl(url) !== null;
|
|
7145
|
+
function luhn11(digits4) {
|
|
7146
|
+
let sum = 0;
|
|
7147
|
+
for (let at = digits4.length - 1, double = false; at >= 0; at -= 1, double = !double) {
|
|
7148
|
+
let digit = digits4.charCodeAt(at) - 48;
|
|
7149
|
+
if (double)
|
|
7150
|
+
digit = digit * 2 > 9 ? digit * 2 - 9 : digit * 2;
|
|
7151
|
+
sum += digit;
|
|
7152
|
+
}
|
|
7153
|
+
return sum % 10 === 0;
|
|
7154
|
+
}
|
|
7155
|
+
function readBody25(body) {
|
|
7156
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT41)
|
|
7157
|
+
return null;
|
|
7158
|
+
try {
|
|
7159
|
+
const value = JSON.parse(body);
|
|
7160
|
+
return record36(value) && JSON.stringify(value) === body ? value : null;
|
|
7161
|
+
}
|
|
7162
|
+
catch {
|
|
7163
|
+
return null;
|
|
7164
|
+
}
|
|
7165
|
+
}
|
|
7166
|
+
function usaepayBodyVerdict(body) {
|
|
7167
|
+
const value = readBody25(body);
|
|
7168
|
+
const card = value === null ? null : value.creditcard;
|
|
7169
|
+
if (value === null || Object.keys(value).join() !== "creditcard" || !record36(card) || Object.keys(card).join() !== "number,expiration,cvc" || typeof card.number !== "string" || !CARD_NUMBER21.test(card.number) || !luhn11(card.number) || typeof card.expiration !== "string" || !EXPIRATION2.test(card.expiration) || typeof card.cvc !== "string" || !SECURITY_CODE25.test(card.cvc))
|
|
7170
|
+
return refuse42("usaepay_body_unsupported");
|
|
7171
|
+
return CARD41;
|
|
7172
|
+
}
|
|
7173
|
+
var usaepay_default = /* @__PURE__ */ registerProcessor({
|
|
7174
|
+
psp: USAEPAY_PSP,
|
|
7175
|
+
definitions: [
|
|
7176
|
+
{
|
|
7177
|
+
psp: "usaepay",
|
|
7178
|
+
// The frame's card request, as the header above reads it. sandbox.usaepay.com is USAePay's sandbox, pinned to test
|
|
7179
|
+
// rows, which send only USAePay's documented test cards (hostEnvironmentPinned, device-replay.js S7).
|
|
7180
|
+
// Ships dark: served only to a client that declares `usaepay_payment_key`, and only for a company the backend's
|
|
7181
|
+
// processor gate turns USAePay on for. `(?![\w/.%-])` ends the path for a consumer that tests `match` unanchored.
|
|
7182
|
+
capability: "usaepay_payment_key",
|
|
7183
|
+
match: "(?:www|secure|sandbox)\\.usaepay\\.com/api/v2/pub/payment_keys(?![\\w/.%-])",
|
|
7184
|
+
hosts: ["^www\\.usaepay\\.com$", "^secure\\.usaepay\\.com$", "^sandbox\\.usaepay\\.com$"],
|
|
7185
|
+
sandboxHosts: ["^sandbox\\.usaepay\\.com$"],
|
|
7186
|
+
hostEnvironmentPinned: true,
|
|
7187
|
+
encoding: "json",
|
|
7188
|
+
// The frame's Authorization, which carries the merchant's public key. Origin, Referer and cookies never ride.
|
|
7189
|
+
passthroughHeaders: ["^authorization$"],
|
|
7190
|
+
jsonCardFields: [["creditcard", "number"]]
|
|
7191
|
+
}
|
|
7192
|
+
],
|
|
7193
|
+
// Only the cardholder's device sends this card, after a person approves; no reviewed list names usaepay.
|
|
7194
|
+
refusedOperations: [USAEPAY_OPERATION],
|
|
7195
|
+
// The public key mints a payment key and reads nothing: the merchant's server runs the sale with its private key.
|
|
7196
|
+
settlementReadback: {
|
|
7197
|
+
answer: "none",
|
|
7198
|
+
reason: "tokenization_credential_cannot_read_charges",
|
|
7199
|
+
note: "The tokenization credential cannot read a charge; the shop charges the token later with its own credentials.",
|
|
7200
|
+
source: "https://help.usaepay.info/developer/payjs-v2/ , https://help.usaepay.info/api/rest/"
|
|
7201
|
+
},
|
|
7202
|
+
exactUrl: isUsaepayPaymentKeysUrl,
|
|
7203
|
+
bodyGate: (url, body) => url !== void 0 && !isUsaepayPaymentKeysUrl(url) ? refuse42("usaepay_url_refused") : usaepayBodyVerdict(body)
|
|
7204
|
+
// No amount reader: the request names none, so the agent's pair is the figure the cardholder approves.
|
|
7205
|
+
});
|
|
7206
|
+
// src/processors/vtex_payments.js
|
|
7207
|
+
var VTEX_PAYMENTS_PSP = "vtex_payments";
|
|
7208
|
+
var VTEX_PAYMENTS_OPERATION = "vtex_payments.card_request";
|
|
7209
|
+
var VTEX_PAYMENTS_FALLBACK_HOST = "api.vtexvault.com";
|
|
7210
|
+
var VTEX_PAYMENTS_LINE_KEYS = /* @__PURE__ */ Object.freeze([
|
|
7211
|
+
"currencyCode",
|
|
7212
|
+
"paymentSystem",
|
|
7213
|
+
"accountId",
|
|
7214
|
+
"value",
|
|
7215
|
+
"referenceValue",
|
|
7216
|
+
"installments",
|
|
7217
|
+
"installmentsInterestRate",
|
|
7218
|
+
"installmentsValue",
|
|
7219
|
+
"groupName",
|
|
7220
|
+
"fields",
|
|
7221
|
+
"transaction",
|
|
7222
|
+
"id"
|
|
7223
|
+
]);
|
|
7224
|
+
var VTEX_PAYMENTS_FIELD_KEYS = /* @__PURE__ */ Object.freeze([
|
|
7225
|
+
"address",
|
|
7226
|
+
"accountId",
|
|
7227
|
+
"validationCode",
|
|
7228
|
+
"metadata",
|
|
7229
|
+
"document",
|
|
7230
|
+
"holderName",
|
|
7231
|
+
"cardNumber",
|
|
7232
|
+
"dueDate",
|
|
7233
|
+
"deviceFingerprint",
|
|
7234
|
+
"addressId"
|
|
7235
|
+
]);
|
|
7236
|
+
var VTEX_PAYMENTS_ADDRESS_KEYS = /* @__PURE__ */ Object.freeze([
|
|
7237
|
+
"street",
|
|
7238
|
+
"complement",
|
|
7239
|
+
"number",
|
|
7240
|
+
"city",
|
|
7241
|
+
"reference",
|
|
7242
|
+
"addressType",
|
|
7243
|
+
"neighborhood",
|
|
7244
|
+
"addressId",
|
|
7245
|
+
"state",
|
|
7246
|
+
"country",
|
|
7247
|
+
"postalCode"
|
|
7248
|
+
]);
|
|
7249
|
+
var VTEX_PAYMENTS_NETWORKS = /* @__PURE__ */ Object.freeze({ 1: "amex", 2: "visa", 4: "mastercard", 5: "discover" });
|
|
7250
|
+
var VTEX_PAYMENTS_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
7251
|
+
Object.freeze({ account: "alssports", origin: "https://www.als.com", merchant: "Al's Sporting Goods", currency: "USD" }),
|
|
7252
|
+
Object.freeze({ account: "roadrunnersports", origin: "https://www.roadrunnersports.com", merchant: "Road Runner Sports", currency: "USD" })
|
|
7253
|
+
]);
|
|
7254
|
+
var BODY_LIMIT42 = 16384;
|
|
7255
|
+
var ACCOUNT_HOST = /^([a-z0-9]{1,63})\.vtexvault\.com$/;
|
|
7256
|
+
var PATH = /^\/api\/payments\/transactions\/([0-9A-Fa-f]{32})\/payments$/;
|
|
7257
|
+
var ORDER_GROUP = /^[0-9]{6,24}$/;
|
|
7258
|
+
var BASE647 = /^[A-Za-z0-9+/]{4,1020}={0,2}$/;
|
|
7259
|
+
var CARD_NUMBER22 = /^[0-9]{12,19}$/;
|
|
7260
|
+
var SECURITY_CODE26 = /^[0-9]{3,4}$/;
|
|
7261
|
+
var DUE_DATE = /^(?:0[1-9]|1[0-2])\/[0-9]{2}$/;
|
|
7262
|
+
var CURRENCY6 = /^[A-Z]{3}$/;
|
|
7263
|
+
var TRANSACTION_ID = /^[0-9A-Fa-f]{32}$/;
|
|
7264
|
+
var MERCHANT_NAME = /^[A-Za-z0-9_.-]{1,64}$/;
|
|
7265
|
+
var SHORT_ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
7266
|
+
var FINGERPRINT4 = /^[A-Za-z0-9_.:=+/-]{1,256}$/;
|
|
7267
|
+
var TEXT4 = /^[^\u0000-\u001f\u007f]{1,200}$/;
|
|
7268
|
+
var CARD_DIGITS2 = /[0-9]{12,}/;
|
|
7269
|
+
var DEVICE_INFO_KEYS = Object.freeze(["sw", "sh", "cd", "tz", "lang", "java", "sourceApplication"]);
|
|
7270
|
+
var record37 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
7271
|
+
var own18 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
7272
|
+
var refuse43 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
7273
|
+
var CARD42 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
7274
|
+
var inOrder8 = (value, keys) => {
|
|
7275
|
+
let at = 0;
|
|
7276
|
+
for (const name of Object.keys(value)) {
|
|
7277
|
+
while (at < keys.length && keys[at] !== name)
|
|
7278
|
+
at += 1;
|
|
7279
|
+
if (at === keys.length)
|
|
7280
|
+
return false;
|
|
7281
|
+
at += 1;
|
|
7282
|
+
}
|
|
7283
|
+
return true;
|
|
7284
|
+
};
|
|
7285
|
+
var cardDigits2 = (text10) => CARD_DIGITS2.test(text10.replace(/[^0-9A-Za-z]/g, ""));
|
|
7286
|
+
var plainText8 = (value) => typeof value === "string" && TEXT4.test(value) && !cardDigits2(value);
|
|
7287
|
+
var count = (value) => Number.isSafeInteger(value) && value >= 0;
|
|
7288
|
+
var BASE64_ALPHABET2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
7289
|
+
function base64Text2(input) {
|
|
7290
|
+
if (input.length % 4 !== 0)
|
|
7291
|
+
return null;
|
|
7292
|
+
const stripped = input.replace(/={1,2}$/, "");
|
|
7293
|
+
let out = "";
|
|
7294
|
+
let bits = 0;
|
|
7295
|
+
let value = 0;
|
|
7296
|
+
for (const character of stripped) {
|
|
7297
|
+
const sextet = BASE64_ALPHABET2.indexOf(character);
|
|
7298
|
+
if (sextet < 0)
|
|
7299
|
+
return null;
|
|
7300
|
+
value = value << 6 | sextet;
|
|
7301
|
+
bits += 6;
|
|
7302
|
+
if (bits >= 8) {
|
|
7303
|
+
bits -= 8;
|
|
7304
|
+
out += String.fromCharCode(value >> bits & 255);
|
|
7305
|
+
value &= (1 << bits) - 1;
|
|
7306
|
+
}
|
|
7307
|
+
}
|
|
7308
|
+
return out;
|
|
7309
|
+
}
|
|
7310
|
+
function deviceInfoSound(text10) {
|
|
7311
|
+
if (typeof text10 !== "string" || !BASE647.test(text10))
|
|
7312
|
+
return false;
|
|
7313
|
+
const decoded = base64Text2(text10);
|
|
7314
|
+
if (decoded === null)
|
|
7315
|
+
return false;
|
|
7316
|
+
let info;
|
|
7317
|
+
try {
|
|
7318
|
+
info = JSON.parse(decoded);
|
|
7319
|
+
}
|
|
7320
|
+
catch {
|
|
7321
|
+
return false;
|
|
7322
|
+
}
|
|
7323
|
+
if (!record37(info) || !Object.keys(info).every((key) => DEVICE_INFO_KEYS.includes(key)))
|
|
7324
|
+
return false;
|
|
7325
|
+
for (const key of ["sw", "sh", "cd"])
|
|
7326
|
+
if (own18(info, key) && !(count(info[key]) && info[key] <= 1e5))
|
|
7327
|
+
return false;
|
|
7328
|
+
if (own18(info, "tz") && !(Number.isSafeInteger(info.tz) && Math.abs(info.tz) <= 1440))
|
|
7329
|
+
return false;
|
|
7330
|
+
if (own18(info, "lang") && !(typeof info.lang === "string" && /^[A-Za-z]{0,8}$/.test(info.lang)))
|
|
7331
|
+
return false;
|
|
7332
|
+
if (own18(info, "java") && typeof info.java !== "boolean")
|
|
7333
|
+
return false;
|
|
7334
|
+
return !own18(info, "sourceApplication") || typeof info.sourceApplication === "string" && /^[A-Za-z0-9_.-]{1,32}$/.test(info.sourceApplication);
|
|
7335
|
+
}
|
|
7336
|
+
function vtexPaymentsCardTarget(url) {
|
|
7337
|
+
if (typeof url !== "string" || url.length > 8192)
|
|
7338
|
+
return null;
|
|
7339
|
+
let parsed;
|
|
7340
|
+
try {
|
|
7341
|
+
parsed = new URL(url);
|
|
7342
|
+
}
|
|
7343
|
+
catch {
|
|
7344
|
+
return null;
|
|
7345
|
+
}
|
|
7346
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || parsed.hash)
|
|
7347
|
+
return null;
|
|
7348
|
+
const path = PATH.exec(parsed.pathname);
|
|
7349
|
+
const host = ACCOUNT_HOST.exec(parsed.hostname);
|
|
7350
|
+
if (!path || !host)
|
|
7351
|
+
return null;
|
|
7352
|
+
const fallback = parsed.hostname === VTEX_PAYMENTS_FALLBACK_HOST;
|
|
7353
|
+
const names = [...parsed.searchParams.keys()];
|
|
7354
|
+
const expected = ["orderId", "deviceInfo", ...parsed.searchParams.has("callbackUrl") ? ["callbackUrl"] : [], ...fallback ? ["an"] : []];
|
|
7355
|
+
if (names.length !== expected.length || names.some((name, i) => name !== expected[i]))
|
|
7356
|
+
return null;
|
|
7357
|
+
const orderId = parsed.searchParams.get("orderId");
|
|
7358
|
+
if (!ORDER_GROUP.test(orderId) || !deviceInfoSound(parsed.searchParams.get("deviceInfo")))
|
|
7359
|
+
return null;
|
|
7360
|
+
if (parsed.searchParams.has("callbackUrl")) {
|
|
7361
|
+
let callback;
|
|
7362
|
+
try {
|
|
7363
|
+
callback = new URL(parsed.searchParams.get("callbackUrl"));
|
|
7364
|
+
}
|
|
7365
|
+
catch {
|
|
7366
|
+
return null;
|
|
7367
|
+
}
|
|
7368
|
+
if (callback.protocol !== "https:" || callback.username || callback.password || callback.searchParams.get("step") !== "payment" || callback.searchParams.get("og") !== orderId)
|
|
7369
|
+
return null;
|
|
7370
|
+
}
|
|
7371
|
+
const account = fallback ? parsed.searchParams.get("an") : host[1];
|
|
7372
|
+
if (!/^[a-z0-9]{1,63}$/.test(account) || account === "api")
|
|
7373
|
+
return null;
|
|
7374
|
+
return Object.freeze({ account, transactionId: path[1], orderId, fallback });
|
|
7375
|
+
}
|
|
7376
|
+
function isVtexPaymentsCardUrl(url) {
|
|
7377
|
+
const target = vtexPaymentsCardTarget(url);
|
|
7378
|
+
return target !== null && !target.fallback;
|
|
7379
|
+
}
|
|
7380
|
+
function readBody26(body) {
|
|
7381
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT42)
|
|
7382
|
+
return null;
|
|
7383
|
+
let value;
|
|
7384
|
+
try {
|
|
7385
|
+
value = JSON.parse(body);
|
|
7386
|
+
if (!Array.isArray(value) || JSON.stringify(value) !== body)
|
|
7387
|
+
return null;
|
|
7388
|
+
}
|
|
7389
|
+
catch {
|
|
7390
|
+
return null;
|
|
7391
|
+
}
|
|
7392
|
+
return value;
|
|
7393
|
+
}
|
|
7394
|
+
function cardLine(line) {
|
|
7395
|
+
if (!record37(line))
|
|
7396
|
+
return false;
|
|
7397
|
+
const fields = record37(line.fields) ? line.fields : {};
|
|
7398
|
+
return line.groupName === "creditCardPaymentGroup" || line.groupName === "debitCardPaymentGroup" || own18(line, "accountId") || own18(fields, "accountId") || own18(fields, "cardNumber") || own18(fields, "validationCode") || own18(fields, "dueDate");
|
|
7399
|
+
}
|
|
7400
|
+
function addressSound(address2) {
|
|
7401
|
+
if (!record37(address2) || !inOrder8(address2, VTEX_PAYMENTS_ADDRESS_KEYS))
|
|
7402
|
+
return false;
|
|
7403
|
+
for (const [key, value] of Object.entries(address2)) {
|
|
7404
|
+
if (key === "addressType") {
|
|
7405
|
+
if (value !== "billing")
|
|
7406
|
+
return false;
|
|
7407
|
+
continue;
|
|
7408
|
+
}
|
|
7409
|
+
if (key === "addressId") {
|
|
7410
|
+
if (!(typeof value === "string" && SHORT_ID.test(value)))
|
|
7411
|
+
return false;
|
|
7412
|
+
continue;
|
|
7413
|
+
}
|
|
7414
|
+
if (value === null && (key === "complement" || key === "reference"))
|
|
7415
|
+
continue;
|
|
7416
|
+
if (!(value === "" || plainText8(value)))
|
|
7417
|
+
return false;
|
|
7418
|
+
}
|
|
7419
|
+
return true;
|
|
7420
|
+
}
|
|
7421
|
+
function fieldsSound(fields) {
|
|
7422
|
+
if (!record37(fields) || !inOrder8(fields, VTEX_PAYMENTS_FIELD_KEYS) || own18(fields, "metadata"))
|
|
7423
|
+
return false;
|
|
7424
|
+
if (!(typeof fields.cardNumber === "string" && CARD_NUMBER22.test(fields.cardNumber)))
|
|
7425
|
+
return false;
|
|
7426
|
+
if (!(typeof fields.validationCode === "string" && SECURITY_CODE26.test(fields.validationCode)))
|
|
7427
|
+
return false;
|
|
7428
|
+
if (!(typeof fields.dueDate === "string" && DUE_DATE.test(fields.dueDate)))
|
|
7429
|
+
return false;
|
|
7430
|
+
if (!plainText8(fields.holderName))
|
|
7431
|
+
return false;
|
|
7432
|
+
if (own18(fields, "document") && !(fields.document === "" || plainText8(fields.document) && fields.document.length <= 32))
|
|
7433
|
+
return false;
|
|
7434
|
+
if (own18(fields, "address") && !addressSound(fields.address))
|
|
7435
|
+
return false;
|
|
7436
|
+
if (own18(fields, "deviceFingerprint") && !(typeof fields.deviceFingerprint === "string" && FINGERPRINT4.test(fields.deviceFingerprint)))
|
|
7437
|
+
return false;
|
|
7438
|
+
return !own18(fields, "addressId") || typeof fields.addressId === "string" && SHORT_ID.test(fields.addressId);
|
|
7439
|
+
}
|
|
7440
|
+
function vtexPaymentsBodyVerdict(body, target) {
|
|
7441
|
+
const lines = readBody26(body);
|
|
7442
|
+
if (lines === null || lines.length === 0 || !lines.every(record37))
|
|
7443
|
+
return refuse43("vtex_payments_body_unsupported");
|
|
7444
|
+
const cards = lines.filter(cardLine);
|
|
7445
|
+
if (cards.some((line2) => own18(line2, "accountId") || own18(line2.fields ?? {}, "accountId")))
|
|
7446
|
+
return refuse43("vtex_payments_saved_card");
|
|
7447
|
+
if (cards.length === 0)
|
|
7448
|
+
return refuse43("vtex_payments_body_unsupported");
|
|
7449
|
+
if (lines.length !== 1 || own18(lines[0], "id"))
|
|
7450
|
+
return refuse43("vtex_payments_split_payment");
|
|
7451
|
+
const line = lines[0];
|
|
7452
|
+
if (!inOrder8(line, VTEX_PAYMENTS_LINE_KEYS) || line.groupName !== "creditCardPaymentGroup")
|
|
7453
|
+
return refuse43("vtex_payments_body_unsupported");
|
|
7454
|
+
if (!(typeof line.currencyCode === "string" && CURRENCY6.test(line.currencyCode)) || !own18(VTEX_PAYMENTS_NETWORKS, line.paymentSystem) || !Number.isSafeInteger(line.paymentSystem) || !(count(line.value) && line.value > 0))
|
|
7455
|
+
return refuse43("vtex_payments_body_unsupported");
|
|
7456
|
+
if (line.installments !== 1 || line.referenceValue !== line.value || own18(line, "installmentsInterestRate") && line.installmentsInterestRate !== 0 || own18(line, "installmentsValue") && line.installmentsValue !== line.value)
|
|
7457
|
+
return refuse43("vtex_payments_installments");
|
|
7458
|
+
const transaction = line.transaction;
|
|
7459
|
+
if (!record37(transaction) || Object.keys(transaction).join() !== "id,merchantName" || !(typeof transaction.id === "string" && TRANSACTION_ID.test(transaction.id)) || !(typeof transaction.merchantName === "string" && MERCHANT_NAME.test(transaction.merchantName)))
|
|
7460
|
+
return refuse43("vtex_payments_body_unsupported");
|
|
7461
|
+
if (target && transaction.id.toUpperCase() !== target.transactionId.toUpperCase())
|
|
7462
|
+
return refuse43("vtex_payments_split_payment");
|
|
7463
|
+
return fieldsSound(line.fields) ? CARD42 : refuse43("vtex_payments_body_unsupported");
|
|
7464
|
+
}
|
|
7465
|
+
function vtexPaymentsAmount(body) {
|
|
7466
|
+
if (vtexPaymentsBodyVerdict(body).verdict !== "card")
|
|
7467
|
+
return null;
|
|
7468
|
+
const [line] = JSON.parse(body);
|
|
7469
|
+
return { amountCents: line.value, currency: line.currencyCode.toLowerCase() };
|
|
7470
|
+
}
|
|
7471
|
+
var NETWORK_OF = Object.freeze({
|
|
7472
|
+
visa: (number) => /^4[0-9]{12}(?:[0-9]{3}){0,2}$/.test(number),
|
|
7473
|
+
mastercard: (number) => /^(?: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})$/.test(number),
|
|
7474
|
+
amex: (number) => /^3[47][0-9]{13}$/.test(number),
|
|
7475
|
+
discover: (number) => /^(?:6011[0-9]{12}|64[4-9][0-9]{13}|65[0-9]{14})$/.test(number)
|
|
7476
|
+
});
|
|
7477
|
+
var NETWORK_NAME = Object.freeze({ visa: "Visa", mastercard: "Mastercard", amex: "American Express", discover: "Discover" });
|
|
7478
|
+
var vtex_payments_default = /* @__PURE__ */ registerProcessor({
|
|
7479
|
+
psp: VTEX_PAYMENTS_PSP,
|
|
7480
|
+
definitions: [
|
|
7481
|
+
{
|
|
7482
|
+
psp: "vtex_payments",
|
|
7483
|
+
// Ollie's card post to a VTEX account's own vault, as the header above reads it, and the fallback host, which
|
|
7484
|
+
// the gate recognizes only to refuse, so the agent's placeholder never reaches it either. VTEX has no test host:
|
|
7485
|
+
// every request is live. Prepared only: Ollie gives the post 12 seconds. Ships dark: served only to a client that
|
|
7486
|
+
// declares `vtex_payments_card_payment`, on for Agentcard's own company alone (backend
|
|
7487
|
+
// checkout-processor-gate.ts), and autopilot never sends it.
|
|
7488
|
+
capability: "vtex_payments_card_payment",
|
|
7489
|
+
match: "[a-z0-9-]{1,63}\\.vtexvault\\.com/api/payments/transactions/[A-Za-z0-9-]{1,64}/payments(?![\\w/.%-])",
|
|
7490
|
+
hosts: ["^[a-z0-9-]{1,63}\\.vtexvault\\.com$"],
|
|
7491
|
+
preparationRequired: true,
|
|
7492
|
+
encoding: "json",
|
|
7493
|
+
// Ollie's fetch sets the JSON content type alone. Origin, Referer and cookies never ride.
|
|
7494
|
+
passthroughHeaders: [],
|
|
7495
|
+
jsonCardFields: [[0, "fields", "cardNumber"]]
|
|
7496
|
+
}
|
|
7497
|
+
],
|
|
7498
|
+
// Only the cardholder's device sends it, after a person approves; no reviewed list names vtex_payments.
|
|
7499
|
+
refusedOperations: [VTEX_PAYMENTS_OPERATION],
|
|
7500
|
+
// Not surveyed: VTEX names a payment's end only to the store's own API keys and at the gatewayCallback that follows.
|
|
7501
|
+
settlementReadback: "not_surveyed",
|
|
7502
|
+
exactUrl: isVtexPaymentsCardUrl,
|
|
7503
|
+
bodyGate: (url, body) => {
|
|
7504
|
+
if (url === void 0)
|
|
7505
|
+
return vtexPaymentsBodyVerdict(body);
|
|
7506
|
+
const target = vtexPaymentsCardTarget(url);
|
|
7507
|
+
if (target === null)
|
|
7508
|
+
return refuse43("vtex_payments_url_refused");
|
|
7509
|
+
return target.fallback ? refuse43("vtex_payments_fallback_refused") : vtexPaymentsBodyVerdict(body, target);
|
|
7510
|
+
},
|
|
7511
|
+
amount: (template) => record37(template) && isVtexPaymentsCardUrl(template.url) ? vtexPaymentsAmount(template.body) : null
|
|
7512
|
+
});
|
|
6225
7513
|
// src/processors/index.generated.js
|
|
6226
7514
|
var REGISTERED_MODULES = Object.freeze({
|
|
6227
|
-
|
|
7515
|
+
bluesnap: bluesnap_default,
|
|
7516
|
+
iyzico: iyzico_default,
|
|
7517
|
+
midtrans: midtrans_default,
|
|
7518
|
+
oceanpayment: oceanpayment_default,
|
|
7519
|
+
paymentwall: paymentwall_default,
|
|
7520
|
+
payplug: payplug_default,
|
|
7521
|
+
processout: processout_default,
|
|
7522
|
+
usaepay: usaepay_default,
|
|
7523
|
+
vtex_payments: vtex_payments_default
|
|
6228
7524
|
});
|
|
6229
7525
|
// src/registry.js
|
|
6230
7526
|
var REGISTERED_PROCESSORS = Object.values(REGISTERED_MODULES);
|
|
@@ -6412,7 +7708,7 @@ function carriesCardFields(recognizer, body) {
|
|
|
6412
7708
|
if (typeof body !== "string" || body === "")
|
|
6413
7709
|
return false;
|
|
6414
7710
|
const anyCase = recognizer.caseInsensitiveFormKeys === true;
|
|
6415
|
-
const wanted = anyCase ? fields.map((
|
|
7711
|
+
const wanted = anyCase ? fields.map((field3) => String(field3).toLowerCase()) : fields;
|
|
6416
7712
|
for (const chunk of body.split("&")) {
|
|
6417
7713
|
const eq = chunk.indexOf("=");
|
|
6418
7714
|
if (eq <= 0 || eq === chunk.length - 1)
|
|
@@ -6503,20 +7799,20 @@ var KEEP_ON_FILE_REFUSAL = "Refusing to pay: this Primer payment would keep the
|
|
|
6503
7799
|
var UNSUPPORTED_SDK_REFUSAL = "Refusing to pay: this checkout uses a Primer SDK Agentcard does not support yet. Nothing was sent.";
|
|
6504
7800
|
var NETWORK_MISMATCH_REFUSAL = "Refusing to pay: this Primer payment names a card network that is not your card's. Nothing was sent.";
|
|
6505
7801
|
var FILL_REFUSAL = "Could not fill the card fields for Primer. Nothing was sent.";
|
|
6506
|
-
var
|
|
7802
|
+
var BODY_LIMIT43 = 16384;
|
|
6507
7803
|
var RESPONSE_LIMIT = 32768;
|
|
6508
7804
|
var ROOT_KEYS10 = ["paymentInstrument", "userDescription", "tokenType", "paymentFlow"];
|
|
6509
7805
|
var INSTRUMENT_KEYS = ["number", "cvv", "expirationMonth", "expirationYear", "cardholderName", "preferredNetwork"];
|
|
6510
7806
|
var REQUIRED_INSTRUMENT_KEYS = ["number", "cvv", "expirationMonth", "expirationYear"];
|
|
6511
|
-
var
|
|
7807
|
+
var record38 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
6512
7808
|
var owns8 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
6513
|
-
var
|
|
7809
|
+
var exact5 = (pattern, value) => typeof value === "string" && pattern.exec(value)?.[0] === value;
|
|
6514
7810
|
var text9 = (value, max) => typeof value === "string" && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
|
|
6515
7811
|
var digits3 = (value, min, max) => typeof value === "string" && value.length >= min && value.length <= max && !/[^0-9]/.test(value);
|
|
6516
7812
|
var panLike2 = (value) => /(?:[0-9][ _.:-]*){12,}/.test(value);
|
|
6517
7813
|
var plain2 = (value, max) => text9(value, max) && !panLike2(value);
|
|
6518
|
-
var
|
|
6519
|
-
var
|
|
7814
|
+
var MONTH22 = /^(?:0[1-9]|1[0-2])$/;
|
|
7815
|
+
var YEAR23 = /^20[0-9]{2}$/;
|
|
6520
7816
|
var NETWORK3 = /^[A-Z][A-Z_]{1,31}$/;
|
|
6521
7817
|
function isPrimerTokenizeUrl(url, method = "POST") {
|
|
6522
7818
|
if (method !== "POST" || typeof url !== "string" || url.length > 256 || url.includes("?") || url.includes("#"))
|
|
@@ -6531,7 +7827,7 @@ function isPrimerTokenizeUrl(url, method = "POST") {
|
|
|
6531
7827
|
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;
|
|
6532
7828
|
}
|
|
6533
7829
|
function judgeBody6(body) {
|
|
6534
|
-
if (typeof body !== "string" || body === "" || body.length >
|
|
7830
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT43)
|
|
6535
7831
|
return null;
|
|
6536
7832
|
let value;
|
|
6537
7833
|
try {
|
|
@@ -6540,16 +7836,16 @@ function judgeBody6(body) {
|
|
|
6540
7836
|
catch {
|
|
6541
7837
|
return null;
|
|
6542
7838
|
}
|
|
6543
|
-
if (!
|
|
7839
|
+
if (!record38(value) || !roundTrips(value, body))
|
|
6544
7840
|
return null;
|
|
6545
7841
|
if (!Object.keys(value).every((key) => ROOT_KEYS10.includes(key)) || !owns8(value, "paymentInstrument"))
|
|
6546
7842
|
return null;
|
|
6547
7843
|
const instrument = value.paymentInstrument;
|
|
6548
|
-
if (!
|
|
7844
|
+
if (!record38(instrument) || !Object.keys(instrument).every((key) => INSTRUMENT_KEYS.includes(key)) || !REQUIRED_INSTRUMENT_KEYS.every((key) => owns8(instrument, key)))
|
|
6549
7845
|
return null;
|
|
6550
|
-
if (!digits3(instrument.number, 12, 19) || !digits3(instrument.cvv, 3, 4) || !
|
|
7846
|
+
if (!digits3(instrument.number, 12, 19) || !digits3(instrument.cvv, 3, 4) || !exact5(MONTH22, instrument.expirationMonth) || !exact5(YEAR23, instrument.expirationYear))
|
|
6551
7847
|
return null;
|
|
6552
|
-
if (owns8(instrument, "cardholderName") && instrument.cardholderName !== null && !plain2(instrument.cardholderName, 256) || owns8(instrument, "preferredNetwork") && instrument.preferredNetwork !== null && !
|
|
7848
|
+
if (owns8(instrument, "cardholderName") && instrument.cardholderName !== null && !plain2(instrument.cardholderName, 256) || owns8(instrument, "preferredNetwork") && instrument.preferredNetwork !== null && !exact5(NETWORK3, instrument.preferredNetwork) || owns8(value, "userDescription") && value.userDescription !== null && !plain2(value.userDescription, 256) || owns8(value, "tokenType") && value.tokenType !== "MULTI_USE" || owns8(value, "paymentFlow") && value.paymentFlow !== "VAULT")
|
|
6553
7849
|
return null;
|
|
6554
7850
|
return { value, keepOnFile: owns8(value, "tokenType") || owns8(value, "paymentFlow") };
|
|
6555
7851
|
}
|
|
@@ -6573,7 +7869,7 @@ var CLIENT_TOKEN = /^[A-Za-z0-9._~+/=-]{16,4096}$/;
|
|
|
6573
7869
|
var REQUEST_ID = /^[A-Za-z0-9-]{1,64}$/;
|
|
6574
7870
|
var API_VERSION = /^2\.[0-9]{1,2}$/;
|
|
6575
7871
|
function readHeaders(headers) {
|
|
6576
|
-
if (!
|
|
7872
|
+
if (!record38(headers))
|
|
6577
7873
|
return null;
|
|
6578
7874
|
const folded = /* @__PURE__ */ new Map();
|
|
6579
7875
|
for (const [name, value] of Object.entries(headers)) {
|
|
@@ -6591,9 +7887,9 @@ function headersRefusal(headers) {
|
|
|
6591
7887
|
const version = folded.get("primer-sdk-version");
|
|
6592
7888
|
if (typeof version !== "string")
|
|
6593
7889
|
return "unsupported";
|
|
6594
|
-
if (!
|
|
7890
|
+
if (!exact5(LEGACY_SDK_VERSION, version))
|
|
6595
7891
|
return "unsupported_sdk";
|
|
6596
|
-
if (!
|
|
7892
|
+
if (!exact5(CONTENT_TYPE2, folded.get("content-type")) || !exact5(CLIENT_TOKEN, folded.get("primer-client-token")) || folded.has("primer-sdk-client") && folded.get("primer-sdk-client") !== "WEB" || folded.has("x-api-version") && !exact5(API_VERSION, folded.get("x-api-version")) || folded.has("primer-sdk-checkout-session-id") && !exact5(REQUEST_ID, folded.get("primer-sdk-checkout-session-id")) || folded.has("x-request-id") && !exact5(REQUEST_ID, folded.get("x-request-id")))
|
|
6597
7893
|
return "unsupported";
|
|
6598
7894
|
return null;
|
|
6599
7895
|
}
|
|
@@ -6620,7 +7916,7 @@ function onTokenizePath(url) {
|
|
|
6620
7916
|
}
|
|
6621
7917
|
}
|
|
6622
7918
|
function primerTokenizeRefusal(request) {
|
|
6623
|
-
if (!
|
|
7919
|
+
if (!record38(request) || request.method !== "POST" || !isPrimerTokenizeUrl(request.url))
|
|
6624
7920
|
return "unsupported";
|
|
6625
7921
|
return headersRefusal(request.headers) ?? primerBodyRefusal(request.body);
|
|
6626
7922
|
}
|
|
@@ -6635,7 +7931,7 @@ function primerCardOnFileRefusal(url, options, policy = PRIMER_SESSION_CARD_ON_F
|
|
|
6635
7931
|
return "unsupported";
|
|
6636
7932
|
if (new URL(url).hostname !== LIVE_PCI_HOST)
|
|
6637
7933
|
return null;
|
|
6638
|
-
return primerCardOnFileDisclosure(url, policy) &&
|
|
7934
|
+
return primerCardOnFileDisclosure(url, policy) && record38(options) && options.keepOnFile === true ? null : "keep_on_file";
|
|
6639
7935
|
}
|
|
6640
7936
|
function primerRefusalMessage(reason) {
|
|
6641
7937
|
if (reason === "keep_on_file")
|
|
@@ -6696,8 +7992,8 @@ function injectPrimerCard(body, card) {
|
|
|
6696
7992
|
}
|
|
6697
7993
|
var TOKEN4 = /^[A-Za-z0-9_-]{8,256}$/;
|
|
6698
7994
|
var ERROR_ID = /^[A-Za-z][A-Za-z0-9_.-]{0,63}$/;
|
|
6699
|
-
var
|
|
6700
|
-
var
|
|
7995
|
+
var CODE9 = /^[A-Z][A-Z0-9_]{0,63}$/;
|
|
7996
|
+
var NETWORK_NAME2 = /^[A-Za-z][A-Za-z0-9 _-]{0,31}$/;
|
|
6701
7997
|
var RESPONSE_MONTH = /^(?:0?[1-9]|1[0-2])$/;
|
|
6702
7998
|
var RESPONSE_YEAR = /^(?:[0-9]{2}|20[0-9]{2})$/;
|
|
6703
7999
|
var PROTOCOL2 = /^[0-9]{1,2}(?:\.[0-9]{1,2}){0,2}$/;
|
|
@@ -6719,25 +8015,25 @@ function readAnswer(body) {
|
|
|
6719
8015
|
return null;
|
|
6720
8016
|
try {
|
|
6721
8017
|
const value = JSON.parse(body);
|
|
6722
|
-
return
|
|
8018
|
+
return record38(value) ? value : null;
|
|
6723
8019
|
}
|
|
6724
8020
|
catch {
|
|
6725
8021
|
return null;
|
|
6726
8022
|
}
|
|
6727
8023
|
}
|
|
6728
|
-
var tokenValue = (value) =>
|
|
8024
|
+
var tokenValue = (value) => exact5(TOKEN4, value) && !panLike2(value);
|
|
6729
8025
|
var optional = (value, key, check) => !owns8(value, key) || value[key] === null || check(value[key]);
|
|
6730
8026
|
function cardDetails(data) {
|
|
6731
|
-
if (!
|
|
8027
|
+
if (!record38(data) || !exact5(/^[0-9]{4}$/, data.last4Digits))
|
|
6732
8028
|
return null;
|
|
6733
|
-
if (!optional(data, "first6Digits", (v) =>
|
|
8029
|
+
if (!optional(data, "first6Digits", (v) => exact5(/^[0-9]{6}$/, v)) || !optional(data, "expirationMonth", (v) => exact5(RESPONSE_MONTH, v)) || !optional(data, "expirationYear", (v) => exact5(RESPONSE_YEAR, v)) || !optional(data, "cardholderName", (v) => plain2(v, 256)) || !optional(data, "network", (v) => exact5(NETWORK_NAME2, v)) || !optional(data, "isNetworkTokenized", (v) => typeof v === "boolean") || !optional(data, "binData", record38))
|
|
6734
8030
|
return null;
|
|
6735
8031
|
const safe = { last4Digits: data.last4Digits };
|
|
6736
8032
|
for (const key of ["first6Digits", "expirationMonth", "expirationYear", "cardholderName", "network", "isNetworkTokenized"]) {
|
|
6737
8033
|
if (owns8(data, key) && data[key] !== null)
|
|
6738
8034
|
safe[key] = data[key];
|
|
6739
8035
|
}
|
|
6740
|
-
if (
|
|
8036
|
+
if (record38(data.binData)) {
|
|
6741
8037
|
const bin = {};
|
|
6742
8038
|
for (const key of BIN_KEYS) {
|
|
6743
8039
|
if (!owns8(data.binData, key) || data.binData[key] === null)
|
|
@@ -6748,12 +8044,14 @@ function cardDetails(data) {
|
|
|
6748
8044
|
}
|
|
6749
8045
|
safe.binData = bin;
|
|
6750
8046
|
}
|
|
8047
|
+
if ([safe.network, ...Object.values(safe.binData ?? {})].reduce((sum, value) => sum + (typeof value === "string" ? digitCount(value) : 0), 0) > NAME_DIGITS)
|
|
8048
|
+
return null;
|
|
6751
8049
|
return safe;
|
|
6752
8050
|
}
|
|
6753
8051
|
function threeDsSummary(value) {
|
|
6754
8052
|
if (value === void 0 || value === null)
|
|
6755
8053
|
return null;
|
|
6756
|
-
if (!
|
|
8054
|
+
if (!record38(value) || !exact5(CODE9, value.responseCode) || !optional(value, "reasonCode", (v) => exact5(CODE9, v)) || !optional(value, "reasonText", (v) => plain2(v, 256)) || !optional(value, "protocolVersion", (v) => v === "" || exact5(PROTOCOL2, v)) || !optional(value, "challengeIssued", (v) => typeof v === "boolean"))
|
|
6757
8055
|
return void 0;
|
|
6758
8056
|
const safe = { responseCode: value.responseCode };
|
|
6759
8057
|
for (const key of ["reasonCode", "reasonText", "protocolVersion", "challengeIssued"]) {
|
|
@@ -6781,8 +8079,8 @@ function rebuildToken(value) {
|
|
|
6781
8079
|
}
|
|
6782
8080
|
function primerErrorId(body) {
|
|
6783
8081
|
const value = readAnswer(body);
|
|
6784
|
-
const id = value &&
|
|
6785
|
-
return
|
|
8082
|
+
const id = value && record38(value.error) ? value.error.errorId : null;
|
|
8083
|
+
return exact5(ERROR_ID, id) && !panLike2(id) ? id : null;
|
|
6786
8084
|
}
|
|
6787
8085
|
function matchesCard(details, card) {
|
|
6788
8086
|
const number = card && typeof card.number === "string" ? card.number : "";
|