@agent-cards/sdk 0.21.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/CHANGELOG.md +87 -2
  2. package/PREFLIGHT.md +32 -0
  3. package/README.md +1177 -23
  4. package/dist/aci.d.ts +173 -0
  5. package/dist/aci.generated.d.ts +87 -0
  6. package/dist/aci.generated.js +306 -0
  7. package/dist/aci.js +371 -0
  8. package/dist/adyen-merchant-hosted.generated.d.ts +3 -3
  9. package/dist/adyen-merchant-hosted.generated.js +302 -56
  10. package/dist/agentcard.d.ts +9 -2
  11. package/dist/agentcard.js +4 -2
  12. package/dist/amadeus-checkout.generated.d.ts +57 -0
  13. package/dist/amadeus-checkout.generated.js +549 -0
  14. package/dist/amadeus.d.ts +41 -0
  15. package/dist/amadeus.js +81 -0
  16. package/dist/builtin-registry.generated.js +1 -1
  17. package/dist/card-endpoint-facts.d.ts +96 -0
  18. package/dist/card-endpoint-facts.js +275 -0
  19. package/dist/card-endpoint-page.d.ts +54 -0
  20. package/dist/card-endpoint-page.js +69 -0
  21. package/dist/card-endpoint.d.ts +298 -0
  22. package/dist/card-endpoint.js +438 -0
  23. package/dist/card-fields.generated.d.ts +5 -3
  24. package/dist/card-fields.generated.js +284 -7
  25. package/dist/cdp.d.ts +5 -1
  26. package/dist/cdp.js +1155 -141
  27. package/dist/client.d.ts +456 -20
  28. package/dist/client.js +1072 -104
  29. package/dist/creditguard.generated.d.ts +79 -0
  30. package/dist/creditguard.generated.js +662 -0
  31. package/dist/cse-body.js +11 -1
  32. package/dist/cybersource-flex.d.ts +30 -0
  33. package/dist/cybersource-flex.generated.d.ts +27 -1
  34. package/dist/cybersource-flex.generated.js +42 -2
  35. package/dist/cybersource-flex.js +46 -0
  36. package/dist/datatrans.d.ts +96 -0
  37. package/dist/datatrans.generated.d.ts +64 -0
  38. package/dist/datatrans.generated.js +426 -0
  39. package/dist/datatrans.js +178 -0
  40. package/dist/ekashu.d.ts +35 -0
  41. package/dist/ekashu.js +55 -0
  42. package/dist/elavon-converge.d.ts +37 -0
  43. package/dist/elavon-converge.generated.d.ts +49 -0
  44. package/dist/elavon-converge.generated.js +439 -0
  45. package/dist/elavon-converge.js +84 -0
  46. package/dist/eprotect.d.ts +152 -0
  47. package/dist/eprotect.generated.d.ts +77 -0
  48. package/dist/eprotect.generated.js +498 -0
  49. package/dist/eprotect.js +222 -0
  50. package/dist/hosted-form.d.ts +3 -2
  51. package/dist/hosted-form.js +3 -2
  52. package/dist/index.d.ts +17 -3
  53. package/dist/index.js +6 -1
  54. package/dist/juspay-gate.d.ts +82 -0
  55. package/dist/juspay-gate.js +126 -0
  56. package/dist/juspay.generated.d.ts +89 -0
  57. package/dist/juspay.generated.js +705 -0
  58. package/dist/lifecycle.d.ts +60 -6
  59. package/dist/lifecycle.js +122 -8
  60. package/dist/merchant-card-endpoints.generated.d.ts +122 -0
  61. package/dist/merchant-card-endpoints.generated.js +4261 -0
  62. package/dist/merchant-hosted.d.ts +4 -1
  63. package/dist/merchant-hosted.js +5 -2
  64. package/dist/merchant-session-probe.d.ts +48 -0
  65. package/dist/merchant-session-probe.js +53 -0
  66. package/dist/merchant-session.generated.d.ts +69 -0
  67. package/dist/merchant-session.generated.js +919 -0
  68. package/dist/payrails.d.ts +133 -0
  69. package/dist/payrails.generated.d.ts +73 -0
  70. package/dist/payrails.generated.js +596 -0
  71. package/dist/payrails.js +305 -0
  72. package/dist/pelecard.d.ts +32 -0
  73. package/dist/pelecard.generated.d.ts +32 -0
  74. package/dist/pelecard.generated.js +283 -0
  75. package/dist/pelecard.js +42 -0
  76. package/dist/pre-claim.d.ts +81 -2
  77. package/dist/pre-claim.js +1023 -5
  78. package/dist/preflight-catalog.json +2267 -288
  79. package/dist/preflight-schemas.json +183 -6
  80. package/dist/preflight.generated.d.ts +1 -1
  81. package/dist/preflight.generated.js +243 -4
  82. package/dist/preparation.d.ts +12 -3
  83. package/dist/preparation.js +63 -12
  84. package/dist/prepared-processor.d.ts +84 -5
  85. package/dist/prepared-processor.js +147 -6
  86. package/dist/primer.d.ts +53 -0
  87. package/dist/primer.generated.d.ts +38 -0
  88. package/dist/primer.generated.js +624 -0
  89. package/dist/primer.js +82 -0
  90. package/dist/registry.d.ts +100 -8
  91. package/dist/registry.js +85 -11
  92. package/dist/shiji-sts.d.ts +144 -0
  93. package/dist/shiji-sts.generated.d.ts +72 -0
  94. package/dist/shiji-sts.generated.js +913 -0
  95. package/dist/shiji-sts.js +222 -0
  96. package/dist/stripe-checkout.generated.d.ts +1 -1
  97. package/dist/stripe-checkout.generated.js +764 -9
  98. package/dist/stripe-setup.d.ts +16 -0
  99. package/dist/stripe-setup.js +61 -0
  100. package/dist/substitutions.generated.js +187 -29
  101. package/dist/verifone.d.ts +68 -0
  102. package/dist/verifone.generated.d.ts +51 -0
  103. package/dist/verifone.generated.js +1413 -0
  104. package/dist/verifone.js +119 -0
  105. package/dist/voice-types.d.ts +27 -0
  106. package/dist/voice.d.ts +6 -1
  107. package/dist/voice.js +6 -1
  108. package/dist/wspay.d.ts +41 -0
  109. package/dist/wspay.generated.d.ts +41 -0
  110. package/dist/wspay.generated.js +370 -0
  111. package/dist/wspay.js +65 -0
  112. package/examples/preflight/kernel-native/inventory.json +1 -1
  113. package/package.json +3 -3
@@ -1,6 +1,6 @@
1
1
  // @ts-nocheck
2
2
  // Generated from @agent-cards/payment-core. Do not edit.
3
- // artifact-sha256: 26a574d3944a8fbf0c12ddc9378d2ae3772bd2cdc78f95a5db1b61c037ee5474
3
+ // artifact-sha256: 2a58cd64ab81d468d022c21c6f4d6be6e5be4cd29acd1ad8576b549981433afa
4
4
  // src/deep-freeze.js
5
5
  function deepFreeze(value) {
6
6
  if (value && typeof value === "object" && !Object.isFrozen(value)) {
@@ -180,6 +180,70 @@ var PROCESSOR_DEFINITIONS = deepFreeze([
180
180
  callbackUrls: ["success_url_address", "fail_url_address", "notify_url_address"]
181
181
  }
182
182
  },
183
+ {
184
+ psp: "ekashu",
185
+ // NMI Hosted Payment Page (formerly eKashu, the Creditcall gateway): the card page
186
+ // London Luton's drop-off charge, and APCOA's other airport tenants, send the driver to.
187
+ // The merchant's page posts an ENTRY form top-level to live.ekashu.com/ (test:
188
+ // test.ekashu.com/) with the amount, the result URLs and a SHA256HMAC over them (hash
189
+ // code 2.0.0), and no card. NMI answers with its own card page under an HttpOnly session
190
+ // cookie and an anti-forgery token, so a card form rebuilt away from that session is
191
+ // refused by NMI (processors/ekashu.js has the recorded shapes). The paused request is
192
+ // therefore the entry, a Document navigation that carries no card: the cardholder's
193
+ // device repeats it over the end-to-end TLS relay, fills the card into the page NMI
194
+ // returns to it and posts it back in that same session, and the runtime resolves the
195
+ // paused navigation with the hosted_form notice. Only the entry path is matched: NMI's
196
+ // card post (/index.php) and its 3-D Secure calls (ajax_3d_secure_v2_*.php) carry a card,
197
+ // and the SDK refuses them in the agent's browser, so no dummy card ever reaches NMI.
198
+ // Dark: served only to a client that declares the capability, and gated off for every
199
+ // org the operator has not allowlisted.
200
+ capability: "ekashu_hosted_payment_page",
201
+ match: "(?:live|test)\\.ekashu\\.com/",
202
+ hosts: ["^live\\.ekashu\\.com$", "^test\\.ekashu\\.com$"],
203
+ sandboxHosts: ["^test\\.ekashu\\.com$"],
204
+ // A live row reaches live.ekashu.com only and a test row test.ekashu.com only, and the
205
+ // test host receives only documented test cards (device-replay.js).
206
+ hostEnvironmentPinned: true,
207
+ encoding: "form",
208
+ passthroughHeaders: [],
209
+ mode: "hosted_form",
210
+ hostedForm: {
211
+ // The card goes into the page NMI returns to the device, not into the paused entry,
212
+ // which must carry none (processors/ekashu.js checkEkashuEntry). The device never
213
+ // posts a form of its own: the Vault's form-action policy leaves these hosts out.
214
+ cardIn: "processor_page",
215
+ // The server callback too: the device never returns the buyer's browser to the merchant,
216
+ // so a merchant NMI tells of a payment only through that return never records it.
217
+ required: [
218
+ "ekashu_seller_id",
219
+ "ekashu_seller_key",
220
+ "ekashu_amount",
221
+ "ekashu_currency",
222
+ "ekashu_reference",
223
+ "ekashu_hash_code",
224
+ "ekashu_hash_code_type",
225
+ "ekashu_hash_code_version",
226
+ "ekashu_success_url",
227
+ "ekashu_failure_url",
228
+ "ekashu_callback_success_url"
229
+ ],
230
+ card: {
231
+ number: "ekashu_card_number",
232
+ month: "ekashu_expires_end_month",
233
+ year: "ekashu_expires_end_year",
234
+ cvc: "ekashu_verification_value",
235
+ firstName: "ekashu_card_first_name",
236
+ lastName: "ekashu_card_last_name"
237
+ },
238
+ amount: { sum: "ekashu_amount", currency: "ekashu_currency" },
239
+ // The terminal, the merchant's own reference and the amount name one payment; NMI's
240
+ // duplicate check (ekashu_duplicate_check) keys on the same reference.
241
+ dedupe: ["ekashu_seller_id", "ekashu_reference", "ekashu_amount", "ekashu_currency"],
242
+ sale: { key: "ekashu_request_type", values: ["AUTH"] },
243
+ token: "ekashu_card_reference",
244
+ callbackUrls: ["ekashu_success_url", "ekashu_failure_url", "ekashu_return_url"]
245
+ }
246
+ },
183
247
  // ── Verified tokenizers (plaintext PAN in the body) ───────────────────────
184
248
  // Each entry below was checked against the PSP's own shipped browser SDK or a
185
249
  // live probe, then run through resolveRecognizerForUrl with positive, sibling
@@ -205,9 +269,10 @@ var PROCESSOR_DEFINITIONS = deepFreeze([
205
269
  // Accept.js. PAN@ securePaymentContainerRequest.data.token.cardNumber.
206
270
  // Auth is body-level (merchantAuthentication: apiLoginID + clientKey) — nothing to replay.
207
271
  // NOTE: prod is api2, not api. `api.authorize.net` is the server-side AIM/API host and is
208
- // deliberately NOT allowlisted — a browser never posts a PAN there. Legacy SIM/DPM
209
- // (secure2.authorize.net/gateway/transact.dll) is excluded for the same reason plus: it is
210
- // retired, and it is a top-level form POST rather than an XHR.
272
+ // deliberately NOT allowlisted: a browser never posts a PAN there. SIM and DPM
273
+ // (secure2.authorize.net/gateway/transact.dll) are deprecated by Authorize.Net, not retired, and
274
+ // post the card as a top-level form navigation rather than an XHR: the separate
275
+ // authorize_net_dpm entry (mode hosted_form) covers them, on hosts this entry never shares.
211
276
  // Coverage caveat: AcceptUI (the hosted lightbox) renders its fields inside an
212
277
  // accept.authorize.net iframe, so that POST is cross-origin to the merchant page and an
213
278
  // in-page hook cannot observe it. This entry covers the Accept.js custom-fields path, which
@@ -232,6 +297,35 @@ var PROCESSOR_DEFINITIONS = deepFreeze([
232
297
  encoding: "json",
233
298
  passthroughHeaders: ["^accept$"]
234
299
  },
300
+ {
301
+ psp: "worldpay_eprotect",
302
+ // Worldpay eProtect (Vantiv / Litle PayPage), not Access Worldpay above.
303
+ // The first card request that is a GET: the vendor's eProtect-api / litle-api scripts (and the
304
+ // Worldpay iframe, which runs them) inject ONE JSONP <script> whose query carries the PAN and CVV
305
+ // RSA-encrypted under the vendor's per-environment key. eprotect.js holds the query grammar,
306
+ // the pinned keys and the answer rules; recognition also requires isEprotectTokenRequest, so
307
+ // ppstats, script files, payframes and every other /eProtect/paypage query stay unrecognized.
308
+ // The alternation is wrapped (the EBANX rule) and the path has a right-edge guard for the SDK's
309
+ // unanchored test.
310
+ match: "(?:request\\.eprotect\\.vantivcnp\\.com|request\\.eprotect\\.vantivprelive\\.com)/eProtect/paypage(?![\\w/.-])",
311
+ hosts: ["^request\\.eprotect\\.vantivcnp\\.com$", "^request\\.eprotect\\.vantivprelive\\.com$"],
312
+ // Pre-live (certification) host: sandbox rows only, and only the guide's test cards on the device.
313
+ sandboxHosts: ["^request\\.eprotect\\.vantivprelive\\.com$"],
314
+ hostEnvironmentPinned: true,
315
+ // Ships dark: served only to an SDK that declares this capability, and gated off for every org
316
+ // until an operator allowlists one (CHECKOUT_GATED_PROCESSOR_ORGS).
317
+ capability: "worldpay_eprotect_jsonp",
318
+ // Merchant deadlines are 10 to 15 s with a 5 s failover, so the cardholder approves before Pay.
319
+ preparationRequired: true,
320
+ // `encoding` describes the query, since the request has no body. No captured header is ever
321
+ // replayed, and the card rides in the query of one GET whose answer is JSONP.
322
+ encoding: "form",
323
+ passthroughHeaders: [],
324
+ request: { method: "GET", cardIn: "query", response: "jsonp" },
325
+ // The api3 failover host re-sends the same query after 5 s. The SDK aborts it; it is never a
326
+ // destination, so it is in no `hosts`, manifest, CSP or relay list.
327
+ abortHosts: ["^secondary\\.eprotect\\.vantivcnp\\.com$"]
328
+ },
235
329
  {
236
330
  psp: "nuvei",
237
331
  // Safecharge Fields. PAN@ paymentOption.card.cardNumber.
@@ -247,7 +341,20 @@ var PROCESSOR_DEFINITIONS = deepFreeze([
247
341
  hosts: ["^secure\\.safecharge\\.com$", "^ppp-test\\.safecharge\\.com$"],
248
342
  sandboxHosts: ["^ppp-test\\.safecharge\\.com$"],
249
343
  encoding: "json",
250
- passthroughHeaders: []
344
+ passthroughHeaders: [],
345
+ // Where Nuvei's own scripts put the card, read from safecharge.js and
346
+ // fields/sfc_inner_card.min.js: paymentOption.card on all three endpoints,
347
+ // and cardData when Nuvei Fields' getToken posts cardTokenization.do. The
348
+ // initPayment and clientPayment endpoints also pay without a card: with a
349
+ // ccTempToken the merchant's server issued (Air France completes its Nuvei
350
+ // payments this way, behind Amadeus), a saved userPaymentOptionId, a wallet
351
+ // or an APM. createPayment sends each of those to initPayment first and then
352
+ // to clientPayment, so both continue untouched. A tokenization without a
353
+ // card is refused. So is a payment without a card once the attachment has
354
+ // handed Nuvei the card: its token may be one Nuvei minted from the
355
+ // approved card (checkout client.ts withoutCard).
356
+ jsonCardFields: [["paymentOption", "card", "cardNumber"], ["cardData", "cardNumber"]],
357
+ passWithoutCard: "(?:secure|ppp-test)\\.safecharge\\.com/ppp/api/v1/(?:clientPayment|websdk/initPaymentWithCardTokenization)\\.do"
251
358
  },
252
359
  // bluesnap: DELIBERATELY NOT SHIPPED — it cannot be intercepted at all. Its tokenizer is a PUT, and isCardRequest
253
360
  // gates on POST — but accepting PUT is not enough on its own. hpf.js fires the
@@ -517,6 +624,139 @@ var PROCESSOR_DEFINITIONS = deepFreeze([
517
624
  encoding: "json",
518
625
  passthroughHeaders: ["^authorization$", "^x-gp-version$"]
519
626
  },
627
+ {
628
+ psp: "authorize_net_dpm",
629
+ // Authorize.Net Direct Post Method and SIM with a relay response: deprecated by Authorize.Net, still
630
+ // served, end of life "to be determined" (upgrade guide; SIM guide ch. 3 and app. C; sdk-php 1.9.9
631
+ // AuthorizeNetDPM, sdk-dotnet 1.8.1 DPMFormGenerator, sdk-ruby 1.8.1, sdk-java 1.8.0). The merchant's
632
+ // own card form (DPM), or Authorize.Net's hosted form the merchant frames (SIM, x_show_form=pf_receipt),
633
+ // posts ONE form navigation, application/x-www-form-urlencoded, to /gateway/transact.dll with the
634
+ // plaintext card in x_card_num, x_exp_date (one field: MMYY, MM/YY, MM-YY, MMYYYY, MM/YYYY or
635
+ // MM-YYYY) and, only when the merchant collects it, x_card_code. Beside it rides the merchant's
636
+ // fingerprint: x_login (the public API Login ID), x_fp_sequence, x_fp_timestamp and x_fp_hash, an HMAC
637
+ // over login^sequence^timestamp^amount^currency under the merchant's Signature Key. Authorize.Net
638
+ // refuses it after 1 hour (97), spends it once (98) and refuses a changed amount (99). It POSTs the
639
+ // result to x_relay_url server to server, then answers whichever browser submitted with the
640
+ // merchant's relay page. No cookie, no auth header and no encryption, so this is Tranzila's
641
+ // hosted_form: the cardholder's device rebuilds and submits the same form and the paused navigation
642
+ // resolves with the synthetic page. No relay and no prepare(): the create refuses a fingerprint more
643
+ // than 40 minutes old or more than 15 minutes ahead instead (authorize-net-dpm.js, with the rest of
644
+ // the template policy). Authorize.Net reads field names without regard to case (live forms post
645
+ // x_Background_URL and x_cust_ID), so every key comparison for this entry ignores case.
646
+ // The same URL without a card continues untouched: SIM step 1 (x_show_form=PAYMENT_FORM), an eCheck
647
+ // (x_method=ECHECK) and Visa Checkout on the SIM form. NOT here: api2 and apitest (Accept.js, the
648
+ // authorize_net entry); never armed: cardpresent., api., accept., captcha., account. and
649
+ // sandbox.authorize.net. Hosts are the three literal labels. test.authorize.net is Authorize.Net's
650
+ // sandbox gateway, pinned to test rows and documented test cards (S7).
651
+ // Ships dark: served only to a client that declares authorize_net_dpm_form, gated off for every org
652
+ // until an operator allowlists one, and never sent by autopilot (EXCLUDED_OPERATIONS).
653
+ capability: "authorize_net_dpm_form",
654
+ match: "(secure2|secure|test)\\.authorize\\.net/gateway/transact\\.dll(?![\\w/.-])",
655
+ hosts: ["^secure2\\.authorize\\.net$", "^secure\\.authorize\\.net$", "^test\\.authorize\\.net$"],
656
+ sandboxHosts: ["^test\\.authorize\\.net$"],
657
+ hostEnvironmentPinned: true,
658
+ // The endpoint is the bare URL: a query string or a fragment, even an empty one, is not this
659
+ // endpoint (recognition.js resolveRecognizerForUrl), so the create, the vault and the enclave all
660
+ // refuse it. transact.dll can read a query parameter as a form field, which would carry x_tran_key,
661
+ // x_type or x_relay_url past the template policy, and the URL is stored with the row.
662
+ bareEndpoint: true,
663
+ encoding: "form",
664
+ passthroughHeaders: [],
665
+ caseInsensitiveFormKeys: true,
666
+ cardFields: ["x_card_num"],
667
+ passWithoutCard: "(secure2|secure|test)\\.authorize\\.net/gateway/transact\\.dll",
668
+ mode: "hosted_form",
669
+ hostedForm: {
670
+ required: ["x_login", "x_amount", "x_fp_sequence", "x_fp_timestamp", "x_fp_hash", "x_relay_response"],
671
+ // One composed expiry field, written in the width and separator of the agent's dummy.
672
+ card: { number: "x_card_num", expiry: "x_exp_date", cvc: "x_card_code" },
673
+ // Filled only when the template carries the key; never added.
674
+ optional: ["cvc"],
675
+ amount: { sum: "x_amount", currency: "x_currency_code" },
676
+ // Authorize.Net spends a fingerprint once, so the fingerprint is the submission.
677
+ dedupe: ["x_login", "x_fp_sequence", "x_fp_timestamp", "x_fp_hash"],
678
+ // Absent or empty also means AUTH_CAPTURE.
679
+ sale: { key: "x_type", values: ["AUTH_CAPTURE"] },
680
+ callbackUrls: ["x_relay_url", "x_receipt_link_url", "x_cancel_url"],
681
+ policy: "authorize_net_dpm"
682
+ }
683
+ },
684
+ {
685
+ psp: "primer",
686
+ // Primer Web SDK v2 (Headless Checkout and hosted fields): Printful (printful.com) loads
687
+ // sdk.primer.io/web/v2.63.0; GetYourGuide (getyourguide.com) tokenizes with Primer's hosted fields and
688
+ // Primer routes the token to Adyen, Checkout.com or J.P. Morgan server side. PAN@ paymentInstrument.number,
689
+ // with cvv, expirationMonth (MM) and expirationYear (YYYY) beside it. Primer's hidden api-controller iframe
690
+ // (origin https://sdk.primer.io) resolves the core's "$.cardNumber-card" placeholders and POSTs plaintext
691
+ // JSON to `${pciUrl}/payment-instruments`, with the session's primer-client-token and no client-side
692
+ // encryption. pciUrl comes from the session: sdk.api.sandbox.primer.io (Primer's iOS client-token fixture),
693
+ // sdk.api.primer.io (production, inferred from the same naming and DNS; confirmed on first observation).
694
+ // The same URL also tokenizes PayPal, Apple Pay, Google Pay and Klarna with no card: jsonCardFields and
695
+ // passWithoutCard let those continue untouched. The siblings on the host (/{id}/exchange for a saved card,
696
+ // /{id}/vault, /payments, /3ds, /three-d-secure, /client-session) never carry a new card, and the
697
+ // right-edge boundary and the exact-URL rule in resolveRecognizerForUrl keep them out. primer.js judges the
698
+ // whole request, refuses a body that asks Primer to save the card (tokenType MULTI_USE, paymentFlow VAULT),
699
+ // Primer Checkout's primer-js SDK (its request gives up after 30 s) and a preferredNetwork that is not the
700
+ // card's own, and writes only the card fields. Staging and dev hosts are deliberately absent, and the
701
+ // sandbox host is pinned (S7): a sandbox row sends only documented test cards there, a live row never
702
+ // points at it. The request names no amount: the token is charged later.
703
+ // Ships dark: served only to a client that declares `primer_payment_instruments`, gated off for every
704
+ // org until an operator allowlists one, and never replayed by autopilot (EXCLUDED_OPERATIONS). A client
705
+ // session can save the card with no sign in the request, so the API also refuses every live row at
706
+ // create until the cardholder can consent to that save; only a test row pays.
707
+ capability: "primer_payment_instruments",
708
+ match: "sdk\\.api(?:\\.sandbox)?\\.primer\\.io/payment-instruments(?![\\w/.-])",
709
+ hosts: ["^sdk\\.api\\.primer\\.io$", "^sdk\\.api\\.sandbox\\.primer\\.io$"],
710
+ sandboxHosts: ["^sdk\\.api\\.sandbox\\.primer\\.io$"],
711
+ hostEnvironmentPinned: true,
712
+ encoding: "json",
713
+ // What Primer's controller sends beside the body; primer.js checks their shapes before any replay.
714
+ passthroughHeaders: [
715
+ "^primer-client-token$",
716
+ "^primer-sdk-client$",
717
+ "^primer-sdk-version$",
718
+ "^primer-sdk-checkout-session-id$",
719
+ "^x-api-version$",
720
+ "^x-request-id$"
721
+ ],
722
+ jsonCardFields: [["paymentInstrument", "number"]],
723
+ passWithoutCard: "sdk\\.api(?:\\.sandbox)?\\.primer\\.io/payment-instruments"
724
+ },
725
+ {
726
+ psp: "amadeus_checkout",
727
+ // Outpayce (Amadeus Payment Platform): Air France and KLM, one shared release.
728
+ // PAN@ data.mopdata.pan (JSON, plaintext inside TLS). Two card-bearing XHRs on one host:
729
+ // 1. Checkout Web SDK: the SDK hands {PPID, data, action} to its tunnel iframe
730
+ // (prd.payment.amadeus.com/checkout/sdk/<v>/form-fields/tunnel.html), which swaps the pan and
731
+ // CVV iframes' ids for the typed digits and posts it to ARIAPP/pay: text/plain, no cookies, a
732
+ // 30 s timeout, HTTP 200 only.
733
+ // 2. Data Collection Page (DCP): the page at /1ASIATP/ATPDCP/land/?DCPID= posts
734
+ // {DCPID, action, data} to ATPDCP/collect, same-origin JSON, the whole card in one body.
735
+ // ONE URL, MANY ACTIONS. Only an add carrying a card mopid's pan, or a store carrying a pan, is a
736
+ // card request (amadeus-body.js, which card-fields.js asks for this psp); load, bin, prepare,
737
+ // obfees, installments, tdsinit, verify, fetch, cancel, the wallet actions and DCP bin_check,
738
+ // expired and back carry at most the agent's dummy and continue untouched (passWithoutCard).
739
+ // amadeus-checkout.js holds the exact-URL rule, the whole-request check, both fills and the answer
740
+ // judge (sources there). Hosts are the two literal paypages hosts, never a wildcard label:
741
+ // paypages.dev (1ASIATPD), the airline intranet hosts, the playground, paypages.*.payment.outpayce.com
742
+ // (resolves, but no shipped SDK allowlists it) and the hosted page's own origin are absent, and the
743
+ // test host takes no DCP store until one is observed. The test host is pinned (S7): a create
744
+ // refuses it on a live row, and the device sends it only documented test cards.
745
+ // Ships dark: served only to a client that declares amadeus_checkout_actions.v1 (one that judges
746
+ // these bodies and prepares before the page's first request), gated off for every org until an
747
+ // operator allowlists one, prepared before Pay (S4: the tunnel abandons the add after 30 s), and
748
+ // never replayed by autopilot (EXCLUDED_OPERATIONS).
749
+ capability: "amadeus_checkout_actions.v1",
750
+ match: "(?:paypages\\.payment\\.amadeus\\.com/1ASIATP/(?:ARIAPP/pay|ATPDCP/collect)|paypages\\.test\\.payment\\.amadeus\\.com/1ASIATP[UMK]?/ARIAPP/pay)(?![\\w/.-])",
751
+ hosts: ["^paypages\\.payment\\.amadeus\\.com$", "^paypages\\.test\\.payment\\.amadeus\\.com$"],
752
+ sandboxHosts: ["^paypages\\.test\\.payment\\.amadeus\\.com$"],
753
+ hostEnvironmentPinned: true,
754
+ preparationRequired: true,
755
+ encoding: "json",
756
+ passthroughHeaders: ["^amadeus-checkout-sdk-version$", "^amadeus-checkout-sdk-host$", "^amadeus-checkout-sdk-flavor$"],
757
+ jsonCardFields: [["data", "mopdata", "pan"]],
758
+ passWithoutCard: "(?:paypages\\.payment\\.amadeus\\.com/1ASIATP/(?:ARIAPP/pay|ATPDCP/collect)|paypages\\.test\\.payment\\.amadeus\\.com/1ASIATP[UMK]?/ARIAPP/pay)"
759
+ },
520
760
  // ── Encrypted on the device under a pinned key ────────────────────────────
521
761
  {
522
762
  psp: "fiserv",
@@ -573,6 +813,38 @@ var PROCESSOR_DEFINITIONS = deepFreeze([
573
813
  fields: ["keyId", "encryptedKey", "encryptionBlock", "aesIv"]
574
814
  }
575
815
  },
816
+ {
817
+ psp: "verifone",
818
+ // Verifone eCommerce Secure Card Capture (verifone.js), The Container Store's card path. The
819
+ // merchant's page encrypts the card with OpenPGP under the merchant's own Verifone key and
820
+ // posts the blob to the MERCHANT's server, which calls Verifone: nothing card-bearing goes
821
+ // from the browser to a Verifone host. So this entry recognizes no URL and names no host: a
822
+ // Verifone card request is found only through a reviewed merchant profile
823
+ // (verifone-profiles.js), whose endpoint, body rules and pinned key (verifone-keys.js) the
824
+ // backend, the SDK and the Vault page read by the profile's id (verifone.js). `hosts` is empty
825
+ // and `match` never matches, so the registry, the enclave's destinations and the SDK's card
826
+ // patterns gain nothing, and resolveRecognizerForUrl never resolves a URL to verifone. The
827
+ // blob is a 15-minute bearer at the merchant and a 3-D Secure challenge needs the cardholder,
828
+ // so the cardholder approves every payment: dark until an org is allowlisted, and autopilot
829
+ // refuses verifone at all three gates.
830
+ capability: "verifone_card_capture",
831
+ // A Verifone card is encrypted only for a request the cardholder already approved through a
832
+ // prepare() for the same reviewed profile: the backend refuses an unprepared create (409
833
+ // preparation_required) and the SDK refuses locally before it prompts, as for Fiserv.
834
+ preparationRequired: true,
835
+ match: "(?!)",
836
+ hosts: [],
837
+ encoding: "json",
838
+ // The browser continues the merchant's own request with its own headers; none is stored.
839
+ passthroughHeaders: [],
840
+ clientSideEncrypted: true,
841
+ mode: "cse",
842
+ cse: {
843
+ // Where the blob sits is each profile's leg (holder and field), never one path for the psp.
844
+ at: "merchant_profile",
845
+ fields: ["encryptedCard"]
846
+ }
847
+ },
576
848
  {
577
849
  psp: "gravy",
578
850
  // Gravy (Gr4vy) payment orchestration, Secure Fields. PAN@ payment_method.number,
@@ -658,9 +930,369 @@ var PROCESSOR_DEFINITIONS = deepFreeze([
658
930
  hostEnvironmentPinned: true,
659
931
  encoding: "jwe",
660
932
  passthroughHeaders: []
933
+ },
934
+ {
935
+ psp: "juspay",
936
+ // Juspay Express Checkout, the merchant-page card flow Swiggy web ships (reviewed bundle
937
+ // web-payments.7cf02545077d488.js, SHA-256 08336f74599b7f756e4b17ed8747af8caa5d248879f7c0dd3d89f0abd8347504).
938
+ // The page tokenizes the card at /card/tokenize and pays at /txns with the token; juspay.js
939
+ // holds the whole protocol and says why only /txns is taken over.
940
+ // - Paused: the POST /txns that carries a synthetic token the SDK answered the placeholder
941
+ // tokenize with (never the tokenize itself: a real ctkn_ needs no merchant secret and pays
942
+ // any order of that merchant for 15 minutes). The SDK answers the placeholder tokenize and
943
+ // refuses the /v2/card/fingerprint lookup, so the placeholder never reaches Juspay.
944
+ // - deviceSteps.tokenize: the one other request the cardholder's device sends, the real
945
+ // card's tokenize, on the paused request's own host (request-policy.js
946
+ // assertAllowedDeviceStep). Definitions-only: the served row does not carry it.
947
+ // - NOT here, on purpose: api.juspay.io and api-ns1.juspay.in. Juspay operates both and
948
+ // serves the same API there, but no reviewed page was seen sending a card to either; the
949
+ // SDK refuses a card-bearing request to them instead of pausing it.
950
+ // - Headers: x-merchantid and x-routing-id only. client_auth_token can be scoped to a
951
+ // customer and Swiggy's card legs never send it; the merchant's API key must never reach
952
+ // a browser, so authorization is never passed.
953
+ // - Dark: served only to a client that declares juspay_txns.v1, and off for every org
954
+ // until one is allowlisted. The sandbox host takes only documented test cards (S7).
955
+ // - Autopilot never replays it: the enclave sends one request and Juspay needs two.
956
+ capability: "juspay_txns.v1",
957
+ match: "(api|sandbox)\\.juspay\\.in/txns(?![\\w/-])",
958
+ hosts: ["^api\\.juspay\\.in$", "^sandbox\\.juspay\\.in$"],
959
+ sandboxHosts: ["^sandbox\\.juspay\\.in$"],
960
+ hostEnvironmentPinned: true,
961
+ encoding: "form",
962
+ passthroughHeaders: ["^x-merchantid$", "^x-routing-id$"],
963
+ deviceSteps: { tokenize: "(api|sandbox)\\.juspay\\.in/card/tokenize" }
964
+ },
965
+ {
966
+ psp: "datatrans",
967
+ // Datatrans / PCI Proxy Secure Fields 2.0.0 in TOKENIZE mode (field.js 3.24.602):
968
+ // British Airways's Nexus checkout (merchantId 3000024893) and legacy ba-sell (3000025858). PAN@
969
+ // cardNumber (form). Datatrans's own card-number iframe document on pay.datatrans.com sends the
970
+ // whole card as one jQuery XHR to its relative URL `paymentField`: form-encoded, with the CVV read
971
+ // from its same-origin CVV frame and the expiry (expm, expy) from the merchant page, plus mode,
972
+ // formId, paymentMethod, merchantId and usage; no amount, key, cookie or signature. The server keys
973
+ // the form by formId in the body, and the replay gate (PCI Proxy's public sandbox merchant) showed
974
+ // it accepts that body from another client with no cookie, origin or referer.
975
+ // paymentField/cardInfo is a 12-digit BIN lookup on the same host and must never match: the
976
+ // right-edge boundary and the exact-URL rule in resolveRecognizerForUrl keep it (and every query,
977
+ // port and case variant) out. Wallet, bank-account and CVV-only posts share the URL and carry no
978
+ // cardNumber: cardFields and passWithoutCard let them continue untouched. The GET that loads the
979
+ // iframe document shares the path, and the POST gate keeps it out. datatrans.js judges the whole
980
+ // request, refuses usage=REGISTRATION (card on file) until that decision is made and a
981
+ // paymentMethod that is not the card's own, and writes only cardNumber, cvv, expm and expy.
982
+ // Hosts are the two literal labels (never *.datatrans.com: api., 3d. and admin. are other
983
+ // services, and PCI Proxy's custom domains are not recognized); the sandbox host is pinned (S7):
984
+ // it takes only documented test cards, and a live row never points at it.
985
+ // Ships dark: served only to a client that declares `datatrans_secure_fields_tokenize`, gated off
986
+ // for every org until an operator allowlists one, and never replayed by autopilot
987
+ // (EXCLUDED_OPERATIONS).
988
+ capability: "datatrans_secure_fields_tokenize",
989
+ match: "pay(?:\\.sandbox)?\\.datatrans\\.com/upp/payment/SecureFields/paymentField(?:[?#]|$)",
990
+ hosts: ["^pay\\.datatrans\\.com$", "^pay\\.sandbox\\.datatrans\\.com$"],
991
+ sandboxHosts: ["^pay\\.sandbox\\.datatrans\\.com$"],
992
+ hostEnvironmentPinned: true,
993
+ encoding: "form",
994
+ passthroughHeaders: [],
995
+ // the replay gate needed none: no x-requested-with, cookie, origin or referer
996
+ cardFields: ["cardNumber"],
997
+ passWithoutCard: "pay(?:\\.sandbox)?\\.datatrans\\.com/upp/payment/SecureFields/paymentField"
998
+ },
999
+ {
1000
+ psp: "pelecard",
1001
+ // Pelecard Iframe/Redirect 2.0, the hosted payment page Uman tourist tax (aumantax.com)
1002
+ // loads in an iframe. PAN@ root CreditCardNumber, expiry MMYY @ CreditCardDate, CVV @ CvvNumber.
1003
+ // Pelecard's own page (/PaymentGW?transactionId=<guid>) posts the flat SubmitModel JSON with one
1004
+ // jQuery XHR (Payment.js sendAjax, sha256 75c37541...a669caea) to generalParameters.urlTransaction,
1005
+ // the same host's /PaymentGW/Transaction: no cookie, no auth header, no client-side encryption.
1006
+ // The amount, currency, action type (J4 charge, J2 registration, J5 hold) and CreateToken are bound
1007
+ // to the TransactionId at the merchant's server-side init and never ride in the request.
1008
+ // The same URL also serves the wallet, Bit, PIN pad and bank tabs with no card: jsonCardFields and
1009
+ // passWithoutCard let those continue untouched. pelecard.js checks the exact URL (also in
1010
+ // resolveRecognizerForUrl), validates the whole body, writes only the card fields, and refuses a
1011
+ // saved token, a track, installments, a buyer-typed total and a body that asks to keep the card.
1012
+ // NOT here: /PaymentGW/TimeOutTransaction (the dwell timer posts the same card fields there),
1013
+ // /PaymentGW/CheckCreditCard, EndOfProcess, init and the other PaymentGW routes; gateway20qa
1014
+ // (Pelecard QA); the legacy 1.0 page on gateway.pelecard.biz (/PayProcess/Transaction, a top-level
1015
+ // form). Hosts are the two literal labels, never a wildcard. No sandboxHosts: Pelecard's public test
1016
+ // terminals run on the same gateway21 host as live ones (the terminal bound to the TransactionId
1017
+ // decides, and neither the request nor the page names it), so the S7 host rule has no test-only
1018
+ // host to pin, and the device's test-card rule cannot tell a test payment from a live one here.
1019
+ // A live row can therefore send a real card to a payment page created on a public test terminal,
1020
+ // whose transactions anyone holding Pelecard's published demo credentials can read back.
1021
+ // Ships dark: served only to a client that declares `pelecard_transaction`, gated off for every org
1022
+ // until an operator allowlists one, and never replayed by autopilot (EXCLUDED_OPERATIONS).
1023
+ capability: "pelecard_transaction",
1024
+ match: "(?:gateway21|gateway20)\\.pelecard\\.biz/PaymentGW/Transaction(?![\\w/.-])",
1025
+ hosts: ["^gateway21\\.pelecard\\.biz$", "^gateway20\\.pelecard\\.biz$"],
1026
+ encoding: "json",
1027
+ // jQuery's own same-origin marker, pinned to `XMLHttpRequest` by pelecard.js; nothing else rides.
1028
+ passthroughHeaders: ["^x-requested-with$"],
1029
+ jsonCardFields: [["CreditCardNumber"]],
1030
+ passWithoutCard: "(?:gateway21|gateway20)\\.pelecard\\.biz/PaymentGW/Transaction"
1031
+ },
1032
+ {
1033
+ psp: "aci",
1034
+ // ACI Worldwide Open Payment Platform, COPYandPAY widget (Halfords). PAN@ card.number (form, dot keys).
1035
+ // Each PCI iframe (/v1/pciIframe.html) posts the one field it holds, as a jQuery form XHR, to
1036
+ // POST /v1/checkouts/{id} (no suffix); ACI merges them on the checkout. aci.js holds the leg
1037
+ // rules, the fill and the answer judge (sources there). The id segment is the documented
1038
+ // <32 hex>.<cluster>-vm-tx<nn>; (?![\w/.-]) is the right edge for the SDK's unanchored test and
1039
+ // keeps /payment, /bins and /registration out of `match`. Hosts are the four literal hosts ACI
1040
+ // serves the widget from, never a wildcard label; white-label OPP hosts need their own evidence.
1041
+ // Ships dark: served only to a client that declares aci_split_card.v1 (one that holds the
1042
+ // sibling legs below), gated off for every org until an operator allowlists one, and never
1043
+ // replayed by autopilot (EXCLUDED_OPERATIONS).
1044
+ capability: "aci_split_card.v1",
1045
+ match: "(?:eu-prod\\.oppwa\\.com|oppwa\\.com|eu-test\\.oppwa\\.com|test\\.oppwa\\.com)/v1/checkouts/[0-9A-F]{32}\\.[a-z0-9]{1,16}-vm-tx[0-9]{1,3}(?![\\w/.-])",
1046
+ hosts: ["^eu-prod\\.oppwa\\.com$", "^oppwa\\.com$", "^eu-test\\.oppwa\\.com$", "^test\\.oppwa\\.com$"],
1047
+ // eu-test and test.oppwa.com are ACI's INTEGRATOR_TEST hosts. Pinned (S7): a create refuses a
1048
+ // test host on a live row and a live host on a test row, and the device sends only documented
1049
+ // test cards (ACI's own included, aci.js ACI_TEST_PANS) to a test host.
1050
+ sandboxHosts: ["^eu-test\\.oppwa\\.com$", "^test\\.oppwa\\.com$"],
1051
+ hostEnvironmentPinned: true,
1052
+ // ACI's widget abandons Pay after its 60 s channel timeout, so the cardholder unlocks first (S4).
1053
+ preparationRequired: true,
1054
+ encoding: "form",
1055
+ passthroughHeaders: [],
1056
+ // no auth header; X-Requested-With is not replayed (it would force a CORS preflight)
1057
+ cardFields: ["card.number"],
1058
+ // One card, several legs on one checkout id. `absorb` legs (the page's CVC and expiry, dummy
1059
+ // values) are held and answered with the approved leg's answer, never forwarded; `pass` legs
1060
+ // (the holder) continue untouched; `siblingKeys` may ride any leg. `continuation` is the merchant
1061
+ // form's /payment submission, which continues with `remove` taken out after `brandField` is
1062
+ // checked against the approved card's network and every other key against the ones the widget
1063
+ // sends (aci.js prepareAciContinuation).
1064
+ splitCard: {
1065
+ absorb: ["card.cvv", "card.expiryMonth", "card.expiryYear"],
1066
+ pass: ["card.holder"],
1067
+ siblingKeys: ["customParameters[SHOPPER_EndToEndIdentity]"],
1068
+ continuation: {
1069
+ match: "(?:eu-prod\\.oppwa\\.com|oppwa\\.com|eu-test\\.oppwa\\.com|test\\.oppwa\\.com)/v1/checkouts/[0-9A-F]{32}\\.[a-z0-9]{1,16}-vm-tx[0-9]{1,3}/payment(?![\\w/.-])",
1070
+ remove: ["card.expiryMonth", "card.expiryYear"],
1071
+ brandField: "paymentBrand"
1072
+ }
1073
+ }
1074
+ },
1075
+ {
1076
+ psp: "creditguard",
1077
+ // Hyp CreditGuard PPS, the hosted page merchants frame at https://pps.creditguard.co.il/?txId=<uuid>
1078
+ // (SeboCalm). Its Angular transaction service posts the card to /services/v1/txn/<txId>/process as
1079
+ // same-origin JSON, no auth header, no cookie: the txId is the only credential and the submit is the
1080
+ // sale itself. PAN@ root `cardNumber` (expMonth MM, expYear YY, cvv, personalId) in plaintext, or one
1081
+ // js-jose JWE in root `jwePayload` when the transaction carries a jwePublicKey (creditguard.js keeps
1082
+ // that variant behind a flag). Sources: templates/cgt-basic/main.js on pps and ppsuat, reviewed
1083
+ // 2026-09-25. /card/details, /card/details/dcc, /cc/ddc/init, /cg3ds/*, /otp/request and
1084
+ // /applepay|paybox|pcp/process share the prefix, carry the agent's placeholder or no card, and fall
1085
+ // out at the exact path; (?![\w/-]) is the right edge for the SDK's unanchored test. pps2 is a
1086
+ // production host (cg-safecharge-3ds envConfig: pps, pps2, cgmpi = prod). The legacy MPI page
1087
+ // (cgmpi.creditguard.co.il), pps-dev, ppsqa, pps-qa1 and cguat2 are deliberately absent.
1088
+ // creditguard.js judges the whole request before a card is written and fills only the card fields.
1089
+ // Ships dark: served only to a client that declares `creditguard_pps_process`, gated off for every
1090
+ // org until an operator allowlists one, never replayed by autopilot (EXCLUDED_OPERATIONS).
1091
+ capability: "creditguard_pps_process",
1092
+ match: "(?:pps|pps2|ppsuat)\\.creditguard\\.co\\.il/services/v1/txn/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/process(?![\\w/-])",
1093
+ hosts: ["^pps\\.creditguard\\.co\\.il$", "^pps2\\.creditguard\\.co\\.il$", "^ppsuat\\.creditguard\\.co\\.il$"],
1094
+ // ppsuat is CreditGuard's UAT page. Pinned (S7): a create refuses it on a live row and pps or pps2
1095
+ // on a test row, and the device sends only documented test cards to it.
1096
+ sandboxHosts: ["^ppsuat\\.creditguard\\.co\\.il$"],
1097
+ hostEnvironmentPinned: true,
1098
+ // S4: the submit names no amount, so a card is sent only after the cardholder approved a
1099
+ // prepare() that read the transaction (GET /services/v1/txn/<txId>, creditguard.js).
1100
+ preparationRequired: true,
1101
+ encoding: "json",
1102
+ // The device sends Content-Type (and Accept) JSON itself; nothing the page sent is replayed.
1103
+ passthroughHeaders: [],
1104
+ // A /process body without either (Google Pay, a saved cardId, a js-jose object fallback) is not a
1105
+ // new card, and with no passWithoutCard it is refused instead of paused.
1106
+ jsonCardFields: [["cardNumber"], ["jwePayload"]]
1107
+ },
1108
+ {
1109
+ psp: "payrails",
1110
+ // Payrails web SDK v6 (assets.payrails.io/web-sdk/v6/payrails.js 6.5.0), Blacklane's consumer
1111
+ // booking checkout: cardForm.tokenize() POSTs vaultConfiguration.links.saveInstrument.href. Body
1112
+ // (JSON.stringify, sent as text/plain): {holderReference, paymentMethod:'card', storeInstrument,
1113
+ // futureUsage, data:{encryptedData, vaultProviderConfigId}}. encryptedData is a compact JWE
1114
+ // (RSA-OAEP-256 + A256CBC-HS512, no kid) of {holderName, cardNumber, expiryMonth, expiryYear,
1115
+ // securityCode, holderReference}, built in the assets.payrails.io secure frame under the
1116
+ // session's vaultConfiguration.encryptionPublicKey. That key is per session, reaches us only
1117
+ // through the agent's page and cannot be pinned, so the mode is device_encrypt: the cardholder's
1118
+ // device encrypts the real card and sends this request itself (payrails-replay.js), and the
1119
+ // ciphertext never returns to the page. Dynamic payment-method forms save non-card instruments
1120
+ // on the same URL with no data.encryptedData: jsonCardFields claims only a card save and
1121
+ // passWithoutCard lets the rest continue untouched. payrails.js holds the request guard, the
1122
+ // card-on-file policy, the session-key and workspace checks and the answer rules. NOT here:
1123
+ // /public/payment/instruments/tokenize (web-cse used directly), api.payrails.io and the
1124
+ // execution authorize links (card-form payments, stored-card CVC), and assets.payrails.io.
1125
+ // `capability` keeps the entry out of BUILTIN_REGISTRY and every org until one opts in; the API
1126
+ // serves it only to a client that also asks for modes=device_encrypt. The two staging hosts are
1127
+ // pinned to sandbox rows (S7). Autopilot refuses it by operation (payrails.device_encrypted_card).
1128
+ capability: "payrails_device_encrypt",
1129
+ match: "(?:api-pub|api-pub\\.staging|sandbox-api-pub\\.staging)\\.payrails\\.io/public/payment/instruments(?![\\w/.-])",
1130
+ hosts: ["^api-pub\\.payrails\\.io$", "^api-pub\\.staging\\.payrails\\.io$", "^sandbox-api-pub\\.staging\\.payrails\\.io$"],
1131
+ sandboxHosts: ["^api-pub\\.staging\\.payrails\\.io$", "^sandbox-api-pub\\.staging\\.payrails\\.io$"],
1132
+ hostEnvironmentPinned: true,
1133
+ encoding: "json",
1134
+ // body shape; the SDK sends text/plain, replayed verbatim
1135
+ passthroughHeaders: ["^authorization$", "^x-idempotency-key$", "^x-client-version$", "^x-client-type$"],
1136
+ jsonCardFields: [["data", "encryptedData"]],
1137
+ passWithoutCard: "(?:api-pub|api-pub\\.staging|sandbox-api-pub\\.staging)\\.payrails\\.io/public/payment/instruments",
1138
+ clientSideEncrypted: true,
1139
+ // older SDKs read this and refuse locally
1140
+ mode: "device_encrypt",
1141
+ deviceEncrypt: {
1142
+ scheme: "payrails-jwe",
1143
+ // RSA-OAEP-256 + A256CBC-HS512, compact
1144
+ key: "session",
1145
+ // from the init payload the runtime captured, never pinned
1146
+ at: ["data", "encryptedData"],
1147
+ keyBits: [2048, 3072, 4096],
1148
+ // e = 65537; the wrapped key's length must equal the modulus length
1149
+ futureUsage: ["CardOnFile", "UnscheduledCardOnFile"],
1150
+ expiryYear: "YY"
1151
+ // Blacklane's single MM/YY field
1152
+ }
1153
+ },
1154
+ {
1155
+ psp: "elavon_converge",
1156
+ // Elavon Converge Hosted Payment Page (redirect, pageType hpp), NY DMV. Converge's
1157
+ // own AngularJS page posts the card as same-origin JSON to /hosted-payments/service/payment/hpp/process.
1158
+ // PAN@ paymentData.ssl_card_number (digits), expiry@ paymentData.ssl_exp_date (MMYY), CVC@
1159
+ // paymentData.ssl_cvv2cvc2. No client-side encryption; the session rides in the body (`context`).
1160
+ // Sources: assets/hpp-2.505.07.js, byte-identical on both hosts, reviewed 2026-09-25. The same URL
1161
+ // carries wallet, ACH and loan payments and the follow-ups after 3DS2, Pay Defense or a surcharge
1162
+ // quote: the Converge body gate decides (elavon-converge.js convergeBodyVerdict, which card-fields.js
1163
+ // asks first, so the SDK's generated copy carries it). The lightbox (hpm/process), Checkout.js
1164
+ // (hpe/process) and every other hpp/ call fall out at the exact path; (?![\w/.%-]) is the right edge
1165
+ // for the SDK's unanchored test. Hosts are two literal labels, never *.convergepay.com (www and demo
1166
+ // are the merchant web UI).
1167
+ // Ships dark: served only to a client that declares `converge_hpp_process`, gated off for every org
1168
+ // until an operator allowlists one, never replayed by autopilot (EXCLUDED_OPERATIONS).
1169
+ capability: "converge_hpp_process",
1170
+ match: "api(?:\\.demo)?\\.convergepay\\.com/hosted-payments/service/payment/hpp/process(?![\\w/.%-])",
1171
+ hosts: ["^api\\.convergepay\\.com$", "^api\\.demo\\.convergepay\\.com$"],
1172
+ // api.demo is Converge's demo environment. Pinned (S7): a create refuses it on a live row and the
1173
+ // production host on a test row, and the device sends only documented test cards to it.
1174
+ sandboxHosts: ["^api\\.demo\\.convergepay\\.com$"],
1175
+ hostEnvironmentPinned: true,
1176
+ encoding: "json",
1177
+ // The device sends Content-Type JSON itself; no Origin, Cookie, Referer or XSRF header is replayed.
1178
+ passthroughHeaders: [],
1179
+ jsonCardFields: [["paymentData", "ssl_card_number"]],
1180
+ // An electronic check or financing payment on the same URL carries no card and continues untouched.
1181
+ passWithoutCard: "api(?:\\.demo)?\\.convergepay\\.com/hosted-payments/service/payment/hpp/process"
1182
+ },
1183
+ {
1184
+ psp: "wspay",
1185
+ // WSPay Components (WSPay's build of Monri Components 1.6.0), Valamar's booking payment.
1186
+ // PAN@ payment_method.data.pan, expiry YYMM @ .expiration_date, cvv @ .cvv. The processor
1187
+ // iframe (/v2/js/payment-method-component-dynamic.html) XHRs POST /v2/payment/{client_secret}/confirm
1188
+ // with `Authorization: WP3-v2-Client <authenticity token>` (proxy /dist/monri.js sha256 33fb5b45...).
1189
+ // /confirm is the only card route the proxy serves: /v2/payment/{cs}/token and /v2/temp-tokenize
1190
+ // answer 404 exactly like bogus control paths (card-free probes, 2026-09-23). The same URL also
1191
+ // carries saved_card and temp_card_id bodies with no new card, so wspay.js validates the whole
1192
+ // body, writes only the three card fields and never uses the generic walk; there is no `compose`
1193
+ // on purpose (it widens what the generic walk would call a card). The client_secret segment is a
1194
+ // per-payment bearer secret. (?![\w/-]) is the right edge for the SDK's unanchored test.
1195
+ // NOT here: ipg.monri.com / ipgtest.monri.com (Monri direct: no CORS headers, behind Cloudflare,
1196
+ // needs the relay; a separate `monri` entry), ipgdev.monri.com, the ipg[test].webteh.hr hosts in
1197
+ // the bundle's whitelist (they do not resolve) and form[test].wspay.biz (WSPay Form, another product).
1198
+ // Ships dark: the recognizer is served only to a client that declares `wspay_confirm` for an
1199
+ // org an operator allowlisted, the processor is gated off for every other org, and autopilot
1200
+ // never replays it (EXCLUDED_OPERATIONS). GET /coverage and POST /coverage/assess describe it
1201
+ // on the same rule; only the preflight rules, which identify its scripts and frames, name
1202
+ // WSPay to every client. A confirm that asks WSPay to keep the card on file is refused unless
1203
+ // the caller carries the cardholder's consent (wspay.js).
1204
+ capability: "wspay_confirm",
1205
+ match: "proxy(?:-test)?\\.wspay\\.biz/v2/payment/[A-Za-z0-9_-]{1,128}/confirm(?![\\w/-])",
1206
+ hosts: ["^proxy\\.wspay\\.biz$", "^proxy-test\\.wspay\\.biz$"],
1207
+ // proxy-test is WSPay's test platform. Pinned (S7): a create refuses it on a live row and
1208
+ // proxy.wspay.biz on a test row, and the device sends it only the shared public network test
1209
+ // cards (test-pans.js), never a real card. WSPay's own test card list is unverified.
1210
+ sandboxHosts: ["^proxy-test\\.wspay\\.biz$"],
1211
+ hostEnvironmentPinned: true,
1212
+ encoding: "json",
1213
+ // The iframe's own Accept is load-bearing (Worldpay precedent); cookie/origin/referer never ride.
1214
+ passthroughHeaders: ["^authorization$", "^accept$"]
1215
+ },
1216
+ {
1217
+ psp: "shiji_sts",
1218
+ // Shiji Payment Solutions STS, the card leg of the MyCheck Wallet V3 (Shiji Group) that La Quinta
1219
+ // by Wyndham loads in its booking page. sts.proxy.v2.1.js encrypts the PAN digits and the "MM/YY"
1220
+ // expiry, each on its own, with JSEncrypt (RSAES-PKCS1-v1_5) under the RSA-1024 key it hardcodes,
1221
+ // and fetch-POSTs application/json {accessToken, pan, expires, keySequence?} to /v1/token/getTokenId;
1222
+ // after MyCheck's payment-methods call it posts {accessToken, cvv, keySequence?} to
1223
+ // /v1/token/getCvvId. ONE entry covers both paths: they share the host, and resolveRecognizerForUrl
1224
+ // takes the first definition by host, so a second entry would never be reached. shiji-sts.js judges
1225
+ // which a request is: getTokenId is the one prompt, getCvvId a companion that never prompts and is
1226
+ // continued only when bound to the getTokenId the runtime continued. The device encrypts under the
1227
+ // key shiji-sts.js pins (SPKI SHA-256 c7846a0f...5a469ff7), never one from a row, a request or a
1228
+ // page, and the runtime swaps the ciphertexts at the body root: cse.at '' is the root, which the
1229
+ // Adyen substitution refuses, so only substituteShijiSts writes this body. No auth header: the
1230
+ // accessToken rides in the body. NOT allowlisted: iframe.vault.cn.{prod,uat}.shijipayment.cn (in the
1231
+ // proxy's table, never chosen by the wallet) and api.vault.eu.prod.shijipayment.com (not the
1232
+ // browser's host). `capability` keeps the entry out of BUILTIN_REGISTRY, serves it only to a client
1233
+ // that declares shiji_sts_pinned_key, and leaves it off for every org until one is opted in. The UAT
1234
+ // host is the sandbox host and the environment is pinned (S7): UAT only on sandbox rows, with
1235
+ // documented test cards. Every getTokenId is refused as card on file (a hotel guarantee) until the
1236
+ // consent decision is made (shiji-sts.js SHIJI_STS_KEEP_ON_FILE). `(?![\w/-])` ends the path as
1237
+ // on mercado_pago and paysafe: a consumer that tests `match` unanchored never takes
1238
+ // /v1/token/getTokenIdX or /v1/token/getTokenId/x for a card request.
1239
+ capability: "shiji_sts_pinned_key",
1240
+ encryptedCardFields: { number: "pan", expiry: "expires", cvc: "cvv" },
1241
+ match: "iframe\\.vault\\.eu\\.(?:prod|uat)\\.shijipayment\\.com/v1/token/(?:getTokenId|getCvvId)(?![\\w/-])",
1242
+ hosts: ["^iframe\\.vault\\.eu\\.prod\\.shijipayment\\.com$", "^iframe\\.vault\\.eu\\.uat\\.shijipayment\\.com$"],
1243
+ sandboxHosts: ["^iframe\\.vault\\.eu\\.uat\\.shijipayment\\.com$"],
1244
+ hostEnvironmentPinned: true,
1245
+ encoding: "json",
1246
+ passthroughHeaders: [],
1247
+ clientSideEncrypted: true,
1248
+ mode: "cse",
1249
+ cse: { scheme: "rsa-pkcs1v15", at: "", fields: ["pan", "expires", "cvv"] }
1250
+ },
1251
+ {
1252
+ psp: "worldline_mycheckout",
1253
+ // Worldline Connect MyCheckout, the hosted payment page DHL Express's MyDHL+ sends its card
1254
+ // payments to. The page submits the card as a top-level form POST to /checkout on its own host
1255
+ // (a Document navigation, like Tranzila's), so the cardholder's device rebuilds that form with
1256
+ // the real card and submits it itself (mode hosted_form) and the paused navigation is
1257
+ // answered with the submission notice. The same URL takes the page's cancel and every non-card
1258
+ // payment product; only a body with cardNumber is a card request, and the rest continue
1259
+ // untouched (cardFields, passWithoutCard). A card body is taken over only in the one plain
1260
+ // shape worldline-mycheckout.js admits (worldlineMyCheckoutRequestRefusal): no card kept for
1261
+ // later, no wallet, a covered card product. The form names no amount (the merchant fixed it
1262
+ // when it created the hosted checkout), so the agent's amount is the price the cardholder
1263
+ // approves. `payment.` is the subdomain Worldline says always works, on pay1 (Europe) and pay2
1264
+ // (US) and their pre-production twins; a merchant's own MyCheckout subdomain is not admitted.
1265
+ // resolveRecognizerForUrl takes only the four endpoints written exactly. `capability` keeps
1266
+ // the entry out of BUILTIN_REGISTRY, serves it only to a client that declares
1267
+ // worldline_mycheckout_form, and leaves it off for every org until one is opted in; the
1268
+ // pre-production hosts take only test rows and documented test cards (hostEnvironmentPinned).
1269
+ capability: "worldline_mycheckout_form",
1270
+ match: "payment\\.pay[12](?:\\.preprod)?\\.checkout\\.worldline-solutions\\.com/checkout(?![\\w/.-])",
1271
+ hosts: [
1272
+ "^payment\\.pay1\\.checkout\\.worldline-solutions\\.com$",
1273
+ "^payment\\.pay2\\.checkout\\.worldline-solutions\\.com$",
1274
+ "^payment\\.pay1\\.preprod\\.checkout\\.worldline-solutions\\.com$",
1275
+ "^payment\\.pay2\\.preprod\\.checkout\\.worldline-solutions\\.com$"
1276
+ ],
1277
+ sandboxHosts: ["^payment\\.pay1\\.preprod\\.checkout\\.worldline-solutions\\.com$", "^payment\\.pay2\\.preprod\\.checkout\\.worldline-solutions\\.com$"],
1278
+ hostEnvironmentPinned: true,
1279
+ encoding: "form",
1280
+ passthroughHeaders: [],
1281
+ cardFields: ["cardNumber"],
1282
+ passWithoutCard: "payment\\.pay[12](?:\\.preprod)?\\.checkout\\.worldline-solutions\\.com/checkout",
1283
+ mode: "hosted_form",
1284
+ hostedForm: {
1285
+ required: ["publicMerchantId", "token", "requestToken", "idempotenceKey", "doPayment"],
1286
+ // expiryDate is one MM/YY field; the device writes it in the page's own delimiter.
1287
+ card: { number: "cardNumber", expiry: "expiryDate", cvc: "cvv" },
1288
+ // The merchant and the hosted checkout: one prompt per hosted checkout.
1289
+ dedupe: ["publicMerchantId", "token"],
1290
+ // A checked "remember" asks Worldline to keep the card for later purchases.
1291
+ token: "remember"
1292
+ }
661
1293
  }
662
1294
  ]);
663
- var PSP_RECOGNIZERS = deepFreeze(PROCESSOR_DEFINITIONS.map(({ compose, encryptedCardFields, ...definition }) => definition));
1295
+ var PSP_RECOGNIZERS = deepFreeze(PROCESSOR_DEFINITIONS.map(({ compose, encryptedCardFields, deviceSteps, deviceEncrypt, ...definition }) => definition));
664
1296
  var PSP_CLIENT_TABLE = deepFreeze(PROCESSOR_DEFINITIONS.map((definition) => ({
665
1297
  psp: definition.psp,
666
1298
  match: new RegExp(definition.match, "i"),
@@ -669,21 +1301,31 @@ var PSP_CLIENT_TABLE = deepFreeze(PROCESSOR_DEFINITIONS.map((definition) => ({
669
1301
  headers: definition.passthroughHeaders.map((source) => new RegExp(source, "i")),
670
1302
  ...definition.sandboxHosts ? { sandboxHosts: definition.sandboxHosts.map((source) => new RegExp(source, "i")) } : {},
671
1303
  ...definition.hostEnvironmentPinned ? { hostEnvironmentPinned: true } : {},
1304
+ ...definition.request ? { request: definition.request } : {},
672
1305
  ...definition.mode ? { mode: definition.mode } : {},
673
1306
  ...definition.clientSideEncrypted ? { clientSideEncrypted: true } : {},
674
1307
  ...definition.compose ? { compose: definition.compose } : {},
675
1308
  ...definition.encryptedCardFields ? { cse: { fields: definition.encryptedCardFields } } : {},
676
- ...definition.hostedForm ? { form: definition.hostedForm.card } : {}
1309
+ ...definition.caseInsensitiveFormKeys ? { caseInsensitiveFormKeys: true } : {},
1310
+ // The device's copy of the form's card keys (forms.js hostedFormPairs), with the card roles a
1311
+ // template may lack (`optional`), so the vault fills exactly what the definition names.
1312
+ ...definition.hostedForm ? { form: {
1313
+ ...definition.hostedForm.card,
1314
+ ...definition.hostedForm.optional ? { optional: definition.hostedForm.optional } : {}
1315
+ } } : {},
1316
+ ...definition.hostedForm?.cardIn ? { formCardIn: definition.hostedForm.cardIn } : {},
1317
+ ...definition.deviceSteps ? { deviceSteps: Object.fromEntries(Object.entries(definition.deviceSteps).map(([step, source]) => [step, new RegExp(source, "i")])) } : {},
1318
+ ...definition.deviceEncrypt ? { deviceEncrypt: definition.deviceEncrypt } : {}
677
1319
  })));
678
1320
  function buildBuiltinRegistry(recognizers) {
679
- return recognizers.filter((definition) => !definition.capability).map(({ cse, hostedForm, ...definition }) => ({
1321
+ return recognizers.filter((definition) => !definition.capability).map(({ cse, hostedForm, deviceEncrypt, ...definition }) => ({
680
1322
  ...definition,
681
1323
  match: new RegExp(definition.match, "i"),
682
1324
  passthroughHeaders: definition.passthroughHeaders.map((source) => new RegExp(source, "i"))
683
1325
  }));
684
1326
  }
685
1327
  var BUILTIN_REGISTRY = deepFreeze(buildBuiltinRegistry(PSP_RECOGNIZERS));
686
- var CHECKOUT_MODES = deepFreeze(["token", "cse", "hosted_form"]);
1328
+ var CHECKOUT_MODES = deepFreeze(["token", "cse", "hosted_form", "card_endpoint", "device_encrypt"]);
687
1329
  function recognizerByPsp(psp) {
688
1330
  return typeof psp === "string" ? PSP_CLIENT_TABLE.find((entry) => entry.psp === psp) ?? null : null;
689
1331
  }
@@ -694,6 +1336,116 @@ function trustedClientRecognizer(pspOrEntry) {
694
1336
  throw new Error("Refusing to pay: unknown payment processor.");
695
1337
  return definition;
696
1338
  }
1339
+ // src/datatrans.js
1340
+ var DATATRANS_HOSTS = Object.freeze(["pay.datatrans.com", "pay.sandbox.datatrans.com"]);
1341
+ var DATATRANS_REFUSAL_REASONS = Object.freeze(["unsupported", "card_on_file", "brand_mismatch", "unregistered_merchant"]);
1342
+ var DATATRANS_REGISTRATION_POLICIES = Object.freeze(["refuse", "disclose", "agentcard_single_use"]);
1343
+ var DATATRANS_REVIEWED_MERCHANT_IDS = Object.freeze({
1344
+ "pay.datatrans.com": Object.freeze([]),
1345
+ "pay.sandbox.datatrans.com": Object.freeze(["1110022968", "1100007006"])
1346
+ });
1347
+ var DATATRANS_PAYMENT_METHODS = Object.freeze(["VIS", "ECA", "AMX", "DIN", "DIS", "JCB", "CUP", "MAU", "UAP", "DNK"]);
1348
+ var DATATRANS_TEST_PANS = Object.freeze([
1349
+ "4242424242424242",
1350
+ "4900000000000086",
1351
+ "4900000000000003",
1352
+ "5404000000000001",
1353
+ "5200000000000007",
1354
+ "5200000000000080",
1355
+ "375811111111115",
1356
+ "375000000000007",
1357
+ "375811111111123",
1358
+ "36168002586009",
1359
+ "36167719110012",
1360
+ "6011000000000004",
1361
+ "3569990010030442",
1362
+ "3569990010030400",
1363
+ "6362970000457013",
1364
+ "3841000000000007",
1365
+ "6200104444444447",
1366
+ "6210946888060008",
1367
+ "6759000000000018",
1368
+ "6759000000000026",
1369
+ "4000001000000034",
1370
+ "4000001000000018",
1371
+ "4000001000000042",
1372
+ "4000001000000026",
1373
+ "5100001000000022",
1374
+ "5100001000000048",
1375
+ "5100001000000014",
1376
+ "5100001000000030",
1377
+ "340000100000024",
1378
+ "340000100000040",
1379
+ "340000100000016",
1380
+ "340000100000032",
1381
+ "36000010000022",
1382
+ "3550998599961037"
1383
+ ]);
1384
+ // src/amadeus-checkout.js
1385
+ var AMADEUS_CARD_URLS = Object.freeze({
1386
+ production: Object.freeze({
1387
+ sdk: Object.freeze(["https://paypages.payment.amadeus.com/1ASIATP/ARIAPP/pay"]),
1388
+ dcp: Object.freeze(["https://paypages.payment.amadeus.com/1ASIATP/ATPDCP/collect"])
1389
+ }),
1390
+ // pdt, uat, mig and skl. DCP was seen on the production path only, so the test host takes no store.
1391
+ sandbox: Object.freeze({
1392
+ sdk: Object.freeze([
1393
+ "https://paypages.test.payment.amadeus.com/1ASIATP/ARIAPP/pay",
1394
+ "https://paypages.test.payment.amadeus.com/1ASIATPU/ARIAPP/pay",
1395
+ "https://paypages.test.payment.amadeus.com/1ASIATPM/ARIAPP/pay",
1396
+ "https://paypages.test.payment.amadeus.com/1ASIATPK/ARIAPP/pay"
1397
+ ]),
1398
+ dcp: Object.freeze([])
1399
+ })
1400
+ });
1401
+ var AMADEUS_MERCHANT_EXPIRY_POLICIES = Object.freeze(["refuse", "fill"]);
1402
+ var AMADEUS_REFUSAL_REASONS = Object.freeze([
1403
+ "unsupported",
1404
+ "card_on_file",
1405
+ "split_tender",
1406
+ "installments",
1407
+ "currency_conversion",
1408
+ "amadeus_3ds",
1409
+ "saved_card",
1410
+ "vendor_mismatch",
1411
+ "header_binding",
1412
+ "merchant_held_expiry",
1413
+ "dcp_field_config_unreviewed"
1414
+ ]);
1415
+ var MESSAGES = Object.freeze({
1416
+ unsupported: "Refusing to pay: unsupported Amadeus card request.",
1417
+ card_on_file: "Refusing to pay: this Amadeus payment would let the merchant keep your card on file, which needs your consent first. Nothing was sent.",
1418
+ split_tender: "Refusing to pay: this Amadeus payment splits the total across more than one payment method. Nothing was sent.",
1419
+ installments: "Refusing to pay: this Amadeus payment asks to pay in installments. Nothing was sent.",
1420
+ currency_conversion: "Refusing to pay: this Amadeus payment converts the total into another currency. Nothing was sent.",
1421
+ amadeus_3ds: "Refusing to pay: this Amadeus payment set up its card check for a different card. Nothing was sent.",
1422
+ saved_card: "Refusing to pay: this Amadeus payment uses a card saved with the merchant, not your Vault card. Nothing was sent.",
1423
+ vendor_mismatch: "Refusing to pay: this Amadeus payment names a card network that is not your card's. Nothing was sent.",
1424
+ header_binding: "Refusing to pay: this Amadeus card form does not belong to the merchant you approved. Nothing was sent.",
1425
+ merchant_held_expiry: "Refusing to pay: this merchant sends your card's expiry date separately, which Agentcard cannot fill yet. Nothing was sent.",
1426
+ dcp_field_config_unreviewed: "Refusing to pay: Agentcard has not reviewed this merchant's Amadeus card form yet. Nothing was sent."
1427
+ });
1428
+ var SDK_FLAVORS = Object.freeze(["Core-Sdk", "Angular-Web-Sdk"]);
1429
+ var LABEL = "[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?";
1430
+ var SDK_HOST = new RegExp(`^${LABEL}(?:\\.${LABEL})+(?::[0-9]{1,5})?$`, "i");
1431
+ var SDK_HEADERS = Object.freeze(["amadeus-checkout-sdk-version", "amadeus-checkout-sdk-host", "amadeus-checkout-sdk-flavor"]);
1432
+ var SDK_DATA_KEYS = Object.freeze(["mopid", "mopdata", "fingerprint"]);
1433
+ var SDK_MOPDATA_KEYS = Object.freeze(["pan", "CVV", "holdername", "expmonth", "expyear", "vendor", "address", "contact"]);
1434
+ var SDK_MOPDATA_REFUSALS = Object.freeze({
1435
+ prefill_index: "saved_card",
1436
+ installmentPlansID: "installments",
1437
+ selectedInstallmentPlan: "installments",
1438
+ options: "currency_conversion",
1439
+ tdsSessionId: "amadeus_3ds",
1440
+ tdsDeviceInformation: "amadeus_3ds"
1441
+ });
1442
+ var AMADEUS_DCP_REVIEWED_KEYS = Object.freeze(["vendor", "pan", "expdate", "owner", "cvv", "address", "city", "zipCode", "country", "state"]);
1443
+ var DCP_TEXT_KEYS = Object.freeze(["address", "city", "zipCode", "country", "state"]);
1444
+ var NETWORKS = Object.freeze(["visa", "mastercard", "amex"]);
1445
+ var DECLINE_LABELS = Object.freeze(["label_error_payment", "label_error_bin", "label_error_bin_vendor", "label_error_bin_type"]);
1446
+ var EXPIRED_LABELS = Object.freeze(["session_timeout", "ppid_expired"]);
1447
+ var REF_KEYS = Object.freeze(["recloc", "orderId", "mopId", "pri", "approvalcode", "externalId", "paymentMerchantReference", "prr"]);
1448
+ var PAYMENT_INFORMATION_KEYS = Object.freeze(["approvalcode", "pri", "externalId", "mopId"]);
697
1449
  // src/recognition.js
698
1450
  var PATTERN_WITHOUT_CARD_FIELDS = Object.freeze({
699
1451
  stripe: "api\\.stripe\\.com/v1/(payment_methods|tokens|setup_intents/seti_\\w+/confirm|payment_intents/pi_\\w+/confirm)"
@@ -704,6 +1456,7 @@ var WITHOUT_CHECKOUT_SESSIONS = Object.freeze({
704
1456
  passWithoutCard: "api\\.stripe\\.com/v1/(sources|confirmation_tokens)"
705
1457
  })
706
1458
  });
1459
+ var ONLY_WITH_CARD_FIELDS = Object.freeze(["amadeus_checkout"]);
707
1460
  // src/request-policy.js
708
1461
  var HEADER_NEVER_FORWARD = /^(cookie|set-cookie|authorization2|proxy-authorization|host|content-length|origin|referer)$/i;
709
1462
  var ALLOWED_MEDIA_TYPES = {
@@ -738,6 +1491,8 @@ function contentTypeFor(pspOrEntry, headers) {
738
1491
  function replayHeaders(pspOrEntry, captured = {}) {
739
1492
  const rec = trustedClientRecognizer(pspOrEntry);
740
1493
  const headers = { "content-type": contentTypeFor(rec, captured) };
1494
+ if (rec.psp === "creditguard")
1495
+ headers.accept = "application/json";
741
1496
  for (const [name, value] of Object.entries(captured)) {
742
1497
  if (rec.headers.some((pattern) => pattern.test(name)) && !HEADER_NEVER_FORWARD.test(name))
743
1498
  headers[name] = value;