@agent-cards/sdk 0.23.16 → 0.23.18

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.
@@ -1,6 +1,6 @@
1
1
  // @ts-nocheck
2
2
  // Generated from @agent-cards/payment-core. Do not edit.
3
- // artifact-sha256: e4858832550c43f6e3cbef0c64facb820d7ae9b5118a2c8c4fcadb429c94b2b0
3
+ // artifact-sha256: 0021d69ee6583030342d0f5ed625f1cb4bec88236f01fbf7450e41293f6f450d
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
@@ -663,10 +663,10 @@ var TYPED_ARRAY = Object.getPrototypeOf(Uint8Array.prototype);
663
663
  var typedArrayName = Object.getOwnPropertyDescriptor(TYPED_ARRAY, Symbol.toStringTag).get;
664
664
  function parseRsaPublicKey(key) {
665
665
  const spki = key && typeof key === "object" ? key.spki : void 0;
666
- const pin4 = key && typeof key === "object" ? key.sha256 : void 0;
666
+ const pin5 = key && typeof key === "object" ? key.sha256 : void 0;
667
667
  if (typeof spki !== "string" || spki.length > 1024 || spki.length % 4 !== 0 || !BASE64.test(spki))
668
668
  throw refuse6("key");
669
- if (typeof pin4 !== "string" || !SHA256_HEX.test(pin4))
669
+ if (typeof pin5 !== "string" || !SHA256_HEX.test(pin5))
670
670
  throw refuse6("key");
671
671
  let binary;
672
672
  try {
@@ -678,7 +678,7 @@ function parseRsaPublicKey(key) {
678
678
  if (btoa(binary) !== spki)
679
679
  throw refuse6("key");
680
680
  const der = Uint8Array.from(binary, (c) => c.charCodeAt(0));
681
- if (sha256Hex(der) !== pin4)
681
+ if (sha256Hex(der) !== pin5)
682
682
  throw refuse6("key");
683
683
  const outer = readElement(der, 0, 48);
684
684
  if (outer.end !== der.length || outer.start + RSA_ALGORITHM.length > der.length)
@@ -1442,6 +1442,558 @@ function paymongoBodyVerdict(body, session) {
1442
1442
  const code = judgeCardAttach(parsed, session);
1443
1443
  return code === null ? CARD9 : refuse10(code);
1444
1444
  }
1445
+ // src/gopay.js
1446
+ var GOPAY_PSP = "gopay";
1447
+ var GOPAY_CARD_FORM_HOSTS = /* @__PURE__ */ Object.freeze({ "secure.gopay.com": "production", "secure.sandbox.gopay.com": "test" });
1448
+ var GOPAY_CARD_FORM_PATH = "/gp-card-comm/h/";
1449
+ var BODY_LIMIT7 = 1024;
1450
+ var ROOT_KEYS4 = /* @__PURE__ */ Object.freeze(["SG", "cardData", "type"]);
1451
+ var CARD_KEYS6 = /* @__PURE__ */ Object.freeze(["cardNumber", "cvc", "expiration"]);
1452
+ var TOKEN2 = /^[0-9A-Fa-f]{16,1024}$/;
1453
+ var SIGNATURE = /^[0-9A-Fa-f]{64}$/;
1454
+ var LANGUAGE = /^[a-z]{2}(?:-[A-Za-z]{2})?$/;
1455
+ var VERSION = /^[A-Za-z0-9]{1,16}$/;
1456
+ var QUERY_NAMES = /* @__PURE__ */ Object.freeze(["lang", "ver", "SG"]);
1457
+ var CARD_NUMBER7 = /^[0-9]{16}$/;
1458
+ var CODE = /^[0-9]{3}$/;
1459
+ var EXPIRATION = /^[0-9]{2}(?:0[1-9]|1[0-2])$/;
1460
+ var CARD_PAYMENT = "PAYMENT_CARD";
1461
+ var record8 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
1462
+ var sameKeys4 = (value, keys) => {
1463
+ const own2 = Object.keys(value);
1464
+ return own2.length === keys.length && own2.every((key, at) => key === keys[at]);
1465
+ };
1466
+ var refuse11 = (code) => Object.freeze({ verdict: "refuse", code });
1467
+ var CARD10 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
1468
+ function luhn(digits) {
1469
+ let sum = 0;
1470
+ for (let at = 0; at < digits.length; at += 1) {
1471
+ let digit = Number(digits[digits.length - 1 - at]);
1472
+ if (at % 2 === 1) {
1473
+ digit *= 2;
1474
+ if (digit > 9)
1475
+ digit -= 9;
1476
+ }
1477
+ sum += digit;
1478
+ }
1479
+ return sum % 10 === 0;
1480
+ }
1481
+ function gopayCardFormUrl(url) {
1482
+ if (typeof url !== "string" || url.length > 2048 || url.includes("#"))
1483
+ return null;
1484
+ let parsed;
1485
+ try {
1486
+ parsed = new URL(url);
1487
+ }
1488
+ catch {
1489
+ return null;
1490
+ }
1491
+ if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password)
1492
+ return null;
1493
+ const environment = Object.prototype.hasOwnProperty.call(GOPAY_CARD_FORM_HOSTS, parsed.hostname) ? GOPAY_CARD_FORM_HOSTS[parsed.hostname] : null;
1494
+ if (environment === null || !parsed.pathname.startsWith(GOPAY_CARD_FORM_PATH))
1495
+ return null;
1496
+ if (!TOKEN2.test(parsed.pathname.slice(GOPAY_CARD_FORM_PATH.length)))
1497
+ return null;
1498
+ const names = [...parsed.searchParams.keys()];
1499
+ if (names.some((name) => !QUERY_NAMES.includes(name)) || new Set(names).size !== names.length)
1500
+ return null;
1501
+ const signature = parsed.searchParams.get("SG");
1502
+ const language = parsed.searchParams.get("lang");
1503
+ const version = parsed.searchParams.get("ver");
1504
+ if (signature === null || !SIGNATURE.test(signature) || language !== null && !LANGUAGE.test(language) || version !== null && !VERSION.test(version))
1505
+ return null;
1506
+ return Object.freeze({ host: parsed.hostname, environment, signature });
1507
+ }
1508
+ function readBody4(body) {
1509
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT7)
1510
+ return null;
1511
+ let value;
1512
+ try {
1513
+ value = JSON.parse(body);
1514
+ if (!record8(value) || JSON.stringify(value) !== body)
1515
+ return null;
1516
+ }
1517
+ catch {
1518
+ return null;
1519
+ }
1520
+ return value;
1521
+ }
1522
+ function gopayBodyVerdict(body, url) {
1523
+ let target;
1524
+ if (url !== void 0) {
1525
+ target = gopayCardFormUrl(url);
1526
+ if (target === null)
1527
+ return refuse11("gopay_url_refused");
1528
+ }
1529
+ const value = readBody4(body);
1530
+ if (value === null || !sameKeys4(value, ROOT_KEYS4) || !record8(value.cardData) || !sameKeys4(value.cardData, CARD_KEYS6)) {
1531
+ return refuse11("gopay_body_unsupported");
1532
+ }
1533
+ const card = value.cardData;
1534
+ if (typeof value.SG !== "string" || !SIGNATURE.test(value.SG) || typeof card.cardNumber !== "string" || !CARD_NUMBER7.test(card.cardNumber) || !luhn(card.cardNumber) || typeof card.cvc !== "string" || !CODE.test(card.cvc) || typeof card.expiration !== "string" || !EXPIRATION.test(card.expiration) || typeof value.type !== "string") {
1535
+ return refuse11("gopay_body_unsupported");
1536
+ }
1537
+ if (value.type !== CARD_PAYMENT)
1538
+ return refuse11("gopay_card_saving_refused");
1539
+ if (target !== void 0 && value.SG !== target.signature)
1540
+ return refuse11("gopay_signature_mismatch");
1541
+ return CARD10;
1542
+ }
1543
+ // src/payrexx.js
1544
+ var PAYREXX_PSP = "payrexx";
1545
+ var PAYREXX_FRAME_HOST = "checkout.payrexx.com";
1546
+ var PAYREXX_PAY_PSP_ID = "44";
1547
+ var PAYREXX_BODY_KEYS = /* @__PURE__ */ Object.freeze([
1548
+ "instance",
1549
+ "pspId",
1550
+ "card[number]",
1551
+ "card[cardholder]",
1552
+ "card[exp_month]",
1553
+ "card[exp_year]",
1554
+ "card[cvc]",
1555
+ "card[brand]",
1556
+ "amount",
1557
+ "currency",
1558
+ "isTokenization",
1559
+ "isSubscription",
1560
+ "isPreAuthorization",
1561
+ "isMoto",
1562
+ "email"
1563
+ ]);
1564
+ var BODY_LIMIT8 = 16384;
1565
+ var URL_LIMIT3 = 128;
1566
+ var FRAME_QUERY = /^\?pspId=([1-9][0-9]{0,3})&lang=([a-z]{2})$/;
1567
+ var GROUPED = /^[0-9]{4} [0-9]{4} [0-9]{4} [0-9]{4}$/;
1568
+ var VISA2 = /^4[0-9]{15}$/;
1569
+ var MASTERCARD2 = /^(?: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})$/;
1570
+ var SECURITY_CODE7 = /^[0-9]{3}$/;
1571
+ var MONTH3 = /^(?:0[1-9]|1[0-2])$/;
1572
+ var YEAR3 = /^20[0-9]{2}$/;
1573
+ var HOLDER2 = /^[\p{L}\p{M}][\p{L}\p{M} '.-]{0,44}$/u;
1574
+ var INSTANCE = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
1575
+ var AMOUNT2 = /^[1-9][0-9]{0,8}$/;
1576
+ var CURRENCY = /^[A-Z]{3}$/;
1577
+ var EMAIL = /^[^\s@]{1,64}@[^\s@]{1,189}$/;
1578
+ var FLAGS = /* @__PURE__ */ Object.freeze(["isTokenization", "isSubscription", "isPreAuthorization", "isMoto"]);
1579
+ var CARD_DIGITS = /[0-9](?:[ -]?[0-9]){11}/;
1580
+ var THREE_DS_KEY = /^(?:threeDSServerTransID|threeDSVersion|postAuth|authData\[[A-Za-z]{1,32}\])$/;
1581
+ var refuse12 = (code) => Object.freeze({ verdict: "refuse", code });
1582
+ var CARD11 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
1583
+ var CONTINUE5 = /* @__PURE__ */ Object.freeze({ verdict: "continue" });
1584
+ function payrexxFrameTarget(url) {
1585
+ if (typeof url !== "string" || url.length > URL_LIMIT3 || url.includes("#"))
1586
+ return null;
1587
+ let parsed;
1588
+ try {
1589
+ parsed = new URL(url);
1590
+ }
1591
+ catch {
1592
+ return null;
1593
+ }
1594
+ if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || parsed.hostname !== PAYREXX_FRAME_HOST || parsed.pathname !== "/")
1595
+ return null;
1596
+ const query = FRAME_QUERY.exec(parsed.search);
1597
+ return query ? Object.freeze({ pspId: query[1], lang: query[2] }) : null;
1598
+ }
1599
+ function readForm2(body) {
1600
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT8)
1601
+ return null;
1602
+ try {
1603
+ const pairs = body.split("&").map((chunk) => {
1604
+ const eq = chunk.indexOf("=");
1605
+ if (eq <= 0)
1606
+ throw new URIError("not a form pair");
1607
+ return [decodeURIComponent(chunk.slice(0, eq)), decodeURIComponent(chunk.slice(eq + 1))];
1608
+ });
1609
+ return pairs.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join("&") === body ? pairs : null;
1610
+ }
1611
+ catch {
1612
+ return null;
1613
+ }
1614
+ }
1615
+ function cardNetwork2(digits) {
1616
+ if (VISA2.test(digits))
1617
+ return "visa";
1618
+ return MASTERCARD2.test(digits) ? "mastercard" : null;
1619
+ }
1620
+ function judgeBody2(body) {
1621
+ const pairs = readForm2(body);
1622
+ if (pairs === null)
1623
+ return { verdict: refuse12("payrexx_body_unsupported"), pairs: null };
1624
+ const keys = pairs.map(([key]) => key);
1625
+ const value = Object.fromEntries(pairs);
1626
+ if (!pairs.some(([key, entry]) => key.startsWith("card[") && key !== "card[brand]" && entry !== "")) {
1627
+ return pairs.some(([key, entry]) => key !== "encryptedCard" && CARD_DIGITS.test(entry)) ? { verdict: refuse12("payrexx_body_unsupported"), pairs: null } : { verdict: CONTINUE5, pairs: null };
1628
+ }
1629
+ if (new Set(keys).size !== keys.length)
1630
+ return { verdict: refuse12("payrexx_body_unsupported"), pairs: null };
1631
+ if (keys.includes("encryptedCard"))
1632
+ return { verdict: refuse12("payrexx_wallet_card"), pairs: null };
1633
+ if (keys.some((key) => THREE_DS_KEY.test(key)))
1634
+ return { verdict: refuse12("payrexx_three_ds_resend"), pairs: null };
1635
+ if (value.pspId !== PAYREXX_PAY_PSP_ID)
1636
+ return { verdict: refuse12("payrexx_other_provider"), pairs: null };
1637
+ if (keys.length !== PAYREXX_BODY_KEYS.length || !keys.every((key, at) => key === PAYREXX_BODY_KEYS[at])) {
1638
+ return { verdict: refuse12("payrexx_body_unsupported"), pairs: null };
1639
+ }
1640
+ const number = value["card[number]"];
1641
+ const network = GROUPED.test(number) ? cardNetwork2(number.replace(/ /g, "")) : null;
1642
+ if (network === null || value["card[brand]"] !== network || !SECURITY_CODE7.test(value["card[cvc]"]) || !MONTH3.test(value["card[exp_month]"]) || !YEAR3.test(value["card[exp_year]"]) || !HOLDER2.test(value["card[cardholder]"]) || !INSTANCE.test(value.instance) || !AMOUNT2.test(value.amount) || !CURRENCY.test(value.currency) || !(value.email === "" || value.email.length <= 254 && EMAIL.test(value.email)) || !FLAGS.every((flag) => value[flag] === "true" || value[flag] === "false")) {
1643
+ return { verdict: refuse12("payrexx_body_unsupported"), pairs: null };
1644
+ }
1645
+ if (value.isTokenization === "true" || value.isSubscription === "true")
1646
+ return { verdict: refuse12("payrexx_keep_on_file"), pairs: null };
1647
+ if (value.isPreAuthorization === "true" || value.isMoto === "true")
1648
+ return { verdict: refuse12("payrexx_not_a_sale"), pairs: null };
1649
+ return { verdict: CARD11, pairs };
1650
+ }
1651
+ function payrexxBodyVerdict(body) {
1652
+ return judgeBody2(body).verdict;
1653
+ }
1654
+ function payrexxGateVerdict(url, body) {
1655
+ const target = payrexxFrameTarget(url);
1656
+ if (target === null)
1657
+ return refuse12("payrexx_url_refused");
1658
+ const verdict = payrexxBodyVerdict(body);
1659
+ return verdict.verdict === "card" && target.pspId !== PAYREXX_PAY_PSP_ID ? refuse12("payrexx_other_provider") : verdict;
1660
+ }
1661
+ // src/komoju.js
1662
+ var KOMOJU_PSP = "komoju";
1663
+ var KOMOJU_HOST = "komoju.com";
1664
+ var KOMOJU_SECURE_TOKEN_URL = "https://komoju.com/api/v1/secure_tokens";
1665
+ var KOMOJU_TOKEN_URL = "https://komoju.com/api/v1/tokens";
1666
+ var KOMOJU_RETURN_URL_PREFIX = "https://multipay.komoju.com/secure-token-return.html?session_id=";
1667
+ var BODY_LIMIT9 = 4096;
1668
+ var URL_LIMIT4 = 128;
1669
+ var SESSION_ID = /^[a-z0-9]{25}$/;
1670
+ var SESSION_PAY_PATH = /^\/api\/v1\/sessions\/([a-z0-9]{25})\/pay$/;
1671
+ var TOKEN_ID = /^tok_[a-z0-9]{20,32}$/;
1672
+ var TOP_KEYS = /* @__PURE__ */ Object.freeze(["amount", "currency", "payment_details", "return_url"]);
1673
+ var KOMOJU_CARD_KEYS = /* @__PURE__ */ Object.freeze(["type", "name", "number", "month", "year", "verification_value", "email"]);
1674
+ var PAY_KEYS = /* @__PURE__ */ Object.freeze(["payment_details", "api_locale"]);
1675
+ var AMOUNT_MAX = 99999999;
1676
+ var CURRENCY2 = /^[A-Z]{3}$/;
1677
+ var NUMBER2 = /^[0-9]{12,19}$/;
1678
+ var MONTH4 = /^(?:0[1-9]|1[0-2])$/;
1679
+ var YEAR4 = /^[0-9]{2}$/;
1680
+ var SECURITY_CODE8 = /^[0-9]{3,4}$/;
1681
+ var PAGE_NAME = /^[\x20-\x7e]{1,64}$/;
1682
+ var NAME_DIGITS_MAX = 11;
1683
+ var EMAIL2 = /^[\x21-\x7e]{1,64}@[\x21-\x7e]{1,189}$/;
1684
+ var LOCALE = /^[a-z]{2}(?:-[A-Za-z]{2,4})?$/;
1685
+ var PAN_LIKE3 = /(?:[0-9][ _.:-]*){12,}/;
1686
+ var record9 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
1687
+ var sameKeys5 = (value, keys) => {
1688
+ const own2 = Object.keys(value);
1689
+ return own2.length === keys.length && own2.every((key, at) => key === keys[at]);
1690
+ };
1691
+ var refuse13 = (code) => Object.freeze({ verdict: "refuse", code });
1692
+ var CARD12 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
1693
+ var CONTINUE6 = /* @__PURE__ */ Object.freeze({ verdict: "continue" });
1694
+ function komojuTarget(url) {
1695
+ if (typeof url !== "string" || url.length > URL_LIMIT4 || url.includes("?") || url.includes("#"))
1696
+ return null;
1697
+ let parsed;
1698
+ try {
1699
+ parsed = new URL(url);
1700
+ }
1701
+ catch {
1702
+ return null;
1703
+ }
1704
+ if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || parsed.hostname !== KOMOJU_HOST)
1705
+ return null;
1706
+ if (url === KOMOJU_SECURE_TOKEN_URL)
1707
+ return Object.freeze({ kind: "secure_token" });
1708
+ if (url === KOMOJU_TOKEN_URL)
1709
+ return Object.freeze({ kind: "token" });
1710
+ const pay = SESSION_PAY_PATH.exec(parsed.pathname);
1711
+ return pay ? Object.freeze({ kind: "session_pay", session: pay[1] }) : null;
1712
+ }
1713
+ function readJson3(body) {
1714
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT9)
1715
+ return null;
1716
+ try {
1717
+ const value = JSON.parse(body);
1718
+ return record9(value) && JSON.stringify(value) === body ? value : null;
1719
+ }
1720
+ catch {
1721
+ return null;
1722
+ }
1723
+ }
1724
+ function carriesCard(details) {
1725
+ return record9(details) && Object.keys(details).some((key) => /^(?:number|card_?number|pan)$/i.test(key));
1726
+ }
1727
+ function judgeSecureToken(value) {
1728
+ if (!sameKeys5(value, TOP_KEYS))
1729
+ return "komoju_body_unsupported";
1730
+ const details = value.payment_details;
1731
+ if (!Number.isSafeInteger(value.amount) || value.amount < 0 || value.amount > AMOUNT_MAX || typeof value.currency !== "string" || !CURRENCY2.test(value.currency) || typeof value.return_url !== "string" || !value.return_url.startsWith(KOMOJU_RETURN_URL_PREFIX) || !SESSION_ID.test(value.return_url.slice(KOMOJU_RETURN_URL_PREFIX.length)) || !record9(details) || !sameKeys5(details, KOMOJU_CARD_KEYS) || details.type !== "credit_card" || typeof details.name !== "string" || !PAGE_NAME.test(details.name) || details.name.trim() === "" || details.name.replace(/[^0-9]/g, "").length > NAME_DIGITS_MAX || typeof details.number !== "string" || !NUMBER2.test(details.number) || typeof details.month !== "string" || !MONTH4.test(details.month) || typeof details.year !== "string" || !YEAR4.test(details.year) || typeof details.verification_value !== "string" || !SECURITY_CODE8.test(details.verification_value) || typeof details.email !== "string" || !EMAIL2.test(details.email) || PAN_LIKE3.test(details.email)) {
1732
+ return "komoju_body_unsupported";
1733
+ }
1734
+ return value.amount === 0 ? "komoju_keeps_card" : null;
1735
+ }
1736
+ function tokenPay(value) {
1737
+ const keys = Object.keys(value);
1738
+ return (sameKeys5(value, PAY_KEYS) || keys.length === 1 && keys[0] === "payment_details") && typeof value.payment_details === "string" && TOKEN_ID.test(value.payment_details) && (value.api_locale === void 0 || typeof value.api_locale === "string" && LOCALE.test(value.api_locale));
1739
+ }
1740
+ function komojuBodyVerdict(body, url) {
1741
+ let target = null;
1742
+ if (url !== void 0) {
1743
+ target = komojuTarget(url);
1744
+ if (target === null)
1745
+ return refuse13("komoju_url_refused");
1746
+ }
1747
+ const value = readJson3(body);
1748
+ if (target !== null && target.kind !== "secure_token") {
1749
+ if (value !== null && target.kind === "session_pay" && tokenPay(value))
1750
+ return CONTINUE6;
1751
+ return refuse13(value !== null && carriesCard(value.payment_details) ? "komoju_fallback_refused" : "komoju_body_unsupported");
1752
+ }
1753
+ if (value === null)
1754
+ return refuse13("komoju_body_unsupported");
1755
+ if (target === null && tokenPay(value))
1756
+ return CONTINUE6;
1757
+ if (target === null && !Object.prototype.hasOwnProperty.call(value, "return_url") && carriesCard(value.payment_details)) {
1758
+ return refuse13("komoju_fallback_refused");
1759
+ }
1760
+ const code = judgeSecureToken(value);
1761
+ return code === null ? CARD12 : refuse13(code);
1762
+ }
1763
+ // src/paygent.js
1764
+ var PAYGENT_PSP = "paygent";
1765
+ var PAYGENT_TOKEN_HOSTS = /* @__PURE__ */ Object.freeze({
1766
+ production: Object.freeze(["token.paygent.co.jp"]),
1767
+ sandbox: Object.freeze(["sandbox.paygent.co.jp"])
1768
+ });
1769
+ var PAYGENT_TOKEN_PATH = "/n/token/request";
1770
+ var PAYGENT_BODY_KEYS = /* @__PURE__ */ Object.freeze([
1771
+ "merchant_id",
1772
+ "token_generate_key",
1773
+ "card_number",
1774
+ "card_expire_year",
1775
+ "card_expire_month",
1776
+ "card_cvc",
1777
+ "card_name"
1778
+ ]);
1779
+ var BODY_LIMIT10 = 2048;
1780
+ var URL_LIMIT5 = 128;
1781
+ var MERCHANT_ID = /^[0-9]{5,6}$/;
1782
+ var LIVE_KEY = /^live_[A-Za-z0-9]{24}$/;
1783
+ var SANDBOX_KEY = /^(?!live_)[a-z]{1,8}_[A-Za-z0-9]{24}$/;
1784
+ var NUMBER3 = /^[0-9]{12,19}$/;
1785
+ var YEAR5 = /^[0-9]{2}$/;
1786
+ var MONTH5 = /^(?:0?[1-9]|1[0-2])$/;
1787
+ var SECURITY_CODE9 = /^[0-9]{3,4}$/;
1788
+ var PAGE_HOLDER = /^(?:[A-Za-z][A-Za-z .'-]{0,44})?$/;
1789
+ var refuse14 = (code) => Object.freeze({ verdict: "refuse", code });
1790
+ var CARD13 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
1791
+ function paygentEnvironment(url) {
1792
+ if (typeof url !== "string" || url.length > URL_LIMIT5 || url.includes("?") || url.includes("#"))
1793
+ return null;
1794
+ let parsed;
1795
+ try {
1796
+ parsed = new URL(url);
1797
+ }
1798
+ catch {
1799
+ return null;
1800
+ }
1801
+ if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || parsed.pathname !== PAYGENT_TOKEN_PATH)
1802
+ return null;
1803
+ if (PAYGENT_TOKEN_HOSTS.production.includes(parsed.hostname))
1804
+ return "production";
1805
+ if (PAYGENT_TOKEN_HOSTS.sandbox.includes(parsed.hostname))
1806
+ return "sandbox";
1807
+ return null;
1808
+ }
1809
+ function readBody5(body) {
1810
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT10)
1811
+ return null;
1812
+ try {
1813
+ const pairs = body.split("&").map((chunk) => {
1814
+ const eq = chunk.indexOf("=");
1815
+ if (eq <= 0)
1816
+ throw new URIError("not a pair");
1817
+ return [chunk.slice(0, eq), decodeURIComponent(chunk.slice(eq + 1))];
1818
+ });
1819
+ return pairs.map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join("&") === body ? pairs : null;
1820
+ }
1821
+ catch {
1822
+ return null;
1823
+ }
1824
+ }
1825
+ var CVC_ONLY_KEYS = /* @__PURE__ */ Object.freeze(["merchant_id", "token_generate_key", "card_cvc", "cvc_only_flg"]);
1826
+ var sameKeys6 = (pairs, keys) => pairs.length === keys.length && pairs.every(([key], at) => key === keys[at]);
1827
+ function judgeBody3(body) {
1828
+ const pairs = readBody5(body);
1829
+ if (pairs === null)
1830
+ return { code: "paygent_body_unsupported", pairs: null };
1831
+ if (sameKeys6(pairs, CVC_ONLY_KEYS))
1832
+ return { code: "paygent_cvc_only", pairs: null };
1833
+ if (!sameKeys6(pairs, PAYGENT_BODY_KEYS))
1834
+ return { code: "paygent_body_unsupported", pairs: null };
1835
+ const value = Object.fromEntries(pairs);
1836
+ if (!MERCHANT_ID.test(value.merchant_id) || !(LIVE_KEY.test(value.token_generate_key) || SANDBOX_KEY.test(value.token_generate_key)) || !NUMBER3.test(value.card_number) || !YEAR5.test(value.card_expire_year) || !MONTH5.test(value.card_expire_month) || !SECURITY_CODE9.test(value.card_cvc) || !PAGE_HOLDER.test(value.card_name)) {
1837
+ return { code: "paygent_body_unsupported", pairs: null };
1838
+ }
1839
+ return { code: null, pairs };
1840
+ }
1841
+ function paygentBodyVerdict(body) {
1842
+ const { code } = judgeBody3(body);
1843
+ return code === null ? CARD13 : refuse14(code);
1844
+ }
1845
+ function paygentRequestVerdict(url, body) {
1846
+ const environment = paygentEnvironment(url);
1847
+ if (environment === null)
1848
+ return refuse14("paygent_url_refused");
1849
+ const { code, pairs } = judgeBody3(body);
1850
+ if (code !== null)
1851
+ return refuse14(code);
1852
+ const key = pairs[1][1];
1853
+ return (environment === "production" ? LIVE_KEY : SANDBOX_KEY).test(key) ? CARD13 : refuse14("paygent_key_environment");
1854
+ }
1855
+ // src/multipart-form.js
1856
+ var BODY_LIMIT11 = 65536;
1857
+ var CRLF = "\r\n";
1858
+ var BOUNDARY_CHARACTERS = "[A-Za-z0-9'+_.-]{1,70}";
1859
+ var BOUNDARY = new RegExp(`^${BOUNDARY_CHARACTERS}$`);
1860
+ var CONTENT_TYPE = new RegExp(`^multipart/form-data; ?boundary=(${BOUNDARY_CHARACTERS})$`, "i");
1861
+ var DISPOSITION = /^content-disposition: ?form-data; name="([^"\\\r\n]*)"$/i;
1862
+ var FILE_HINT = /^content-disposition:.*;\s*filename\*?=|^content-type:/i;
1863
+ var refusal = (code) => Object.freeze({ refusal: code });
1864
+ var listed = (list, name) => Array.isArray(list) && list.includes(name);
1865
+ function multipartBoundary(contentType) {
1866
+ const match = typeof contentType === "string" ? CONTENT_TYPE.exec(contentType) : null;
1867
+ return match ? match[1] : null;
1868
+ }
1869
+ function boundaryOf(body, contentType) {
1870
+ const lineEnd = body.indexOf(CRLF);
1871
+ const firstLine = body.startsWith("--") && lineEnd !== -1 ? body.slice(2, lineEnd) : null;
1872
+ if (firstLine === null || !BOUNDARY.test(firstLine))
1873
+ return null;
1874
+ if (contentType === void 0 || contentType === null)
1875
+ return firstLine;
1876
+ return multipartBoundary(contentType) === firstLine ? firstLine : null;
1877
+ }
1878
+ function readMultipartForm(body, contentType) {
1879
+ if (typeof body !== "string" || body.length > BODY_LIMIT11)
1880
+ return refusal("multipart_not_form");
1881
+ const boundary = boundaryOf(body, contentType);
1882
+ if (boundary === null)
1883
+ return refusal("multipart_not_form");
1884
+ const dash = `--${boundary}`;
1885
+ const delimiter = `${CRLF}${dash}`;
1886
+ const parts = [];
1887
+ let position = dash.length + CRLF.length;
1888
+ for (;;) {
1889
+ const headerEnd = body.indexOf(`${CRLF}${CRLF}`, position);
1890
+ if (headerEnd === -1)
1891
+ return refusal("multipart_not_form");
1892
+ const headers = body.slice(position, headerEnd).split(CRLF);
1893
+ if (headers.some((line) => FILE_HINT.test(line)))
1894
+ return refusal("multipart_file_part");
1895
+ const disposition = headers.length === 1 ? DISPOSITION.exec(headers[0]) : null;
1896
+ if (!disposition)
1897
+ return refusal("multipart_not_form");
1898
+ const start = headerEnd + 2 * CRLF.length;
1899
+ const end = body.indexOf(delimiter, start);
1900
+ if (end === -1)
1901
+ return refusal("multipart_not_form");
1902
+ parts.push(Object.freeze({ name: disposition[1], value: body.slice(start, end), start, end }));
1903
+ position = end + delimiter.length;
1904
+ if (body.startsWith("--", position)) {
1905
+ const rest = body.slice(position + 2);
1906
+ return rest === "" || rest === CRLF ? Object.freeze({ boundary, parts: Object.freeze(parts) }) : refusal("multipart_not_form");
1907
+ }
1908
+ if (!body.startsWith(CRLF, position))
1909
+ return refusal("multipart_not_form");
1910
+ position += CRLF.length;
1911
+ }
1912
+ }
1913
+ function soundRule(rule) {
1914
+ if (!rule || typeof rule !== "object" || !Array.isArray(rule.parts) || !Array.isArray(rule.card) || rule.card.length === 0)
1915
+ return false;
1916
+ const names = [...rule.parts, ...rule.card];
1917
+ if (!names.every((name) => typeof name === "string" && name !== ""))
1918
+ return false;
1919
+ return new Set(rule.card).size === rule.card.length && rule.card.every((name) => rule.parts.includes(name));
1920
+ }
1921
+ function judge(body, contentType, rule) {
1922
+ if (!soundRule(rule))
1923
+ throw new TypeError("A multipart rule lists its part names and, among them, its card parts.");
1924
+ const read = readMultipartForm(body, contentType);
1925
+ if (read.refusal)
1926
+ return read;
1927
+ if (read.parts.some((part) => !listed(rule.parts, part.name)))
1928
+ return refusal("multipart_unknown_part");
1929
+ for (const name of rule.card) {
1930
+ const count = read.parts.filter((part) => part.name === name).length;
1931
+ if (count === 0)
1932
+ return refusal("multipart_missing_card_part");
1933
+ if (count > 1)
1934
+ return refusal("multipart_duplicate_card_part");
1935
+ }
1936
+ return read;
1937
+ }
1938
+ function multipartFormRefusal(body, contentType, rule) {
1939
+ const read = judge(body, contentType, rule);
1940
+ return read.refusal ?? null;
1941
+ }
1942
+ // src/pay-nl.js
1943
+ var PAY_NL_PSP = "pay_nl";
1944
+ var PAY_NL_TOKEN_URL = "https://payment.pay.nl/v1/Payment/getCardToken/json";
1945
+ var PAY_NL_PARTS = /* @__PURE__ */ Object.freeze([
1946
+ "serviceId",
1947
+ "requestToken",
1948
+ "payment[method]",
1949
+ "payment[card][number]",
1950
+ "payment[card][name]",
1951
+ "payment[card][cvc]",
1952
+ "payment[card][expire_month]",
1953
+ "payment[card][expire_year]"
1954
+ ]);
1955
+ var PAY_NL_CARD_PARTS = /* @__PURE__ */ Object.freeze([
1956
+ "payment[card][number]",
1957
+ "payment[card][name]",
1958
+ "payment[card][cvc]",
1959
+ "payment[card][expire_month]",
1960
+ "payment[card][expire_year]"
1961
+ ]);
1962
+ var pin4 = (fields) => Object.freeze({ ...fields, origins: Object.freeze([...fields.origins]), serviceIds: Object.freeze([...fields.serviceIds]) });
1963
+ var PAY_NL_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
1964
+ pin4({ id: "weeztix", merchant: "Weeztix", origins: ["https://shop.weeztix.com"], serviceIds: ["SL-6399-2740"] })
1965
+ ]);
1966
+ var RULE = /* @__PURE__ */ Object.freeze({ parts: PAY_NL_PARTS, card: PAY_NL_CARD_PARTS });
1967
+ var SERVICE_ID = /^SL-\d{4}-\d{4}$/;
1968
+ var REQUEST_TOKEN = /^[0-9a-f]{40}$/i;
1969
+ var NUMBER4 = /^[0-9]{8,19}$/;
1970
+ var HOLDER3 = /^\p{L}+(?: \p{L}+)*$/u;
1971
+ var HOLDER_LIMIT2 = 256;
1972
+ var SECURITY_CODE10 = /^[0-9]{3,4}$/;
1973
+ var MONTH6 = /^(?:0[1-9]|1[0-2])$/;
1974
+ var YEAR6 = /^[0-9]{2}$/;
1975
+ var refuse15 = (code) => Object.freeze({ verdict: "refuse", code });
1976
+ var CARD14 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
1977
+ function isPayNlTokenUrl(url) {
1978
+ return url === PAY_NL_TOKEN_URL;
1979
+ }
1980
+ function readBody6(body, contentType) {
1981
+ if (multipartFormRefusal(body, contentType, RULE) !== null)
1982
+ return null;
1983
+ const { parts } = readMultipartForm(body, contentType);
1984
+ if (parts.length !== PAY_NL_PARTS.length || !parts.every((part, at) => part.name === PAY_NL_PARTS[at]))
1985
+ return null;
1986
+ const value = Object.fromEntries(parts.map((part) => [part.name, part.value]));
1987
+ const name = value["payment[card][name]"];
1988
+ if (!SERVICE_ID.test(value.serviceId) || !REQUEST_TOKEN.test(value.requestToken) || value["payment[method]"] !== "card" || !NUMBER4.test(value["payment[card][number]"]) || name.length > HOLDER_LIMIT2 || !HOLDER3.test(name) || !SECURITY_CODE10.test(value["payment[card][cvc]"]) || !MONTH6.test(value["payment[card][expire_month]"]) || !YEAR6.test(value["payment[card][expire_year]"]))
1989
+ return null;
1990
+ return value;
1991
+ }
1992
+ function payNlBodyVerdict(body, contentType) {
1993
+ return readBody6(body, contentType) === null ? refuse15("pay_nl_body_unsupported") : CARD14;
1994
+ }
1995
+ var ERROR_KEYS = /* @__PURE__ */ Object.freeze(["errorId", "errorTag", "errorMessage", "errorFieldName"]);
1996
+ var REQUEST_KEYS = /* @__PURE__ */ Object.freeze(["result", ...ERROR_KEYS]);
1445
1997
  // src/card-fields.js
1446
1998
  function processorGate(recognizer, url, body) {
1447
1999
  if (recognizer && recognizer.psp === LYRA_PSP)
@@ -1451,6 +2003,8 @@ function processorGate(recognizer, url, body) {
1451
2003
  return { verdict: "refuse", code: "wix_payments_url_refused" };
1452
2004
  return wixPaymentsBodyVerdict(body);
1453
2005
  }
2006
+ if (recognizer && recognizer.psp === KOMOJU_PSP)
2007
+ return komojuBodyVerdict(body, url);
1454
2008
  if (recognizer && recognizer.psp === PADDLE_VGS_PSP) {
1455
2009
  if (url !== void 0 && !isPaddleVgsCardsUrl(url))
1456
2010
  return { verdict: "refuse", code: "paddle_vgs_url_refused" };
@@ -1461,6 +2015,17 @@ function processorGate(recognizer, url, body) {
1461
2015
  return { verdict: "refuse", code: "payfast_url_refused" };
1462
2016
  return payfastBodyVerdict(body);
1463
2017
  }
2018
+ if (recognizer && recognizer.psp === PAYREXX_PSP) {
2019
+ return url !== void 0 ? payrexxGateVerdict(url, body) : payrexxBodyVerdict(body);
2020
+ }
2021
+ if (recognizer && recognizer.psp === PAYGENT_PSP) {
2022
+ return url !== void 0 ? paygentRequestVerdict(url, body) : paygentBodyVerdict(body);
2023
+ }
2024
+ if (recognizer && recognizer.psp === PAY_NL_PSP) {
2025
+ if (url !== void 0 && !isPayNlTokenUrl(url))
2026
+ return { verdict: "refuse", code: "pay_nl_url_refused" };
2027
+ return payNlBodyVerdict(body);
2028
+ }
1464
2029
  if (recognizer && recognizer.psp === PADDLE_TOKENEX_PSP) {
1465
2030
  const target = url !== void 0 ? paddleTokenexPayTarget(url) : null;
1466
2031
  if (url !== void 0 && target === null)
@@ -1473,6 +2038,8 @@ function processorGate(recognizer, url, body) {
1473
2038
  return { verdict: "refuse", code: "paymongo_url_refused" };
1474
2039
  return paymongoBodyVerdict(body, session);
1475
2040
  }
2041
+ if (recognizer && recognizer.psp === GOPAY_PSP)
2042
+ return gopayBodyVerdict(body, url);
1476
2043
  if (recognizer && recognizer.psp === GRAVY_PSP)
1477
2044
  return gravyBodyVerdict(body);
1478
2045
  if (recognizer && recognizer.psp === MONERIS_PSP) {
package/dist/cdp.js CHANGED
@@ -7,7 +7,7 @@ import { MercadoCheckoutGate } from './mercado-checkout.js';
7
7
  import { MERCADO_CHECKOUT_PATTERN } from './mercado-checkout.generated.js';
8
8
  import { JuspayCheckoutGate } from './juspay-gate.js';
9
9
  import { ACI_CHECKOUT_REUSED, AciGate, playwrightReplacesNavigationBody } from './aci.js';
10
- import { EprotectGate } from './eprotect.js';
10
+ import { EprotectGate, classifyEprotectRequest, eprotectScriptAnswer } from './eprotect.js';
11
11
  import { dispatchPreClaim, eventUrl, isArmedCreditguardCall } from './pre-claim.js';
12
12
  import { GMO_TOKEN_V1_PATTERNS, gmoRequestShop, isGmoTokenV1Request, recognizesGmo } from './gmo.js';
13
13
  import { isPaddleVgsCardsUrl } from './paddle-vgs.generated.js';
@@ -1549,6 +1549,23 @@ function replayOf(result, timeoutMs) {
1549
1549
  return { mode: 'token', authorizationId, status: response.status, headers: { ...response.headers }, body: response.body, amountVerified: null,
1550
1550
  ...(result.processor_context !== undefined ? { processorContext: result.processor_context } : {}), ...execution };
1551
1551
  }
1552
+ /**
1553
+ * Worldpay eProtect's registration, resumed by the business. The read carries the registration as the API
1554
+ * stored it, bare JSON, and the paused request is the vendor's JSONP <script>, which runs its answer and reads
1555
+ * the registration only through the callback the paused URL named. So it gets the answer authorize() gives on
1556
+ * the create path (client.ts): the registration inside that callback, under Worldpay's script type, and only a
1557
+ * registration payment-core's judge accepts for that URL. A read in any other mode never answers it either. The
1558
+ * paused URL alone decides, whatever recognizer claimed it. Any other request's replay passes as it came, and a
1559
+ * create's replay never comes here, so no answer is wrapped twice.
1560
+ */
1561
+ function eprotectResumedReplay(replay, request) {
1562
+ if (classifyEprotectRequest(request.url, request.method)?.kind !== 'registration')
1563
+ return replay;
1564
+ const answer = replay.mode === 'token' ? eprotectScriptAnswer(request.url, replay) : null;
1565
+ if (replay.mode !== 'token' || !answer)
1566
+ throw new PaymentOutcomeUnknownError(replay.authorizationId, 'eprotect_registration_unconfirmed');
1567
+ return { ...replay, status: answer.status, headers: answer.headers, body: answer.body };
1568
+ }
1552
1569
  /** The recogniser that claimed a paused request, by processor name, so a caller never re-matches the URL; null on a duck-typed vault without the read. */
1553
1570
  function recognizerNameOf(opts, url, method) {
1554
1571
  const read = opts.vault.recognizerOf;
@@ -2763,7 +2780,7 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
2763
2780
  // through controller.resume; the replay it hands back goes down the same delivery path as a create's.
2764
2781
  const pause = opts.pauseOnly ? pauseForBusiness(opts, lifecycle, attempt.signal, { url: request.url, method: request.method, headers: request.headers ?? {}, body }, pageOrigin) : null;
2765
2782
  businessPause = pause;
2766
- const replay = pause ? await pause.replay : await opts.vault.authorize({
2783
+ const replay = pause ? eprotectResumedReplay(await pause.replay, request) : await opts.vault.authorize({
2767
2784
  user: opts.user,
2768
2785
  merchant: opts.merchant,
2769
2786
  amount: opts.amount,