@agent-cards/sdk 0.23.28 → 0.24.1

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.
Files changed (110) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/PREFLIGHT.md +7 -1
  3. package/README.md +197 -102
  4. package/dist/aci.d.ts +52 -22
  5. package/dist/aci.js +79 -15
  6. package/dist/adyen-merchant-hosted.generated.d.ts +2 -2
  7. package/dist/adyen-merchant-hosted.generated.js +586 -55
  8. package/dist/agent-amount.generated.js +1 -1
  9. package/dist/agentcard.d.ts +4 -5
  10. package/dist/agentcard.js +4 -5
  11. package/dist/amadeus.d.ts +9 -3
  12. package/dist/amadeus.js +33 -4
  13. package/dist/api-module.d.ts +1 -7
  14. package/dist/api-module.js +3 -5
  15. package/dist/{voice-retry.js → api-retry.js} +1 -1
  16. package/dist/api-types.d.ts +53 -0
  17. package/dist/{voice-types.js → api-types.js} +7 -2
  18. package/dist/approvals.d.ts +166 -0
  19. package/dist/approvals.js +213 -0
  20. package/dist/aurus.d.ts +33 -0
  21. package/dist/aurus.js +75 -0
  22. package/dist/builtin-registry.generated.js +1 -1
  23. package/dist/buy.d.ts +20 -101
  24. package/dist/buy.js +19 -74
  25. package/dist/capabilities.generated.js +1 -1
  26. package/dist/card-fields.generated.js +2864 -249
  27. package/dist/cardlink-vpos.d.ts +43 -0
  28. package/dist/cardlink-vpos.js +90 -0
  29. package/dist/cdp.d.ts +3 -13
  30. package/dist/cdp.js +244 -175
  31. package/dist/checkout-com.generated.js +5 -1
  32. package/dist/client.d.ts +170 -22
  33. package/dist/client.js +281 -40
  34. package/dist/creditguard.generated.d.ts +4 -4
  35. package/dist/cybersource-flex.generated.d.ts +39 -1
  36. package/dist/cybersource-flex.generated.js +100 -11
  37. package/dist/datatrans.generated.js +22 -1
  38. package/dist/eghl.d.ts +40 -0
  39. package/dist/eghl.js +72 -0
  40. package/dist/elavon-converge.generated.js +5 -3
  41. package/dist/gmo.generated.js +7 -2
  42. package/dist/hold.d.ts +8 -0
  43. package/dist/hold.js +43 -2
  44. package/dist/hosted-entry.js +4 -0
  45. package/dist/index.d.ts +9 -15
  46. package/dist/index.js +6 -10
  47. package/dist/lifecycle.d.ts +9 -61
  48. package/dist/lifecycle.js +24 -10
  49. package/dist/merchant-card-endpoints.generated.d.ts +6 -1
  50. package/dist/merchant-card-endpoints.generated.js +344 -19
  51. package/dist/merchant-hosted.d.ts +8 -1
  52. package/dist/nike-order.d.ts +51 -0
  53. package/dist/nike-order.js +81 -0
  54. package/dist/oceanpayment.d.ts +38 -0
  55. package/dist/oceanpayment.js +70 -0
  56. package/dist/paddle-tokenex.generated.js +111 -11
  57. package/dist/payplug.d.ts +41 -0
  58. package/dist/payplug.js +71 -0
  59. package/dist/payrails.generated.js +33 -8
  60. package/dist/pre-claim.d.ts +11 -0
  61. package/dist/pre-claim.js +130 -7
  62. package/dist/preflight-capabilities.generated.d.ts +0 -4
  63. package/dist/preflight-capabilities.generated.js +0 -5
  64. package/dist/preflight-catalog.json +200 -6
  65. package/dist/preflight-playwright.d.ts +2 -2
  66. package/dist/preflight-playwright.js +63 -14
  67. package/dist/preflight-schemas.json +18 -0
  68. package/dist/preflight.generated.d.ts +5 -4
  69. package/dist/preflight.generated.js +63 -3
  70. package/dist/preparation.d.ts +7 -0
  71. package/dist/preparation.js +21 -0
  72. package/dist/prepared-processor.d.ts +18 -5
  73. package/dist/prepared-processor.js +48 -8
  74. package/dist/primer.generated.js +2889 -268
  75. package/dist/processout.generated.d.ts +61 -0
  76. package/dist/processout.generated.js +577 -0
  77. package/dist/requests.js +1 -1
  78. package/dist/shiji-sts.generated.js +111 -11
  79. package/dist/stripe-checkout.generated.js +2761 -319
  80. package/dist/substitutions.generated.js +553 -26
  81. package/dist/tap-payments.generated.js +111 -11
  82. package/dist/twoc2p.generated.js +111 -11
  83. package/dist/url-masks/bluesnap.d.ts +2 -0
  84. package/dist/url-masks/bluesnap.js +15 -0
  85. package/dist/url-masks/oceanpayment.d.ts +2 -0
  86. package/dist/url-masks/oceanpayment.js +13 -0
  87. package/dist/url-masks/payplug.d.ts +2 -0
  88. package/dist/url-masks/payplug.js +13 -0
  89. package/dist/url-masks/vtex_payments.d.ts +2 -0
  90. package/dist/url-masks/vtex_payments.js +12 -0
  91. package/dist/url-masks.generated.d.ts +1 -1
  92. package/dist/url-masks.generated.js +6 -2
  93. package/dist/verifone.generated.js +42 -2
  94. package/dist/vtex-payments.generated.d.ts +127 -0
  95. package/dist/vtex-payments.generated.js +544 -0
  96. package/dist/webhooks.d.ts +2 -2
  97. package/dist/webhooks.js +2 -2
  98. package/examples/preflight/kernel-native/inventory.json +1 -1
  99. package/package.json +6 -8
  100. package/dist/languages.d.ts +0 -23
  101. package/dist/languages.js +0 -76
  102. package/dist/voice-pkce.d.ts +0 -49
  103. package/dist/voice-pkce.js +0 -147
  104. package/dist/voice-stream.generated.d.ts +0 -118
  105. package/dist/voice-stream.generated.js +0 -170
  106. package/dist/voice-types.d.ts +0 -735
  107. package/dist/voice.d.ts +0 -373
  108. package/dist/voice.js +0 -815
  109. package/readme.test.mjs +0 -53
  110. /package/dist/{voice-retry.d.ts → api-retry.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  // @ts-nocheck
2
2
  // Generated from @agent-cards/payment-core. Do not edit.
3
- // artifact-sha256: c278e78b910411f826f9313f7dde769c3c0eb483df9bcd4f6280eec186ce4c98
3
+ // artifact-sha256: f21676a30bdae7f57fc6f082de081b702b2e8cb4d7af10779b1d674cfd256b1d
4
4
  // src/card-number-key.js
5
5
  var CARD_NUMBER_KEY = /^(number|card_number|cardnumber|cardNum|card_num|pan)$/i;
6
6
  // src/json-path.js
@@ -101,8 +101,8 @@ function parseConvergeBody(body) {
101
101
  return parsed;
102
102
  }
103
103
  function convergeAmountCents(value) {
104
- const text9 = typeof value === "number" && Number.isFinite(value) ? String(value) : value;
105
- const m = typeof text9 === "string" ? AMOUNT.exec(text9) : null;
104
+ const text10 = typeof value === "number" && Number.isFinite(value) ? String(value) : value;
105
+ const m = typeof text10 === "string" ? AMOUNT.exec(text10) : null;
106
106
  if (!m)
107
107
  return null;
108
108
  const cents2 = Number(m[1]) * 100 + Number(((m[2] ?? "") + "00").slice(0, 2));
@@ -357,8 +357,8 @@ var CONTROL = /[\u0000-\u001f\u007f]/;
357
357
  var cardLikeName = (name) => (name.match(/[0-9]/g) ?? []).length >= 12;
358
358
  var record3 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
359
359
  var sameKeys = (value, keys) => {
360
- const own13 = Object.keys(value);
361
- return own13.length === keys.length && own13.every((key, at) => key === keys[at]);
360
+ const own23 = Object.keys(value);
361
+ return own23.length === keys.length && own23.every((key, at) => key === keys[at]);
362
362
  };
363
363
  var refuse4 = (code) => Object.freeze({ verdict: "refuse", code });
364
364
  var CARD4 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
@@ -582,9 +582,9 @@ var K = /* @__PURE__ */ new Uint32Array([
582
582
  3329325298
583
583
  ]);
584
584
  var rotr = (x, n) => x >>> n | x << 32 - n;
585
- function utf8(text9) {
585
+ function utf8(text10) {
586
586
  const out = [];
587
- for (const char of text9) {
587
+ for (const char of text10) {
588
588
  let cp = char.codePointAt(0);
589
589
  if (cp >= 55296 && cp <= 57343)
590
590
  cp = 65533;
@@ -659,6 +659,7 @@ var BASE64 = /^[A-Za-z0-9+/]+={0,2}$/;
659
659
  var SHA256_HEX = /^[0-9a-f]{64}$/;
660
660
  var RSA_ALGORITHM = [48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0];
661
661
  var MODULUS_BYTES = [128, 256, 384, 512];
662
+ var SMALL_MODULUS_BYTES = 64;
662
663
  var TYPED_ARRAY = Object.getPrototypeOf(Uint8Array.prototype);
663
664
  var typedArrayName = Object.getOwnPropertyDescriptor(TYPED_ARRAY, Symbol.toStringTag).get;
664
665
  function parseRsaPublicKey(key) {
@@ -667,6 +668,9 @@ function parseRsaPublicKey(key) {
667
668
  const named = key && typeof key === "object" && Object.prototype.hasOwnProperty.call(key, "exponent") ? key.exponent : void 0;
668
669
  if (named !== void 0 && named !== 17)
669
670
  throw refuse6("key");
671
+ const sized = key && typeof key === "object" && Object.prototype.hasOwnProperty.call(key, "bits") ? key.bits : void 0;
672
+ if (sized !== void 0 && sized !== 512)
673
+ throw refuse6("key");
670
674
  if (typeof spki !== "string" || spki.length > 1024 || spki.length % 4 !== 0 || !BASE64.test(spki))
671
675
  throw refuse6("key");
672
676
  if (typeof pin10 !== "string" || !SHA256_HEX.test(pin10))
@@ -699,7 +703,8 @@ function parseRsaPublicKey(key) {
699
703
  if (exponent.end !== rsa.end)
700
704
  throw refuse6("key");
701
705
  const n = modulus.bytes;
702
- if (!MODULUS_BYTES.includes(n.length) || !(n[0] & 128) || !(n[n.length - 1] & 1))
706
+ const sizes = sized === 512 ? [SMALL_MODULUS_BYTES] : MODULUS_BYTES;
707
+ if (!sizes.includes(n.length) || !(n[0] & 128) || !(n[n.length - 1] & 1))
703
708
  throw refuse6("key");
704
709
  const e = exponent.bytes;
705
710
  const expected = named === 17 ? [17] : [1, 0, 1];
@@ -713,13 +718,13 @@ function readElement(der, at, tag) {
713
718
  let length = der[at + 1];
714
719
  let start = at + 2;
715
720
  if (length & 128) {
716
- const count = length & 127;
717
- if (count === 0 || count > 2 || start + count > der.length || der[start] === 0)
721
+ const count2 = length & 127;
722
+ if (count2 === 0 || count2 > 2 || start + count2 > der.length || der[start] === 0)
718
723
  throw refuse6("key");
719
- length = count === 1 ? der[start] : der[start] * 256 + der[start + 1];
724
+ length = count2 === 1 ? der[start] : der[start] * 256 + der[start + 1];
720
725
  if (length < 128)
721
726
  throw refuse6("key");
722
- start += count;
727
+ start += count2;
723
728
  }
724
729
  if (start + length > der.length)
725
730
  throw refuse6("key");
@@ -771,8 +776,8 @@ var PADDLE_TOKENEX_PSP = "paddle_tokenex";
771
776
  var PADDLE_TOKENEX_FACT_KEYS = /* @__PURE__ */ Object.freeze(["card_first_six", "card_last_four", "expiry_month", "expiry_year", "card_brand"]);
772
777
  var record4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
773
778
  var sameKeys2 = (value, keys) => {
774
- const own13 = Object.keys(value);
775
- return own13.length === keys.length && own13.every((key, at) => key === keys[at]);
779
+ const own23 = Object.keys(value);
780
+ return own23.length === keys.length && own23.every((key, at) => key === keys[at]);
776
781
  };
777
782
  var refuse7 = (code) => Object.freeze({ verdict: "refuse", code });
778
783
  var CARD6 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
@@ -842,8 +847,8 @@ function readPay(body, line, environment2) {
842
847
  const card = record4(method) && sameKeys2(method, ["card"]) ? method.card : null;
843
848
  if (!record4(card) || !(sameKeys2(card, PAY_CARD_KEYS) || sameKeys2(card, [...PAY_CARD_KEYS, "session_tracking"])))
844
849
  return null;
845
- const metadata = card.metadata;
846
- if (!record4(metadata) || !sameKeys2(metadata, METADATA_KEYS2) || typeof metadata.cardholder_name !== "string" || metadata.cardholder_name.length > NAME_LIMIT2 || CONTROL2.test(metadata.cardholder_name) || cardLikeName2(metadata.cardholder_name) || typeof metadata.card_first_six !== "string" || !FIRST_SIX.test(metadata.card_first_six) || typeof metadata.card_last_four !== "string" || !LAST_FOUR.test(metadata.card_last_four) || !expiryMonth(metadata.expiry_month) || !expiryYear(metadata.expiry_year) || !FRAME_BRANDS.includes(metadata.card_brand))
850
+ const metadata2 = card.metadata;
851
+ 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))
847
852
  return null;
848
853
  const details = card.three_d_s;
849
854
  if (!record4(details) || !sameKeys2(details, ["browser_info"]) || typeof details.browser_info !== "string" || !BROWSER_INFO.test(details.browser_info))
@@ -1261,8 +1266,8 @@ var TEXT_LIMIT = 256;
1261
1266
  var CONTROL4 = /[\u0000-\u001f\u007f]/;
1262
1267
  var record6 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
1263
1268
  var sameKeys3 = (value, keys) => {
1264
- const own13 = Object.keys(value);
1265
- return own13.length === keys.length && own13.every((key, at) => key === keys[at]);
1269
+ const own23 = Object.keys(value);
1270
+ return own23.length === keys.length && own23.every((key, at) => key === keys[at]);
1266
1271
  };
1267
1272
  var plainText = (value) => typeof value === "string" && value.length <= TEXT_LIMIT && !CONTROL4.test(value) && (value.match(/[0-9]/g) ?? []).length < 12;
1268
1273
  var refuse9 = (code) => Object.freeze({ verdict: "refuse", code });
@@ -1292,13 +1297,13 @@ function billingFields(value) {
1292
1297
  if (names.length > MAX_FIELDS)
1293
1298
  return false;
1294
1299
  return names.every((name) => {
1295
- const field2 = value[name];
1300
+ const field5 = value[name];
1296
1301
  if (!FIELD_NAME.test(name))
1297
1302
  return false;
1298
- if (!record6(field2))
1299
- return billingText(field2);
1300
- const nested = Object.keys(field2);
1301
- return nested.length <= MAX_NESTED_FIELDS && nested.every((key) => FIELD_NAME.test(key) && billingText(field2[key]));
1303
+ if (!record6(field5))
1304
+ return billingText(field5);
1305
+ const nested = Object.keys(field5);
1306
+ return nested.length <= MAX_NESTED_FIELDS && nested.every((key) => FIELD_NAME.test(key) && billingText(field5[key]));
1302
1307
  });
1303
1308
  }
1304
1309
  function wixPaymentsBodyVerdict(body) {
@@ -1372,14 +1377,14 @@ function readJson2(body) {
1372
1377
  catch {
1373
1378
  return { parsed: null, exact: false };
1374
1379
  }
1375
- let exact4 = false;
1380
+ let exact5 = false;
1376
1381
  try {
1377
- exact4 = body.length <= BODY_LIMIT6 && JSON.stringify(parsed) === body;
1382
+ exact5 = body.length <= BODY_LIMIT6 && JSON.stringify(parsed) === body;
1378
1383
  }
1379
1384
  catch {
1380
- exact4 = false;
1385
+ exact5 = false;
1381
1386
  }
1382
- return { parsed, exact: exact4 };
1387
+ return { parsed, exact: exact5 };
1383
1388
  }
1384
1389
  function billingValue(value) {
1385
1390
  if (value === UNDEFINED)
@@ -1393,15 +1398,15 @@ function judgeCardAttach(args, session) {
1393
1398
  return "paymongo_body_unsupported";
1394
1399
  }
1395
1400
  const id = args[0].slice(3);
1396
- const attributes = args[1].data.attributes;
1397
- const details = attributes.details;
1401
+ const attributes2 = args[1].data.attributes;
1402
+ const details = attributes2.details;
1398
1403
  if (record7(details) && CLICK_TO_PAY_KEYS.some((key) => own(details, key)))
1399
1404
  return "paymongo_click_to_pay";
1400
- if (!keysAre(args[1], ["data"]) || !keysAre(args[1].data, ["attributes"]) || !keysAre(attributes, PAYMONGO_ATTRIBUTE_KEYS) || !record7(details) || !keysAre(details, PAYMONGO_CARD_KEYS))
1405
+ if (!keysAre(args[1], ["data"]) || !keysAre(args[1].data, ["attributes"]) || !keysAre(attributes2, PAYMONGO_ATTRIBUTE_KEYS) || !record7(details) || !keysAre(details, PAYMONGO_CARD_KEYS))
1401
1406
  return "paymongo_body_unsupported";
1402
1407
  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))
1403
1408
  return "paymongo_body_unsupported";
1404
- const billing = attributes.billing;
1409
+ const billing = attributes2.billing;
1405
1410
  if (!record7(billing) || !keysAre(billing, PAYMONGO_BILLING_KEYS) || !record7(billing.address) || !keysAre(billing.address, PAYMONGO_ADDRESS_KEYS))
1406
1411
  return "paymongo_body_unsupported";
1407
1412
  if (billing.name === UNDEFINED || !billingValue(billing.name) || !billingValue(billing.email) || !billingValue(billing.phone) || !PAYMONGO_ADDRESS_KEYS.every((key) => billingValue(billing.address[key])))
@@ -1409,7 +1414,7 @@ function judgeCardAttach(args, session) {
1409
1414
  const third = args[2];
1410
1415
  if (!record7(third) || !keysAre(third, ["viewerAccept"]) || !billingValue(third.viewerAccept))
1411
1416
  return "paymongo_body_unsupported";
1412
- if (attributes.return_url !== `${ORIGIN}${id}` || session !== void 0 && session !== id)
1417
+ if (attributes2.return_url !== `${ORIGIN}${id}` || session !== void 0 && session !== id)
1413
1418
  return "paymongo_session_mismatch";
1414
1419
  return null;
1415
1420
  }
@@ -1434,14 +1439,14 @@ function attachType(parsed) {
1434
1439
  return typeof type === "string" ? type : null;
1435
1440
  }
1436
1441
  function paymongoBodyVerdict(body, session) {
1437
- const { parsed, exact: exact4 } = readJson2(body);
1442
+ const { parsed, exact: exact5 } = readJson2(body);
1438
1443
  const type = parsed === null ? null : attachType(parsed);
1439
1444
  if (type !== "card") {
1440
1445
  if (parsed === null)
1441
1446
  return body === void 0 || body === null || body === "" ? CONTINUE4 : refuse10("paymongo_body_unsupported");
1442
1447
  return namesCardValue(parsed) ? refuse10("paymongo_body_unsupported") : CONTINUE4;
1443
1448
  }
1444
- if (!exact4)
1449
+ if (!exact5)
1445
1450
  return refuse10("paymongo_body_unsupported");
1446
1451
  const code = judgeCardAttach(parsed, session);
1447
1452
  return code === null ? CARD9 : refuse10(code);
@@ -1464,8 +1469,8 @@ var EXPIRATION = /^[0-9]{2}(?:0[1-9]|1[0-2])$/;
1464
1469
  var CARD_PAYMENT = "PAYMENT_CARD";
1465
1470
  var record8 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
1466
1471
  var sameKeys4 = (value, keys) => {
1467
- const own13 = Object.keys(value);
1468
- return own13.length === keys.length && own13.every((key, at) => key === keys[at]);
1472
+ const own23 = Object.keys(value);
1473
+ return own23.length === keys.length && own23.every((key, at) => key === keys[at]);
1469
1474
  };
1470
1475
  var refuse11 = (code) => Object.freeze({ verdict: "refuse", code });
1471
1476
  var CARD10 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
@@ -1695,8 +1700,8 @@ var LOCALE = /^[a-z]{2}(?:-[A-Za-z]{2,4})?$/;
1695
1700
  var PAN_LIKE3 = /(?:[0-9][ _.:-]*){12,}/;
1696
1701
  var record9 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
1697
1702
  var sameKeys5 = (value, keys) => {
1698
- const own13 = Object.keys(value);
1699
- return own13.length === keys.length && own13.every((key, at) => key === keys[at]);
1703
+ const own23 = Object.keys(value);
1704
+ return own23.length === keys.length && own23.every((key, at) => key === keys[at]);
1700
1705
  };
1701
1706
  var refuse13 = (code) => Object.freeze({ verdict: "refuse", code });
1702
1707
  var CARD12 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
@@ -1948,10 +1953,10 @@ function judge(body, contentType, rule) {
1948
1953
  if (read.parts.some((part) => !listed(rule.parts, part.name)))
1949
1954
  return refusal("multipart_unknown_part");
1950
1955
  for (const name of rule.card) {
1951
- const count = read.parts.filter((part) => part.name === name).length;
1952
- if (count === 0)
1956
+ const count2 = read.parts.filter((part) => part.name === name).length;
1957
+ if (count2 === 0)
1953
1958
  return refusal("multipart_missing_card_part");
1954
- if (count > 1)
1959
+ if (count2 > 1)
1955
1960
  return refusal("multipart_duplicate_card_part");
1956
1961
  }
1957
1962
  return read;
@@ -2112,7 +2117,7 @@ var luhn2 = (digits3) => {
2112
2117
  return sum % 10 === 0;
2113
2118
  };
2114
2119
  var ANY_NETWORK = /^[2-6][0-9]{12,18}$/;
2115
- var holdsCardShape = (text9, shape = NETWORK) => (text9.match(/[0-9]{13,}/g) ?? []).some((run) => run.length > 19 || shape.test(run) && luhn2(run));
2120
+ var holdsCardShape = (text10, shape = NETWORK) => (text10.match(/[0-9]{13,}/g) ?? []).some((run) => run.length > 19 || shape.test(run) && luhn2(run));
2116
2121
  var phone = (value) => typeof value === "string" && PHONE.test(value) && (value.match(/[0-9]/g) ?? []).length >= 6 && (value.match(/[0-9]/g) ?? []).length <= 15;
2117
2122
  var refuse16 = (code) => Object.freeze({ verdict: "refuse", code });
2118
2123
  var CARD15 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
@@ -2340,13 +2345,13 @@ var printable = (value) => [...value].every((ch) => ch.charCodeAt(0) >= 32 && ch
2340
2345
  function typed(value, limit = 256) {
2341
2346
  return typeof value === "string" && value.length >= 1 && value.length <= limit && !PAN_LIKE4.test(value) && printable(value);
2342
2347
  }
2343
- function decodeBase64(text9) {
2344
- if (typeof text9 !== "string" || !BASE643.test(text9) || text9.length % 4 !== 0)
2348
+ function decodeBase64(text10) {
2349
+ if (typeof text10 !== "string" || !BASE643.test(text10) || text10.length % 4 !== 0)
2345
2350
  return null;
2346
2351
  let bits = 0;
2347
2352
  let value = 0;
2348
2353
  let out = "";
2349
- for (const ch of text9.replace(/=+$/, "")) {
2354
+ for (const ch of text10.replace(/=+$/, "")) {
2350
2355
  value = (value << 6 | BASE64_ALPHABET.indexOf(ch)) & 16777215;
2351
2356
  bits += 6;
2352
2357
  if (bits >= 8) {
@@ -2356,8 +2361,8 @@ function decodeBase64(text9) {
2356
2361
  }
2357
2362
  return out;
2358
2363
  }
2359
- function soundDevice(text9) {
2360
- const json = decodeBase64(text9);
2364
+ function soundDevice(text10) {
2365
+ const json = decodeBase64(text10);
2361
2366
  if (json === null)
2362
2367
  return false;
2363
2368
  let value;
@@ -2475,17 +2480,17 @@ function sumupBodyVerdict(body, url) {
2475
2480
  var SALTED = /* @__PURE__ */ Object.freeze([83, 97, 108, 116, 101, 100, 95, 95]);
2476
2481
  var B64 = /^[A-Za-z0-9+/]+={0,2}$/;
2477
2482
  var FIELD_LIMIT = 1024;
2478
- function decodeCanonical(text9) {
2479
- if (typeof text9 !== "string" || text9.length === 0 || text9.length % 4 !== 0 || !B64.test(text9))
2483
+ function decodeCanonical(text10) {
2484
+ if (typeof text10 !== "string" || text10.length === 0 || text10.length % 4 !== 0 || !B64.test(text10))
2480
2485
  return null;
2481
2486
  let binary;
2482
2487
  try {
2483
- binary = atob(text9);
2488
+ binary = atob(text10);
2484
2489
  }
2485
2490
  catch {
2486
2491
  return null;
2487
2492
  }
2488
- if (btoa(binary) !== text9)
2493
+ if (btoa(binary) !== text10)
2489
2494
  return null;
2490
2495
  return Uint8Array.from(binary, (char) => char.charCodeAt(0));
2491
2496
  }
@@ -2727,8 +2732,8 @@ var TEXT_LIMIT3 = 256;
2727
2732
  var CONTROL7 = /[\u0000-\u001f\u007f]/;
2728
2733
  var record13 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
2729
2734
  var sameKeys7 = (value, keys) => {
2730
- const own13 = Object.keys(value);
2731
- return own13.length === keys.length && own13.every((key, at) => key === keys[at]);
2735
+ const own23 = Object.keys(value);
2736
+ return own23.length === keys.length && own23.every((key, at) => key === keys[at]);
2732
2737
  };
2733
2738
  var plainText3 = (value) => typeof value === "string" && value.length <= TEXT_LIMIT3 && !CONTROL7.test(value) && (value.match(/[0-9]/g) ?? []).length < 12;
2734
2739
  var refuse19 = (code) => Object.freeze({ verdict: "refuse", code });
@@ -3005,10 +3010,10 @@ function paypalBodyVerdict(body) {
3005
3010
  if (number === void 0 || number === null || number === "")
3006
3011
  return CONTINUE9;
3007
3012
  const context = value.application_context;
3008
- const attributes = record14(card.attributes) ? card.attributes : null;
3009
- if (record14(context) && context.vault === true || own3(card, "stored_credential") || attributes && (own3(attributes, "vault") || own3(attributes, "customer")))
3013
+ const attributes2 = record14(card.attributes) ? card.attributes : null;
3014
+ if (record14(context) && context.vault === true || own3(card, "stored_credential") || attributes2 && (own3(attributes2, "vault") || own3(attributes2, "customer")))
3010
3015
  return refuse20("paypal_card_on_file");
3011
- if (attributes && record14(attributes.verification) && attributes.verification.method === "SCA_ALWAYS")
3016
+ if (attributes2 && record14(attributes2.verification) && attributes2.verification.method === "SCA_ALWAYS")
3012
3017
  return refuse20("paypal_three_ds");
3013
3018
  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))
3014
3019
  return refuse20("paypal_body_unsupported");
@@ -3022,7 +3027,7 @@ function paypalBodyVerdict(body) {
3022
3027
  if (own3(card, "billing_address") && !(keysWithin2(card.billing_address, ADDRESS_KEYS3) && Object.values(card.billing_address).every(text3))) {
3023
3028
  return refuse20("paypal_body_unsupported");
3024
3029
  }
3025
- if (own3(card, "attributes") && !(keysWithin2(attributes, ["installments"]) && installmentsOk(attributes.installments))) {
3030
+ if (own3(card, "attributes") && !(keysWithin2(attributes2, ["installments"]) && installmentsOk(attributes2.installments))) {
3026
3031
  return refuse20("paypal_body_unsupported");
3027
3032
  }
3028
3033
  return CARD19;
@@ -3424,7 +3429,7 @@ var YEAR11 = /^[0-9]{2}$/;
3424
3429
  var CODE4 = /^[0-9]{3}$/;
3425
3430
  var NAME_LIMIT3 = 100;
3426
3431
  var NAME_WORD = /[a-z]+/gi;
3427
- var printable2 = (text9) => [...text9].every((character) => {
3432
+ var printable2 = (text10) => [...text10].every((character) => {
3428
3433
  const point = character.codePointAt(0);
3429
3434
  return point >= 32 && !(point >= 127 && point <= 159) && point !== 8232 && point !== 8233;
3430
3435
  });
@@ -3433,8 +3438,8 @@ var HOSTNAME = /^(?=.{1,253}$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](
3433
3438
  var PUBLISHABLE_KEY = /^[A-Za-z0-9]{16,64}$/;
3434
3439
  var record18 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
3435
3440
  var sameKeys8 = (value, keys) => {
3436
- const own13 = Object.keys(value);
3437
- return own13.length === keys.length && own13.every((key, at) => key === keys[at]);
3441
+ const own23 = Object.keys(value);
3442
+ return own23.length === keys.length && own23.every((key, at) => key === keys[at]);
3438
3443
  };
3439
3444
  var refuse24 = (code) => Object.freeze({ verdict: "refuse", code });
3440
3445
  var CARD23 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
@@ -3804,7 +3809,7 @@ var POSTAL_CODE3 = /^[A-Za-z0-9_]{0,16}$/;
3804
3809
  var COUNTRY4 = /^[A-Z]{2}$/;
3805
3810
  var TEXT_LIMIT7 = 256;
3806
3811
  var CONTROL10 = /[\u0000-\u001f\u007f]/;
3807
- var cardLike2 = (text9) => (text9.match(/[0-9]/g) ?? []).length >= 12;
3812
+ var cardLike2 = (text10) => (text10.match(/[0-9]/g) ?? []).length >= 12;
3808
3813
  var text5 = (value) => typeof value === "string" && value.length <= TEXT_LIMIT7 && !CONTROL10.test(value) && !cardLike2(value);
3809
3814
  var record21 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
3810
3815
  var own5 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
@@ -4125,11 +4130,11 @@ var LONG_TEXT_LIMIT = BODY_LIMIT25;
4125
4130
  var record22 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
4126
4131
  var owns6 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
4127
4132
  var sameKeys9 = (value, keys) => {
4128
- const own13 = Object.keys(value);
4129
- return own13.length === keys.length && own13.every((key, at) => key === keys[at]);
4133
+ const own23 = Object.keys(value);
4134
+ return own23.length === keys.length && own23.every((key, at) => key === keys[at]);
4130
4135
  };
4131
4136
  var exact3 = (pattern, value) => typeof value === "string" && pattern.test(value);
4132
- var printable3 = (text9) => [...text9].every((character) => {
4137
+ var printable3 = (text10) => [...text10].every((character) => {
4133
4138
  const point = character.codePointAt(0);
4134
4139
  return point >= 32 && !(point >= 127 && point <= 159) && point !== 8232 && point !== 8233;
4135
4140
  });
@@ -4202,7 +4207,7 @@ function companyStore(value) {
4202
4207
  return record22(value) && sameKeys9(value, COMPANY_KEYS) && whole(value.CompanyNumber, 1) && COMPANY_KEYS.slice(1).every((key) => key.startsWith("Show") ? flag(value[key]) : pageText(value[key]));
4203
4208
  }
4204
4209
  var SUM_TEXT = /^(?:0*[1-9][0-9]*(?:\.[0-9]+)?|0+\.[0-9]*[1-9][0-9]*)$/;
4205
- var sumText = (text9, sum) => text9 === null || typeof text9 === "string" && SUM_TEXT.test(text9) && Number.parseFloat(text9) === sum;
4210
+ var sumText = (text10, sum) => text10 === null || typeof text10 === "string" && SUM_TEXT.test(text10) && Number.parseFloat(text10) === sum;
4206
4211
  function chosenProduct(value) {
4207
4212
  return record22(value) && sameKeys9(value, PRODUCT_KEYS) && whole(value.MinQuantity) && whole(value.MaxQuantity) && whole(value.JumpsInQuantity) && value.SelectedBuyQuantity === 1 && Array.isArray(value.QuantityOptions) && value.QuantityOptions.length === 0 && pageText(value.Comments) && flag(value.IsManualSum) && Array.isArray(value.PaymentsOptions) && flag(value.IsCouponActive) && typeof value.ManualPrice === "number" && sumText(value.ManualPriceTxt, value.ManualPrice) && flag(value.IsVatFree) && Array.isArray(value.SpecialPrices) && (value.PreConfiguredPrice === null || typeof value.PreConfiguredPrice === "number") && flag(value.IsPreSelected) && typeof value.CurrentInventory === "number" && flag(value.CheckInventory) && exact3(PRODUCT_ID, value.uid) && pageText(value.imageUrl) && typeof value.name === "string" && pageText(value.name) && pageText(value.description) && typeof value.BasePrice === "number" && typeof value.PriceBeforeDiscount === "number" && whole(value.BaseISOCurrency) && typeof value.PriceToShow === "number" && typeof value.PriceBeforeDiscountToShow === "number" && flag(value.IsCurrent);
4208
4213
  }
@@ -4433,7 +4438,7 @@ var sameKeys10 = (value, keys) => {
4433
4438
  };
4434
4439
  var refuse28 = (code) => Object.freeze({ verdict: "refuse", code });
4435
4440
  var CARD27 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
4436
- var printable4 = (text9) => [...text9].every((character) => {
4441
+ var printable4 = (text10) => [...text10].every((character) => {
4437
4442
  const point = character.codePointAt(0);
4438
4443
  return point >= 32 && !(point >= 127 && point <= 159) && point !== 8232 && point !== 8233;
4439
4444
  });
@@ -4525,8 +4530,8 @@ var POSTAL_CODE4 = /^[A-Za-z0-9 -]{0,16}$/;
4525
4530
  var CIPHERTEXT_B64 = /^[A-Za-z0-9+/]{341}[AQgw]==$/;
4526
4531
  var record24 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
4527
4532
  var sameKeys11 = (value, keys) => {
4528
- const own13 = Object.keys(value);
4529
- return own13.length === keys.length && own13.every((key, at) => key === keys[at]);
4533
+ const own23 = Object.keys(value);
4534
+ return own23.length === keys.length && own23.every((key, at) => key === keys[at]);
4530
4535
  };
4531
4536
  var refuse29 = (code) => Object.freeze({ verdict: "refuse", code });
4532
4537
  var failed = (code) => (
@@ -4677,14 +4682,14 @@ function readJson7(body) {
4677
4682
  catch {
4678
4683
  return { parsed: null, exact: false };
4679
4684
  }
4680
- let exact4 = false;
4685
+ let exact5 = false;
4681
4686
  try {
4682
- exact4 = JSON.stringify(parsed) === body;
4687
+ exact5 = JSON.stringify(parsed) === body;
4683
4688
  }
4684
4689
  catch {
4685
- exact4 = false;
4690
+ exact5 = false;
4686
4691
  }
4687
- return { parsed, exact: exact4 };
4692
+ return { parsed, exact: exact5 };
4688
4693
  }
4689
4694
  function numberDigits(number) {
4690
4695
  if (typeof number !== "string")
@@ -4761,7 +4766,7 @@ function judgeCard2(parsed) {
4761
4766
  return null;
4762
4767
  }
4763
4768
  function fastspringBodyVerdict(body) {
4764
- const { parsed, exact: exact4 } = readJson7(body);
4769
+ const { parsed, exact: exact5 } = readJson7(body);
4765
4770
  if (!record25(parsed))
4766
4771
  return body === void 0 || body === null || body === "" ? CONTINUE11 : refuse30("fastspring_body_unsupported");
4767
4772
  if (parsed.paymentType !== "card") {
@@ -4769,7 +4774,7 @@ function fastspringBodyVerdict(body) {
4769
4774
  return refuse30("fastspring_body_unsupported");
4770
4775
  return typeof parsed.paymentType === "string" && parsed.paymentType !== "" ? CONTINUE11 : refuse30("fastspring_body_unsupported");
4771
4776
  }
4772
- if (!exact4)
4777
+ if (!exact5)
4773
4778
  return refuse30("fastspring_body_unsupported");
4774
4779
  const code = judgeCard2(parsed);
4775
4780
  return code === null ? CARD29 : refuse30(code);
@@ -4995,20 +5000,20 @@ function readBody18(body) {
4995
5000
  function amountValue(value) {
4996
5001
  if (typeof value === "number" && !Number.isFinite(value))
4997
5002
  return false;
4998
- const text9 = typeof value === "number" ? String(value) : value;
4999
- if (typeof text9 !== "string" || !AMOUNT_TEXT.test(text9))
5003
+ const text10 = typeof value === "number" ? String(value) : value;
5004
+ if (typeof text10 !== "string" || !AMOUNT_TEXT.test(text10))
5000
5005
  return false;
5001
- const amount2 = Number(text9);
5006
+ const amount2 = Number(text10);
5002
5007
  return amount2 > 0 && amount2 <= AMOUNT_LIMIT3;
5003
5008
  }
5004
5009
  function billingDetails(value) {
5005
5010
  if (!record27(value) || !inOrder5(value, BILLING_KEYS))
5006
5011
  return false;
5007
5012
  return Object.keys(value).every((key) => {
5008
- const field2 = value[key];
5013
+ const field5 = value[key];
5009
5014
  if (key !== "address")
5010
- return key === "mobile_number" || key === "phone_number" ? typeof field2 === "string" && PHONE4.test(field2) : plainText6(field2);
5011
- return record27(field2) && inOrder5(field2, ADDRESS_KEYS5) && Object.keys(field2).every((name) => plainText6(field2[name]));
5015
+ return key === "mobile_number" || key === "phone_number" ? typeof field5 === "string" && PHONE4.test(field5) : plainText6(field5);
5016
+ return record27(field5) && inOrder5(field5, ADDRESS_KEYS5) && Object.keys(field5).every((name) => plainText6(field5[name]));
5012
5017
  });
5013
5018
  }
5014
5019
  function cardData(value) {
@@ -5038,8 +5043,8 @@ function xenditBodyVerdict(body) {
5038
5043
  if (own9(value, "fp_session_id") && (typeof value.fp_session_id !== "string" || !FP_SESSION.test(value.fp_session_id)))
5039
5044
  return refuse32("xendit_body_unsupported");
5040
5045
  if (own9(value, "metadata")) {
5041
- const metadata = value.metadata;
5042
- if (!record27(metadata) || Object.keys(metadata).length !== 1 || !record27(metadata._forter) || Object.keys(metadata._forter).length !== 1 || typeof metadata._forter.token !== "string" || !FORTER_TOKEN.test(metadata._forter.token))
5046
+ const metadata2 = value.metadata;
5047
+ 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))
5043
5048
  return refuse32("xendit_body_unsupported");
5044
5049
  }
5045
5050
  if (own9(value, "mid_label") && (typeof value.mid_label !== "string" || !MID_LABEL.test(value.mid_label)))
@@ -5196,10 +5201,10 @@ function isPaymobPayUrl(url) {
5196
5201
  var BASE645 = /^[A-Za-z0-9+/]+={0,2}$/;
5197
5202
  var BASE64URL = /^[A-Za-z0-9_-]+$/;
5198
5203
  var ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
5199
- function decodeBase642(text9, url) {
5200
- if (typeof text9 !== "string" || text9 === "")
5204
+ function decodeBase642(text10, url) {
5205
+ if (typeof text10 !== "string" || text10 === "")
5201
5206
  return null;
5202
- let body = text9;
5207
+ let body = text10;
5203
5208
  if (url) {
5204
5209
  if (!BASE64URL.test(body) || body.length % 4 === 1)
5205
5210
  return null;
@@ -5232,15 +5237,15 @@ function decodeBase642(text9, url) {
5232
5237
  function jsonOf(bytes) {
5233
5238
  if (!bytes)
5234
5239
  return null;
5235
- let text9;
5240
+ let text10;
5236
5241
  try {
5237
- text9 = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
5242
+ text10 = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
5238
5243
  }
5239
5244
  catch {
5240
5245
  return null;
5241
5246
  }
5242
5247
  try {
5243
- const value = JSON.parse(text9);
5248
+ const value = JSON.parse(text10);
5244
5249
  return record29(value) ? value : null;
5245
5250
  }
5246
5251
  catch {
@@ -5317,14 +5322,14 @@ function readJson8(body) {
5317
5322
  catch {
5318
5323
  return { parsed: null, exact: false };
5319
5324
  }
5320
- let exact4 = false;
5325
+ let exact5 = false;
5321
5326
  try {
5322
- exact4 = body.length <= BODY_LIMIT32 && JSON.stringify(parsed) === body;
5327
+ exact5 = body.length <= BODY_LIMIT32 && JSON.stringify(parsed) === body;
5323
5328
  }
5324
5329
  catch {
5325
- exact4 = false;
5330
+ exact5 = false;
5326
5331
  }
5327
- return { parsed, exact: exact4 };
5332
+ return { parsed, exact: exact5 };
5328
5333
  }
5329
5334
  function namesCardValue3(parsed) {
5330
5335
  const pending = parsed !== null && typeof parsed === "object" ? [parsed] : [];
@@ -5341,7 +5346,7 @@ function namesCardValue3(parsed) {
5341
5346
  return false;
5342
5347
  }
5343
5348
  function addressBlock(value) {
5344
- return record29(value) && Object.keys(value).length <= 32 && Object.entries(value).every(([key, text9]) => FIELD.test(key) && !CARD_MEMBER4.test(key) && (text9 === null || typeof text9 === "string" && TEXT3.test(text9)));
5349
+ return record29(value) && Object.keys(value).length <= 32 && Object.entries(value).every(([key, text10]) => FIELD.test(key) && !CARD_MEMBER4.test(key) && (text10 === null || typeof text10 === "string" && TEXT3.test(text10)));
5345
5350
  }
5346
5351
  function judgeCardPayment(parsed) {
5347
5352
  const source = parsed.source;
@@ -5385,8 +5390,8 @@ function judgeCardPayment(parsed) {
5385
5390
  function paymobBodyVerdict(body) {
5386
5391
  if (body === void 0 || body === null || body === "")
5387
5392
  return CONTINUE12;
5388
- const { parsed, exact: exact4 } = readJson8(body);
5389
- if (!exact4 || !record29(parsed) || !record29(parsed.source) || typeof parsed.source.subtype !== "string")
5393
+ const { parsed, exact: exact5 } = readJson8(body);
5394
+ if (!exact5 || !record29(parsed) || !record29(parsed.source) || typeof parsed.source.subtype !== "string")
5390
5395
  return refuse34("paymob_body_unsupported");
5391
5396
  const subtype = parsed.source.subtype;
5392
5397
  if (subtype === "CARD") {
@@ -5839,8 +5844,8 @@ function cardNamed2(key) {
5839
5844
  const phrase = words.join(" ");
5840
5845
  return words.some((word) => CARD_WORDS.includes(word)) || ["security code", "codigo seguridad", "codigo verificacion"].some((said) => phrase.includes(said));
5841
5846
  }
5842
- function carriesCardNumber(text9) {
5843
- for (const [run] of text9.matchAll(/[0-9]+(?:[ ._/,-][0-9]+)*/g)) {
5847
+ function carriesCardNumber(text10) {
5848
+ for (const [run] of text10.matchAll(/[0-9]+(?:[ ._/,-][0-9]+)*/g)) {
5844
5849
  const groups = run.split(/[ ._/,-]/);
5845
5850
  for (let first = 0; first < groups.length; first += 1) {
5846
5851
  let digits3 = "";
@@ -5853,17 +5858,17 @@ function carriesCardNumber(text9) {
5853
5858
  }
5854
5859
  return false;
5855
5860
  }
5856
- var wholeCardNumber = (text9) => /^[2-6][0-9]{12,18}$/.test(text9) && luhn7(text9);
5861
+ var wholeCardNumber = (text10) => /^[2-6][0-9]{12,18}$/.test(text10) && luhn7(text10);
5857
5862
  function membersRefusal(root) {
5858
5863
  const pending = [[root, ""]];
5859
5864
  while (pending.length > 0) {
5860
5865
  const [node, path] = pending.pop();
5861
- const own13 = path === "" ? TRANSACTION_MEMBERS : owns7(RECORD_MEMBERS, path) ? RECORD_MEMBERS[path] : null;
5866
+ const own23 = path === "" ? TRANSACTION_MEMBERS : owns7(RECORD_MEMBERS, path) ? RECORD_MEMBERS[path] : null;
5862
5867
  for (const [key, child] of Object.entries(node)) {
5863
5868
  const at = Array.isArray(node) ? path : path === "" ? key : `${path}.${key}`;
5864
5869
  if (at === "checkoutCreditCard")
5865
5870
  continue;
5866
- if (own13 !== null && !own13.includes(key))
5871
+ if (own23 !== null && !own23.includes(key))
5867
5872
  return true;
5868
5873
  if (TEXT_RECORDS.includes(path) && child !== null && typeof child !== "string")
5869
5874
  return true;
@@ -6084,7 +6089,17 @@ var TOKEN_FACTS = /* @__PURE__ */ Object.freeze([
6084
6089
  "primary"
6085
6090
  ]);
6086
6091
  // src/registration.js
6087
- var PARTS = { psp: "id", definitions: "list", refusedOperations: "list", settlementReadback: "any", exactUrl: "rule", bodyGate: "rule", amount: "rule" };
6092
+ var PARTS = {
6093
+ psp: "id",
6094
+ definitions: "list",
6095
+ refusedOperations: "list",
6096
+ settlementReadback: "any",
6097
+ exactUrl: "rule",
6098
+ bodyGate: "rule",
6099
+ amount: "rule",
6100
+ hostedEntry: "rule",
6101
+ limitations: "sentences"
6102
+ };
6088
6103
  var PSP_ID = /^[a-z][a-z0-9_]*$/;
6089
6104
  var registrationProblems = (spec) => problemsOf(spec, PARTS);
6090
6105
  function problemsOf(spec, parts) {
@@ -6100,9 +6115,14 @@ function problemsOf(spec, parts) {
6100
6115
  continue;
6101
6116
  if (kind === "rule" && typeof value !== "function")
6102
6117
  problems2.push(`${psp}: ${key} is not a function`);
6118
+ if (kind === "flag" && value !== true)
6119
+ problems2.push(`${psp}: ${key} is not true`);
6103
6120
  if (kind === "numbers" && !((Array.isArray(value) || value instanceof Set) && [...value].every((n) => typeof n === "string" && /^\d{12,19}$/.test(n)))) {
6104
6121
  problems2.push(`${psp}: ${key} is not a list of card numbers`);
6105
6122
  }
6123
+ if (kind === "sentences" && !(Array.isArray(value) && value.length > 0 && value.every((s) => typeof s === "string" && s.trim() !== ""))) {
6124
+ problems2.push(`${psp}: ${key} is not a list of sentences`);
6125
+ }
6106
6126
  }
6107
6127
  if ("definitions" in parts) {
6108
6128
  if (!Array.isArray(spec.definitions) || spec.definitions.length === 0)
@@ -6113,6 +6133,10 @@ function problemsOf(spec, parts) {
6113
6133
  if (typeof id !== "string" || !id.startsWith(`${psp}.`))
6114
6134
  problems2.push(`${psp}: ${JSON.stringify(id)} is not one of its operations`);
6115
6135
  }
6136
+ const pages = Array.isArray(spec.definitions) ? spec.definitions.filter((d) => d?.hostedForm?.cardIn === "processor_page") : [];
6137
+ if (spec.hostedEntry !== void 0 && (pages.length === 0 || pages.some((d) => d.hostedForm.policy !== void 0))) {
6138
+ problems2.push(`${psp}: hostedEntry needs a definition whose hosted form takes the card on the processor's page and names no policy`);
6139
+ }
6116
6140
  }
6117
6141
  return problems2;
6118
6142
  }
@@ -6125,176 +6149,2752 @@ function registered(spec, parts) {
6125
6149
  function registerProcessor(spec) {
6126
6150
  return registered(spec, PARTS);
6127
6151
  }
6128
- // src/processors/midtrans.js
6129
- var MIDTRANS_PSP = "midtrans";
6130
- var MIDTRANS_OPERATION = "midtrans.card_request";
6131
- var MIDTRANS_TOKEN_URL = "https://api.midtrans.com/v2/token";
6132
- var MIDTRANS_SANDBOX_TOKEN_URL = "https://api.sandbox.midtrans.com/v2/token";
6133
- var MIDTRANS_TOKEN_KEYS = /* @__PURE__ */ Object.freeze(["card_cvv", "card_number", "card_exp_month", "card_exp_year", "installment_term"]);
6134
- var BODY_LIMIT35 = 4096;
6135
- var CARD_NUMBER18 = /^[0-9]{12,19}$/;
6136
- var SECURITY_CODE22 = /^[0-9]{3,4}$/;
6137
- var MONTH19 = /^(?:0[1-9]|1[0-2])$/;
6138
- var YEAR20 = /^20[0-9]{2}$/;
6139
- var TERM = /^[0-9]{1,3}$/;
6140
- var record32 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
6141
- var own12 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
6142
- var inOrder6 = (value, keys) => {
6143
- let at = 0;
6144
- for (const name of Object.keys(value)) {
6145
- while (at < keys.length && keys[at] !== name)
6146
- at += 1;
6147
- if (at === keys.length)
6148
- return false;
6149
- at += 1;
6150
- }
6151
- return true;
6152
- };
6152
+ // src/processors/aurus.js
6153
+ var AURUS_PSP = "aurus";
6154
+ var AURUS_OPERATION = "aurus.card_request";
6155
+ var AURUS_FRAME_HOST = /^pecst[0-9]{2}\.aurusepay\.com$/;
6156
+ var AURUS_TOKEN_PATH = "/storeservices/ecom/oneTimeToken";
6157
+ var AURUS_PARTS = /* @__PURE__ */ Object.freeze(["Param", "formFactorId", "txnDateTime", "encryptionFlag", "sha256Flag", "hmacAuthData", "payload"]);
6158
+ var URL_LIMIT14 = 256;
6159
+ var BODY_LIMIT35 = 32768;
6160
+ var SERVER = /^es[0-9]{2}\.auruspay\.com$/;
6161
+ var HEX = /^[0-9A-Fa-f]{2,8192}$/;
6162
+ var FORM_FACTOR = /^[0-9]{1,16}$/;
6163
+ var DATE_TIME = /^[0-9]{14}$/;
6164
+ var FRAMED = /^STX[0-9]{1,6}\[FS\][0-9A-Fa-f]{2,16384}\[FS\]7[Bb][0-9A-Fa-f]{0,24576}7[Dd]ETX$/;
6153
6165
  var refuse37 = (code) => Object.freeze({ verdict: "refuse", code });
6154
6166
  var CARD36 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
6155
- function isMidtransTokenUrl(url) {
6156
- return url === MIDTRANS_TOKEN_URL || url === MIDTRANS_SANDBOX_TOKEN_URL;
6167
+ function aurusTokenUrl(url) {
6168
+ if (typeof url !== "string" || url.length > URL_LIMIT14 || url.includes("#"))
6169
+ return null;
6170
+ let parsed;
6171
+ try {
6172
+ parsed = new URL(url);
6173
+ }
6174
+ catch {
6175
+ return null;
6176
+ }
6177
+ if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !AURUS_FRAME_HOST.test(parsed.hostname) || parsed.pathname !== AURUS_TOKEN_PATH)
6178
+ return null;
6179
+ const query = parsed.search.startsWith("?") ? parsed.search.slice(1).split("&") : [];
6180
+ if (query.length !== 2)
6181
+ return null;
6182
+ const [d1, d2] = query.map((pair) => pair.split("="));
6183
+ if (d1.length !== 2 || d2.length !== 2 || d1[0] !== "d1" || d2[0] !== "d2" || !SERVER.test(d1[1]) || !SERVER.test(d2[1]))
6184
+ return null;
6185
+ return Object.freeze({ host: parsed.hostname });
6157
6186
  }
6187
+ var isAurusTokenUrl = (url) => aurusTokenUrl(url) !== null;
6158
6188
  function readBody21(body) {
6159
6189
  if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT35)
6160
6190
  return null;
6161
- let value;
6162
- try {
6163
- value = JSON.parse(body);
6164
- if (!record32(value) || JSON.stringify(value) !== body)
6191
+ const pairs = body.split("&");
6192
+ if (pairs.length !== AURUS_PARTS.length)
6193
+ return null;
6194
+ const value = {};
6195
+ for (const [at, pair] of pairs.entries()) {
6196
+ const cut = pair.indexOf("=");
6197
+ if (cut < 0 || pair.slice(0, cut) !== AURUS_PARTS[at])
6165
6198
  return null;
6199
+ value[AURUS_PARTS[at]] = pair.slice(cut + 1);
6166
6200
  }
6167
- catch {
6201
+ if (!HEX.test(value.Param) || !FORM_FACTOR.test(value.formFactorId) || !DATE_TIME.test(value.txnDateTime) || value.encryptionFlag !== "00" || value.sha256Flag !== "1" || !FRAMED.test(value.hmacAuthData) || !FRAMED.test(value.payload))
6168
6202
  return null;
6169
- }
6170
6203
  return value;
6171
6204
  }
6172
- function midtransBodyVerdict(body) {
6173
- const value = readBody21(body);
6174
- if (value === null || !inOrder6(value, MIDTRANS_TOKEN_KEYS)) {
6175
- if (record32(value) && (own12(value, "token_id") || own12(value, "two_click")) && !own12(value, "card_number"))
6176
- return refuse37("midtrans_saved_card");
6177
- return refuse37("midtrans_body_unsupported");
6205
+ function aurusBodyVerdict(body) {
6206
+ return readBody21(body) === null ? refuse37("aurus_body_unsupported") : CARD36;
6207
+ }
6208
+ var aurus_default = /* @__PURE__ */ registerProcessor({
6209
+ psp: AURUS_PSP,
6210
+ definitions: [
6211
+ {
6212
+ psp: "aurus",
6213
+ // The frame's card request, as the header above reads it. No sandbox host is known: Aurus's test instances were
6214
+ // not read, so none is listed and no environment is pinned.
6215
+ // Ships dark: served only to a client that declares `aurus_one_time_token`, and only for a company the backend's
6216
+ // processor gate turns Aurus on for. `(?![\w/.%-])` ends the path for a consumer that tests `match` unanchored.
6217
+ capability: "aurus_one_time_token",
6218
+ match: "pecst[0-9]{2}\\.aurusepay\\.com/storeservices/ecom/oneTimeToken(?![\\w/.%-])",
6219
+ hosts: ["^pecst[0-9]{2}\\.aurusepay\\.com$"],
6220
+ encoding: "form",
6221
+ // The frame's XHR marker. Origin, Referer and cookies never ride.
6222
+ passthroughHeaders: ["^x-requested-with$"]
6223
+ }
6224
+ ],
6225
+ // Only the cardholder's device would send this card, after a person approves; no reviewed list names aurus.
6226
+ refusedOperations: [AURUS_OPERATION],
6227
+ // The frame mints a one-time token and reads nothing: the store's server charges it with its own credentials.
6228
+ settlementReadback: {
6229
+ answer: "none",
6230
+ reason: "tokenization_credential_cannot_read_charges",
6231
+ note: "The tokenization credential cannot read a charge; the shop charges the token later with its own credentials.",
6232
+ source: "https://www.oreillyauto.com/checkout (Aurus's ecom iframe, read 2026-10-31)"
6233
+ },
6234
+ exactUrl: isAurusTokenUrl,
6235
+ bodyGate: (url, body) => url !== void 0 && !isAurusTokenUrl(url) ? refuse37("aurus_url_refused") : aurusBodyVerdict(body),
6236
+ limitations: ["The card frame seals the card in the page under a public key its own script carries; the cardholder's device does not seal for Aurus yet, so a held request opens no approval that pays."]
6237
+ });
6238
+ // src/processors/bluesnap.js
6239
+ var BLUESNAP_PSP = "bluesnap";
6240
+ var BLUESNAP_OPERATION = "bluesnap.card_request";
6241
+ var BLUESNAP_HOSTS = /* @__PURE__ */ Object.freeze({ 1: "ws1.bluesnap.com", 2: "ws2.bluesnap.com", _: "sandpay.bluesnap.com" });
6242
+ var BLUESNAP_SANDBOX_HOST = "sandpay.bluesnap.com";
6243
+ var BLUESNAP_CARD_KEYS = /* @__PURE__ */ Object.freeze(["cvv", "ccNumber", "expDate"]);
6244
+ var BLUESNAP_LEG_KEYS = /* @__PURE__ */ Object.freeze(["cvv", "expDate"]);
6245
+ var BODY_LIMIT36 = 1024;
6246
+ var TOKEN_URL2 = /^https:\/\/(ws1|ws2|sandpay)\.bluesnap\.com\/services\/2\/payment-fields-tokens\/([0-9a-f]{64}_[12]?)$/;
6247
+ var CARD_NUMBER18 = /^[0-9]{12,19}$/;
6248
+ var SECURITY_CODE22 = /^[0-9]{3,4}$/;
6249
+ var EXPIRY3 = /^(?:0[1-9]|1[0-2])\/20[0-9]{2}$/;
6250
+ var SAVED_CARD_KEYS2 = ["last4Digits", "lastFourDigits", "ccType"];
6251
+ var record32 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
6252
+ var own12 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
6253
+ var refuse38 = (code) => Object.freeze({ verdict: "refuse", code });
6254
+ var CARD37 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
6255
+ var LEG = /* @__PURE__ */ Object.freeze({ verdict: "continue" });
6256
+ function bluesnapTokenUrl(url) {
6257
+ const match = typeof url === "string" ? TOKEN_URL2.exec(url) : null;
6258
+ if (!match || BLUESNAP_HOSTS[match[2].slice(-1)] !== `${match[1]}.bluesnap.com`)
6259
+ return null;
6260
+ const host = `${match[1]}.bluesnap.com`;
6261
+ return Object.freeze({ host, token: match[2], environment: host === BLUESNAP_SANDBOX_HOST ? "sandbox" : "production" });
6262
+ }
6263
+ function isBluesnapTokenUrl(url) {
6264
+ return bluesnapTokenUrl(url) !== null;
6265
+ }
6266
+ function readBody22(body) {
6267
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT36)
6268
+ return null;
6269
+ try {
6270
+ const value = JSON.parse(body);
6271
+ return record32(value) && JSON.stringify(value) === body ? value : null;
6272
+ }
6273
+ catch {
6274
+ return null;
6178
6275
  }
6179
- if (!own12(value, "card_cvv") || !own12(value, "card_number") || !own12(value, "card_exp_month") || !own12(value, "card_exp_year")) {
6180
- return refuse37("midtrans_body_unsupported");
6276
+ }
6277
+ function bluesnapBodyVerdict(body) {
6278
+ const value = readBody22(body);
6279
+ if (value === null)
6280
+ return refuse38("bluesnap_body_unsupported");
6281
+ const keys = Object.keys(value);
6282
+ if (keys.some((key) => SAVED_CARD_KEYS2.includes(key)))
6283
+ return refuse38(own12(value, "ccNumber") ? "bluesnap_body_unsupported" : "bluesnap_saved_card");
6284
+ 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))) {
6285
+ return refuse38("bluesnap_body_unsupported");
6181
6286
  }
6182
- if (typeof value.card_cvv !== "string" || !SECURITY_CODE22.test(value.card_cvv) || typeof value.card_number !== "string" || !CARD_NUMBER18.test(value.card_number) || typeof value.card_exp_month !== "string" || !MONTH19.test(value.card_exp_month) || typeof value.card_exp_year !== "string" || !YEAR20.test(value.card_exp_year))
6183
- return refuse37("midtrans_body_unsupported");
6184
- if (own12(value, "installment_term") && (typeof value.installment_term !== "string" || !TERM.test(value.installment_term)))
6185
- return refuse37("midtrans_body_unsupported");
6186
- return CARD36;
6287
+ 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)))
6288
+ return refuse38("bluesnap_body_unsupported");
6289
+ return own12(value, "ccNumber") ? CARD37 : LEG;
6187
6290
  }
6188
- var midtrans_default = /* @__PURE__ */ registerProcessor({
6189
- psp: MIDTRANS_PSP,
6291
+ var bluesnap_default = /* @__PURE__ */ registerProcessor({
6292
+ psp: BLUESNAP_PSP,
6190
6293
  definitions: [
6191
6294
  {
6192
- psp: "midtrans",
6193
- // Snap's token request, as the header above reads it. Sandbox has its own host, so the device sends a
6194
- // test-mode request only Midtrans' documented test cards (hostEnvironmentPinned, device-replay.js S7).
6195
- // Ships dark: served only to a client that declares `midtrans_card_token`, gated off for every org until an
6196
- // operator lists one (`midtrans:<org>`), and the backend's gate serves only Agentcard's own company until the
6197
- // token's publishable key is bound to the merchant (backend config.ts MIDTRANS_KEY_BOUND_TO_MERCHANT).
6198
- capability: "midtrans_card_token",
6199
- match: "api\\.(?:sandbox\\.)?midtrans\\.com/v2/token",
6200
- hosts: ["^api\\.midtrans\\.com$", "^api\\.sandbox\\.midtrans\\.com$"],
6201
- sandboxHosts: ["^api\\.sandbox\\.midtrans\\.com$"],
6295
+ psp: "bluesnap",
6296
+ // The card fields' PUTs, as the header above reads them. The sandbox has its own server, so the device sends a
6297
+ // test-mode request only documented test cards (hostEnvironmentPinned, device-replay.js S7). `(?![\w/.%-])`
6298
+ // ends the token for a consumer that tests `match` unanchored; the exact-URL rule pins each server to its suffix.
6299
+ // Ships dark: served only to a client that declares `bluesnap_hosted_payment_fields`, and the backend's gate turns
6300
+ // it on for Agentcard's own company alone, in code.
6301
+ capability: "bluesnap_hosted_payment_fields",
6302
+ match: "(?:ws1|ws2|sandpay)\\.bluesnap\\.com/services/2/payment-fields-tokens/[0-9a-f]{64}_[12]?(?![\\w/.%-])",
6303
+ hosts: ["^ws1\\.bluesnap\\.com$", "^ws2\\.bluesnap\\.com$", "^sandpay\\.bluesnap\\.com$"],
6304
+ sandboxHosts: ["^sandpay\\.bluesnap\\.com$"],
6202
6305
  hostEnvironmentPinned: true,
6203
6306
  encoding: "json",
6204
- // Snap's own headers: the publishable client key (Authorization Basic) and X-Service. Origin, Referer and
6205
- // cookies never ride.
6206
- passthroughHeaders: ["^authorization$", "^x-service$"],
6207
- jsonCardFields: [["card_number"]]
6307
+ // The frames' own headers, each held to its shape by bluesnapRequestRefusal. Origin, Referer and cookies never
6308
+ // ride (the frames send no cookie).
6309
+ passthroughHeaders: ["^authorization$", "^bluesnap_version_header$", "^bluesnap_origin_version_header$", "^bluesnap_origin_header$"],
6310
+ jsonCardFields: [["ccNumber"]],
6311
+ // The expiry and code frames' PUTs: held by the checkout SDK and answered with the card request's answer.
6312
+ splitCard: { absorb: [...BLUESNAP_LEG_KEYS], pass: [], siblingKeys: [] },
6313
+ request: { method: "PUT", cardIn: "body", response: "json" }
6208
6314
  }
6209
6315
  ],
6210
- // Only the cardholder's device sends a token, after a person approves; no reviewed list names midtrans.
6211
- refusedOperations: [MIDTRANS_OPERATION],
6212
- // Not surveyed: the token moves no money, and the merchant's own charge names its status by the order id alone.
6316
+ // Only the cardholder's device sends the card, after a person approves; no reviewed list names bluesnap.
6317
+ refusedOperations: [BLUESNAP_OPERATION],
6318
+ // Not surveyed: the PUT moves no money, and the merchant's own charge is a server call Agentcard never sees.
6213
6319
  settlementReadback: "not_surveyed",
6214
- exactUrl: isMidtransTokenUrl,
6215
- bodyGate: (url, body) => url !== void 0 && !isMidtransTokenUrl(url) ? { verdict: "refuse", code: "midtrans_url_refused" } : midtransBodyVerdict(body)
6320
+ exactUrl: isBluesnapTokenUrl,
6321
+ bodyGate: (url, body) => url !== void 0 && !isBluesnapTokenUrl(url) ? { verdict: "refuse", code: "bluesnap_url_refused" } : bluesnapBodyVerdict(body)
6216
6322
  });
6217
- // src/processors/index.generated.js
6218
- var REGISTERED_MODULES = Object.freeze({
6219
- midtrans: midtrans_default
6323
+ // src/processors/ekashu.js
6324
+ var EKASHU_HOSTS = Object.freeze(["live.ekashu.com", "test.ekashu.com"]);
6325
+ var EKASHU_TEST_PANS = Object.freeze(["4100000000000100", "5100000000000107"]);
6326
+ var EKASHU_SIGNED_FIELDS = Object.freeze([
6327
+ "ekashu_3d_secure_verify",
6328
+ "ekashu_amount",
6329
+ "ekashu_amount_format",
6330
+ "ekashu_auto_confirm",
6331
+ "ekashu_callback_failure_url",
6332
+ "ekashu_callback_include_post",
6333
+ "ekashu_callback_success_url",
6334
+ "ekashu_card_address_editable",
6335
+ "ekashu_card_address_required",
6336
+ "ekashu_card_address_verify",
6337
+ "ekashu_card_email_address_mandatory",
6338
+ "ekashu_card_phone_number_mandatory",
6339
+ "ekashu_card_title_mandatory",
6340
+ "ekashu_card_zip_code_verify",
6341
+ "ekashu_currency",
6342
+ "ekashu_delivery_address_editable",
6343
+ "ekashu_delivery_address_required",
6344
+ "ekashu_delivery_email_address_mandatory",
6345
+ "ekashu_delivery_phone_number_mandatory",
6346
+ "ekashu_delivery_title_mandatory",
6347
+ "ekashu_description",
6348
+ "ekashu_device",
6349
+ "ekashu_duplicate_check",
6350
+ "ekashu_duplicate_minutes",
6351
+ "ekashu_failure_return_text",
6352
+ "ekashu_failure_url",
6353
+ "ekashu_hash_code_format",
6354
+ "ekashu_hash_code_type",
6355
+ "ekashu_hash_code_version",
6356
+ "ekashu_include_post",
6357
+ "ekashu_invoice_address_editable",
6358
+ "ekashu_invoice_address_required",
6359
+ "ekashu_invoice_email_address_mandatory",
6360
+ "ekashu_invoice_phone_number_mandatory",
6361
+ "ekashu_invoice_title_mandatory",
6362
+ "ekashu_locale",
6363
+ "ekashu_payment_methods",
6364
+ "ekashu_reference",
6365
+ "ekashu_request_type",
6366
+ "ekashu_return_text",
6367
+ "ekashu_seller_address",
6368
+ "ekashu_seller_email_address",
6369
+ "ekashu_seller_id",
6370
+ "ekashu_seller_key",
6371
+ "ekashu_seller_name",
6372
+ "ekashu_shortcut_icon",
6373
+ "ekashu_style_sheet",
6374
+ "ekashu_success_url",
6375
+ "ekashu_title",
6376
+ "ekashu_verification_value_mask",
6377
+ "ekashu_verification_value_verify",
6378
+ "ekashu_viewport"
6379
+ ]);
6380
+ var REQUIRED = Object.freeze([
6381
+ "ekashu_seller_id",
6382
+ "ekashu_seller_key",
6383
+ "ekashu_amount",
6384
+ "ekashu_currency",
6385
+ "ekashu_reference",
6386
+ "ekashu_hash_code",
6387
+ "ekashu_hash_code_type",
6388
+ "ekashu_hash_code_version",
6389
+ "ekashu_success_url",
6390
+ "ekashu_failure_url",
6391
+ "ekashu_callback_success_url"
6392
+ ]);
6393
+ var CARD_KEYS16 = Object.freeze([
6394
+ "ekashu_card_number",
6395
+ "ekashu_expires_end_month",
6396
+ "ekashu_expires_end_year",
6397
+ "ekashu_verification_value",
6398
+ "ekashu_valid_from_month",
6399
+ "ekashu_valid_from_year",
6400
+ "ekashu_issue_number"
6401
+ ]);
6402
+ var PAGE_KEYS = Object.freeze(["ekashu_stage", "ekashu_context", "ekashu_submission_id"]);
6403
+ var STORED_KEYS = Object.freeze(["ekashu_card_hash", "ekashu_card_reference", "ekashu_cof_initiated_by", "ekashu_cof_reason", "ekashu_cof_id"]);
6404
+ var REDIRECT_KEYS = Object.freeze(["ekashu_success_url", "ekashu_failure_url", "ekashu_return_url"]);
6405
+ var CALLBACK_KEYS = Object.freeze(["ekashu_callback_success_url", "ekashu_callback_failure_url"]);
6406
+ var MAX_ENTRY = 16 * 1024;
6407
+ var MAX_PAGE = 256 * 1024;
6408
+ var EKASHU_SELLERS = Object.freeze([
6409
+ Object.freeze({ sellerId: "25060100", merchant: "Heathrow Drop-off", entryHost: "heathrowdropoff.apcoa.com", callbackHost: "incomingapi.apcoa.co.uk" })
6410
+ ]);
6411
+ var CARD_FIELDS = Object.freeze({
6412
+ number: "ekashu_card_number",
6413
+ month: "ekashu_expires_end_month",
6414
+ year: "ekashu_expires_end_year",
6415
+ cvc: "ekashu_verification_value"
6220
6416
  });
6221
- // src/registry.js
6222
- var REGISTERED_PROCESSORS = Object.values(REGISTERED_MODULES);
6223
- var ids = REGISTERED_PROCESSORS.map((processor) => processor.psp);
6224
- var problems = REGISTERED_PROCESSORS.flatMap(registrationProblems);
6225
- for (const [name, processor] of Object.entries(REGISTERED_MODULES)) {
6226
- if (processor.psp !== name)
6227
- problems.push(`processors/${name}.js registers ${JSON.stringify(processor.psp)}`);
6417
+ var NAME_FIELDS = Object.freeze({ first: "ekashu_card_first_name", last: "ekashu_card_last_name" });
6418
+ var LEFT_EMPTY = Object.freeze(["ekashu_card_title", "ekashu_valid_from_month", "ekashu_valid_from_year", "ekashu_issue_number"]);
6419
+ var VISIBLE = /* @__PURE__ */ new Set([...Object.values(CARD_FIELDS), ...Object.values(NAME_FIELDS), ...LEFT_EMPTY]);
6420
+ // src/processors/redsys.js
6421
+ var REDSYS_HOSTS = Object.freeze(["sis.redsys.es"]);
6422
+ var REDSYS_ENTRY_PATHS = Object.freeze(["/sis/realizarPago", "/sis/realizarPago/utf-8"]);
6423
+ var REDSYS_MERCHANTS = Object.freeze([]);
6424
+ var MAX_ENTRY2 = 16 * 1024;
6425
+ var MAX_PARAMETERS = 8 * 1024;
6426
+ var FORM_KEY = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
6427
+ var ENTRY_KEYS = Object.freeze(["Ds_SignatureVersion", "Ds_MerchantParameters", "Ds_Signature"]);
6428
+ var REQUIRED2 = Object.freeze([
6429
+ "DS_MERCHANT_AMOUNT",
6430
+ "DS_MERCHANT_CURRENCY",
6431
+ "DS_MERCHANT_MERCHANTCODE",
6432
+ "DS_MERCHANT_ORDER",
6433
+ "DS_MERCHANT_TERMINAL",
6434
+ "DS_MERCHANT_TRANSACTIONTYPE",
6435
+ "DS_MERCHANT_MERCHANTURL",
6436
+ "DS_MERCHANT_URLOK",
6437
+ "DS_MERCHANT_URLKO"
6438
+ ]);
6439
+ var STORED = Object.freeze([
6440
+ "DS_MERCHANT_IDENTIFIER",
6441
+ "DS_MERCHANT_GROUP",
6442
+ "DS_MERCHANT_COF_INI",
6443
+ "DS_MERCHANT_COF_TYPE",
6444
+ "DS_MERCHANT_COF_TXNID"
6445
+ ]);
6446
+ var SPECIAL = Object.freeze([
6447
+ "DS_MERCHANT_DIRECTPAYMENT",
6448
+ "DS_MERCHANT_SUMTOTAL",
6449
+ "DS_MERCHANT_DATEFRECUENCY",
6450
+ "DS_MERCHANT_CHARGEEXPIRYDATE",
6451
+ "DS_MERCHANT_IDOPER"
6452
+ ]);
6453
+ var CARD_PARAMETERS = Object.freeze(["DS_MERCHANT_PAN", "DS_MERCHANT_EXPIRYDATE", "DS_MERCHANT_CVV2"]);
6454
+ var CURRENCIES = Object.freeze({ 978: "eur", 840: "usd", 826: "gbp", 756: "chf" });
6455
+ function decode(text10) {
6456
+ return decodeURIComponent(text10.replace(/\+/g, " "));
6228
6457
  }
6229
- if (ids.some((id, i) => i > 0 && ids[i - 1] >= id))
6230
- problems.push(`registered processors out of id order: ${ids.join(", ")}`);
6231
- if (problems.length)
6232
- throw new Error(`payment-core registry refused: ${problems.join("; ")}`);
6233
- var BY_PSP = new Map(REGISTERED_PROCESSORS.map((processor) => [processor.psp, processor]));
6234
- var REGISTERED_IDS = Object.freeze(ids);
6235
- var REGISTERED_DEFINITIONS = Object.freeze(REGISTERED_PROCESSORS.flatMap((processor) => processor.definitions));
6236
- var REGISTERED_REFUSED_OPERATIONS = Object.freeze(REGISTERED_PROCESSORS.flatMap((processor) => processor.refusedOperations ?? []));
6237
- var REGISTERED_SETTLEMENT_READBACK = Object.freeze(REGISTERED_PROCESSORS.filter((processor) => processor.settlementReadback !== void 0).map((processor) => [processor.psp, processor.settlementReadback]));
6238
- function registeredRule(psp, name) {
6239
- return typeof psp === "string" ? BY_PSP.get(psp)?.[name] : void 0;
6458
+ function parseRedsysForm(body) {
6459
+ if (typeof body !== "string" || body.length === 0 || body.length > MAX_ENTRY2 || /[^\x21-\x7e]/.test(body))
6460
+ return null;
6461
+ const pairs = [];
6462
+ const seen = /* @__PURE__ */ new Set();
6463
+ for (const chunk of body.split("&")) {
6464
+ const eq = chunk.indexOf("=");
6465
+ if (eq < 1)
6466
+ return null;
6467
+ let key;
6468
+ let value;
6469
+ try {
6470
+ key = decode(chunk.slice(0, eq));
6471
+ value = decode(chunk.slice(eq + 1));
6472
+ }
6473
+ catch {
6474
+ return null;
6475
+ }
6476
+ if (!FORM_KEY.test(key) || value.length > MAX_PARAMETERS || /[\u0000-\u001f\u007f]/.test(value))
6477
+ return null;
6478
+ const folded = key.toLowerCase();
6479
+ if (seen.has(folded))
6480
+ return null;
6481
+ seen.add(folded);
6482
+ pairs.push({ key, value });
6483
+ }
6484
+ return pairs;
6240
6485
  }
6241
- // src/card-fields.js
6242
- function processorGate(recognizer, url, body) {
6243
- if (recognizer && recognizer.psp === LYRA_PSP)
6244
- return lyraBodyVerdict(body, url);
6245
- if (recognizer && recognizer.psp === WIX_PAYMENTS_PSP) {
6246
- if (url !== void 0 && !isWixPaymentsTokenizeUrl(url))
6247
- return { verdict: "refuse", code: "wix_payments_url_refused" };
6248
- return wixPaymentsBodyVerdict(body);
6486
+ var MAX_PAGE2 = 256 * 1024;
6487
+ var CARD_FIELDS2 = Object.freeze({
6488
+ shown: "Sis_card-number",
6489
+ expiry: "SIS_card-expiration",
6490
+ cvc: "Sis_Tarjeta_CVV2",
6491
+ holder: "cardholderName",
6492
+ number: "Sis_Numero_Tarjeta",
6493
+ month: "Sis_Caducidad_Tarjeta_Mes",
6494
+ year: "Sis_Caducidad_Tarjeta_Anno"
6495
+ });
6496
+ var BROWSER_FIELDS = Object.freeze([
6497
+ "browserJavaEnabled",
6498
+ "browserJavascriptEnabled",
6499
+ "browserLanguage",
6500
+ "browserColorDepth",
6501
+ "browserScreenHeight",
6502
+ "browserScreenWidth",
6503
+ "browserTZ",
6504
+ "browserUserAgent"
6505
+ ]);
6506
+ var AS_SERVED = Object.freeze(["cvvObligatorio", "threeDSCompInd", "fuc", "terminal", "merchantOrder", "bcancel"]);
6507
+ var CARD_PAGE = /* @__PURE__ */ new Set([...Object.values(CARD_FIELDS2), ...BROWSER_FIELDS, ...AS_SERVED]);
6508
+ var VISIBLE2 = /* @__PURE__ */ new Set([CARD_FIELDS2.shown, CARD_FIELDS2.expiry, CARD_FIELDS2.cvc, CARD_FIELDS2.holder]);
6509
+ var METHOD_PAGE = /* @__PURE__ */ new Set(["resultadoMethod", ...BROWSER_FIELDS, "threeDSCompInd"]);
6510
+ var REDSYS_REFUSALS = Object.freeze(["redsys_card_page", "redsys_3ds_challenge", "redsys_declined"]);
6511
+ // src/processors/cardlink_vpos.js
6512
+ var CARDLINK_VPOS_PSP = "cardlink_vpos";
6513
+ var CARDLINK_VPOS_HOSTS = Object.freeze({
6514
+ "vpos.eurocommerce.gr": "worldline",
6515
+ "ecommerce.cardlink.gr": "cardlink",
6516
+ "www.alphaecommerce.gr": "nexi"
6517
+ });
6518
+ var CARDLINK_VPOS_TEST_HOSTS = Object.freeze([
6519
+ "eurocommerce-test.cardlink.gr",
6520
+ "ecommerce-test.cardlink.gr",
6521
+ "alphaecommerce-test.cardlink.gr"
6522
+ ]);
6523
+ var CARDLINK_VPOS_ENTRY_PATH = "/vpos/shophandlermpi";
6524
+ var CARDLINK_VPOS_MERCHANTS = Object.freeze([
6525
+ Object.freeze({ merchant: "Holy Great Monastery of Vatopedi", mid: "0021713862", vposHost: "vpos.eurocommerce.gr", host: "www.vatopedi.gr" })
6526
+ ]);
6527
+ var CARDLINK_VPOS_ENTRY_FIELDS = Object.freeze([
6528
+ "version",
6529
+ "mid",
6530
+ "lang",
6531
+ "deviceCategory",
6532
+ "orderid",
6533
+ "orderDesc",
6534
+ "orderAmount",
6535
+ "currency",
6536
+ "payerEmail",
6537
+ "payerPhone",
6538
+ "billCountry",
6539
+ "billState",
6540
+ "billZip",
6541
+ "billCity",
6542
+ "billAddress",
6543
+ "weight",
6544
+ "dimensions",
6545
+ "shipCountry",
6546
+ "shipState",
6547
+ "shipZip",
6548
+ "shipCity",
6549
+ "shipAddress",
6550
+ "addFraudScore",
6551
+ "maxPayRetries",
6552
+ "reject3dsU",
6553
+ "payMethod",
6554
+ "trType",
6555
+ "extInstallmentoffset",
6556
+ "extInstallmentperiod",
6557
+ "extRecurringfrequency",
6558
+ "extRecurringenddate",
6559
+ "blockScore",
6560
+ "cssUrl",
6561
+ "confirmUrl",
6562
+ "cancelUrl",
6563
+ "extTokenOptions",
6564
+ "extToken",
6565
+ "var1",
6566
+ "var2",
6567
+ "var3",
6568
+ "var4",
6569
+ "var5",
6570
+ "var6",
6571
+ "var7",
6572
+ "var8",
6573
+ "var9",
6574
+ "digest"
6575
+ ]);
6576
+ var KNOWN = new Set(CARDLINK_VPOS_ENTRY_FIELDS);
6577
+ var REQUIRED3 = Object.freeze([
6578
+ "version",
6579
+ "mid",
6580
+ "orderid",
6581
+ "orderDesc",
6582
+ "orderAmount",
6583
+ "currency",
6584
+ "payerEmail",
6585
+ "confirmUrl",
6586
+ "cancelUrl",
6587
+ "digest"
6588
+ ]);
6589
+ var STORED2 = Object.freeze(["extTokenOptions", "extToken"]);
6590
+ var SPECIAL2 = Object.freeze(["extInstallmentoffset", "extInstallmentperiod", "extRecurringfrequency", "extRecurringenddate"]);
6591
+ var CURRENCIES2 = Object.freeze({ EUR: "eur" });
6592
+ var MAX_URL = 512;
6593
+ var MAX_ENTRY3 = 8 * 1024;
6594
+ var MAX_VALUE = 256;
6595
+ var own13 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
6596
+ var field2 = (name, reason) => ({ ok: false, code: "hosted_form_field_refused", field: name, reason });
6597
+ function cardlinkVposEntryHost(raw) {
6598
+ if (typeof raw !== "string" || raw.length > MAX_URL || raw.includes("?") || raw.includes("#"))
6599
+ return null;
6600
+ let url;
6601
+ try {
6602
+ url = new URL(raw);
6249
6603
  }
6250
- if (recognizer && recognizer.psp === KOMOJU_PSP)
6251
- return komojuBodyVerdict(body, url);
6252
- if (recognizer && recognizer.psp === HIPAY_PSP) {
6253
- if (url !== void 0 && !isHipayTokenUrl(url))
6254
- return { verdict: "refuse", code: "hipay_url_refused" };
6255
- return hipayBodyVerdict(body);
6604
+ catch {
6605
+ return null;
6256
6606
  }
6257
- if (recognizer && recognizer.psp === PAYPAL_PSP) {
6258
- if (url !== void 0 && !isPaypalConfirmUrl(url))
6259
- return { verdict: "refuse", code: "paypal_url_refused" };
6260
- return paypalBodyVerdict(body);
6607
+ if (url.href !== raw || url.protocol !== "https:" || url.port || url.username || url.password || !own13(CARDLINK_VPOS_HOSTS, url.hostname) || url.pathname !== CARDLINK_VPOS_ENTRY_PATH)
6608
+ return null;
6609
+ return url.hostname;
6610
+ }
6611
+ function isCardlinkVposEntryUrl(raw) {
6612
+ return cardlinkVposEntryHost(raw) !== null;
6613
+ }
6614
+ function parseCardlinkVposForm(body) {
6615
+ if (typeof body !== "string" || body.length === 0 || body.length > MAX_ENTRY3 || /[^\x21-\x7e]/.test(body))
6616
+ return null;
6617
+ const pairs = [];
6618
+ const seen = /* @__PURE__ */ new Set();
6619
+ for (const chunk of body.split("&")) {
6620
+ const eq = chunk.indexOf("=");
6621
+ if (eq < 1)
6622
+ return null;
6623
+ let key;
6624
+ let value;
6625
+ try {
6626
+ key = decodeURIComponent(chunk.slice(0, eq).replace(/\+/g, " "));
6627
+ value = decodeURIComponent(chunk.slice(eq + 1).replace(/\+/g, " "));
6628
+ }
6629
+ catch {
6630
+ return null;
6631
+ }
6632
+ if (!/^[A-Za-z_.][A-Za-z0-9_.-]{0,63}$/.test(key) || value.length > MAX_VALUE || /[\u0000-\u001f\u007f]/.test(value))
6633
+ return null;
6634
+ if (seen.has(key))
6635
+ return null;
6636
+ seen.add(key);
6637
+ pairs.push({ key, value });
6261
6638
  }
6262
- if (recognizer && recognizer.psp === MAKECOMMERCE_PSP)
6263
- return makecommerceBodyVerdict(body, url);
6264
- if (recognizer && recognizer.psp === OPENPAY_PSP)
6265
- return openpayBodyVerdict(body, url);
6266
- if (recognizer && recognizer.psp === POYNT_PSP) {
6267
- if (url !== void 0 && !isPoyntNonceUrl(url))
6268
- return { verdict: "refuse", code: "poynt_url_refused" };
6269
- return poyntBodyVerdict(body);
6639
+ return pairs;
6640
+ }
6641
+ function cardlinkVposMerchant(mid, vposHost, merchants = CARDLINK_VPOS_MERCHANTS) {
6642
+ if (typeof mid !== "string" || typeof vposHost !== "string" || !Array.isArray(merchants))
6643
+ return null;
6644
+ const found = merchants.filter((row) => !!row && typeof row.merchant === "string" && row.merchant.trim() !== "" && row.mid === mid && row.vposHost === vposHost && typeof row.host === "string" && row.host !== "");
6645
+ return found.length === 1 ? found[0] : null;
6646
+ }
6647
+ function entryAmount(values) {
6648
+ const amount2 = values.get("orderAmount");
6649
+ const code = values.get("currency");
6650
+ const currency = typeof code === "string" && own13(CURRENCIES2, code) ? CURRENCIES2[code] : null;
6651
+ if (!currency || typeof amount2 !== "string" || !/^(?:0|[1-9]\d{0,11})(?:\.\d{1,2})?$/.test(amount2))
6652
+ return null;
6653
+ const [whole2, fraction = ""] = amount2.split(".");
6654
+ const cents2 = Number(whole2) * 100 + Number(fraction.padEnd(2, "0"));
6655
+ return Number.isSafeInteger(cents2) && cents2 > 0 ? { amountCents: cents2, currency } : null;
6656
+ }
6657
+ function httpsUrl(value) {
6658
+ let url;
6659
+ try {
6660
+ url = new URL(value);
6270
6661
  }
6271
- if (recognizer && recognizer.psp === CARDCOM_PSP)
6272
- return cardcomBodyVerdict(body, url);
6273
- if (recognizer && recognizer.psp === TOAST_PSP) {
6274
- if (url !== void 0 && !isToastPaymentMethodsUrl(url))
6275
- return { verdict: "refuse", code: "toast_url_refused" };
6276
- return toastBodyVerdict(body);
6662
+ catch {
6663
+ return null;
6277
6664
  }
6278
- if (recognizer && recognizer.psp === PAYU_LATAM_PSP)
6279
- return payuLatamBodyVerdict(body, url);
6280
- if (recognizer && recognizer.psp === PADDLE_VGS_PSP) {
6281
- if (url !== void 0 && !isPaddleVgsCardsUrl(url))
6282
- return { verdict: "refuse", code: "paddle_vgs_url_refused" };
6283
- return paddleVgsBodyVerdict(body);
6665
+ if (url.protocol !== "https:" || url.username || url.password || url.port || url.hash)
6666
+ return null;
6667
+ return url;
6668
+ }
6669
+ function checkCardlinkVposEntry(body, { url = null, merchants = CARDLINK_VPOS_MERCHANTS } = {}) {
6670
+ const vposHost = cardlinkVposEntryHost(url);
6671
+ if (!vposHost)
6672
+ return field2("(url)", "malformed_field");
6673
+ const pairs = parseCardlinkVposForm(body);
6674
+ if (!pairs)
6675
+ return field2("(body)", "malformed");
6676
+ const values = new Map(pairs.map(({ key, value }) => [key, value]));
6677
+ for (const { key } of pairs) {
6678
+ if (KNOWN.has(key))
6679
+ continue;
6680
+ return field2(key, /^(?:card[._]|cvv|cmd$|trid$|st$|paystep$|paymentmethod$)/i.test(key) ? "card_in_entry" : "not_an_entry");
6681
+ }
6682
+ const missing = REQUIRED3.filter((name) => !values.get(name));
6683
+ if (missing.length)
6684
+ return { ok: false, code: "hosted_form_template_incomplete", missing };
6685
+ if (values.get("version") !== "2")
6686
+ return field2("version", "malformed");
6687
+ if (!/^[A-Za-z0-9+/]{43}=$/.test(values.get("digest")))
6688
+ return field2("digest", "unsigned");
6689
+ for (const name of STORED2)
6690
+ if (values.has(name))
6691
+ return field2(name, "stored_credential");
6692
+ for (const name of SPECIAL2)
6693
+ if (values.get(name))
6694
+ return field2(name, "special_flow");
6695
+ for (let i = 1; i <= 9; i += 1)
6696
+ if (/moto\s*=\s*true/i.test(values.get(`var${i}`) ?? ""))
6697
+ return field2(`var${i}`, "moto");
6698
+ if (values.has("trType") && values.get("trType") !== "1")
6699
+ return field2("trType", "not_a_sale");
6700
+ const method = values.get("payMethod");
6701
+ if (method)
6702
+ return field2("payMethod", /^iris$/i.test(method) ? "not_a_card_payment" : "special_flow");
6703
+ const amount2 = entryAmount(values);
6704
+ if (!amount2)
6705
+ return field2(own13(CURRENCIES2, values.get("currency")) ? "orderAmount" : "currency", "malformed");
6706
+ if (!/^\d{1,30}$/.test(values.get("mid")))
6707
+ return field2("mid", "malformed");
6708
+ if (!/^[A-Za-z0-9]{1,50}$/.test(values.get("orderid")))
6709
+ return field2("orderid", "malformed");
6710
+ const seller = cardlinkVposMerchant(values.get("mid"), vposHost, merchants);
6711
+ if (!seller)
6712
+ return field2("mid", "seller_unreviewed");
6713
+ for (const name of ["confirmUrl", "cancelUrl"]) {
6714
+ const target = httpsUrl(values.get(name));
6715
+ if (!target || target.hostname !== seller.host)
6716
+ return field2(name, "callback_host");
6284
6717
  }
6285
- if (recognizer && recognizer.psp === PAYFAST_PSP) {
6286
- if (url !== void 0 && !isPayfastPayUrl(url))
6287
- return { verdict: "refuse", code: "payfast_url_refused" };
6288
- return payfastBodyVerdict(body);
6718
+ return {
6719
+ ok: true,
6720
+ pairs,
6721
+ gated: false,
6722
+ dedupe: [vposHost, values.get("mid"), values.get("orderid"), values.get("orderAmount"), values.get("currency")],
6723
+ seller
6724
+ };
6725
+ }
6726
+ function cardlinkVposEntryAmount(body) {
6727
+ const pairs = parseCardlinkVposForm(body);
6728
+ return pairs ? entryAmount(new Map(pairs.map(({ key, value }) => [key, value]))) : null;
6729
+ }
6730
+ var CARDLINK_VPOS_TDS2_FIELDS = Object.freeze([
6731
+ "TDS2_Navigator_language",
6732
+ "TDS2_Navigator_jsEnabled",
6733
+ "TDS2_Navigator_javaEnabled",
6734
+ "TDS2_Screen_colorDepth",
6735
+ "TDS2_Screen_height",
6736
+ "TDS2_Screen_width",
6737
+ "TDS2_screen_pixelDepth",
6738
+ "TDS2_TimezoneOffset"
6739
+ ]);
6740
+ var PAGE_FIELDS = Object.freeze(["trid", "st", "payStep", "cmd", "startbonus", "bonusdata"]);
6741
+ var WALLET_FIELDS2 = Object.freeze(["walletId", "applePayResponse"]);
6742
+ var CARD38 = Object.freeze({ number: "card.pan", holder: "card.holderName", month: "card.expiryMonth", year: "card.expiryYear", cvc: "card.cvv" });
6743
+ var TEXT_CONTROLS = /* @__PURE__ */ new Set([CARD38.number, CARD38.holder, CARD38.cvc]);
6744
+ var SELECT_CONTROLS = /* @__PURE__ */ new Set([CARD38.month, CARD38.year]);
6745
+ var MAX_PAGE3 = 256 * 1024;
6746
+ var COOKIE_DOMAINS = Object.freeze({
6747
+ "vpos.eurocommerce.gr": "eurocommerce.gr",
6748
+ "ecommerce.cardlink.gr": "cardlink.gr",
6749
+ "www.alphaecommerce.gr": "alphaecommerce.gr"
6750
+ });
6751
+ var POST_REQUIRED = Object.freeze(["trid", "st", "cmd", CARD38.number, CARD38.holder, CARD38.month, CARD38.year, CARD38.cvc, "makepayment"]);
6752
+ var POST_EMPTY = Object.freeze(["payStep", "startbonus", "bonusdata", ...WALLET_FIELDS2]);
6753
+ var POST_ALLOWED = /* @__PURE__ */ new Set([...POST_REQUIRED, ...POST_EMPTY, "paymentMethod", ...CARDLINK_VPOS_TDS2_FIELDS]);
6754
+ var CARDLINK_VPOS_REFUSALS = Object.freeze([
6755
+ "cardlink_vpos_card_refused",
6756
+ "cardlink_vpos_card_page",
6757
+ "cardlink_vpos_3ds_challenge",
6758
+ "cardlink_vpos_declined"
6759
+ ]);
6760
+ var REFUSAL_FOR = Object.freeze({
6761
+ card_refused: "cardlink_vpos_card_refused",
6762
+ card_page: "cardlink_vpos_card_page",
6763
+ challenge: "cardlink_vpos_3ds_challenge",
6764
+ declined: "cardlink_vpos_declined"
6765
+ });
6766
+ var CARDLINK_VPOS_CAPABILITY = "cardlink_vpos_hosted_payment_page";
6767
+ var CARDLINK_VPOS_OPERATION = "cardlink_vpos.hosted_sale";
6768
+ var cardlink_vpos_default = /* @__PURE__ */ registerProcessor({
6769
+ psp: CARDLINK_VPOS_PSP,
6770
+ definitions: [
6771
+ {
6772
+ psp: "cardlink_vpos",
6773
+ // The merchant's signed entry, as the header above reads it: a Document navigation that carries no card. The
6774
+ // cardholder's device repeats it over the end-to-end TLS relay, fills the card into the page the VPOS returns
6775
+ // and posts it in that same session, and the runtime resolves the paused navigation with the hosted_form notice.
6776
+ // Only the entry path on the three live hosts is matched (isCardlinkVposEntryUrl). The card page posts to the same
6777
+ // path, so the SDK fails every other post to these hosts in the agent's browser, and no placeholder card reaches
6778
+ // the VPOS. The test hosts are listed so a live host classifies as live and the create refuses a test row there;
6779
+ // no entry on them is paused. Ships dark: served only to a client that declares
6780
+ // `cardlink_vpos_hosted_payment_page`, and gated off for every company the operator has not turned it on for.
6781
+ capability: CARDLINK_VPOS_CAPABILITY,
6782
+ match: "(?:vpos\\.eurocommerce\\.gr|ecommerce\\.cardlink\\.gr|www\\.alphaecommerce\\.gr)/vpos/shophandlermpi(?![\\w/.%;=!-])",
6783
+ hosts: [
6784
+ "^vpos\\.eurocommerce\\.gr$",
6785
+ "^ecommerce\\.cardlink\\.gr$",
6786
+ "^www\\.alphaecommerce\\.gr$",
6787
+ "^eurocommerce-test\\.cardlink\\.gr$",
6788
+ "^ecommerce-test\\.cardlink\\.gr$",
6789
+ "^alphaecommerce-test\\.cardlink\\.gr$"
6790
+ ],
6791
+ sandboxHosts: ["^eurocommerce-test\\.cardlink\\.gr$", "^ecommerce-test\\.cardlink\\.gr$", "^alphaecommerce-test\\.cardlink\\.gr$"],
6792
+ hostEnvironmentPinned: true,
6793
+ encoding: "form",
6794
+ // A form navigation: no captured header is ever replayed.
6795
+ passthroughHeaders: [],
6796
+ mode: "hosted_form",
6797
+ hostedForm: {
6798
+ // The card goes into the VPOS's own page on the device, never into the entry, which must carry none
6799
+ // (checkCardlinkVposEntry). The entry's rules come with this registration (hostedEntry below), so no policy is
6800
+ // named here.
6801
+ cardIn: "processor_page",
6802
+ required: [...REQUIRED3],
6803
+ // The card page's own fields, which the device fills on that page.
6804
+ card: { number: "card.pan", month: "card.expiryMonth", year: "card.expiryYear", cvc: "card.cvv" },
6805
+ // The host, the mid, the order id and the amount name one payment; the entry's rules read the host from its URL.
6806
+ dedupe: ["(vposHost)", "mid", "orderid", "orderAmount", "currency"]
6807
+ }
6808
+ }
6809
+ ],
6810
+ // Only the cardholder's device repeats an entry, after a person approves; no reviewed list names cardlink_vpos.
6811
+ refusedOperations: [CARDLINK_VPOS_OPERATION],
6812
+ // Not surveyed: the VPOS tells the merchant the result through the browser's return and a copy to its server, both
6813
+ // signed under the merchant's secret, which Agentcard never holds.
6814
+ settlementReadback: "not_surveyed",
6815
+ exactUrl: isCardlinkVposEntryUrl,
6816
+ hostedEntry: (body, { url }) => checkCardlinkVposEntry(body, { url }),
6817
+ amount: (template) => template && isCardlinkVposEntryUrl(template.url) ? cardlinkVposEntryAmount(template.body) : null,
6818
+ limitations: [
6819
+ "The paused request is the merchant's signed entry form, which carries no card; the cardholder's device sends it to Cardlink's VPOS over the end-to-end TLS relay and fills the card into the page the VPOS returns.",
6820
+ "Agentcard takes only a reviewed merchant's entry: its mid and the host it posts to name the merchant the cardholder is shown, and its confirm and cancel URLs must sit on that merchant's own host.",
6821
+ "Agentcard takes one plain payment only and refuses an entry that asks for a stored card, installments, a recurring schedule, a pre-authorization, MOTO or a preselected payment method.",
6822
+ "The VPOS runs EMV 3-D Secure on the card. A frictionless answer pays; a challenge ends the payment on the device with nothing charged.",
6823
+ "The browser receives a submission notice, not the processor result."
6824
+ ]
6825
+ });
6826
+ // src/processors/eghl.js
6827
+ var EGHL_PSP = "eghl";
6828
+ var EGHL_OPERATION = "eghl.hosted_sale";
6829
+ var EGHL_HOST = "securepay.e-ghl.com";
6830
+ var EGHL_SANDBOX_HOST = "test2pay.ghl.com";
6831
+ var LIVE_PATH = "/ipg/payment.aspx";
6832
+ var SANDBOX_PATH = "/ipgsg/payment.aspx";
6833
+ var MAX_URL2 = 8192;
6834
+ var field3 = (name, reason) => ({ ok: false, code: "hosted_form_field_refused", field: name, reason });
6835
+ function eghlEntry(raw) {
6836
+ if (typeof raw !== "string" || raw.length > MAX_URL2 || raw.includes("#"))
6837
+ return null;
6838
+ let url;
6839
+ try {
6840
+ url = new URL(raw);
6289
6841
  }
6290
- if (recognizer && recognizer.psp === PAYREXX_PSP) {
6291
- return url !== void 0 ? payrexxGateVerdict(url, body) : payrexxBodyVerdict(body);
6842
+ catch {
6843
+ return null;
6292
6844
  }
6293
- if (recognizer && recognizer.psp === PAYGENT_PSP) {
6294
- return url !== void 0 ? paygentRequestVerdict(url, body) : paygentBodyVerdict(body);
6845
+ if (url.href !== raw || url.protocol !== "https:" || url.port || url.username || url.password || url.search.length < 2)
6846
+ return null;
6847
+ const path = url.pathname.toLowerCase();
6848
+ const query = url.search.slice(1);
6849
+ if (url.hostname === EGHL_HOST && path === LIVE_PATH)
6850
+ return Object.freeze({ test: false, query });
6851
+ if (url.hostname === EGHL_SANDBOX_HOST && path === SANDBOX_PATH)
6852
+ return Object.freeze({ test: true, query });
6853
+ return null;
6854
+ }
6855
+ function isEghlEntryUrl(raw) {
6856
+ return eghlEntry(raw) !== null;
6857
+ }
6858
+ var EGHL_MERCHANTS = Object.freeze([
6859
+ Object.freeze({ merchant: "BookXcess", serviceId: "BXS", payee: "BookXcess Sdn Bhd", returnHosts: Object.freeze(["shopify.ghl.com:11443"]), test: false })
6860
+ ]);
6861
+ var SERVICE_ID2 = /^[A-Za-z0-9]{3}$/;
6862
+ var HOST = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)+(?::[1-9]\d{0,4})?$/;
6863
+ function eghlMerchant(serviceId, { test = false, merchants = EGHL_MERCHANTS } = {}) {
6864
+ if (typeof serviceId !== "string" || !SERVICE_ID2.test(serviceId) || !Array.isArray(merchants))
6865
+ return null;
6866
+ const found = merchants.filter((row) => !!row && typeof row.merchant === "string" && row.merchant.trim() !== "" && typeof row.payee === "string" && row.payee.trim() !== "" && row.serviceId === serviceId && row.test === test && Array.isArray(row.returnHosts) && row.returnHosts.length > 0 && row.returnHosts.every((host) => typeof host === "string" && HOST.test(host)));
6867
+ return found.length === 1 ? found[0] : null;
6868
+ }
6869
+ var REQUIRED4 = Object.freeze([
6870
+ "TransactionType",
6871
+ "PymtMethod",
6872
+ "ServiceID",
6873
+ "PaymentID",
6874
+ "OrderNumber",
6875
+ "MerchantReturnURL",
6876
+ "MerchantCallBackURL",
6877
+ "Amount",
6878
+ "CurrencyCode",
6879
+ "HashValue"
6880
+ ]);
6881
+ var CARD_KEYS17 = /* @__PURE__ */ new Set(["cardno", "cardexp", "cardcvv2", "cardholder", "param2", "param4", "cvv2", "epmonth2", "epyear2", "custocp"]);
6882
+ var SECRET_KEYS = /* @__PURE__ */ new Set(["password"]);
6883
+ var STORED_KEYS2 = /* @__PURE__ */ new Set([
6884
+ "tokentype",
6885
+ "token",
6886
+ "cardid",
6887
+ "precheckoutid",
6888
+ "reqtoken",
6889
+ "pairingtoken",
6890
+ "reqverifier",
6891
+ "pairingverifier",
6892
+ "checkoutresourceurl"
6893
+ ]);
6894
+ var SPECIAL_KEYS = /* @__PURE__ */ new Set(["eppmonth", "promocode"]);
6895
+ var RESULT_KEYS = Object.freeze(["MerchantReturnURL", "MerchantCallBackURL", "MerchantApprovalURL", "MerchantUnApprovalURL"]);
6896
+ var CURRENCIES3 = /* @__PURE__ */ new Set(["MYR", "SGD", "USD", "PHP", "THB"]);
6897
+ var AMOUNT3 = /^(0|[1-9]\d{0,8})\.(\d{2})$/;
6898
+ function httpsUrl2(value) {
6899
+ let url;
6900
+ try {
6901
+ url = new URL(value);
6295
6902
  }
6296
- if (recognizer && recognizer.psp === PAY_NL_PSP) {
6297
- if (url !== void 0 && !isPayNlTokenUrl(url))
6903
+ catch {
6904
+ return null;
6905
+ }
6906
+ if (url.protocol !== "https:" || url.username || url.password || url.hash)
6907
+ return null;
6908
+ return url;
6909
+ }
6910
+ function entryFields(text10) {
6911
+ const pairs = parseRedsysForm(text10);
6912
+ if (!pairs)
6913
+ return null;
6914
+ return { pairs, values: new Map(pairs.map(({ key, value }) => [key.toLowerCase(), value])) };
6915
+ }
6916
+ function entryAmount2(values) {
6917
+ const currency = values.get("currencycode");
6918
+ const amount2 = AMOUNT3.exec(values.get("amount") ?? "");
6919
+ if (!amount2 || typeof currency !== "string" || !CURRENCIES3.has(currency))
6920
+ return null;
6921
+ const cents2 = Number(amount2[1]) * 100 + Number(amount2[2]);
6922
+ return cents2 > 0 && Number.isSafeInteger(cents2) ? { amountCents: cents2, currency: currency.toLowerCase() } : null;
6923
+ }
6924
+ function checkEghlEntry(body, { url = null, merchants = EGHL_MERCHANTS } = {}) {
6925
+ if (body !== void 0 && body !== null && body !== "")
6926
+ return field3("(body)", "not_an_entry");
6927
+ const entry = eghlEntry(url);
6928
+ if (!entry)
6929
+ return field3("(url)", "malformed_field");
6930
+ const fields = entryFields(entry.query);
6931
+ if (!fields)
6932
+ return field3("(query)", "malformed");
6933
+ const { pairs, values } = fields;
6934
+ for (const { key, value } of pairs) {
6935
+ if (value === "")
6936
+ continue;
6937
+ const folded = key.toLowerCase();
6938
+ if (CARD_KEYS17.has(folded))
6939
+ return field3(key, "card_in_entry");
6940
+ if (SECRET_KEYS.has(folded))
6941
+ return field3(key, "not_an_entry");
6942
+ if (STORED_KEYS2.has(folded))
6943
+ return field3(key, "stored_credential");
6944
+ if (SPECIAL_KEYS.has(folded))
6945
+ return field3(key, "special_flow");
6946
+ }
6947
+ const missing = REQUIRED4.filter((name) => !values.get(name.toLowerCase()));
6948
+ if (missing.length)
6949
+ return { ok: false, code: "hosted_form_template_incomplete", missing };
6950
+ if (values.get("transactiontype") !== "SALE")
6951
+ return field3("TransactionType", "not_a_sale");
6952
+ if (!["ANY", "CC"].includes(values.get("pymtmethod")))
6953
+ return field3("PymtMethod", "special_flow");
6954
+ if (!/^[0-9A-Fa-f]{64}$/.test(values.get("hashvalue")))
6955
+ return field3("HashValue", "unsigned");
6956
+ if (!entryAmount2(values))
6957
+ return field3(CURRENCIES3.has(values.get("currencycode")) ? "Amount" : "CurrencyCode", "malformed");
6958
+ if (!SERVICE_ID2.test(values.get("serviceid")))
6959
+ return field3("ServiceID", "malformed");
6960
+ if (!/^[A-Za-z0-9._-]{1,20}$/.test(values.get("paymentid")))
6961
+ return field3("PaymentID", "malformed");
6962
+ if (values.get("ordernumber").length > 20)
6963
+ return field3("OrderNumber", "malformed");
6964
+ const pageTimeout = values.get("pagetimeout");
6965
+ if (pageTimeout !== void 0 && !/^[1-9]\d{1,4}$/.test(pageTimeout))
6966
+ return field3("PageTimeout", "malformed");
6967
+ const seller = eghlMerchant(values.get("serviceid"), { test: entry.test, merchants });
6968
+ if (!seller)
6969
+ return field3("ServiceID", "seller_unreviewed");
6970
+ for (const name of RESULT_KEYS) {
6971
+ const value = values.get(name.toLowerCase());
6972
+ if (!value)
6973
+ continue;
6974
+ const target = httpsUrl2(value);
6975
+ if (!target || !seller.returnHosts.includes(target.host) || [EGHL_HOST, EGHL_SANDBOX_HOST].includes(target.hostname))
6976
+ return field3(name, "callback_host");
6977
+ }
6978
+ return { ok: true, pairs, gated: false, dedupe: [values.get("serviceid"), values.get("paymentid")], sandbox: entry.test, seller };
6979
+ }
6980
+ function eghlEntryAmount(body, url) {
6981
+ if (body !== void 0 && body !== null && body !== "")
6982
+ return null;
6983
+ const entry = eghlEntry(url);
6984
+ const fields = entry ? entryFields(entry.query) : null;
6985
+ return fields ? entryAmount2(fields.values) : null;
6986
+ }
6987
+ var MAX_PAGE4 = 1024 * 1024;
6988
+ var NEVER_SENT = new Set(["expressCheckoutType", "c2pRememberMeBrowser", "CustOCP", "CustRecurr", "CustAddress"].map((name) => name.toLowerCase()));
6989
+ var PAGE_REQUIRED = Object.freeze([
6990
+ "TransactionType",
6991
+ "ServiceID",
6992
+ "MerchantName",
6993
+ "PaymentID",
6994
+ "Amount",
6995
+ "BaseTxnAmount",
6996
+ "CurrencyCode",
6997
+ "BaseCurrencyCode",
6998
+ "HashValue",
6999
+ "Param2",
7000
+ "Param4",
7001
+ "CardExp",
7002
+ "CVV2",
7003
+ "PymtMethod"
7004
+ ]);
7005
+ var EGHL_REFUSALS = Object.freeze(["eghl_failed", "eghl_cancelled"]);
7006
+ var MAX_ANSWER = 256 * 1024;
7007
+ var RESULT_FIELDS = Object.freeze(["TxnStatus", "ServiceID", "PaymentID", "Amount", "CurrencyCode"]);
7008
+ var eghl_default = /* @__PURE__ */ registerProcessor({
7009
+ psp: EGHL_PSP,
7010
+ definitions: [
7011
+ {
7012
+ psp: "eghl",
7013
+ // The merchant's entry to eGHL's payment page, as the header above reads it: a GET Document navigation whose
7014
+ // query names the payment and which carries no card. The cardholder's device repeats it over the end-to-end TLS
7015
+ // relay and pays on the page eGHL returns to it, and the runtime resolves the paused navigation with the
7016
+ // hosted_form notice. Only the entry is matched (isEghlEntryUrl): the card page's own card post goes to the same
7017
+ // path as a POST. The path is matched in any letter case, as IIS reads it; `(?![\\w/.%-])` ends it for a consumer
7018
+ // that tests `match` unanchored. Ships dark: served only to a client that declares `eghl_hosted_payment_page`, and
7019
+ // gated off for every company the operator has not allowlisted.
7020
+ capability: "eghl_hosted_payment_page",
7021
+ match: "securepay\\.e-ghl\\.com/[Ii][Pp][Gg]/[Pp][Aa][Yy][Mm][Ee][Nn][Tt]\\.[Aa][Ss][Pp][Xx](?![\\w/.%-])|test2pay\\.ghl\\.com/[Ii][Pp][Gg][Ss][Gg]/[Pp][Aa][Yy][Mm][Ee][Nn][Tt]\\.[Aa][Ss][Pp][Xx](?![\\w/.%-])",
7022
+ hosts: ["^securepay\\.e-ghl\\.com$", "^test2pay\\.ghl\\.com$"],
7023
+ sandboxHosts: ["^test2pay\\.ghl\\.com$"],
7024
+ hostEnvironmentPinned: true,
7025
+ // `encoding` describes the card page's own card post, which the device makes as the page does, since the entry
7026
+ // has no body. No captured header is ever replayed.
7027
+ encoding: "form",
7028
+ passthroughHeaders: [],
7029
+ // The paused request is the navigation itself, a GET with the payment in its query.
7030
+ request: { method: "GET", cardIn: "processor_page", response: "document" },
7031
+ mode: "hosted_form",
7032
+ hostedForm: {
7033
+ // The card goes into eGHL's page on the device, never into the entry (checkEghlEntry refuses one there). The
7034
+ // entry's own rules come with this registration (hostedEntry below), so no policy is named here.
7035
+ cardIn: "processor_page",
7036
+ required: ["TransactionType", "PymtMethod", "ServiceID", "PaymentID", "OrderNumber", "MerchantReturnURL", "MerchantCallBackURL", "Amount", "CurrencyCode", "HashValue"],
7037
+ // The card page's own inputs in its card form (frmProcessPayment, read card free on 2026-11-05): the number in
7038
+ // Param2, the expiry in CardExp as YYYYMM, which the page builds from its month and year selects, the code in
7039
+ // CVV2. The cardholder's name goes in Param4.
7040
+ card: { number: "Param2", expiry: "CardExp", cvc: "CVV2" },
7041
+ // eGHL takes one PaymentID once per merchant.
7042
+ dedupe: ["ServiceID", "PaymentID"]
7043
+ }
7044
+ }
7045
+ ],
7046
+ // Only the cardholder's device repeats an entry, after a person approves; no reviewed list names eghl.
7047
+ refusedOperations: [EGHL_OPERATION],
7048
+ // Not surveyed: eGHL tells the merchant's server the result (MerchantCallBackURL), and its return carries a hash only
7049
+ // the merchant can check.
7050
+ settlementReadback: "not_surveyed",
7051
+ exactUrl: isEghlEntryUrl,
7052
+ amount: (template) => template && typeof template === "object" ? eghlEntryAmount(template.body, template.url) : null,
7053
+ hostedEntry: (body, { url = null } = {}) => checkEghlEntry(body, { url }),
7054
+ limitations: [
7055
+ "The paused request is the merchant's redirect to eGHL's payment page, a GET whose query names the payment and carries no card; the cardholder's device repeats it over the end-to-end TLS relay and pays on the page eGHL returns.",
7056
+ "Agentcard takes an entry only for a merchant it reviewed, by the ServiceID inside the merchant's signed entry, and the approval names that merchant and the amount the entry names.",
7057
+ "eGHL runs 3-D Secure on the card. A challenge ends the payment on the device with nothing charged.",
7058
+ "eGHL sends the buyer to the merchant's return page with a result only the merchant can verify, so the browser receives a submission notice, not the processor result."
7059
+ ]
7060
+ });
7061
+ // src/processors/frisbii.js
7062
+ var FRISBII_PSP = "frisbii";
7063
+ var FRISBII_OPERATION = "frisbii.card_request";
7064
+ var FRISBII_HOSTS = /* @__PURE__ */ Object.freeze({ "card.reepay.com": "reepay", "card.frisbii.com": "frisbii" });
7065
+ var FRISBII_TOKEN_PATH = "/v1/token/";
7066
+ var FRISBII_REFUSED_PATHS = /* @__PURE__ */ Object.freeze({
7067
+ "/v1/token/cof/": "frisbii_stored_card_unsupported",
7068
+ "/v1/token/create_click_to_pay": "frisbii_click_to_pay_unsupported"
7069
+ });
7070
+ var BODY_LIMIT37 = 8192;
7071
+ var URL_LIMIT15 = 256;
7072
+ var CARD_NUMBER19 = /^[0-9]{12,19}$/;
7073
+ var MONTH19 = /^(?:0[1-9]|1[0-2])$/;
7074
+ var YEAR20 = /^[0-9]{2}$/;
7075
+ var SECURITY_CODE23 = /^(?:[0-9]{3,4})?$/;
7076
+ var IDENTIFIER2 = /^[A-Za-z0-9_-]{8,128}$/;
7077
+ var SCA_RULES = /* @__PURE__ */ Object.freeze([
7078
+ "DO_NOT_USE_SCA",
7079
+ "MUST_USE_SCA_AUTH",
7080
+ "MUST_USE_SCA_PREAUTH",
7081
+ "USE_SCA_IF_AVAILABLE_AUTH",
7082
+ "USE_SCA_IF_AVAILABLE_PREAUTH"
7083
+ ]);
7084
+ var BODY_ORDER = /* @__PURE__ */ Object.freeze([
7085
+ "number",
7086
+ "month",
7087
+ "year",
7088
+ "cvv",
7089
+ "cardTypeOverride",
7090
+ "click_to_pay_encrypt",
7091
+ "billing_address",
7092
+ "pkey",
7093
+ "recurring",
7094
+ "cardholder_name",
7095
+ "intent",
7096
+ "recurringAverageAmount",
7097
+ "agreementFilter",
7098
+ "strongAuthenticationRule",
7099
+ "tokenStrongAuthenticationRequest"
7100
+ ]);
7101
+ var BODY_REQUIRED = /* @__PURE__ */ Object.freeze(["number", "month", "year", "cvv", "pkey", "recurring", "strongAuthenticationRule"]);
7102
+ var BODY_REFUSED = /* @__PURE__ */ Object.freeze(["cardTypeOverride", "click_to_pay_encrypt", "billing_address"]);
7103
+ var SCA_ORDER = /* @__PURE__ */ Object.freeze(["amount", "currency", "orderId", "orderText", "merchantScaData", "returnUrl", "tokenBrowserInfo"]);
7104
+ var BROWSER_ORDER = /* @__PURE__ */ Object.freeze([
7105
+ "javascriptEnabled",
7106
+ "challengeWindowSize",
7107
+ "colorDepth",
7108
+ "javaEnabled",
7109
+ "screenHeight",
7110
+ "screenWidth",
7111
+ "tz"
7112
+ ]);
7113
+ var LABEL = /^[A-Za-z0-9_-]{1,64}$/;
7114
+ var record33 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
7115
+ var own14 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
7116
+ var refuse39 = (code) => Object.freeze({ verdict: "refuse", code });
7117
+ var CARD39 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
7118
+ var text9 = (value, max) => typeof value === "string" && value.length <= max;
7119
+ var absentOrNull = (value) => value === void 0 || value === null;
7120
+ var inOrder6 = (value, order) => Object.keys(value).every((key) => order.includes(key)) && Object.keys(value).join() === order.filter((key) => own14(value, key)).join();
7121
+ function frisbiiTokenUrl(url) {
7122
+ if (typeof url !== "string" || url.length > URL_LIMIT15 || url.includes("#"))
7123
+ return null;
7124
+ let parsed;
7125
+ try {
7126
+ parsed = new URL(url);
7127
+ }
7128
+ catch {
7129
+ return null;
7130
+ }
7131
+ if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !own14(FRISBII_HOSTS, parsed.hostname) || parsed.pathname !== FRISBII_TOKEN_PATH)
7132
+ return null;
7133
+ const match = /^\?session=([A-Za-z0-9_-]{8,128})$/.exec(parsed.search);
7134
+ return match ? Object.freeze({ host: parsed.hostname, brand: FRISBII_HOSTS[parsed.hostname], session: match[1] }) : null;
7135
+ }
7136
+ var isFrisbiiTokenUrl = (url) => frisbiiTokenUrl(url) !== null;
7137
+ function frisbiiRefusedFlowUrl(url) {
7138
+ if (typeof url !== "string" || url.length > URL_LIMIT15 || url.includes("#"))
7139
+ return null;
7140
+ let parsed;
7141
+ try {
7142
+ parsed = new URL(url);
7143
+ }
7144
+ catch {
7145
+ return null;
7146
+ }
7147
+ if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !own14(FRISBII_HOSTS, parsed.hostname) || !own14(FRISBII_REFUSED_PATHS, parsed.pathname))
7148
+ return null;
7149
+ return FRISBII_REFUSED_PATHS[parsed.pathname];
7150
+ }
7151
+ function luhn9(digits3) {
7152
+ let sum = 0;
7153
+ for (let at = digits3.length - 1, double = false; at >= 0; at -= 1, double = !double) {
7154
+ let digit = digits3.charCodeAt(at) - 48;
7155
+ if (double)
7156
+ digit = digit * 2 > 9 ? digit * 2 - 9 : digit * 2;
7157
+ sum += digit;
7158
+ }
7159
+ return sum % 10 === 0;
7160
+ }
7161
+ function readBody23(body) {
7162
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT37)
7163
+ return null;
7164
+ try {
7165
+ const value = JSON.parse(body);
7166
+ return record33(value) && JSON.stringify(value) === body ? value : null;
7167
+ }
7168
+ catch {
7169
+ return null;
7170
+ }
7171
+ }
7172
+ function browserInfo(info) {
7173
+ return record33(info) && Object.keys(info).join() === BROWSER_ORDER.join() && info.javascriptEnabled === true && typeof info.javaEnabled === "boolean" && /^size_[0-9]{3}x[0-9]{3}$/.test(info.challengeWindowSize) && [info.colorDepth, info.screenHeight, info.screenWidth].every((n) => Number.isSafeInteger(n) && n >= 0 && n <= 1e5) && Number.isSafeInteger(info.tz) && Math.abs(info.tz) <= 1440;
7174
+ }
7175
+ function scaBlock(block, target) {
7176
+ if (!record33(block) || !inOrder6(block, SCA_ORDER) || !own14(block, "returnUrl") || !own14(block, "tokenBrowserInfo"))
7177
+ return false;
7178
+ if (!Number.isSafeInteger(block.amount) || block.amount < 0 || typeof block.currency !== "string" || !/^[A-Z]{3}$/.test(block.currency))
7179
+ return false;
7180
+ if (!(absentOrNull(block.orderId) || text9(block.orderId, 128)) || !(absentOrNull(block.orderText) || text9(block.orderText, 512)))
7181
+ return false;
7182
+ if (!(absentOrNull(block.merchantScaData) || record33(block.merchantScaData)))
7183
+ return false;
7184
+ if (!text9(block.returnUrl, 2048) || !browserInfo(block.tokenBrowserInfo))
7185
+ return false;
7186
+ const back = /^https:\/\/checkout\.(reepay|frisbii)\.com\/return\.001\.html\?id=([A-Za-z0-9_-]{8,128})(?:&[A-Za-z0-9_.~%=+/-]*)*$/.exec(block.returnUrl);
7187
+ return back !== null && (target === null || back[1] === target.brand && back[2] === target.session);
7188
+ }
7189
+ function frisbiiBodyVerdict(body, url) {
7190
+ const value = readBody23(body);
7191
+ if (value === null || !inOrder6(value, BODY_ORDER) || !BODY_REQUIRED.every((key) => own14(value, key)) || BODY_REFUSED.some((key) => own14(value, key)))
7192
+ return refuse39("frisbii_body_unsupported");
7193
+ if (value.recurring === true || value.intent === "CHARGE_AND_STORE")
7194
+ return refuse39("frisbii_card_on_file");
7195
+ const target = url === void 0 ? null : frisbiiTokenUrl(url);
7196
+ if (url !== void 0 && target === null)
7197
+ return refuse39("frisbii_body_unsupported");
7198
+ const sound = typeof value.number === "string" && CARD_NUMBER19.test(value.number) && luhn9(value.number) && typeof value.month === "string" && MONTH19.test(value.month) && typeof value.year === "string" && YEAR20.test(value.year) && typeof value.cvv === "string" && SECURITY_CODE23.test(value.cvv) && typeof value.pkey === "string" && IDENTIFIER2.test(value.pkey) && value.recurring === false && (value.cardholder_name === void 0 || text9(value.cardholder_name, 64)) && (value.intent === void 0 || value.intent === "CHARGE") && (absentOrNull(value.recurringAverageAmount) || Number.isSafeInteger(value.recurringAverageAmount) && value.recurringAverageAmount >= 0) && (absentOrNull(value.agreementFilter) || typeof value.agreementFilter === "string" && LABEL.test(value.agreementFilter) || Array.isArray(value.agreementFilter) && value.agreementFilter.length <= 16 && value.agreementFilter.every((entry) => typeof entry === "string" && LABEL.test(entry))) && SCA_RULES.includes(value.strongAuthenticationRule) && (value.tokenStrongAuthenticationRequest === void 0 || scaBlock(value.tokenStrongAuthenticationRequest, target));
7199
+ return sound ? CARD39 : refuse39("frisbii_body_unsupported");
7200
+ }
7201
+ var frisbii_default = /* @__PURE__ */ registerProcessor({
7202
+ psp: FRISBII_PSP,
7203
+ definitions: [
7204
+ {
7205
+ psp: "frisbii",
7206
+ // The hosted page's card request, as the header above reads it, on both brands' card hosts. A test account
7207
+ // shares the live hosts, so no sandbox host is marked. The match reads the host and the path and ends with it. It
7208
+ // also takes the page's two other card paths, /v1/token/cof/ and /v1/token/create_click_to_pay, so the pause
7209
+ // decision holds them, and the body gate refuses every body there; the exact-URL rule below holds the session
7210
+ // query of the card request. Ships dark: served only to a client that declares `frisbii_card_token`, and only for a company
7211
+ // the backend's processor gate turns Frisbii on for.
7212
+ capability: "frisbii_card_token",
7213
+ match: "card\\.(?:reepay|frisbii)\\.com/v1/token/(?:cof/|create_click_to_pay)?",
7214
+ hosts: ["^card\\.reepay\\.com$", "^card\\.frisbii\\.com$"],
7215
+ encoding: "json",
7216
+ // The page sends no header but its content type. Origin, Referer and cookies never ride.
7217
+ passthroughHeaders: [],
7218
+ jsonCardFields: [["number"]]
7219
+ }
7220
+ ],
7221
+ // Only the cardholder's device would send this card, after a person approves; no reviewed list names frisbii.
7222
+ refusedOperations: [FRISBII_OPERATION],
7223
+ // Not surveyed: the card request mints a token and moves no money, and the page then charges the session with it
7224
+ // in a card-free request. Whether the session's own read (checkout-api /v1/checkout/<session>) can confirm that
7225
+ // charge was not read.
7226
+ settlementReadback: "not_surveyed",
7227
+ exactUrl: (url) => isFrisbiiTokenUrl(url) || frisbiiRefusedFlowUrl(url) !== null,
7228
+ // A stored card's token and Click to Pay are refused whatever their body; the card request is judged by its body.
7229
+ bodyGate: (url, body) => {
7230
+ if (url === void 0)
7231
+ return frisbiiBodyVerdict(body);
7232
+ const flow = frisbiiRefusedFlowUrl(url);
7233
+ if (flow !== null)
7234
+ return refuse39(flow);
7235
+ return isFrisbiiTokenUrl(url) ? frisbiiBodyVerdict(body, url) : refuse39("frisbii_url_refused");
7236
+ },
7237
+ limitations: ["A live Frisbii card goes only to a merchant account a reviewed pin lists, and none is pinned yet."]
7238
+ });
7239
+ // src/processors/iyzico.js
7240
+ var IYZICO_PSP = "iyzico";
7241
+ var IYZICO_OPERATION = "iyzico.card_request";
7242
+ var PATHS = ["/payment/iyzipos/checkoutform/auth/ecom", "/payment/iyzipos/checkoutform/initialize3ds/ecom"];
7243
+ var IYZICO_CARD_URLS = /* @__PURE__ */ Object.freeze(["https://api.iyzipay.com", "https://sandbox-api.iyzipay.com"].flatMap((origin) => PATHS.map((path) => `${origin}${path}`)));
7244
+ var IYZICO_BODY_KEYS = /* @__PURE__ */ Object.freeze([
7245
+ "installment",
7246
+ "paidPrice",
7247
+ "paymentChannel",
7248
+ "paymentCard",
7249
+ "buyerProtected",
7250
+ "gsmNumber",
7251
+ "dccPayment",
7252
+ "dccQueryRrn",
7253
+ "pwiMetadata"
7254
+ ]);
7255
+ var IYZICO_CARD_KEYS = /* @__PURE__ */ Object.freeze([
7256
+ "cardNumber",
7257
+ "cardHolderName",
7258
+ "expireYear",
7259
+ "expireMonth",
7260
+ "cvc",
7261
+ "registerConsumerCard",
7262
+ "registerCard"
7263
+ ]);
7264
+ var BODY_LIMIT38 = 4096;
7265
+ var CARD_NUMBER20 = /^[0-9]{12,19}$/;
7266
+ var SECURITY_CODE24 = /^[0-9]{3,4}$/;
7267
+ var MONTH20 = /^(?:0?[1-9]|1[0-2])$/;
7268
+ var YEAR21 = /^(?:[0-9]{2}|20[0-9]{2})$/;
7269
+ var PRICE = /^([1-9][0-9]{0,8}|0)(?:\.([0-9]{1,2}))?$/;
7270
+ var CHANNELS = /* @__PURE__ */ Object.freeze(["WEB", "MOBILE_WEB", "MOBILE_IOS", "MOBILE_ANDROID", "MOBILE_WINDOWS"]);
7271
+ var METADATA_KEYS3 = /* @__PURE__ */ Object.freeze(["lightRedesign", "pwiGrowthActionDisabled"]);
7272
+ var FLAG = /^[A-Za-z_]{1,16}$/;
7273
+ var HOLDER5 = /^[^\x00-\x1f\x7f0-9]{3,100}$/u;
7274
+ var record34 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
7275
+ var own15 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
7276
+ var inOrder7 = (value, keys) => {
7277
+ let at = 0;
7278
+ for (const name of Object.keys(value)) {
7279
+ while (at < keys.length && keys[at] !== name)
7280
+ at += 1;
7281
+ if (at === keys.length)
7282
+ return false;
7283
+ at += 1;
7284
+ }
7285
+ return true;
7286
+ };
7287
+ var refuse40 = (code) => Object.freeze({ verdict: "refuse", code });
7288
+ var CARD40 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
7289
+ function isIyzicoCardUrl(url) {
7290
+ return typeof url === "string" && IYZICO_CARD_URLS.includes(url);
7291
+ }
7292
+ function readBody24(body) {
7293
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT38)
7294
+ return null;
7295
+ try {
7296
+ const value = JSON.parse(body);
7297
+ return record34(value) && JSON.stringify(value) === body ? value : null;
7298
+ }
7299
+ catch {
7300
+ return null;
7301
+ }
7302
+ }
7303
+ function hundredths(price) {
7304
+ const match = typeof price === "number" && Number.isFinite(price) ? PRICE.exec(String(price)) : null;
7305
+ const value = match ? Number(match[1]) * 100 + Number((match[2] ?? "").padEnd(2, "0")) : 0;
7306
+ return value > 0 ? value : null;
7307
+ }
7308
+ var holderName2 = (name) => typeof name === "string" && HOLDER5.test(name) && name.trim().split(/\s+/).filter((word) => word.length > 1).length > 1;
7309
+ var metadata = (value) => record34(value) && inOrder7(value, METADATA_KEYS3) && Object.values(value).every((flag3) => Array.isArray(flag3) && flag3.length === 1 && typeof flag3[0] === "string" && FLAG.test(flag3[0]));
7310
+ function iyzicoBodyVerdict(body) {
7311
+ const value = readBody24(body);
7312
+ if (value === null)
7313
+ return refuse40("iyzico_body_unsupported");
7314
+ const card = value.paymentCard;
7315
+ if (record34(card) && (own15(card, "cardToken") || own15(card, "ucsToken") || own15(card, "consumerToken")) && !own15(card, "cardNumber"))
7316
+ return refuse40("iyzico_saved_card");
7317
+ if (own15(value, "dccPayment") || own15(value, "dccQueryRrn"))
7318
+ return refuse40("iyzico_dcc_refused");
7319
+ if (own15(value, "gsmNumber") || own15(value, "buyerProtected") && value.buyerProtected !== false || record34(card) && (own15(card, "registerCard") && card.registerCard !== 0 || own15(card, "registerConsumerCard") && card.registerConsumerCard !== false)) {
7320
+ return refuse40("iyzico_keeps_card");
7321
+ }
7322
+ if (Number.isSafeInteger(value.installment) && value.installment > 1)
7323
+ return refuse40("iyzico_installments_refused");
7324
+ if (!inOrder7(value, IYZICO_BODY_KEYS) || !["installment", "paidPrice", "paymentChannel", "paymentCard"].every((key) => own15(value, key)) || value.installment !== 1 || hundredths(value.paidPrice) === null || !CHANNELS.includes(value.paymentChannel) || own15(value, "pwiMetadata") && !metadata(value.pwiMetadata))
7325
+ return refuse40("iyzico_body_unsupported");
7326
+ if (!record34(card) || Object.keys(card).join() !== IYZICO_CARD_KEYS.join() || typeof card.cardNumber !== "string" || !CARD_NUMBER20.test(card.cardNumber) || !holderName2(card.cardHolderName) || typeof card.expireYear !== "string" || !YEAR21.test(card.expireYear) || typeof card.expireMonth !== "string" || !MONTH20.test(card.expireMonth) || typeof card.cvc !== "string" || !SECURITY_CODE24.test(card.cvc))
7327
+ return refuse40("iyzico_body_unsupported");
7328
+ return CARD40;
7329
+ }
7330
+ var iyzico_default = /* @__PURE__ */ registerProcessor({
7331
+ psp: IYZICO_PSP,
7332
+ definitions: [
7333
+ {
7334
+ psp: "iyzico",
7335
+ // The Checkout Form's card payment, as the header above reads it. Sandbox has its own host, so the device sends
7336
+ // a test-mode payment only iyzico's documented test cards (hostEnvironmentPinned, device-replay.js S7). Ships dark:
7337
+ // served only to a client that declares `iyzico_checkout_form`, for a company the backend's gate turns iyzico on
7338
+ // for, and autopilot never sends it.
7339
+ capability: "iyzico_checkout_form",
7340
+ match: "(?:sandbox-)?api\\.iyzipay\\.com/payment/iyzipos/checkoutform/(?:auth|initialize3ds)/ecom",
7341
+ hosts: ["^api\\.iyzipay\\.com$", "^sandbox-api\\.iyzipay\\.com$"],
7342
+ sandboxHosts: ["^sandbox-api\\.iyzipay\\.com$"],
7343
+ hostEnvironmentPinned: true,
7344
+ encoding: "json",
7345
+ // The form's session token and its Accept. Origin, Referer and cookies never ride, and neither does IYZI_LC,
7346
+ // which iyzico's preflight does not allow.
7347
+ passthroughHeaders: ["^x-iyzi-token$", "^accept$"],
7348
+ jsonCardFields: [["paymentCard", "cardNumber"]]
7349
+ }
7350
+ ],
7351
+ // Only the cardholder's device sends it, after a person approves; 3-D Secure needs that person at the browser.
7352
+ refusedOperations: [IYZICO_OPERATION],
7353
+ // iyzico answers the form's result (CF retrieve) only to the merchant's API key and secret.
7354
+ settlementReadback: {
7355
+ answer: "none",
7356
+ reason: "merchant_credential_required",
7357
+ 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.",
7358
+ source: "https://docs.iyzico.com/en/payment-methods/checkoutform/cf-implementation/cf-retrieve"
7359
+ },
7360
+ exactUrl: isIyzicoCardUrl,
7361
+ bodyGate: (url, body) => url !== void 0 && !isIyzicoCardUrl(url) ? refuse40("iyzico_url_refused") : iyzicoBodyVerdict(body)
7362
+ });
7363
+ // src/processors/midtrans.js
7364
+ var MIDTRANS_PSP = "midtrans";
7365
+ var MIDTRANS_OPERATION = "midtrans.card_request";
7366
+ var MIDTRANS_TOKEN_URL = "https://api.midtrans.com/v2/token";
7367
+ var MIDTRANS_SANDBOX_TOKEN_URL = "https://api.sandbox.midtrans.com/v2/token";
7368
+ var MIDTRANS_TOKEN_KEYS = /* @__PURE__ */ Object.freeze(["card_cvv", "card_number", "card_exp_month", "card_exp_year", "installment_term"]);
7369
+ var BODY_LIMIT39 = 4096;
7370
+ var CARD_NUMBER21 = /^[0-9]{12,19}$/;
7371
+ var SECURITY_CODE25 = /^[0-9]{3,4}$/;
7372
+ var MONTH21 = /^(?:0[1-9]|1[0-2])$/;
7373
+ var YEAR22 = /^20[0-9]{2}$/;
7374
+ var TERM = /^[0-9]{1,3}$/;
7375
+ var record35 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
7376
+ var own16 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
7377
+ var inOrder8 = (value, keys) => {
7378
+ let at = 0;
7379
+ for (const name of Object.keys(value)) {
7380
+ while (at < keys.length && keys[at] !== name)
7381
+ at += 1;
7382
+ if (at === keys.length)
7383
+ return false;
7384
+ at += 1;
7385
+ }
7386
+ return true;
7387
+ };
7388
+ var refuse41 = (code) => Object.freeze({ verdict: "refuse", code });
7389
+ var CARD41 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
7390
+ function isMidtransTokenUrl(url) {
7391
+ return url === MIDTRANS_TOKEN_URL || url === MIDTRANS_SANDBOX_TOKEN_URL;
7392
+ }
7393
+ function readBody25(body) {
7394
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT39)
7395
+ return null;
7396
+ let value;
7397
+ try {
7398
+ value = JSON.parse(body);
7399
+ if (!record35(value) || JSON.stringify(value) !== body)
7400
+ return null;
7401
+ }
7402
+ catch {
7403
+ return null;
7404
+ }
7405
+ return value;
7406
+ }
7407
+ function midtransBodyVerdict(body) {
7408
+ const value = readBody25(body);
7409
+ if (value === null || !inOrder8(value, MIDTRANS_TOKEN_KEYS)) {
7410
+ if (record35(value) && (own16(value, "token_id") || own16(value, "two_click")) && !own16(value, "card_number"))
7411
+ return refuse41("midtrans_saved_card");
7412
+ return refuse41("midtrans_body_unsupported");
7413
+ }
7414
+ if (!own16(value, "card_cvv") || !own16(value, "card_number") || !own16(value, "card_exp_month") || !own16(value, "card_exp_year")) {
7415
+ return refuse41("midtrans_body_unsupported");
7416
+ }
7417
+ if (typeof value.card_cvv !== "string" || !SECURITY_CODE25.test(value.card_cvv) || typeof value.card_number !== "string" || !CARD_NUMBER21.test(value.card_number) || typeof value.card_exp_month !== "string" || !MONTH21.test(value.card_exp_month) || typeof value.card_exp_year !== "string" || !YEAR22.test(value.card_exp_year))
7418
+ return refuse41("midtrans_body_unsupported");
7419
+ if (own16(value, "installment_term") && (typeof value.installment_term !== "string" || !TERM.test(value.installment_term)))
7420
+ return refuse41("midtrans_body_unsupported");
7421
+ return CARD41;
7422
+ }
7423
+ var midtrans_default = /* @__PURE__ */ registerProcessor({
7424
+ psp: MIDTRANS_PSP,
7425
+ definitions: [
7426
+ {
7427
+ psp: "midtrans",
7428
+ // Snap's token request, as the header above reads it. Sandbox has its own host, so the device sends a
7429
+ // test-mode request only Midtrans' documented test cards (hostEnvironmentPinned, device-replay.js S7).
7430
+ // Ships dark: served only to a client that declares `midtrans_card_token`, gated off for every org until an
7431
+ // operator lists one (`midtrans:<org>`), and the backend's gate serves only Agentcard's own company until the
7432
+ // token's publishable key is bound to the merchant (backend config.ts MIDTRANS_KEY_BOUND_TO_MERCHANT).
7433
+ capability: "midtrans_card_token",
7434
+ match: "api\\.(?:sandbox\\.)?midtrans\\.com/v2/token",
7435
+ hosts: ["^api\\.midtrans\\.com$", "^api\\.sandbox\\.midtrans\\.com$"],
7436
+ sandboxHosts: ["^api\\.sandbox\\.midtrans\\.com$"],
7437
+ hostEnvironmentPinned: true,
7438
+ encoding: "json",
7439
+ // Snap's own headers: the publishable client key (Authorization Basic) and X-Service. Origin, Referer and
7440
+ // cookies never ride.
7441
+ passthroughHeaders: ["^authorization$", "^x-service$"],
7442
+ jsonCardFields: [["card_number"]]
7443
+ }
7444
+ ],
7445
+ // Only the cardholder's device sends a token, after a person approves; no reviewed list names midtrans.
7446
+ refusedOperations: [MIDTRANS_OPERATION],
7447
+ // Not surveyed: the token moves no money, and the merchant's own charge names its status by the order id alone.
7448
+ settlementReadback: "not_surveyed",
7449
+ exactUrl: isMidtransTokenUrl,
7450
+ bodyGate: (url, body) => url !== void 0 && !isMidtransTokenUrl(url) ? { verdict: "refuse", code: "midtrans_url_refused" } : midtransBodyVerdict(body)
7451
+ });
7452
+ // src/processors/monei.js
7453
+ var MONEI_PSP = "monei";
7454
+ var MONEI_OPERATION = "monei.card_request";
7455
+ var MONEI_TOKENS_URL = "https://api.monei.com/v1/tokens";
7456
+ var BODY_LIMIT40 = 1024;
7457
+ var PAYMENT_ID = /^(?:[0-9a-f]{32}|[0-9a-f]{40})$/;
7458
+ var MONEI_CARD_KEYS = /* @__PURE__ */ Object.freeze(["number", "expMonth", "expYear", "cvc"]);
7459
+ var NUMBER8 = /^[0-9]{12,19}$/;
7460
+ var MONTH22 = /^(?:0[1-9]|1[0-2])$/;
7461
+ var YEAR23 = /^[0-9]{2}$/;
7462
+ var CODE8 = /^[0-9]{3,4}$/;
7463
+ var record36 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
7464
+ var keysAre2 = (value, keys) => {
7465
+ const found = Object.keys(value);
7466
+ return found.length === keys.length && found.every((key, at) => key === keys[at]);
7467
+ };
7468
+ var refuse42 = (code) => Object.freeze({ verdict: "refuse", code });
7469
+ var CARD42 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
7470
+ function luhn10(digits3) {
7471
+ let sum = 0;
7472
+ for (let at = 0; at < digits3.length; at += 1) {
7473
+ let digit = Number(digits3[digits3.length - 1 - at]);
7474
+ if (at % 2 === 1) {
7475
+ digit *= 2;
7476
+ if (digit > 9)
7477
+ digit -= 9;
7478
+ }
7479
+ sum += digit;
7480
+ }
7481
+ return sum % 10 === 0;
7482
+ }
7483
+ function isMoneiTokensUrl(url) {
7484
+ return url === MONEI_TOKENS_URL;
7485
+ }
7486
+ function readBody26(body) {
7487
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT40)
7488
+ return null;
7489
+ try {
7490
+ const value = JSON.parse(body);
7491
+ return record36(value) && JSON.stringify(value) === body ? value : null;
7492
+ }
7493
+ catch {
7494
+ return null;
7495
+ }
7496
+ }
7497
+ function moneiBodyVerdict(body, url) {
7498
+ if (url !== void 0 && !isMoneiTokensUrl(url))
7499
+ return refuse42("monei_url_refused");
7500
+ const value = readBody26(body);
7501
+ if (value === null || !keysAre2(value, ["paymentId", "paymentMethod"]) || typeof value.paymentId !== "string" || !PAYMENT_ID.test(value.paymentId))
7502
+ return refuse42("monei_body_unsupported");
7503
+ const method = value.paymentMethod;
7504
+ if (!record36(method) || !keysAre2(method, ["card"]) || !record36(method.card) || !keysAre2(method.card, MONEI_CARD_KEYS))
7505
+ return refuse42("monei_body_unsupported");
7506
+ const { number, expMonth, expYear, cvc } = method.card;
7507
+ if (![number, expMonth, expYear, cvc].every((part) => typeof part === "string"))
7508
+ return refuse42("monei_body_unsupported");
7509
+ if (!NUMBER8.test(number) || !luhn10(number) || !MONTH22.test(expMonth) || !YEAR23.test(expYear) || !CODE8.test(cvc))
7510
+ return refuse42("monei_body_unsupported");
7511
+ return CARD42;
7512
+ }
7513
+ var MONEI_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
7514
+ Object.freeze({ merchant: "Genuins", accountIds: Object.freeze(["8d58ab4c-4ad0-4053-b18f-79d80e9ee158"]), merchantUrls: Object.freeze(["https://genuins.com/"]) })
7515
+ ]);
7516
+ var monei_default = /* @__PURE__ */ registerProcessor({
7517
+ psp: MONEI_PSP,
7518
+ definitions: [
7519
+ {
7520
+ psp: "monei",
7521
+ // The card frame's token request, as the header above reads it. One host serves test and live payments alike,
7522
+ // so no sandbox host is marked: MONEI's record of the payment names its mode, and the device sends a test payment
7523
+ // only MONEI's documented test cards (moneiDeviceRefusal). The frame sets no deadline on the fetch, so the
7524
+ // cardholder approves at the shopper's Pay. `(?![\w/.%-])` ends the path for a consumer that tests `match`
7525
+ // unanchored, and the exact-URL rule below holds the rest. Ships dark: served only to a client that declares
7526
+ // `monei_card_token`, and gated off for every company until the backend's gate names one.
7527
+ capability: "monei_card_token",
7528
+ match: "api\\.monei\\.com/v1/tokens(?![\\w/.%-])",
7529
+ hosts: ["^api\\.monei\\.com$"],
7530
+ encoding: "json",
7531
+ // The frame's two device headers. Origin, Referer and cookies never ride.
7532
+ passthroughHeaders: ["^x-client-env$", "^x-client-fingerprint$"],
7533
+ jsonCardFields: [["paymentMethod", "card", "number"]]
7534
+ }
7535
+ ],
7536
+ // Only the cardholder's device sends a card, after a person approves; no reviewed list names monei.
7537
+ refusedOperations: [MONEI_OPERATION],
7538
+ // Not surveyed: the card request mints a token and moves no money; MONEI's confirm, which the page sends, charges it.
7539
+ settlementReadback: "not_surveyed",
7540
+ exactUrl: isMoneiTokensUrl,
7541
+ bodyGate: (url, body) => moneiBodyVerdict(body, url)
7542
+ // No amount reader: the request names none. MONEI's record of the payment names it, and the device holds that record
7543
+ // to the approved amount before it writes any card.
7544
+ });
7545
+ // src/processors/oceanpayment.js
7546
+ var OCEANPAYMENT_PSP = "oceanpayment";
7547
+ var OCEANPAYMENT_OPERATION = "oceanpayment.card_request";
7548
+ var OCEANPAYMENT_HOSTS = /* @__PURE__ */ Object.freeze({ "secure.oceanpayment.com": "production", "test-secure.oceanpayment.com": "sandbox" });
7549
+ var OCEANPAYMENT_FORM_FIELDS = /* @__PURE__ */ Object.freeze([
7550
+ "card_number_three",
7551
+ "card_number_two",
7552
+ "card_number_temp",
7553
+ "card_number",
7554
+ "card_date",
7555
+ "card_year",
7556
+ "card_month",
7557
+ "card_secureCode",
7558
+ "copyCard",
7559
+ "closePage",
7560
+ "starttime",
7561
+ "endtime",
7562
+ "comloadpage",
7563
+ "timezone",
7564
+ "OSLang",
7565
+ "os",
7566
+ "brower",
7567
+ "BrowerLang",
7568
+ "resolution",
7569
+ "methods",
7570
+ "reference_id",
7571
+ "methods",
7572
+ "reference"
7573
+ ]);
7574
+ var URL_LIMIT16 = 2048;
7575
+ var BODY_LIMIT41 = 8192;
7576
+ var SEND_PAY = /^\/gateway\/sendPay;jsessionid=[A-Za-z0-9._!-]{16,128}$/;
7577
+ var own17 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
7578
+ var exact4 = (pattern, value) => typeof value === "string" && pattern.test(value);
7579
+ var CARD_RUN = /[0-9]{12}/;
7580
+ var printable5 = (max) => (value) => typeof value === "string" && value.length <= max && /^[\x20-\x7e]*$/.test(value) && !CARD_RUN.test(value);
7581
+ 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})$/;
7582
+ var LANGUAGE4 = /^(?:|[A-Za-z]{2,8}(?:[-_][A-Za-z0-9]{1,8}){0,3})$/;
7583
+ var SHAPES2 = /* @__PURE__ */ new Map([
7584
+ ["customerCardType", (v) => v === ""],
7585
+ // The page's paste and typing markers: "0" until typed, the number's length when its key handler read it, or "N"
7586
+ // after a paste.
7587
+ ["card_number_three", (v) => exact4(/^(?:0|N|[1-9]|1[0-9])$/, v)],
7588
+ ["card_number_two", (v) => exact4(/^(?:0|[1-9]|1[0-9])$/, v)],
7589
+ ["card_number_temp", (v) => exact4(/^[0-9]{4}(?: ?[0-9]{4}){3}$/, v)],
7590
+ ["card_number", (v) => exact4(/^[0-9]{16}$/, v)],
7591
+ ["card_date", (v) => exact4(/^(?:0[1-9]|1[0-2])\/[0-9]{2}$/, v)],
7592
+ ["card_year", (v) => exact4(/^20[0-9]{2}$/, v)],
7593
+ ["card_month", (v) => exact4(/^(?:0[1-9]|1[0-2])$/, v)],
7594
+ ["card_secureCode", (v) => exact4(/^[0-9]{3,4}$/, v)],
7595
+ ["copyCard", (v) => v === "" || v === "0" || v === "1"],
7596
+ // PAY NOW's handler sets it to 1 before the page submits.
7597
+ ["closePage", (v) => v === "1"],
7598
+ ["starttime", (v) => exact4(STAMP, v)],
7599
+ ["endtime", (v) => exact4(STAMP, v)],
7600
+ ["comloadpage", (v) => v === "0" || v === "1"],
7601
+ // getTimezoneOffset()/60*-1: whole or fractional hours.
7602
+ ["timezone", (v) => exact4(/^(?:|-?(?:[0-9]|1[0-4])(?:\.[0-9]{1,2})?)$/, v)],
7603
+ ["OSLang", (v) => exact4(LANGUAGE4, v)],
7604
+ ["os", printable5(64)],
7605
+ ["brower", printable5(128)],
7606
+ ["BrowerLang", (v) => exact4(LANGUAGE4, v)],
7607
+ ["resolution", printable5(32)],
7608
+ ["methods", (v) => v === "1"],
7609
+ ["reference_id", (v) => v === ""],
7610
+ // The page's own trade number.
7611
+ ["reference", (v) => exact4(/^[0-9]{1,40}$/, v)],
7612
+ ["button", (v) => v === ""]
7613
+ ]);
7614
+ function oceanpaymentSendPayUrl(url) {
7615
+ if (typeof url !== "string" || url.length > URL_LIMIT16 || url.includes("?") || url.includes("#"))
7616
+ return null;
7617
+ let parsed;
7618
+ try {
7619
+ parsed = new URL(url);
7620
+ }
7621
+ catch {
7622
+ return null;
7623
+ }
7624
+ if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !own17(OCEANPAYMENT_HOSTS, parsed.hostname) || !SEND_PAY.test(parsed.pathname))
7625
+ return null;
7626
+ return Object.freeze({ host: parsed.hostname, environment: OCEANPAYMENT_HOSTS[parsed.hostname] });
7627
+ }
7628
+ var isOceanpaymentSendPayUrl = (url) => oceanpaymentSendPayUrl(url) !== null;
7629
+ function formEncode3(value) {
7630
+ let encoded;
7631
+ try {
7632
+ encoded = encodeURIComponent(value);
7633
+ }
7634
+ catch {
7635
+ return null;
7636
+ }
7637
+ return encoded.replace(/[!'()~]/g, (ch) => `%${ch.charCodeAt(0).toString(16).toUpperCase()}`).replace(/%20/g, "+");
7638
+ }
7639
+ function formDecode2(raw) {
7640
+ if (!/^(?:[A-Za-z0-9*._+-]|%[0-9A-F]{2})*$/.test(raw))
7641
+ return null;
7642
+ let value;
7643
+ try {
7644
+ value = decodeURIComponent(raw.replace(/\+/g, "%20"));
7645
+ }
7646
+ catch {
7647
+ return null;
7648
+ }
7649
+ return formEncode3(value) === raw ? value : null;
7650
+ }
7651
+ function readPairs2(body) {
7652
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT41)
7653
+ return null;
7654
+ const pairs = [];
7655
+ for (const chunk of body.split("&")) {
7656
+ const separator = chunk.indexOf("=");
7657
+ if (separator < 1)
7658
+ return null;
7659
+ const rawName = chunk.slice(0, separator), raw = chunk.slice(separator + 1);
7660
+ const name = formDecode2(rawName), value = formDecode2(raw);
7661
+ if (name === null || value === null)
7662
+ return null;
7663
+ pairs.push({ name, rawName, raw, value });
7664
+ }
7665
+ return pairs;
7666
+ }
7667
+ function formPairs(body) {
7668
+ const pairs = readPairs2(body);
7669
+ if (!pairs)
7670
+ return null;
7671
+ const start = pairs[0].name === "customerCardType" ? 1 : 0;
7672
+ const end = pairs[pairs.length - 1].name === "button" ? pairs.length - 1 : pairs.length;
7673
+ if (end - start !== OCEANPAYMENT_FORM_FIELDS.length || OCEANPAYMENT_FORM_FIELDS.some((name, i) => pairs[start + i].name !== name))
7674
+ return null;
7675
+ return pairs;
7676
+ }
7677
+ var valueOf = (pairs, name) => pairs.find((pair) => pair.name === name)?.value;
7678
+ function bodyRefusal(body) {
7679
+ const pairs = formPairs(body);
7680
+ if (!pairs)
7681
+ return "oceanpayment_body_unsupported";
7682
+ if (pairs[0].name === "customerCardType" && pairs[0].value !== "")
7683
+ return "oceanpayment_card_brand_refused";
7684
+ if (valueOf(pairs, "reference_id") !== "")
7685
+ return "oceanpayment_device_data_refused";
7686
+ if (pairs.some(({ name, value }) => !SHAPES2.get(name)(value)))
7687
+ return "oceanpayment_body_unsupported";
7688
+ const number = valueOf(pairs, "card_number");
7689
+ const temp = valueOf(pairs, "card_number_temp");
7690
+ const [month, year] = valueOf(pairs, "card_date").split("/");
7691
+ if (temp.replace(/ /g, "") !== number || temp !== number && temp !== spaced(number))
7692
+ return "oceanpayment_body_unsupported";
7693
+ if (valueOf(pairs, "card_month") !== month || valueOf(pairs, "card_year") !== `20${year}`)
7694
+ return "oceanpayment_body_unsupported";
7695
+ return null;
7696
+ }
7697
+ var spaced = (number) => number.replace(/([0-9]{4})(?=[0-9])/g, "$1 ");
7698
+ function oceanpaymentBodyVerdict(body) {
7699
+ const code = bodyRefusal(body);
7700
+ return code ? Object.freeze({ verdict: "refuse", code }) : Object.freeze({ verdict: "card" });
7701
+ }
7702
+ var oceanpayment_default = /* @__PURE__ */ registerProcessor({
7703
+ psp: OCEANPAYMENT_PSP,
7704
+ definitions: [
7705
+ {
7706
+ psp: "oceanpayment",
7707
+ // The hosted page's card post, as the header above reads it. The sandbox has its own host, so a test row's device
7708
+ // sends only Oceanpayment's documented test cards (hostEnvironmentPinned, device-replay.js S7).
7709
+ // Ships dark: served only to a client that declares `oceanpayment_hosted_payment_page`, and only for a company the
7710
+ // backend's processor gate turns Oceanpayment on for. `(?![\w/.%;=!-])` ends the path for a consumer that tests
7711
+ // `match` unanchored.
7712
+ capability: "oceanpayment_hosted_payment_page",
7713
+ match: "(?:test-)?secure\\.oceanpayment\\.com/gateway/sendPay;jsessionid=[A-Za-z0-9._!-]{16,128}(?![\\w/.%;=!-])",
7714
+ hosts: ["^secure\\.oceanpayment\\.com$", "^test-secure\\.oceanpayment\\.com$"],
7715
+ sandboxHosts: ["^test-secure\\.oceanpayment\\.com$"],
7716
+ hostEnvironmentPinned: true,
7717
+ encoding: "form",
7718
+ // A form navigation: nothing but its type is replayed. Origin, Referer and cookies never ride.
7719
+ passthroughHeaders: [],
7720
+ cardFields: ["card_number"]
7721
+ }
7722
+ ],
7723
+ // Only the cardholder's device sends this card, after a person approves; no reviewed list names oceanpayment.
7724
+ refusedOperations: [OCEANPAYMENT_OPERATION],
7725
+ // Not surveyed: Oceanpayment tells the merchant's server the result (its noticeUrl), and reading a payment back takes the
7726
+ // merchant's own secure code, which Agentcard never holds.
7727
+ settlementReadback: "not_surveyed",
7728
+ exactUrl: isOceanpaymentSendPayUrl,
7729
+ bodyGate: (url, body) => url !== void 0 && !isOceanpaymentSendPayUrl(url) ? Object.freeze({ verdict: "refuse", code: "oceanpayment_url_refused" }) : oceanpaymentBodyVerdict(body)
7730
+ // No amount reader: the post names none, so the agent's pair is the figure the cardholder approves.
7731
+ });
7732
+ // src/processors/paymentwall.js
7733
+ var PAYMENTWALL_PSP = "paymentwall";
7734
+ var PAYMENTWALL_OPERATION = "paymentwall.card_request";
7735
+ var PAYMENTWALL_TOKEN_URL = "https://pwgateway.com/api/token";
7736
+ var PAYMENTWALL_SANDBOX_TOKEN_URL = "https://api.paymentwall.com/api/brick/token";
7737
+ var BODY_LIMIT42 = 2048;
7738
+ var KEY3 = "public_key";
7739
+ var PUBLIC_KEY2 = /^(?:t_)?[A-Za-z0-9]{16,64}$/;
7740
+ var SHAPES3 = /* @__PURE__ */ Object.freeze({
7741
+ [KEY3]: PUBLIC_KEY2,
7742
+ "card[number]": /^[0-9]{12,19}$/,
7743
+ "card[exp_month]": /^(?:0?[1-9]|1[0-2])$/,
7744
+ "card[exp_year]": /^(?:[0-9]{2}|20[0-9]{2})$/,
7745
+ "card[cvv]": /^[0-9]{3,4}$/
7746
+ });
7747
+ var refuse43 = (code) => Object.freeze({ verdict: "refuse", code });
7748
+ var CARD43 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
7749
+ function luhn11(digits3) {
7750
+ let sum = 0;
7751
+ for (let at = 0; at < digits3.length; at += 1) {
7752
+ let digit = Number(digits3[digits3.length - 1 - at]);
7753
+ if (at % 2 === 1) {
7754
+ digit *= 2;
7755
+ if (digit > 9)
7756
+ digit -= 9;
7757
+ }
7758
+ sum += digit;
7759
+ }
7760
+ return sum % 10 === 0;
7761
+ }
7762
+ function paymentwallUrlEnvironment(url) {
7763
+ if (url === PAYMENTWALL_TOKEN_URL)
7764
+ return "production";
7765
+ return url === PAYMENTWALL_SANDBOX_TOKEN_URL ? "sandbox" : null;
7766
+ }
7767
+ function isPaymentwallTokenUrl(url) {
7768
+ return paymentwallUrlEnvironment(url) !== null;
7769
+ }
7770
+ function paymentwallKeyEnvironment(publicKey) {
7771
+ if (typeof publicKey !== "string" || !PUBLIC_KEY2.test(publicKey))
7772
+ return null;
7773
+ return publicKey.startsWith("t_") ? "sandbox" : "production";
7774
+ }
7775
+ function readPairs3(body) {
7776
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT42 || !/^[A-Za-z0-9_[\]=&]+$/.test(body))
7777
+ return null;
7778
+ const pairs = /* @__PURE__ */ new Map();
7779
+ for (const chunk of body.split("&")) {
7780
+ const eq = chunk.indexOf("=");
7781
+ if (eq <= 0 || chunk.indexOf("=", eq + 1) !== -1)
7782
+ return null;
7783
+ const key = chunk.slice(0, eq);
7784
+ if (pairs.has(key))
7785
+ return null;
7786
+ pairs.set(key, chunk.slice(eq + 1));
7787
+ }
7788
+ return pairs;
7789
+ }
7790
+ function paymentwallBodyVerdict(body, url) {
7791
+ if (url !== void 0 && !isPaymentwallTokenUrl(url))
7792
+ return refuse43("paymentwall_url_refused");
7793
+ const pairs = readPairs3(body);
7794
+ if (pairs === null)
7795
+ return refuse43("paymentwall_body_unsupported");
7796
+ if (pairs.has("card[token]") && !pairs.has("card[number]"))
7797
+ return refuse43("paymentwall_saved_card");
7798
+ const keys = Object.keys(SHAPES3);
7799
+ if (pairs.size !== keys.length || !keys.every((key) => pairs.has(key) && SHAPES3[key].test(pairs.get(key)))) {
7800
+ return refuse43("paymentwall_body_unsupported");
7801
+ }
7802
+ if (!luhn11(pairs.get("card[number]")))
7803
+ return refuse43("paymentwall_body_unsupported");
7804
+ if (url !== void 0 && paymentwallKeyEnvironment(pairs.get(KEY3)) !== paymentwallUrlEnvironment(url))
7805
+ return refuse43("paymentwall_key_refused");
7806
+ return CARD43;
7807
+ }
7808
+ var paymentwall_default = /* @__PURE__ */ registerProcessor({
7809
+ psp: PAYMENTWALL_PSP,
7810
+ definitions: [
7811
+ {
7812
+ psp: "paymentwall",
7813
+ // Brick's token request, as the header above reads it. A test key's request has its own host, so the device sends
7814
+ // it only Paymentwall's documented test cards (hostEnvironmentPinned, device-replay.js S7). Ships dark: served only
7815
+ // to a client that declares `paymentwall_card_token`, for a company the backend's gate turns it on for
7816
+ // (checkout-processor-gate.ts), and the device sends a live card only under a key a reviewed pin names.
7817
+ capability: "paymentwall_card_token",
7818
+ match: "(?:pwgateway\\.com/api/token|api\\.paymentwall\\.com/api/brick/token)",
7819
+ hosts: ["^pwgateway\\.com$", "^api\\.paymentwall\\.com$"],
7820
+ sandboxHosts: ["^api\\.paymentwall\\.com$"],
7821
+ hostEnvironmentPinned: true,
7822
+ encoding: "form",
7823
+ // Brick's XHR sets the form Content-Type alone, and that always rides. Origin, Referer and cookies never do.
7824
+ passthroughHeaders: [],
7825
+ cardFields: ["card[number]"]
7826
+ }
7827
+ ],
7828
+ // Only the cardholder's device sends a card request, after a person approves; no reviewed list names paymentwall.
7829
+ refusedOperations: [PAYMENTWALL_OPERATION],
7830
+ // Not surveyed: the token moves no money, and the charge that spends it happens out of this request.
7831
+ settlementReadback: "not_surveyed",
7832
+ exactUrl: isPaymentwallTokenUrl,
7833
+ bodyGate: (url, body) => paymentwallBodyVerdict(body, url)
7834
+ });
7835
+ // src/processors/payplug.js
7836
+ var PAYPLUG_PSP = "payplug";
7837
+ var PAYPLUG_OPERATION = "payplug.hosted_sale";
7838
+ var PAYPLUG_HOST = "secure.payplug.com";
7839
+ var ENTRY_PATH = /^\/pay\/(?:(test)\/)?([A-Za-z0-9]{22})$/;
7840
+ var MAX_URL3 = 256;
7841
+ var field4 = (name, reason) => ({ ok: false, code: "hosted_form_field_refused", field: name, reason });
7842
+ function payplugEntry(raw) {
7843
+ if (typeof raw !== "string" || raw.length > MAX_URL3 || raw.includes("?") || raw.includes("#"))
7844
+ return null;
7845
+ let url;
7846
+ try {
7847
+ url = new URL(raw);
7848
+ }
7849
+ catch {
7850
+ return null;
7851
+ }
7852
+ if (url.href !== raw || url.protocol !== "https:" || url.hostname !== PAYPLUG_HOST || url.port || url.username || url.password)
7853
+ return null;
7854
+ const match = ENTRY_PATH.exec(url.pathname);
7855
+ return match ? Object.freeze({ id: match[2], test: match[1] === "test" }) : null;
7856
+ }
7857
+ function isPayplugEntryUrl(raw) {
7858
+ return payplugEntry(raw) !== null;
7859
+ }
7860
+ var PAYPLUG_MERCHANTS = Object.freeze([
7861
+ Object.freeze({ merchant: "Lazartigue", origins: Object.freeze(["https://lazartigue.com"]), payee: null, account: null })
7862
+ ]);
7863
+ var ACCOUNT_ID = /^[A-Za-z0-9-]{1,64}$/;
7864
+ function payplugMerchant(checkoutOrigin, merchants = PAYPLUG_MERCHANTS) {
7865
+ if (typeof checkoutOrigin !== "string" || checkoutOrigin.length > MAX_URL3 || !Array.isArray(merchants))
7866
+ return null;
7867
+ let url;
7868
+ try {
7869
+ url = new URL(checkoutOrigin);
7870
+ }
7871
+ catch {
7872
+ return null;
7873
+ }
7874
+ if (url.protocol !== "https:" || url.origin !== checkoutOrigin || url.port)
7875
+ return null;
7876
+ 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));
7877
+ return found.length === 1 ? found[0] : null;
7878
+ }
7879
+ function checkPayplugEntry(body, { url = null, checkoutOrigin = null, merchants = PAYPLUG_MERCHANTS } = {}) {
7880
+ if (body !== void 0 && body !== null && body !== "")
7881
+ return field4("(body)", "not_an_entry");
7882
+ const entry = payplugEntry(url);
7883
+ if (!entry)
7884
+ return field4("(url)", "malformed_field");
7885
+ const seller = payplugMerchant(checkoutOrigin, merchants);
7886
+ if (!seller)
7887
+ return field4("(checkout_origin)", "seller_unreviewed");
7888
+ return { ok: true, pairs: [], gated: false, dedupe: [entry.id], paymentId: entry.id, sandbox: entry.test, seller };
7889
+ }
7890
+ var MAX_PAGE5 = 512 * 1024;
7891
+ var PAYPLUG_REFUSALS = Object.freeze(["payplug_failed", "payplug_expired", "payplug_cancelled"]);
7892
+ var payplug_default = /* @__PURE__ */ registerProcessor({
7893
+ psp: PAYPLUG_PSP,
7894
+ definitions: [
7895
+ {
7896
+ psp: "payplug",
7897
+ // The merchant's redirect to PayPlug's payment page, as the header above reads it: a Document navigation that
7898
+ // carries no card. The cardholder's device repeats it over the end-to-end TLS relay and pays on the page PayPlug
7899
+ // returns to it, and the runtime resolves the paused navigation with the hosted_form notice. Only the entry is
7900
+ // matched (isPayplugEntryUrl): the page's card post and its 3-D Secure steps share the host, and none of them is
7901
+ // the entry. Test and live payments share the host, and the entry's path says which it is. Ships dark: served
7902
+ // only to a client that declares `payplug_hosted_payment_page`, and the backend's gate serves only Agentcard's
7903
+ // own company until a reviewed merchant pays.
7904
+ capability: "payplug_hosted_payment_page",
7905
+ match: "secure\\.payplug\\.com/pay/(?:test/)?[A-Za-z0-9]{22}",
7906
+ hosts: ["^secure\\.payplug\\.com$"],
7907
+ // `encoding` describes the page's own card post, which the device makes as the page does, since the entry has no
7908
+ // body. No captured header is ever replayed.
7909
+ encoding: "form",
7910
+ passthroughHeaders: [],
7911
+ request: { method: "GET", cardIn: "none", response: "html_page" },
7912
+ mode: "hosted_form",
7913
+ hostedForm: {
7914
+ // The card goes into PayPlug's page on the device, never into the entry, which carries no body at all. The
7915
+ // entry's own rules come with this registration (hostedEntry below), so no policy is named here.
7916
+ cardIn: "processor_page",
7917
+ required: [],
7918
+ // The page's card inputs, by the data-payplug role its script reads them by: they carry no name, and the
7919
+ // script posts the card only as its ciphertext, encryptedCard.
7920
+ card: { number: "card_number", expiry: "card_month_year", cvc: "card_cvv" },
7921
+ // The payment's id in the entry's URL names the one payment the merchant created; the entry's rules read it
7922
+ // there (checkPayplugEntry's dedupe), since no form field holds it.
7923
+ dedupe: ["(paymentId)"]
7924
+ }
7925
+ }
7926
+ ],
7927
+ // Only the cardholder's device repeats an entry, after a person approves; no reviewed list names payplug.
7928
+ refusedOperations: [PAYPLUG_OPERATION],
7929
+ // Not surveyed: PayPlug tells only the merchant's server the result, and the browser returns whatever it was.
7930
+ settlementReadback: "not_surveyed",
7931
+ exactUrl: isPayplugEntryUrl,
7932
+ hostedEntry: checkPayplugEntry,
7933
+ limitations: [
7934
+ "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.",
7935
+ "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.",
7936
+ "PayPlug runs 3-D Secure on the card. A challenge ends the payment on the device with nothing charged.",
7937
+ "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."
7938
+ ]
7939
+ });
7940
+ // src/processors/paystack.js
7941
+ var PAYSTACK_PSP = "paystack";
7942
+ var PAYSTACK_OPERATION = "paystack.card_request";
7943
+ var PAYSTACK_CHARGE_URL = "https://standard.paystack.co/charge/";
7944
+ var PAYSTACK_BODY_KEYS = /* @__PURE__ */ Object.freeze([
7945
+ "clientdata",
7946
+ "last4",
7947
+ "trans",
7948
+ "access_code",
7949
+ "device",
7950
+ "offset",
7951
+ "remember_card",
7952
+ "card_holder_name",
7953
+ "transaction_type"
7954
+ ]);
7955
+ var OPTIONAL = /* @__PURE__ */ new Set(["access_code", "card_holder_name", "transaction_type"]);
7956
+ var BODY_LIMIT43 = 4096;
7957
+ var CIPHERTEXT_BYTES2 = [62, 63, 64];
7958
+ var BASE646 = /^[A-Za-z0-9+/]+={0,2}$/;
7959
+ var SHAPES4 = /* @__PURE__ */ Object.freeze({
7960
+ last4: /^[0-9]{4}$/,
7961
+ trans: /^[0-9]{1,20}$/,
7962
+ access_code: /^[A-Za-z0-9]{1,64}$/,
7963
+ device: /^[\x21-\x7e]{1,512}$/,
7964
+ offset: /^-?[0-9]{1,3}$/,
7965
+ remember_card: /^false$/,
7966
+ // A name carries no digit, so no card number can ride in it.
7967
+ card_holder_name: /^[^\x00-\x1f\x7f0-9]{1,128}$/u,
7968
+ transaction_type: /^[a-z_]{1,32}$/
7969
+ });
7970
+ var own18 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
7971
+ var refuse44 = (code) => Object.freeze({ verdict: "refuse", code });
7972
+ function paystackFormValue(value) {
7973
+ return encodeURIComponent(String(value)).replace(/%20/g, "+").replace(/[!'()*~]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
7974
+ }
7975
+ function paystackFormBody(entries) {
7976
+ return entries.map(([key, value]) => `${paystackFormValue(key)}=${paystackFormValue(value)}`).join("&");
7977
+ }
7978
+ function isPaystackChargeUrl(url) {
7979
+ return url === PAYSTACK_CHARGE_URL;
7980
+ }
7981
+ function isCiphertext2(value) {
7982
+ if (value.length % 4 !== 0 || !BASE646.test(value))
7983
+ return false;
7984
+ let binary;
7985
+ try {
7986
+ binary = atob(value);
7987
+ }
7988
+ catch {
7989
+ return false;
7990
+ }
7991
+ return btoa(binary) === value && CIPHERTEXT_BYTES2.includes(binary.length);
7992
+ }
7993
+ function readForm3(body) {
7994
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT43)
7995
+ return null;
7996
+ const entries = [];
7997
+ for (const part of body.split("&")) {
7998
+ const at = part.indexOf("=");
7999
+ if (at <= 0)
8000
+ return null;
8001
+ try {
8002
+ entries.push([decodeURIComponent(part.slice(0, at).replace(/\+/g, " ")), decodeURIComponent(part.slice(at + 1).replace(/\+/g, " "))]);
8003
+ }
8004
+ catch {
8005
+ return null;
8006
+ }
8007
+ }
8008
+ return paystackFormBody(entries) === body ? entries : null;
8009
+ }
8010
+ function paystackBodyVerdict(body) {
8011
+ const entries = readForm3(body);
8012
+ if (entries === null)
8013
+ return refuse44("paystack_body_unsupported");
8014
+ const keys = entries.map(([key]) => key);
8015
+ if (keys.includes("subscription"))
8016
+ return refuse44("paystack_subscription");
8017
+ if (keys.includes("remember_card") && entries.find(([key]) => key === "remember_card")[1] !== "false")
8018
+ return refuse44("paystack_saved_card");
8019
+ const expected = PAYSTACK_BODY_KEYS.filter((key) => !OPTIONAL.has(key) || keys.includes(key));
8020
+ if (keys.length !== expected.length || keys.some((key, i) => key !== expected[i]))
8021
+ return refuse44("paystack_body_unsupported");
8022
+ const fields = Object.fromEntries(entries);
8023
+ if (!isCiphertext2(fields.clientdata))
8024
+ return refuse44("paystack_body_unsupported");
8025
+ for (const [key, shape] of Object.entries(SHAPES4)) {
8026
+ if (own18(fields, key) && !shape.test(fields[key]))
8027
+ return refuse44("paystack_body_unsupported");
8028
+ }
8029
+ return Object.freeze({ verdict: "card", fields: Object.freeze(fields) });
8030
+ }
8031
+ var paystack_default = /* @__PURE__ */ registerProcessor({
8032
+ psp: PAYSTACK_PSP,
8033
+ definitions: [
8034
+ {
8035
+ psp: "paystack",
8036
+ // The card page's charge, as the header above reads it. Live and test transactions share standard.paystack.co,
8037
+ // so no sandbox host is listed and no environment is pinned. Ships dark: served only to a client that declares
8038
+ // `paystack_pinned_key`, and only for a company the backend's processor gate turns Paystack on for.
8039
+ // `(?![\w/.%?#-])` ends the path for a consumer that tests `match` unanchored; the exact-URL rule takes no query.
8040
+ capability: "paystack_pinned_key",
8041
+ match: "standard\\.paystack\\.co/charge/(?![\\w/.%?#-])",
8042
+ hosts: ["^standard\\.paystack\\.co$"],
8043
+ encoding: "form",
8044
+ // The browser's language rides as the page sent it; Origin, Referer and cookies never do (the page sends no cookie).
8045
+ passthroughHeaders: ["^accept-language$"],
8046
+ cardFields: ["clientdata"]
8047
+ }
8048
+ ],
8049
+ // Only the cardholder's device sends this charge, after a person approves; no reviewed list names paystack.
8050
+ refusedOperations: [PAYSTACK_OPERATION],
8051
+ // Not surveyed: reading a charge back takes the merchant's secret key, which Agentcard never holds.
8052
+ settlementReadback: "not_surveyed",
8053
+ exactUrl: isPaystackChargeUrl,
8054
+ bodyGate: (url, body) => url !== void 0 && !isPaystackChargeUrl(url) ? refuse44("paystack_url_refused") : paystackBodyVerdict(body),
8055
+ // No amount reader: the charge names none, so the agent's pair is the figure the cardholder approves.
8056
+ limitations: ["The charge names no merchant and no amount: Paystack's transaction binds both, so the cardholder approves the agent's figure for whichever Paystack merchant opened the checkout."]
8057
+ });
8058
+ // src/processors/processout.js
8059
+ var PROCESSOUT_PSP = "processout";
8060
+ var PROCESSOUT_OPERATION = "processout.card_request";
8061
+ var URL_LIMIT17 = 512;
8062
+ var BODY_LIMIT44 = 4096;
8063
+ 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})$/;
8064
+ var PAGE_KEYS2 = /* @__PURE__ */ Object.freeze(["name", "contact", "preferred_scheme"]);
8065
+ var CONTACT_KEYS = /* @__PURE__ */ Object.freeze(["address1", "address2", "city", "state", "country_code", "zip"]);
8066
+ var DEVICE_KEYS4 = /* @__PURE__ */ Object.freeze([
8067
+ "request_origin",
8068
+ "app_color_depth",
8069
+ "app_language",
8070
+ "app_screen_height",
8071
+ "app_screen_width",
8072
+ "app_timezone_offset",
8073
+ "app_java_enabled"
8074
+ ]);
8075
+ var PROCESSOUT_CARD_KEYS = /* @__PURE__ */ Object.freeze(["number", "exp_month", "exp_year", "cvc2"]);
8076
+ var BODY_KEYS3 = /* @__PURE__ */ new Set([...PAGE_KEYS2, "device", ...DEVICE_KEYS4, ...PROCESSOUT_CARD_KEYS]);
8077
+ var NUMBER9 = /^[0-9]{12,19}$/;
8078
+ var MONTH23 = /^(?:[1-9]|1[0-2])$/;
8079
+ var YEAR24 = /^20[0-9]{2}$/;
8080
+ var CODE9 = /^[0-9]{3,4}$/;
8081
+ var TEXT_LIMIT14 = 256;
8082
+ var SCHEME = /^[A-Za-z][A-Za-z0-9 _-]{0,31}$/;
8083
+ var LANGUAGE5 = /^[A-Za-z]{1,8}(?:-[A-Za-z0-9]{1,8}){0,4}$/;
8084
+ var PAN_LIKE7 = /(?:[0-9][^0-9A-Za-z]*){12,}/;
8085
+ var record37 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
8086
+ var own19 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
8087
+ var refuse45 = (code) => Object.freeze({ verdict: "refuse", code });
8088
+ var CARD44 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
8089
+ var BASE647 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
8090
+ function base64Of(text10) {
8091
+ let out = "";
8092
+ for (let at = 0; at < text10.length; at += 3) {
8093
+ const a = text10.charCodeAt(at);
8094
+ const b = at + 1 < text10.length ? text10.charCodeAt(at + 1) : NaN;
8095
+ const c = at + 2 < text10.length ? text10.charCodeAt(at + 2) : NaN;
8096
+ out += BASE647[a >> 2] + BASE647[(a & 3) << 4 | (Number.isNaN(b) ? 0 : b >> 4)] + (Number.isNaN(b) ? "=" : BASE647[(b & 15) << 2 | (Number.isNaN(c) ? 0 : c >> 6)]) + (Number.isNaN(c) ? "=" : BASE647[c & 63]);
8097
+ }
8098
+ return out;
8099
+ }
8100
+ var basicOf = (projectId) => base64Of(`${projectId}:`);
8101
+ function luhn12(digits3) {
8102
+ let sum = 0;
8103
+ for (let at = 0; at < digits3.length; at += 1) {
8104
+ let digit = Number(digits3[digits3.length - 1 - at]);
8105
+ if (at % 2 === 1) {
8106
+ digit *= 2;
8107
+ if (digit > 9)
8108
+ digit -= 9;
8109
+ }
8110
+ sum += digit;
8111
+ }
8112
+ return sum % 10 === 0;
8113
+ }
8114
+ function processoutCardTarget(url) {
8115
+ if (typeof url !== "string" || url.length > URL_LIMIT17)
8116
+ return null;
8117
+ const match = CARD_URL2.exec(url);
8118
+ if (!match || match[2] !== basicOf(match[1]))
8119
+ return null;
8120
+ return Object.freeze({ projectId: match[1], environment: match[1].startsWith("test-") ? "sandbox" : "production" });
8121
+ }
8122
+ function isProcessoutCardUrl(url) {
8123
+ return processoutCardTarget(url) !== null;
8124
+ }
8125
+ function readBody27(body) {
8126
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT44)
8127
+ return null;
8128
+ try {
8129
+ const value = JSON.parse(body);
8130
+ return record37(value) && JSON.stringify(value) === body ? value : null;
8131
+ }
8132
+ catch {
8133
+ return null;
8134
+ }
8135
+ }
8136
+ var pageText2 = (value) => value === null || typeof value === "string" && value.length <= TEXT_LIMIT14 && !PAN_LIKE7.test(value);
8137
+ var DEVICE_RULES = /* @__PURE__ */ Object.freeze({
8138
+ request_origin: (value) => value === "web",
8139
+ app_color_depth: (value) => Number.isSafeInteger(value) && value >= 1 && value <= 64,
8140
+ app_language: (value) => typeof value === "string" && value.length <= 64 && LANGUAGE5.test(value),
8141
+ app_screen_height: (value) => Number.isSafeInteger(value) && value >= 1 && value <= 1e5,
8142
+ app_screen_width: (value) => Number.isSafeInteger(value) && value >= 1 && value <= 1e5,
8143
+ app_timezone_offset: (value) => Number.isSafeInteger(value) && value >= -1440 && value <= 1440,
8144
+ app_java_enabled: (value) => typeof value === "boolean"
8145
+ });
8146
+ function soundDevice3(value) {
8147
+ const device = value.device;
8148
+ if (!record37(device) || !own19(device, "request_origin") || !own19(device, "app_timezone_offset"))
8149
+ return false;
8150
+ return DEVICE_KEYS4.every((key) => own19(device, key) ? DEVICE_RULES[key](device[key]) && own19(value, key) && value[key] === device[key] : !own19(value, key)) && Object.keys(device).every((key) => DEVICE_KEYS4.includes(key));
8151
+ }
8152
+ function soundPageData(value) {
8153
+ if (own19(value, "name") && !pageText2(value.name))
8154
+ return false;
8155
+ if (own19(value, "preferred_scheme") && !(value.preferred_scheme === null || typeof value.preferred_scheme === "string" && SCHEME.test(value.preferred_scheme)))
8156
+ return false;
8157
+ const contact = value.contact;
8158
+ return record37(contact) && Object.keys(contact).every((key) => CONTACT_KEYS.includes(key) && pageText2(contact[key]));
8159
+ }
8160
+ function processoutBodyVerdict(body, url) {
8161
+ if (url !== void 0 && processoutCardTarget(url) === null)
8162
+ return refuse45("processout_url_refused");
8163
+ const value = readBody27(body);
8164
+ if (value === null || !Object.keys(value).every((key) => BODY_KEYS3.has(key)))
8165
+ return refuse45("processout_body_unsupported");
8166
+ if (!PROCESSOUT_CARD_KEYS.every((key) => typeof value[key] === "string"))
8167
+ return refuse45("processout_body_unsupported");
8168
+ if (!NUMBER9.test(value.number) || !luhn12(value.number) || !MONTH23.test(value.exp_month) || !YEAR24.test(value.exp_year) || !CODE9.test(value.cvc2))
8169
+ return refuse45("processout_body_unsupported");
8170
+ if (!soundPageData(value) || !soundDevice3(value))
8171
+ return refuse45("processout_body_unsupported");
8172
+ return CARD44;
8173
+ }
8174
+ var processout_default = /* @__PURE__ */ registerProcessor({
8175
+ psp: PROCESSOUT_PSP,
8176
+ definitions: [
8177
+ {
8178
+ psp: "processout",
8179
+ // ProcessOut.js's card request, as the header above reads it. One host serves every project, live and sandbox
8180
+ // alike, so no sandbox host is marked: the project id names the environment, and the device sends a sandbox
8181
+ // project only ProcessOut's documented test cards (processoutDeviceRefusal). The page gives up 20 seconds after
8182
+ // its tokenize message, so the lane is prepared only (preparationRequired). The match reads the host and the path,
8183
+ // and ends where the path does, as Pin Payments' does: a card's own record under /cards/, where the code refresh
8184
+ // goes, is never paused. The exact-URL rule below holds the query, the project id and its Basic credential among it.
8185
+ // Ships dark: served only to a client that declares `processout_card_token`, and gated off for every org until
8186
+ // the backend's gate names one.
8187
+ capability: "processout_card_token",
8188
+ match: "api\\.processout\\.com/cards(?![\\w/.%-])",
8189
+ hosts: ["^api\\.processout\\.com$"],
8190
+ preparationRequired: true,
8191
+ encoding: "json",
8192
+ // ProcessOut.js's own headers: the project's Basic credential and the API version. Origin, Referer and cookies
8193
+ // never ride.
8194
+ passthroughHeaders: ["^authorization$", "^api-version$"],
8195
+ jsonCardFields: [["number"]]
8196
+ }
8197
+ ],
8198
+ // Only the cardholder's device sends a card, after a person approves; no reviewed list names processout.
8199
+ refusedOperations: [PROCESSOUT_OPERATION],
8200
+ // Not surveyed: the card request mints a token and moves no money; the store's server charges it under its own
8201
+ // secret key, which Agentcard never holds.
8202
+ settlementReadback: "not_surveyed",
8203
+ exactUrl: isProcessoutCardUrl,
8204
+ bodyGate: (url, body) => processoutBodyVerdict(body, url)
8205
+ });
8206
+ // src/processors/usaepay.js
8207
+ var USAEPAY_PSP = "usaepay";
8208
+ var USAEPAY_OPERATION = "usaepay.card_request";
8209
+ var USAEPAY_HOSTS = /* @__PURE__ */ Object.freeze({
8210
+ "www.usaepay.com": "production",
8211
+ "secure.usaepay.com": "production",
8212
+ "sandbox.usaepay.com": "sandbox"
8213
+ });
8214
+ var USAEPAY_PAYMENT_KEYS_PATH = "/api/v2/pub/payment_keys";
8215
+ var BODY_LIMIT45 = 512;
8216
+ var URL_LIMIT18 = 256;
8217
+ var CARD_NUMBER22 = /^[0-9]{13,19}$/;
8218
+ var EXPIRATION2 = /^(?:0[1-9]|1[0-2])[0-9]{2}$/;
8219
+ var SECURITY_CODE26 = /^(?:[0-9]{3,4})?$/;
8220
+ var record38 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
8221
+ var own20 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
8222
+ var refuse46 = (code) => Object.freeze({ verdict: "refuse", code });
8223
+ var CARD45 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
8224
+ function usaepayPaymentKeysUrl(url) {
8225
+ if (typeof url !== "string" || url.length > URL_LIMIT18 || url.includes("?") || url.includes("#"))
8226
+ return null;
8227
+ let parsed;
8228
+ try {
8229
+ parsed = new URL(url);
8230
+ }
8231
+ catch {
8232
+ return null;
8233
+ }
8234
+ if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !own20(USAEPAY_HOSTS, parsed.hostname) || parsed.pathname !== USAEPAY_PAYMENT_KEYS_PATH)
8235
+ return null;
8236
+ return Object.freeze({ host: parsed.hostname, environment: USAEPAY_HOSTS[parsed.hostname] });
8237
+ }
8238
+ var isUsaepayPaymentKeysUrl = (url) => usaepayPaymentKeysUrl(url) !== null;
8239
+ function luhn13(digits3) {
8240
+ let sum = 0;
8241
+ for (let at = digits3.length - 1, double = false; at >= 0; at -= 1, double = !double) {
8242
+ let digit = digits3.charCodeAt(at) - 48;
8243
+ if (double)
8244
+ digit = digit * 2 > 9 ? digit * 2 - 9 : digit * 2;
8245
+ sum += digit;
8246
+ }
8247
+ return sum % 10 === 0;
8248
+ }
8249
+ function readBody28(body) {
8250
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT45)
8251
+ return null;
8252
+ try {
8253
+ const value = JSON.parse(body);
8254
+ return record38(value) && JSON.stringify(value) === body ? value : null;
8255
+ }
8256
+ catch {
8257
+ return null;
8258
+ }
8259
+ }
8260
+ function usaepayBodyVerdict(body) {
8261
+ const value = readBody28(body);
8262
+ const card = value === null ? null : value.creditcard;
8263
+ if (value === null || Object.keys(value).join() !== "creditcard" || !record38(card) || Object.keys(card).join() !== "number,expiration,cvc" || typeof card.number !== "string" || !CARD_NUMBER22.test(card.number) || !luhn13(card.number) || typeof card.expiration !== "string" || !EXPIRATION2.test(card.expiration) || typeof card.cvc !== "string" || !SECURITY_CODE26.test(card.cvc))
8264
+ return refuse46("usaepay_body_unsupported");
8265
+ return CARD45;
8266
+ }
8267
+ var usaepay_default = /* @__PURE__ */ registerProcessor({
8268
+ psp: USAEPAY_PSP,
8269
+ definitions: [
8270
+ {
8271
+ psp: "usaepay",
8272
+ // The frame's card request, as the header above reads it. sandbox.usaepay.com is USAePay's sandbox, pinned to test
8273
+ // rows, which send only USAePay's documented test cards (hostEnvironmentPinned, device-replay.js S7).
8274
+ // Ships dark: served only to a client that declares `usaepay_payment_key`, and only for a company the backend's
8275
+ // processor gate turns USAePay on for. `(?![\w/.%-])` ends the path for a consumer that tests `match` unanchored.
8276
+ capability: "usaepay_payment_key",
8277
+ match: "(?:www|secure|sandbox)\\.usaepay\\.com/api/v2/pub/payment_keys(?![\\w/.%-])",
8278
+ hosts: ["^www\\.usaepay\\.com$", "^secure\\.usaepay\\.com$", "^sandbox\\.usaepay\\.com$"],
8279
+ sandboxHosts: ["^sandbox\\.usaepay\\.com$"],
8280
+ hostEnvironmentPinned: true,
8281
+ encoding: "json",
8282
+ // The frame's Authorization, which carries the merchant's public key. Origin, Referer and cookies never ride.
8283
+ passthroughHeaders: ["^authorization$"],
8284
+ jsonCardFields: [["creditcard", "number"]]
8285
+ }
8286
+ ],
8287
+ // Only the cardholder's device sends this card, after a person approves; no reviewed list names usaepay.
8288
+ refusedOperations: [USAEPAY_OPERATION],
8289
+ // The public key mints a payment key and reads nothing: the merchant's server runs the sale with its private key.
8290
+ settlementReadback: {
8291
+ answer: "none",
8292
+ reason: "tokenization_credential_cannot_read_charges",
8293
+ note: "The tokenization credential cannot read a charge; the shop charges the token later with its own credentials.",
8294
+ source: "https://help.usaepay.info/developer/payjs-v2/ , https://help.usaepay.info/api/rest/"
8295
+ },
8296
+ exactUrl: isUsaepayPaymentKeysUrl,
8297
+ bodyGate: (url, body) => url !== void 0 && !isUsaepayPaymentKeysUrl(url) ? refuse46("usaepay_url_refused") : usaepayBodyVerdict(body)
8298
+ // No amount reader: the request names none, so the agent's pair is the figure the cardholder approves.
8299
+ });
8300
+ // src/processors/viva_wallet.js
8301
+ var VIVA_WALLET_PSP = "viva_wallet";
8302
+ var VIVA_WALLET_OPERATION = "viva_wallet.card_request";
8303
+ var VIVA_WALLET_HOSTS = /* @__PURE__ */ Object.freeze({ "www.vivapayments.com": "production", "demo.vivapayments.com": "sandbox" });
8304
+ var VIVA_WALLET_CHARGE_TOKENS_PATH = "/web2/checkout/v2/chargetokens";
8305
+ var VIVA_WALLET_BODY_KEYS = /* @__PURE__ */ Object.freeze([
8306
+ "orderCode",
8307
+ "amount",
8308
+ "currencyCode",
8309
+ "holderName",
8310
+ "holderMail",
8311
+ "cvc",
8312
+ "number",
8313
+ "expirationMonth",
8314
+ "expirationYear",
8315
+ "installments",
8316
+ "customer",
8317
+ "rememberCard",
8318
+ "friendlyName",
8319
+ "maskedNumber",
8320
+ "bankId",
8321
+ "selectedBrand",
8322
+ "cardholderBrandSelection",
8323
+ "dccOptions",
8324
+ "dccAccepted",
8325
+ "offerCodes",
8326
+ "loyaltySupported",
8327
+ "redeemedAmount",
8328
+ "retrievalReferenceNumber",
8329
+ "scaRequestedTransactionId",
8330
+ "merchantTrns",
8331
+ "captchaToken"
8332
+ ]);
8333
+ var BODY_LIMIT46 = 16384;
8334
+ var URL_LIMIT19 = 256;
8335
+ var ORDER_CODE = /^[0-9]{16}$/;
8336
+ var CARD_NUMBER23 = /^[0-9]{13,19}$/;
8337
+ var MONTH24 = /^(?:0[1-9]|1[0-2])$/;
8338
+ var YEAR25 = /^[0-9]{2}$/;
8339
+ var SECURITY_CODE27 = /^[0-9]{3,4}$/;
8340
+ var CAPTCHA_TOKEN = /^[A-Za-z0-9_.-]{20,8192}$/;
8341
+ var MEMBER_NAME = /^[A-Za-z][A-Za-z0-9]{0,31}$/;
8342
+ var SHORT_ID = /^[A-Za-z0-9_-]{1,64}$/;
8343
+ var TEXT4 = /^[^\u0000-\u001f\u007f]{0,200}$/;
8344
+ var CARD_DIGITS2 = /[0-9]{12,}/;
8345
+ var record39 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
8346
+ var own21 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
8347
+ var refuse47 = (code) => Object.freeze({ verdict: "refuse", code });
8348
+ var CARD46 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
8349
+ var inOrder9 = (value, keys) => {
8350
+ let at = 0;
8351
+ for (const name of Object.keys(value)) {
8352
+ while (at < keys.length && keys[at] !== name)
8353
+ at += 1;
8354
+ if (at === keys.length)
8355
+ return false;
8356
+ at += 1;
8357
+ }
8358
+ return true;
8359
+ };
8360
+ var cardDigits2 = (text10) => CARD_DIGITS2.test(text10.replace(/[^0-9A-Za-z]/g, ""));
8361
+ var plainText8 = (value) => typeof value === "string" && TEXT4.test(value) && !cardDigits2(value);
8362
+ var scalar = (value) => value === null || typeof value === "boolean" || Number.isSafeInteger(value) && Math.abs(value) < 1e9 || plainText8(value);
8363
+ var flatRecord = (value, limit) => record39(value) && Object.keys(value).length <= limit && Object.entries(value).every(([key, item]) => MEMBER_NAME.test(key) && scalar(item));
8364
+ function vivaWalletChargeTokensUrl(url) {
8365
+ if (typeof url !== "string" || url.length > URL_LIMIT19 || url.includes("?") || url.includes("#"))
8366
+ return null;
8367
+ let parsed;
8368
+ try {
8369
+ parsed = new URL(url);
8370
+ }
8371
+ catch {
8372
+ return null;
8373
+ }
8374
+ if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !own21(VIVA_WALLET_HOSTS, parsed.hostname) || parsed.pathname !== VIVA_WALLET_CHARGE_TOKENS_PATH)
8375
+ return null;
8376
+ return Object.freeze({ host: parsed.hostname, environment: VIVA_WALLET_HOSTS[parsed.hostname] });
8377
+ }
8378
+ var isVivaWalletChargeTokensUrl = (url) => vivaWalletChargeTokensUrl(url) !== null;
8379
+ function luhn14(digits3) {
8380
+ let sum = 0;
8381
+ for (let at = digits3.length - 1, double = false; at >= 0; at -= 1, double = !double) {
8382
+ let digit = digits3.charCodeAt(at) - 48;
8383
+ if (double)
8384
+ digit = digit * 2 > 9 ? digit * 2 - 9 : digit * 2;
8385
+ sum += digit;
8386
+ }
8387
+ return sum % 10 === 0;
8388
+ }
8389
+ function vivaWalletMaskedNumber(number) {
8390
+ return `${number.slice(0, 6)}${"X".repeat(Math.max(0, number.length - 10))}${number.slice(-4)}`;
8391
+ }
8392
+ function readBody29(body) {
8393
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT46)
8394
+ return null;
8395
+ try {
8396
+ const value = JSON.parse(body);
8397
+ return record39(value) && JSON.stringify(value) === body ? value : null;
8398
+ }
8399
+ catch {
8400
+ return null;
8401
+ }
8402
+ }
8403
+ function currencyNumber(value) {
8404
+ if (Number.isSafeInteger(value) && value > 0 && value < 1e3)
8405
+ return value;
8406
+ return typeof value === "string" && /^[0-9]{3}$/.test(value) ? Number(value) : null;
8407
+ }
8408
+ function vivaWalletBodyVerdict(body) {
8409
+ const value = readBody29(body);
8410
+ if (value === null || !Object.keys(value).every((key) => VIVA_WALLET_BODY_KEYS.includes(key))) {
8411
+ return value !== null && (own21(value, "creditCardId") || own21(value, "token")) ? refuse47("viva_wallet_stored_card") : refuse47("viva_wallet_body_unsupported");
8412
+ }
8413
+ if (value.rememberCard !== false)
8414
+ return refuse47(value.rememberCard === true ? "viva_wallet_keep_on_file" : "viva_wallet_body_unsupported");
8415
+ if (value.dccAccepted === true)
8416
+ return refuse47("viva_wallet_currency_conversion");
8417
+ if (own21(value, "dccAccepted") && value.dccAccepted !== false)
8418
+ return refuse47("viva_wallet_body_unsupported");
8419
+ if (own21(value, "scaRequestedTransactionId"))
8420
+ return refuse47("viva_wallet_retry_refused");
8421
+ if (!(value.installments === 0 || value.installments === 1)) {
8422
+ return refuse47(Number.isSafeInteger(value.installments) && value.installments > 1 ? "viva_wallet_installments" : "viva_wallet_body_unsupported");
8423
+ }
8424
+ if (!inOrder9(value, VIVA_WALLET_BODY_KEYS) || ["offerCodes", "loyaltySupported", "redeemedAmount", "retrievalReferenceNumber", "merchantTrns"].some((key) => own21(value, key)))
8425
+ return refuse47("viva_wallet_body_unsupported");
8426
+ const number = value.number;
8427
+ const sound = typeof value.orderCode === "string" && ORDER_CODE.test(value.orderCode) && Number.isSafeInteger(value.amount) && value.amount > 0 && currencyNumber(value.currencyCode) !== null && plainText8(value.holderName) && value.holderName.trim() !== "" && plainText8(value.holderMail) && (value.cvc === null || typeof value.cvc === "string" && SECURITY_CODE27.test(value.cvc)) && typeof number === "string" && CARD_NUMBER23.test(number) && luhn14(number) && typeof value.expirationMonth === "string" && MONTH24.test(value.expirationMonth) && typeof value.expirationYear === "string" && YEAR25.test(value.expirationYear) && flatRecord(value.customer, 12) && (!own21(value, "friendlyName") || plainText8(value.friendlyName)) && value.maskedNumber === vivaWalletMaskedNumber(number) && (!own21(value, "bankId") || typeof value.bankId === "string" && SHORT_ID.test(value.bankId) || Number.isSafeInteger(value.bankId) && value.bankId >= 0) && (!own21(value, "selectedBrand") || value.selectedBrand === null || flatRecord(value.selectedBrand, 16)) && (!own21(value, "cardholderBrandSelection") || typeof value.cardholderBrandSelection === "boolean") && (!own21(value, "dccOptions") || flatRecord(value.dccOptions, 16)) && (!own21(value, "captchaToken") || typeof value.captchaToken === "string" && CAPTCHA_TOKEN.test(value.captchaToken));
8428
+ return sound ? CARD46 : refuse47("viva_wallet_body_unsupported");
8429
+ }
8430
+ var VIVA_WALLET_CURRENCIES = /* @__PURE__ */ Object.freeze({
8431
+ 978: "eur",
8432
+ 826: "gbp",
8433
+ 946: "ron",
8434
+ 985: "pln",
8435
+ 203: "czk",
8436
+ 348: "huf",
8437
+ 752: "sek",
8438
+ 208: "dkk"
8439
+ });
8440
+ function vivaWalletAmount(body) {
8441
+ if (vivaWalletBodyVerdict(body).verdict !== "card")
8442
+ return null;
8443
+ const value = JSON.parse(body);
8444
+ const currency = VIVA_WALLET_CURRENCIES[currencyNumber(value.currencyCode)];
8445
+ return currency ? { amountCents: value.amount, currency } : null;
8446
+ }
8447
+ var VIVA_WALLET_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
8448
+ Object.freeze({
8449
+ id: "klimaka_donation",
8450
+ merchant: "Klimaka",
8451
+ tradeName: "ΚΛΙΜΑΚΑ ΑΜΚΕ",
8452
+ orderCodes: Object.freeze(["7871752880772607"]),
8453
+ origin: "https://www.vivapayments.com",
8454
+ currencyCode: 978
8455
+ }),
8456
+ Object.freeze({
8457
+ id: "desmos_donation",
8458
+ merchant: "Desmos",
8459
+ tradeName: "DESMOS",
8460
+ orderCodes: Object.freeze(["8156257435672606"]),
8461
+ origin: "https://www.vivapayments.com",
8462
+ currencyCode: 978
8463
+ })
8464
+ ]);
8465
+ var CARD_MEMBERS = Object.freeze(["cvc", "number", "expirationMonth", "expirationYear", "maskedNumber"]);
8466
+ var viva_wallet_default = /* @__PURE__ */ registerProcessor({
8467
+ psp: VIVA_WALLET_PSP,
8468
+ definitions: [
8469
+ {
8470
+ psp: "viva_wallet",
8471
+ // The page's card request, as the header above reads it. demo.vivapayments.com is Viva's sandbox, pinned to test
8472
+ // rows, which send only Viva's documented test cards (hostEnvironmentPinned, device-replay.js S7).
8473
+ // Ships dark: served only to a client that declares `viva_smart_checkout_chargetoken`, and only for a company the
8474
+ // backend's processor gate turns Viva Wallet on for. `(?![\w/.%-])` ends the path for a consumer that tests `match`
8475
+ // unanchored.
8476
+ capability: "viva_smart_checkout_chargetoken",
8477
+ match: "(?:www|demo)\\.vivapayments\\.com/web2/checkout/v2/chargetokens(?![\\w/.%-])",
8478
+ hosts: ["^www\\.vivapayments\\.com$", "^demo\\.vivapayments\\.com$"],
8479
+ sandboxHosts: ["^demo\\.vivapayments\\.com$"],
8480
+ hostEnvironmentPinned: true,
8481
+ encoding: "json",
8482
+ // The page sends no Authorization; Origin, Referer, cookies and the reCAPTCHA state never ride.
8483
+ passthroughHeaders: [],
8484
+ jsonCardFields: [["number"]]
8485
+ }
8486
+ ],
8487
+ // Only the cardholder's device sends this card, after a person approves; no reviewed list names viva_wallet.
8488
+ refusedOperations: [VIVA_WALLET_OPERATION],
8489
+ settlementReadback: "not_surveyed",
8490
+ exactUrl: isVivaWalletChargeTokensUrl,
8491
+ bodyGate: (url, body) => url !== void 0 && !isVivaWalletChargeTokensUrl(url) ? refuse47("viva_wallet_url_refused") : vivaWalletBodyVerdict(body),
8492
+ // The body names the order's amount in cents and its numeric currency, which the page's card-free charge repeats.
8493
+ amount: (template) => record39(template) && isVivaWalletChargeTokensUrl(template.url) ? vivaWalletAmount(template.body) : null
8494
+ });
8495
+ // src/processors/vtex_payments.js
8496
+ var VTEX_PAYMENTS_PSP = "vtex_payments";
8497
+ var VTEX_PAYMENTS_OPERATION = "vtex_payments.card_request";
8498
+ var VTEX_PAYMENTS_FALLBACK_HOST = "api.vtexvault.com";
8499
+ var VTEX_PAYMENTS_LINE_KEYS = /* @__PURE__ */ Object.freeze([
8500
+ "currencyCode",
8501
+ "paymentSystem",
8502
+ "accountId",
8503
+ "value",
8504
+ "referenceValue",
8505
+ "installments",
8506
+ "installmentsInterestRate",
8507
+ "installmentsValue",
8508
+ "groupName",
8509
+ "fields",
8510
+ "transaction",
8511
+ "id"
8512
+ ]);
8513
+ var VTEX_PAYMENTS_FIELD_KEYS = /* @__PURE__ */ Object.freeze([
8514
+ "address",
8515
+ "accountId",
8516
+ "validationCode",
8517
+ "metadata",
8518
+ "document",
8519
+ "holderName",
8520
+ "cardNumber",
8521
+ "dueDate",
8522
+ "deviceFingerprint",
8523
+ "addressId"
8524
+ ]);
8525
+ var VTEX_PAYMENTS_ADDRESS_KEYS = /* @__PURE__ */ Object.freeze([
8526
+ "street",
8527
+ "complement",
8528
+ "number",
8529
+ "city",
8530
+ "reference",
8531
+ "addressType",
8532
+ "neighborhood",
8533
+ "addressId",
8534
+ "state",
8535
+ "country",
8536
+ "postalCode"
8537
+ ]);
8538
+ var VTEX_PAYMENTS_NETWORKS = /* @__PURE__ */ Object.freeze({ 1: "amex", 2: "visa", 4: "mastercard", 5: "discover" });
8539
+ var VTEX_PAYMENTS_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
8540
+ Object.freeze({ account: "alssports", origin: "https://www.als.com", merchant: "Al's Sporting Goods", currency: "USD" }),
8541
+ Object.freeze({ account: "roadrunnersports", origin: "https://www.roadrunnersports.com", merchant: "Road Runner Sports", currency: "USD" })
8542
+ ]);
8543
+ var BODY_LIMIT47 = 16384;
8544
+ var ACCOUNT_HOST = /^([a-z0-9]{1,63})\.vtexvault\.com$/;
8545
+ var PATH = /^\/api\/payments\/transactions\/([0-9A-Fa-f]{32})\/payments$/;
8546
+ var ORDER_GROUP = /^[0-9]{6,24}$/;
8547
+ var BASE648 = /^[A-Za-z0-9+/]{4,1020}={0,2}$/;
8548
+ var CARD_NUMBER24 = /^[0-9]{12,19}$/;
8549
+ var SECURITY_CODE28 = /^[0-9]{3,4}$/;
8550
+ var DUE_DATE = /^(?:0[1-9]|1[0-2])\/[0-9]{2}$/;
8551
+ var CURRENCY6 = /^[A-Z]{3}$/;
8552
+ var TRANSACTION_ID = /^[0-9A-Fa-f]{32}$/;
8553
+ var MERCHANT_NAME = /^[A-Za-z0-9_.-]{1,64}$/;
8554
+ var SHORT_ID2 = /^[A-Za-z0-9_-]{1,64}$/;
8555
+ var FINGERPRINT4 = /^[A-Za-z0-9_.:=+/-]{1,256}$/;
8556
+ var TEXT5 = /^[^\u0000-\u001f\u007f]{1,200}$/;
8557
+ var CARD_DIGITS3 = /[0-9]{12,}/;
8558
+ var DEVICE_INFO_KEYS = Object.freeze(["sw", "sh", "cd", "tz", "lang", "java", "sourceApplication"]);
8559
+ var record40 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
8560
+ var own22 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
8561
+ var refuse48 = (code) => Object.freeze({ verdict: "refuse", code });
8562
+ var CARD47 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
8563
+ var inOrder10 = (value, keys) => {
8564
+ let at = 0;
8565
+ for (const name of Object.keys(value)) {
8566
+ while (at < keys.length && keys[at] !== name)
8567
+ at += 1;
8568
+ if (at === keys.length)
8569
+ return false;
8570
+ at += 1;
8571
+ }
8572
+ return true;
8573
+ };
8574
+ var cardDigits3 = (text10) => CARD_DIGITS3.test(text10.replace(/[^0-9A-Za-z]/g, ""));
8575
+ var plainText9 = (value) => typeof value === "string" && TEXT5.test(value) && !cardDigits3(value);
8576
+ var count = (value) => Number.isSafeInteger(value) && value >= 0;
8577
+ var BASE64_ALPHABET2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
8578
+ function base64Text2(input) {
8579
+ if (input.length % 4 !== 0)
8580
+ return null;
8581
+ const stripped = input.replace(/={1,2}$/, "");
8582
+ let out = "";
8583
+ let bits = 0;
8584
+ let value = 0;
8585
+ for (const character of stripped) {
8586
+ const sextet = BASE64_ALPHABET2.indexOf(character);
8587
+ if (sextet < 0)
8588
+ return null;
8589
+ value = value << 6 | sextet;
8590
+ bits += 6;
8591
+ if (bits >= 8) {
8592
+ bits -= 8;
8593
+ out += String.fromCharCode(value >> bits & 255);
8594
+ value &= (1 << bits) - 1;
8595
+ }
8596
+ }
8597
+ return out;
8598
+ }
8599
+ function deviceInfoSound(text10) {
8600
+ if (typeof text10 !== "string" || !BASE648.test(text10))
8601
+ return false;
8602
+ const decoded = base64Text2(text10);
8603
+ if (decoded === null)
8604
+ return false;
8605
+ let info;
8606
+ try {
8607
+ info = JSON.parse(decoded);
8608
+ }
8609
+ catch {
8610
+ return false;
8611
+ }
8612
+ if (!record40(info) || !Object.keys(info).every((key) => DEVICE_INFO_KEYS.includes(key)))
8613
+ return false;
8614
+ for (const key of ["sw", "sh", "cd"])
8615
+ if (own22(info, key) && !(count(info[key]) && info[key] <= 1e5))
8616
+ return false;
8617
+ if (own22(info, "tz") && !(Number.isSafeInteger(info.tz) && Math.abs(info.tz) <= 1440))
8618
+ return false;
8619
+ if (own22(info, "lang") && !(typeof info.lang === "string" && /^[A-Za-z]{0,8}$/.test(info.lang)))
8620
+ return false;
8621
+ if (own22(info, "java") && typeof info.java !== "boolean")
8622
+ return false;
8623
+ return !own22(info, "sourceApplication") || typeof info.sourceApplication === "string" && /^[A-Za-z0-9_.-]{1,32}$/.test(info.sourceApplication);
8624
+ }
8625
+ function vtexPaymentsCardTarget(url) {
8626
+ if (typeof url !== "string" || url.length > 8192)
8627
+ return null;
8628
+ let parsed;
8629
+ try {
8630
+ parsed = new URL(url);
8631
+ }
8632
+ catch {
8633
+ return null;
8634
+ }
8635
+ if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || parsed.hash)
8636
+ return null;
8637
+ const path = PATH.exec(parsed.pathname);
8638
+ const host = ACCOUNT_HOST.exec(parsed.hostname);
8639
+ if (!path || !host)
8640
+ return null;
8641
+ const fallback = parsed.hostname === VTEX_PAYMENTS_FALLBACK_HOST;
8642
+ const names = [...parsed.searchParams.keys()];
8643
+ const expected = ["orderId", "deviceInfo", ...parsed.searchParams.has("callbackUrl") ? ["callbackUrl"] : [], ...fallback ? ["an"] : []];
8644
+ if (names.length !== expected.length || names.some((name, i) => name !== expected[i]))
8645
+ return null;
8646
+ const orderId = parsed.searchParams.get("orderId");
8647
+ if (!ORDER_GROUP.test(orderId) || !deviceInfoSound(parsed.searchParams.get("deviceInfo")))
8648
+ return null;
8649
+ if (parsed.searchParams.has("callbackUrl")) {
8650
+ let callback;
8651
+ try {
8652
+ callback = new URL(parsed.searchParams.get("callbackUrl"));
8653
+ }
8654
+ catch {
8655
+ return null;
8656
+ }
8657
+ if (callback.protocol !== "https:" || callback.username || callback.password || callback.searchParams.get("step") !== "payment" || callback.searchParams.get("og") !== orderId)
8658
+ return null;
8659
+ }
8660
+ const account = fallback ? parsed.searchParams.get("an") : host[1];
8661
+ if (!/^[a-z0-9]{1,63}$/.test(account) || account === "api")
8662
+ return null;
8663
+ return Object.freeze({ account, transactionId: path[1], orderId, fallback });
8664
+ }
8665
+ function isVtexPaymentsCardUrl(url) {
8666
+ const target = vtexPaymentsCardTarget(url);
8667
+ return target !== null && !target.fallback;
8668
+ }
8669
+ function readBody30(body) {
8670
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT47)
8671
+ return null;
8672
+ let value;
8673
+ try {
8674
+ value = JSON.parse(body);
8675
+ if (!Array.isArray(value) || JSON.stringify(value) !== body)
8676
+ return null;
8677
+ }
8678
+ catch {
8679
+ return null;
8680
+ }
8681
+ return value;
8682
+ }
8683
+ function cardLine(line) {
8684
+ if (!record40(line))
8685
+ return false;
8686
+ const fields = record40(line.fields) ? line.fields : {};
8687
+ return line.groupName === "creditCardPaymentGroup" || line.groupName === "debitCardPaymentGroup" || own22(line, "accountId") || own22(fields, "accountId") || own22(fields, "cardNumber") || own22(fields, "validationCode") || own22(fields, "dueDate");
8688
+ }
8689
+ function addressSound(address2) {
8690
+ if (!record40(address2) || !inOrder10(address2, VTEX_PAYMENTS_ADDRESS_KEYS))
8691
+ return false;
8692
+ for (const [key, value] of Object.entries(address2)) {
8693
+ if (key === "addressType") {
8694
+ if (value !== "billing")
8695
+ return false;
8696
+ continue;
8697
+ }
8698
+ if (key === "addressId") {
8699
+ if (!(typeof value === "string" && SHORT_ID2.test(value)))
8700
+ return false;
8701
+ continue;
8702
+ }
8703
+ if (value === null && (key === "complement" || key === "reference"))
8704
+ continue;
8705
+ if (!(value === "" || plainText9(value)))
8706
+ return false;
8707
+ }
8708
+ return true;
8709
+ }
8710
+ function fieldsSound(fields) {
8711
+ if (!record40(fields) || !inOrder10(fields, VTEX_PAYMENTS_FIELD_KEYS) || own22(fields, "metadata"))
8712
+ return false;
8713
+ if (!(typeof fields.cardNumber === "string" && CARD_NUMBER24.test(fields.cardNumber)))
8714
+ return false;
8715
+ if (!(typeof fields.validationCode === "string" && SECURITY_CODE28.test(fields.validationCode)))
8716
+ return false;
8717
+ if (!(typeof fields.dueDate === "string" && DUE_DATE.test(fields.dueDate)))
8718
+ return false;
8719
+ if (!plainText9(fields.holderName))
8720
+ return false;
8721
+ if (own22(fields, "document") && !(fields.document === "" || plainText9(fields.document) && fields.document.length <= 32))
8722
+ return false;
8723
+ if (own22(fields, "address") && !addressSound(fields.address))
8724
+ return false;
8725
+ if (own22(fields, "deviceFingerprint") && !(typeof fields.deviceFingerprint === "string" && FINGERPRINT4.test(fields.deviceFingerprint)))
8726
+ return false;
8727
+ return !own22(fields, "addressId") || typeof fields.addressId === "string" && SHORT_ID2.test(fields.addressId);
8728
+ }
8729
+ function vtexPaymentsBodyVerdict(body, target) {
8730
+ const lines = readBody30(body);
8731
+ if (lines === null || lines.length === 0 || !lines.every(record40))
8732
+ return refuse48("vtex_payments_body_unsupported");
8733
+ const cards = lines.filter(cardLine);
8734
+ if (cards.some((line2) => own22(line2, "accountId") || own22(line2.fields ?? {}, "accountId")))
8735
+ return refuse48("vtex_payments_saved_card");
8736
+ if (cards.length === 0)
8737
+ return refuse48("vtex_payments_body_unsupported");
8738
+ if (lines.length !== 1 || own22(lines[0], "id"))
8739
+ return refuse48("vtex_payments_split_payment");
8740
+ const line = lines[0];
8741
+ if (!inOrder10(line, VTEX_PAYMENTS_LINE_KEYS) || line.groupName !== "creditCardPaymentGroup")
8742
+ return refuse48("vtex_payments_body_unsupported");
8743
+ if (!(typeof line.currencyCode === "string" && CURRENCY6.test(line.currencyCode)) || !own22(VTEX_PAYMENTS_NETWORKS, line.paymentSystem) || !Number.isSafeInteger(line.paymentSystem) || !(count(line.value) && line.value > 0))
8744
+ return refuse48("vtex_payments_body_unsupported");
8745
+ if (line.installments !== 1 || line.referenceValue !== line.value || own22(line, "installmentsInterestRate") && line.installmentsInterestRate !== 0 || own22(line, "installmentsValue") && line.installmentsValue !== line.value)
8746
+ return refuse48("vtex_payments_installments");
8747
+ const transaction = line.transaction;
8748
+ if (!record40(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)))
8749
+ return refuse48("vtex_payments_body_unsupported");
8750
+ if (target && transaction.id.toUpperCase() !== target.transactionId.toUpperCase())
8751
+ return refuse48("vtex_payments_split_payment");
8752
+ return fieldsSound(line.fields) ? CARD47 : refuse48("vtex_payments_body_unsupported");
8753
+ }
8754
+ function vtexPaymentsAmount(body) {
8755
+ if (vtexPaymentsBodyVerdict(body).verdict !== "card")
8756
+ return null;
8757
+ const [line] = JSON.parse(body);
8758
+ return { amountCents: line.value, currency: line.currencyCode.toLowerCase() };
8759
+ }
8760
+ var NETWORK_OF = Object.freeze({
8761
+ visa: (number) => /^4[0-9]{12}(?:[0-9]{3}){0,2}$/.test(number),
8762
+ 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),
8763
+ amex: (number) => /^3[47][0-9]{13}$/.test(number),
8764
+ discover: (number) => /^(?:6011[0-9]{12}|64[4-9][0-9]{13}|65[0-9]{14})$/.test(number)
8765
+ });
8766
+ var NETWORK_NAME = Object.freeze({ visa: "Visa", mastercard: "Mastercard", amex: "American Express", discover: "Discover" });
8767
+ var vtex_payments_default = /* @__PURE__ */ registerProcessor({
8768
+ psp: VTEX_PAYMENTS_PSP,
8769
+ definitions: [
8770
+ {
8771
+ psp: "vtex_payments",
8772
+ // Ollie's card post to a VTEX account's own vault, as the header above reads it, and the fallback host, which
8773
+ // the gate recognizes only to refuse, so the agent's placeholder never reaches it either. VTEX has no test host:
8774
+ // every request is live. Prepared only: Ollie gives the post 12 seconds. Ships dark: served only to a client that
8775
+ // declares `vtex_payments_card_payment`, on for Agentcard's own company alone (backend
8776
+ // checkout-processor-gate.ts), and autopilot never sends it.
8777
+ capability: "vtex_payments_card_payment",
8778
+ match: "[a-z0-9-]{1,63}\\.vtexvault\\.com/api/payments/transactions/[A-Za-z0-9-]{1,64}/payments(?![\\w/.%-])",
8779
+ hosts: ["^[a-z0-9-]{1,63}\\.vtexvault\\.com$"],
8780
+ preparationRequired: true,
8781
+ encoding: "json",
8782
+ // Ollie's fetch sets the JSON content type alone. Origin, Referer and cookies never ride.
8783
+ passthroughHeaders: [],
8784
+ jsonCardFields: [[0, "fields", "cardNumber"]]
8785
+ }
8786
+ ],
8787
+ // Only the cardholder's device sends it, after a person approves; no reviewed list names vtex_payments.
8788
+ refusedOperations: [VTEX_PAYMENTS_OPERATION],
8789
+ // Not surveyed: VTEX names a payment's end only to the store's own API keys and at the gatewayCallback that follows.
8790
+ settlementReadback: "not_surveyed",
8791
+ exactUrl: isVtexPaymentsCardUrl,
8792
+ bodyGate: (url, body) => {
8793
+ if (url === void 0)
8794
+ return vtexPaymentsBodyVerdict(body);
8795
+ const target = vtexPaymentsCardTarget(url);
8796
+ if (target === null)
8797
+ return refuse48("vtex_payments_url_refused");
8798
+ return target.fallback ? refuse48("vtex_payments_fallback_refused") : vtexPaymentsBodyVerdict(body, target);
8799
+ },
8800
+ amount: (template) => record40(template) && isVtexPaymentsCardUrl(template.url) ? vtexPaymentsAmount(template.body) : null
8801
+ });
8802
+ // src/processors/index.generated.js
8803
+ var REGISTERED_MODULES = Object.freeze({
8804
+ aurus: aurus_default,
8805
+ bluesnap: bluesnap_default,
8806
+ cardlink_vpos: cardlink_vpos_default,
8807
+ eghl: eghl_default,
8808
+ frisbii: frisbii_default,
8809
+ iyzico: iyzico_default,
8810
+ midtrans: midtrans_default,
8811
+ monei: monei_default,
8812
+ oceanpayment: oceanpayment_default,
8813
+ paymentwall: paymentwall_default,
8814
+ payplug: payplug_default,
8815
+ paystack: paystack_default,
8816
+ processout: processout_default,
8817
+ usaepay: usaepay_default,
8818
+ viva_wallet: viva_wallet_default,
8819
+ vtex_payments: vtex_payments_default
8820
+ });
8821
+ // src/registry.js
8822
+ var REGISTERED_PROCESSORS = Object.values(REGISTERED_MODULES);
8823
+ var ids = REGISTERED_PROCESSORS.map((processor) => processor.psp);
8824
+ var problems = REGISTERED_PROCESSORS.flatMap(registrationProblems);
8825
+ for (const [name, processor] of Object.entries(REGISTERED_MODULES)) {
8826
+ if (processor.psp !== name)
8827
+ problems.push(`processors/${name}.js registers ${JSON.stringify(processor.psp)}`);
8828
+ }
8829
+ if (ids.some((id, i) => i > 0 && ids[i - 1] >= id))
8830
+ problems.push(`registered processors out of id order: ${ids.join(", ")}`);
8831
+ if (problems.length)
8832
+ throw new Error(`payment-core registry refused: ${problems.join("; ")}`);
8833
+ var BY_PSP = new Map(REGISTERED_PROCESSORS.map((processor) => [processor.psp, processor]));
8834
+ var REGISTERED_IDS = Object.freeze(ids);
8835
+ var REGISTERED_DEFINITIONS = Object.freeze(REGISTERED_PROCESSORS.flatMap((processor) => processor.definitions));
8836
+ var REGISTERED_REFUSED_OPERATIONS = Object.freeze(REGISTERED_PROCESSORS.flatMap((processor) => processor.refusedOperations ?? []));
8837
+ var REGISTERED_SETTLEMENT_READBACK = Object.freeze(REGISTERED_PROCESSORS.filter((processor) => processor.settlementReadback !== void 0).map((processor) => [processor.psp, processor.settlementReadback]));
8838
+ function registeredRule(psp, name) {
8839
+ return typeof psp === "string" ? BY_PSP.get(psp)?.[name] : void 0;
8840
+ }
8841
+ // src/card-fields.js
8842
+ function processorGate(recognizer, url, body) {
8843
+ if (recognizer && recognizer.psp === LYRA_PSP)
8844
+ return lyraBodyVerdict(body, url);
8845
+ if (recognizer && recognizer.psp === WIX_PAYMENTS_PSP) {
8846
+ if (url !== void 0 && !isWixPaymentsTokenizeUrl(url))
8847
+ return { verdict: "refuse", code: "wix_payments_url_refused" };
8848
+ return wixPaymentsBodyVerdict(body);
8849
+ }
8850
+ if (recognizer && recognizer.psp === KOMOJU_PSP)
8851
+ return komojuBodyVerdict(body, url);
8852
+ if (recognizer && recognizer.psp === HIPAY_PSP) {
8853
+ if (url !== void 0 && !isHipayTokenUrl(url))
8854
+ return { verdict: "refuse", code: "hipay_url_refused" };
8855
+ return hipayBodyVerdict(body);
8856
+ }
8857
+ if (recognizer && recognizer.psp === PAYPAL_PSP) {
8858
+ if (url !== void 0 && !isPaypalConfirmUrl(url))
8859
+ return { verdict: "refuse", code: "paypal_url_refused" };
8860
+ return paypalBodyVerdict(body);
8861
+ }
8862
+ if (recognizer && recognizer.psp === MAKECOMMERCE_PSP)
8863
+ return makecommerceBodyVerdict(body, url);
8864
+ if (recognizer && recognizer.psp === OPENPAY_PSP)
8865
+ return openpayBodyVerdict(body, url);
8866
+ if (recognizer && recognizer.psp === POYNT_PSP) {
8867
+ if (url !== void 0 && !isPoyntNonceUrl(url))
8868
+ return { verdict: "refuse", code: "poynt_url_refused" };
8869
+ return poyntBodyVerdict(body);
8870
+ }
8871
+ if (recognizer && recognizer.psp === CARDCOM_PSP)
8872
+ return cardcomBodyVerdict(body, url);
8873
+ if (recognizer && recognizer.psp === TOAST_PSP) {
8874
+ if (url !== void 0 && !isToastPaymentMethodsUrl(url))
8875
+ return { verdict: "refuse", code: "toast_url_refused" };
8876
+ return toastBodyVerdict(body);
8877
+ }
8878
+ if (recognizer && recognizer.psp === PAYU_LATAM_PSP)
8879
+ return payuLatamBodyVerdict(body, url);
8880
+ if (recognizer && recognizer.psp === PADDLE_VGS_PSP) {
8881
+ if (url !== void 0 && !isPaddleVgsCardsUrl(url))
8882
+ return { verdict: "refuse", code: "paddle_vgs_url_refused" };
8883
+ return paddleVgsBodyVerdict(body);
8884
+ }
8885
+ if (recognizer && recognizer.psp === PAYFAST_PSP) {
8886
+ if (url !== void 0 && !isPayfastPayUrl(url))
8887
+ return { verdict: "refuse", code: "payfast_url_refused" };
8888
+ return payfastBodyVerdict(body);
8889
+ }
8890
+ if (recognizer && recognizer.psp === PAYREXX_PSP) {
8891
+ return url !== void 0 ? payrexxGateVerdict(url, body) : payrexxBodyVerdict(body);
8892
+ }
8893
+ if (recognizer && recognizer.psp === PAYGENT_PSP) {
8894
+ return url !== void 0 ? paygentRequestVerdict(url, body) : paygentBodyVerdict(body);
8895
+ }
8896
+ if (recognizer && recognizer.psp === PAY_NL_PSP) {
8897
+ if (url !== void 0 && !isPayNlTokenUrl(url))
6298
8898
  return { verdict: "refuse", code: "pay_nl_url_refused" };
6299
8899
  return payNlBodyVerdict(body);
6300
8900
  }
@@ -6404,7 +9004,7 @@ function carriesCardFields(recognizer, body) {
6404
9004
  if (typeof body !== "string" || body === "")
6405
9005
  return false;
6406
9006
  const anyCase = recognizer.caseInsensitiveFormKeys === true;
6407
- const wanted = anyCase ? fields.map((field2) => String(field2).toLowerCase()) : fields;
9007
+ const wanted = anyCase ? fields.map((field5) => String(field5).toLowerCase()) : fields;
6408
9008
  for (const chunk of body.split("&")) {
6409
9009
  const eq = chunk.indexOf("=");
6410
9010
  if (eq <= 0 || eq === chunk.length - 1)
@@ -6484,15 +9084,28 @@ function namesCardNumber(root, declared) {
6484
9084
  }
6485
9085
  function splitCardLeg(recognizer, body) {
6486
9086
  const split = recognizer && recognizer.splitCard;
6487
- if (!split || typeof split !== "object" || recognizer.encoding !== "form")
9087
+ if (!split || typeof split !== "object" || typeof body !== "string" || body === "")
9088
+ return null;
9089
+ const gate = processorGate(recognizer, void 0, body);
9090
+ if (gate !== null ? gate.verdict !== "continue" : carriesCardFields(recognizer, body))
6488
9091
  return null;
6489
- if (typeof body !== "string" || body === "" || carriesCardFields(recognizer, body))
9092
+ const keys = recognizer.encoding === "form" ? formKeys(body) : recognizer.encoding === "json" ? jsonKeys(body) : null;
9093
+ if (keys === null)
6490
9094
  return null;
6491
9095
  const list = (value) => Array.isArray(value) ? value.filter((key) => typeof key === "string" && key !== "") : [];
6492
9096
  const absorb = list(split.absorb);
6493
9097
  const pass = list(split.pass);
6494
9098
  const sibling = list(split.siblingKeys);
6495
- const own13 = [];
9099
+ const own23 = keys.filter((key) => !sibling.includes(key));
9100
+ if (own23.length === 0)
9101
+ return null;
9102
+ if (own23.every((key) => absorb.includes(key)))
9103
+ return "absorb";
9104
+ if (own23.every((key) => pass.includes(key)))
9105
+ return "pass";
9106
+ return null;
9107
+ }
9108
+ function formKeys(body) {
6496
9109
  const seen = /* @__PURE__ */ new Set();
6497
9110
  for (const chunk of body.split("&")) {
6498
9111
  const eq = chunk.indexOf("=");
@@ -6508,16 +9121,18 @@ function splitCardLeg(recognizer, body) {
6508
9121
  if (seen.has(key))
6509
9122
  return null;
6510
9123
  seen.add(key);
6511
- if (!sibling.includes(key))
6512
- own13.push(key);
6513
9124
  }
6514
- if (own13.length === 0)
9125
+ return [...seen];
9126
+ }
9127
+ function jsonKeys(body) {
9128
+ let parsed;
9129
+ try {
9130
+ parsed = JSON.parse(body);
9131
+ }
9132
+ catch {
6515
9133
  return null;
6516
- if (own13.every((key) => absorb.includes(key)))
6517
- return "absorb";
6518
- if (own13.every((key) => pass.includes(key)))
6519
- return "pass";
6520
- return null;
9134
+ }
9135
+ return isPlainObject(parsed) && JSON.stringify(parsed) === body ? Object.keys(parsed) : null;
6521
9136
  }
6522
9137
  function requestWithoutCard(recognizer, url, body) {
6523
9138
  const gate = processorGate(recognizer, url, body);