@agent-cards/sdk 0.21.0 → 0.22.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 (103) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/PREFLIGHT.md +30 -0
  3. package/README.md +1070 -21
  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 +283 -49
  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.d.ts +177 -0
  18. package/dist/card-endpoint.js +286 -0
  19. package/dist/card-fields.generated.d.ts +5 -3
  20. package/dist/card-fields.generated.js +284 -7
  21. package/dist/cdp.d.ts +5 -1
  22. package/dist/cdp.js +841 -135
  23. package/dist/client.d.ts +403 -19
  24. package/dist/client.js +949 -98
  25. package/dist/creditguard.generated.d.ts +79 -0
  26. package/dist/creditguard.generated.js +662 -0
  27. package/dist/cse-body.js +11 -1
  28. package/dist/datatrans.d.ts +96 -0
  29. package/dist/datatrans.generated.d.ts +64 -0
  30. package/dist/datatrans.generated.js +426 -0
  31. package/dist/datatrans.js +178 -0
  32. package/dist/elavon-converge.d.ts +37 -0
  33. package/dist/elavon-converge.generated.d.ts +49 -0
  34. package/dist/elavon-converge.generated.js +439 -0
  35. package/dist/elavon-converge.js +84 -0
  36. package/dist/eprotect.d.ts +152 -0
  37. package/dist/eprotect.generated.d.ts +77 -0
  38. package/dist/eprotect.generated.js +498 -0
  39. package/dist/eprotect.js +222 -0
  40. package/dist/hosted-form.d.ts +3 -2
  41. package/dist/hosted-form.js +3 -2
  42. package/dist/index.d.ts +17 -3
  43. package/dist/index.js +6 -1
  44. package/dist/juspay-gate.d.ts +82 -0
  45. package/dist/juspay-gate.js +126 -0
  46. package/dist/juspay.generated.d.ts +89 -0
  47. package/dist/juspay.generated.js +705 -0
  48. package/dist/lifecycle.d.ts +57 -6
  49. package/dist/lifecycle.js +119 -8
  50. package/dist/merchant-card-endpoints.generated.d.ts +63 -0
  51. package/dist/merchant-card-endpoints.generated.js +1103 -0
  52. package/dist/merchant-hosted.d.ts +4 -1
  53. package/dist/merchant-hosted.js +5 -2
  54. package/dist/merchant-session-probe.d.ts +48 -0
  55. package/dist/merchant-session-probe.js +53 -0
  56. package/dist/merchant-session.generated.d.ts +69 -0
  57. package/dist/merchant-session.generated.js +919 -0
  58. package/dist/payrails.d.ts +133 -0
  59. package/dist/payrails.generated.d.ts +73 -0
  60. package/dist/payrails.generated.js +596 -0
  61. package/dist/payrails.js +305 -0
  62. package/dist/pelecard.d.ts +32 -0
  63. package/dist/pelecard.generated.d.ts +32 -0
  64. package/dist/pelecard.generated.js +283 -0
  65. package/dist/pelecard.js +42 -0
  66. package/dist/pre-claim.d.ts +72 -2
  67. package/dist/pre-claim.js +857 -5
  68. package/dist/preflight-catalog.json +2218 -287
  69. package/dist/preflight-schemas.json +179 -6
  70. package/dist/preflight.generated.d.ts +1 -1
  71. package/dist/preflight.generated.js +233 -4
  72. package/dist/preparation.d.ts +5 -2
  73. package/dist/preparation.js +36 -10
  74. package/dist/prepared-processor.d.ts +84 -5
  75. package/dist/prepared-processor.js +147 -6
  76. package/dist/primer.d.ts +53 -0
  77. package/dist/primer.generated.d.ts +38 -0
  78. package/dist/primer.generated.js +624 -0
  79. package/dist/primer.js +82 -0
  80. package/dist/registry.d.ts +100 -8
  81. package/dist/registry.js +85 -11
  82. package/dist/shiji-sts.d.ts +144 -0
  83. package/dist/shiji-sts.generated.d.ts +72 -0
  84. package/dist/shiji-sts.generated.js +913 -0
  85. package/dist/shiji-sts.js +222 -0
  86. package/dist/stripe-checkout.generated.d.ts +1 -1
  87. package/dist/stripe-checkout.generated.js +699 -9
  88. package/dist/stripe-setup.d.ts +16 -0
  89. package/dist/stripe-setup.js +61 -0
  90. package/dist/substitutions.generated.js +187 -29
  91. package/dist/verifone.d.ts +68 -0
  92. package/dist/verifone.generated.d.ts +51 -0
  93. package/dist/verifone.generated.js +1401 -0
  94. package/dist/verifone.js +119 -0
  95. package/dist/voice-types.d.ts +27 -0
  96. package/dist/voice.d.ts +6 -1
  97. package/dist/voice.js +6 -1
  98. package/dist/wspay.d.ts +41 -0
  99. package/dist/wspay.generated.d.ts +41 -0
  100. package/dist/wspay.generated.js +370 -0
  101. package/dist/wspay.js +65 -0
  102. package/examples/preflight/kernel-native/inventory.json +1 -1
  103. package/package.json +3 -3
@@ -1,5 +1,5 @@
1
1
  // Generated from @agent-cards/payment-core. Do not edit.
2
- // source-sha256: 3a36f98936b5a93687dd4a052d1d4513935a093736b19475f023b5a0847c6b4a
2
+ // source-sha256: ed01cf8d69fe6aa9e1be54dfd1a9b1e20cdfcb3a498f4b8a934726e38a1639ba
3
3
  import { CHECKOUT_PREFLIGHT_CAPABILITIES } from './preflight-capabilities.generated.js';
4
4
  /** Advisory page discovery. These rules never admit a payment destination. */
5
5
  export const CHECKOUT_PREFLIGHT_VERSION = '1';
@@ -68,6 +68,14 @@ RULES.push({ id: 'fiserv-commercehub-payment-fields', psp: 'fiserv', kinds: ['sc
68
68
  sources: [fiservSource('https://commercehub-checkout.fiservapps.com/sdk/3.8.14/payment-fields.js'), fiservSource('https://orangepay-ecommerce.hdpayments.homedepot.com/env.js')] }, { id: 'fiserv-commercehub-checkout-script', psp: 'fiserv', kinds: ['script'], hostname: /^commercehub-checkout\.fiservapps\.com$/, pathname: /^\/sdk\/[0-9]+\.[0-9]+\.[0-9]+\/checkout\.js$/, origin: 'https://commercehub-checkout.fiservapps.com', path_pattern: '/sdk/:version/checkout.js',
69
69
  sources: [fiservSource('https://developer.fiserv.com/product/CommerceHub/docs/Online-Commerce/Integration-Options/Hosted-Checkout/Hosted-Checkout-Version-Release')] }, { id: 'fiserv-secure-data-capture-frame', psp: 'fiserv', kinds: ['frame', 'iframe', 'document'], hostname: /^commercehub-secure-data-capture\.fiservapps\.com$/, pathname: /^\/sdk-secure\/[0-9]+\.[0-9]+\.[0-9]+\/iframe\.html$/, origin: 'https://commercehub-secure-data-capture.fiservapps.com', path_pattern: '/sdk-secure/:version/iframe.html',
70
70
  sources: [fiservSource('https://commercehub-checkout.fiservapps.com/sdk/3.8.14/payment-fields.js'), fiservSource('https://commercehub-secure-data-capture.fiservapps.com/sdk-secure/3.8.14/iframe.html')] });
71
+ // Verifone eCommerce, read 2026-09-25 from Verifone's own hosts and docs: a merchant page
72
+ // that encrypts the card itself (Secure Card Capture) loads verifone.js from Verifone's
73
+ // jsclient host for its region, byte-identical on every host. Verifone ships dark (its
74
+ // definition names a capability), so the bundled catalog declares no support for it:
75
+ // the script identifies verifone and the result stays unknown.
76
+ const verifoneSource = (reference) => ({ kind: 'primary_source', reference, reviewed_on: '2026-09-25' });
77
+ RULES.push({ id: 'verifone-secure-card-capture-script', psp: 'verifone', kinds: ['script'], hostname: /^us\.jsclient\.verifone\.cloud$/, pathname: /^\/verifone\.js$/, origin: 'https://us.jsclient.verifone.cloud', path_pattern: '/verifone.js',
78
+ sources: [verifoneSource('https://us.jsclient.verifone.cloud/verifone.js'), verifoneSource('https://verifone.cloud/docs/online-payments/securecardcapture')] });
71
79
  // GMO Payment Gateway PG Multipayment (dark: its processor declares a capability, so the bundled
72
80
  // catalog does not list it and these signals stay unknown until a client opts in). Token v2's
73
81
  // mp-token.js identifies the processor. Token v1's ext/js/token.js (a JSONP GET), GMO Elements'
@@ -98,6 +106,173 @@ const cybersourceSources = [
98
106
  RULES.push({ id: 'cybersource-flex-microform-script', psp: 'cybersource_flex', kinds: ['script'], hostname: /^flex\.cybersource\.com$/, pathname: /^\/microform\/bundle\/v2(?:\.[0-9]+\.[0-9]+)?\/flex-microform\.min\.js$/, origin: 'https://flex.cybersource.com', path_pattern: '/microform/bundle/v2{,.:minor.:patch}/flex-microform.min.js',
99
107
  sources: cybersourceSources }, { id: 'cybersource-flex-microform-field', psp: 'cybersource_flex', kinds: ['frame', 'iframe', 'document'], hostname: /^flex\.cybersource\.com$/, pathname: /^\/microform\/bundle\/v2\.[0-9]+\.[0-9]+\/iframe\.html$/, origin: 'https://flex.cybersource.com', path_pattern: '/microform/bundle/v:version/iframe.html',
100
108
  sources: cybersourceSources });
109
+ // Juspay HyperCheckout: Juspay's own hosted payment page (the Session API's payment_links.web),
110
+ // which a merchant embeds in an iframe (IndiGo's payment step). The card request that page makes
111
+ // has not been observed, so the Vault does not take it over, and the rule tells the agent so
112
+ // before it types a placeholder. Juspay is served dark, so no catalog processor entry backs the
113
+ // candidate and the result stays unknown either way.
114
+ RULES.push({ id: 'juspay-hypercheckout-payment-page', psp: 'juspay', kinds: ['document', 'frame', 'iframe'], hostname: /^api\.juspay\.in$/, pathname: /^\/orders\/ordeh_[A-Za-z0-9]+\/payment-page$/, origin: 'https://api.juspay.in', path_pattern: '/orders/:order/payment-page',
115
+ sources: [{ kind: 'primary_source', reference: 'https://juspay.io/in/docs/api-reference/docs/express-checkout/session', reviewed_on: '2026-09-23' }],
116
+ variant_unverified: 'The Juspay HyperCheckout payment page at /orders/:order/payment-page sends the card from Juspay\'s own page, a request the Vault does not take over.' });
117
+ // Pelecard Iframe/Redirect 2.0, reviewed from Pelecard's public payment page scripts and three archived
118
+ // payment pages on 2026-09-25. The processor ships dark: until the bundled catalog serves pelecard, a
119
+ // lone Pelecard signal names the processor and stays unknown. The legacy 1.0 page on
120
+ // gateway.pelecard.biz posts the card as a top-level form and stays unknown through `variant_unverified`.
121
+ const pelecardSource = (reference) => ({ kind: 'primary_source', reference, reviewed_on: '2026-09-25' });
122
+ RULES.push({ id: 'pelecard-payment-page', psp: 'pelecard', kinds: ['document', 'frame', 'iframe'], hostname: /^gateway21\.pelecard\.biz$/, pathname: /^\/PaymentGW\/?$/, origin: 'https://gateway21.pelecard.biz', path_pattern: '/PaymentGW',
123
+ sources: [pelecardSource('https://gateway21.pelecard.biz/ManualIframe/Chart'), pelecardSource('https://docs.pelecard.com/documentation/iframe-redirect-programmer-manual-version-06-2025/')] }, { id: 'pelecard-payment-script', psp: 'pelecard', kinds: ['script'], hostname: /^gateway21\.pelecard\.biz$/, pathname: /^\/Scripts\/Payment\/(?:Payment|General)\.js$/, origin: 'https://gateway21.pelecard.biz', path_pattern: '/Scripts/Payment/{Payment,General}.js',
124
+ sources: [pelecardSource('https://gateway21.pelecard.biz/Scripts/Payment/Payment.js'), pelecardSource('https://gateway21.pelecard.biz/Scripts/Payment/General.js')] }, { id: 'pelecard-legacy-payment-form', psp: 'pelecard', kinds: ['document', 'frame', 'iframe', 'form'], hostname: /^gateway\.pelecard\.biz$/, pathname: /^\/PayProcess\/Transaction$/, origin: 'https://gateway.pelecard.biz', path_pattern: '/PayProcess/Transaction',
125
+ sources: [pelecardSource('https://gateway.pelecard.biz/')],
126
+ variant_unverified: 'The implemented Pelecard adapter covers the Iframe/Redirect 2.0 card submission on gateway21 and gateway20.pelecard.biz; the legacy 1.0 page on gateway.pelecard.biz posts the card as a top-level form and is not admitted.' });
127
+ // ACI Worldwide COPYandPAY (Halfords), reviewed from ACI's own widget files on 2026-09-25. The
128
+ // processor ships dark: until the bundled catalog serves aci, a lone ACI signal names the
129
+ // processor and stays unknown. The widget script URL carries ?checkoutId=, which never matches.
130
+ const aciSource = (reference) => ({ kind: 'primary_source', reference, reviewed_on: '2026-09-25' });
131
+ RULES.push({ id: 'aci-copyandpay-widget-script', psp: 'aci', kinds: ['script'], hostname: /^eu-prod\.oppwa\.com$/, pathname: /^\/v1\/paymentWidgets\.js$/, origin: 'https://eu-prod.oppwa.com', path_pattern: '/v1/paymentWidgets.js',
132
+ sources: [aciSource('https://eu-prod.oppwa.com/v1/paymentWidgets.js'), aciSource('https://docs.aciworldwide.com/integration-guide')] }, { id: 'aci-copyandpay-card-frame', psp: 'aci', kinds: ['frame', 'iframe', 'document'], hostname: /^eu-prod\.oppwa\.com$/, pathname: /^\/v1\/pciIframe\.html$/, origin: 'https://eu-prod.oppwa.com', path_pattern: '/v1/pciIframe.html',
133
+ sources: [aciSource('https://eu-prod.oppwa.com/v1/pciIframe.html'), aciSource('https://eu-prod.oppwa.com/v1/paymentWidgets.js')] });
134
+ // Hyp CreditGuard PPS, reviewed from the public PPS shells and bundles and the Redirect API 2.6 guide
135
+ // on 2026-09-25. The processor ships dark: until the bundled catalog serves creditguard, a lone PPS
136
+ // signal names the processor and stays unknown. The legacy CGMPI page identifies its family and
137
+ // stays unknown through `variant_unverified`.
138
+ const creditguardSource = (reference) => ({ kind: 'primary_source', reference, reviewed_on: '2026-09-25' });
139
+ RULES.push({ id: 'creditguard-pps-hosted-page', psp: 'creditguard', kinds: ['document', 'frame', 'iframe'], hostname: /^pps\.creditguard\.co\.il$/, pathname: /^\/$/, origin: 'https://pps.creditguard.co.il', path_pattern: '/',
140
+ sources: [creditguardSource('https://www.creditguard.co.il/wp-content/uploads/2021/10/CG-Gateway-Redirect-API-for-PPS.pdf'), creditguardSource('https://pps.creditguard.co.il/')] }, { id: 'creditguard-pps-template-script', psp: 'creditguard', kinds: ['script'], hostname: /^pps\.creditguard\.co\.il$/, pathname: /^\/templates\/[A-Za-z0-9_-]{1,64}\/main\.js$/, origin: 'https://pps.creditguard.co.il', path_pattern: '/templates/:template/main.js',
141
+ sources: [creditguardSource('https://pps.creditguard.co.il/templates/cgt-basic/main.js')] }, { id: 'creditguard-legacy-mpi-page', psp: 'creditguard', kinds: ['document', 'frame', 'iframe', 'form'], hostname: /^cgmpi\.creditguard\.co\.il$/, pathname: /^\/CGMPI_Server\/PerformTransaction$/, origin: 'https://cgmpi.creditguard.co.il', path_pattern: '/CGMPI_Server/PerformTransaction',
142
+ sources: [creditguardSource('https://www.creditguard.co.il/wp-content/uploads/2020/11/CG-Gateway-Redirect-API.pdf')],
143
+ variant_unverified: 'The implemented CreditGuard adapter covers the PPS page on pps, pps2 and ppsuat.creditguard.co.il; the legacy CGMPI page on cgmpi.creditguard.co.il is not admitted.' });
144
+ // Primer Web SDK v2, reviewed from Primer's public SDK bundles (sdk.primer.io/web/v2.63.0 and v2.65.0,
145
+ // the @primer-io/checkout-web 2.65.0 loader) and Printful's add-card chunk on 2026-09-25. One host serves
146
+ // the SDK for sandbox and production sessions alike; the session's pciUrl decides where the card goes. The
147
+ // processor ships dark: until the bundled catalog serves primer, a lone Primer signal names the processor
148
+ // and stays unknown. Primer Checkout (@primer-io/primer-js) loads its api-controller from
149
+ // /web/hosted-pages/ and stays unknown through `variant_unverified`.
150
+ const primerSource = (reference) => ({ kind: 'primary_source', reference, reviewed_on: '2026-09-25' });
151
+ RULES.push({ id: 'primer-core-sdk-script', psp: 'primer', kinds: ['script'], hostname: /^sdk\.primer\.io$/, pathname: /^\/web\/v2\.[0-9]+\.[0-9]+\/PrimerCoreSDK\.min\.js$/, origin: 'https://sdk.primer.io', path_pattern: '/web/v2.:minor.:patch/PrimerCoreSDK.min.js',
152
+ sources: [primerSource('https://sdk.primer.io/web/v2.63.0/PrimerCoreSDK.min.js'), primerSource('https://www.npmjs.com/package/@primer-io/checkout-web/v/2.65.0')] }, { id: 'primer-card-frame', psp: 'primer', kinds: ['document', 'frame', 'iframe'], hostname: /^sdk\.primer\.io$/, pathname: /^\/web\/v2\.[0-9]+\.[0-9]+\/(?:hosted-input|api-controller)\.html$/, origin: 'https://sdk.primer.io', path_pattern: '/web/v2.:minor.:patch/{hosted-input,api-controller}.html',
153
+ sources: [primerSource('https://sdk.primer.io/web/v2.63.0/hosted-input.html'), primerSource('https://sdk.primer.io/web/v2.63.0/api-controller.html')] }, { id: 'primer-checkout-api-controller', psp: 'primer', kinds: ['document', 'frame', 'iframe', 'script'], hostname: /^sdk\.primer\.io$/, pathname: /^\/web\/hosted-pages\/v[0-9]+\.[0-9]+\.[0-9]+\/api-controller\.(?:html|mjs)$/, origin: 'https://sdk.primer.io', path_pattern: '/web/hosted-pages/:version/api-controller.{html,mjs}',
154
+ sources: [primerSource('https://sdk.primer.io/web/hosted-pages/v1.1.0/api-controller.mjs'), primerSource('https://www.npmjs.com/package/@primer-io/primer-js/v/1.10.1')],
155
+ variant_unverified: 'The implemented Primer adapter covers the Web SDK v2 card tokenization; Primer Checkout (primer-js) sends the card from a hosted api-controller that gives up on the request after 30 seconds and is not admitted.' });
156
+ // Payrails web SDK v6, reviewed from Payrails' public CDN files, the @payrails/web-sdk 6.5.0 loader
157
+ // and Blacklane's static bundles on 2026-09-25. The loader injects
158
+ // assets.payrails.io/web-sdk/<v6, or a build featureConfig.sdkVersion pins>/payrails.js, and the card
159
+ // form mounts its fields as assets.payrails.io/apps/secure-frame/<v6 or x.y.z>/index.html iframes.
160
+ // Only 6.x is matched, the body and JWE shape the Vault checks. window.__payrailsWebSdk__, the global
161
+ // the bundle publishes, is page state rather than a loaded resource, so discovery never reads it.
162
+ // The processor ships dark: until the bundled catalog serves payrails, a Payrails signal names it and
163
+ // stays unknown. Once served, only the card-form save is covered, and it is conditional on consent.
164
+ const payrailsSource = (reference) => ({ kind: 'primary_source', reference, reviewed_on: '2026-09-25' });
165
+ RULES.push({ id: 'payrails-web-sdk-v6-script', psp: 'payrails', kinds: ['script'], hostname: /^assets\.payrails\.io$/, pathname: /^\/web-sdk\/v?6(?:\.[0-9]+\.[0-9]+)?\/payrails\.js$/, origin: 'https://assets.payrails.io', path_pattern: '/web-sdk/{v6,6.:minor.:patch}/payrails.js',
166
+ sources: [payrailsSource('https://assets.payrails.io/web-sdk/v6/payrails.js'), payrailsSource('https://www.npmjs.com/package/@payrails/web-sdk/v/6.5.0')] }, { id: 'payrails-secure-frame-v6', psp: 'payrails', kinds: ['frame', 'iframe', 'document'], hostname: /^assets\.payrails\.io$/, pathname: /^\/apps\/secure-frame\/(?:v6|6\.[0-9]+\.[0-9]+)\/index\.html$/, origin: 'https://assets.payrails.io', path_pattern: '/apps/secure-frame/{v6,6.:minor.:patch}/index.html',
167
+ sources: [payrailsSource('https://assets.payrails.io/apps/secure-frame/v6/index.html'), payrailsSource('https://docs.payrails.com/docs/secure-fields')] });
168
+ // Elavon Converge Hosted Payment Page (NY DMV), reviewed from Converge's own page shell and bundle
169
+ // on 2026-09-25 (byte-identical on the production and demo hosts). The processor ships dark: until
170
+ // the bundled catalog serves elavon_converge, a lone Converge signal names the processor and stays
171
+ // unknown. The page URL carries ?ssl_txn_auth_token=, which never takes part in matching. The
172
+ // Lightbox modal and Checkout.js are named as unverified variants.
173
+ const convergeSource = (reference) => ({ kind: 'primary_source', reference, reviewed_on: '2026-09-25' });
174
+ RULES.push({ id: 'elavon-converge-hosted-payment-page', psp: 'elavon_converge', kinds: ['document', 'frame', 'iframe'], hostname: /^api\.convergepay\.com$/, pathname: /^\/hosted-payments\/$/, origin: 'https://api.convergepay.com', path_pattern: '/hosted-payments/',
175
+ sources: [convergeSource('https://api.convergepay.com/hosted-payments/'), convergeSource('https://developer.elavon.com/products/hosted-payment-page/v1/take-a-payment')] }, { id: 'elavon-converge-hpp-bundle', psp: 'elavon_converge', kinds: ['script'], hostname: /^api\.convergepay\.com$/, pathname: /^\/hosted-payments\/assets\/hpp-[0-9]+\.[0-9]+\.[0-9]+\.js$/, origin: 'https://api.convergepay.com', path_pattern: '/hosted-payments/assets/hpp-:version.js',
176
+ sources: [convergeSource('https://api.convergepay.com/hosted-payments/assets/hpp-2.505.07.js')] }, { id: 'elavon-converge-lightbox', psp: 'elavon_converge', kinds: ['document', 'frame', 'iframe'], hostname: /^api\.convergepay\.com$/, pathname: /^\/hosted-payments\/hpm\/?$/, origin: 'https://api.convergepay.com', path_pattern: '/hosted-payments/hpm',
177
+ sources: [convergeSource('https://api.demo.convergepay.com/hosted-payments/hpm'), convergeSource('https://api.convergepay.com/hosted-payments/PayWithConverge.js')],
178
+ variant_unverified: 'The implemented Elavon Converge adapter covers the Hosted Payment Page; the Lightbox payment modal at hosted-payments/hpm posts to its own endpoint and is not admitted.' }, { id: 'elavon-converge-checkout-js', psp: 'elavon_converge', kinds: ['script'], hostname: /^api\.convergepay\.com$/, pathname: /^\/hosted-payments\/(?:Checkout|PayWithConverge)\.js$/, origin: 'https://api.convergepay.com', path_pattern: '/hosted-payments/{Checkout,PayWithConverge}.js',
179
+ sources: [convergeSource('https://api.convergepay.com/hosted-payments/Checkout.js'), convergeSource('https://api.convergepay.com/hosted-payments/PayWithConverge.js')],
180
+ variant_unverified: 'The implemented Elavon Converge adapter covers the Hosted Payment Page; Checkout.js and the Lightbox launcher post the card from the merchant page and are not admitted.' });
181
+ // Worldpay eProtect: the vendor's JS API scripts, its iframe client and the Worldpay-origin payframe
182
+ // identify the processor. While its definition ships dark it is outside the bundled capabilities, so
183
+ // a page using it stays unknown here. B&H serves the same script from a domain it names itself,
184
+ // which is identified and refused; any other merchant-named domain stays unidentified, because a
185
+ // host wildcard here would make every card frame attributable to eProtect.
186
+ const eprotectSources = [
187
+ { kind: 'primary_source', reference: 'https://request.eprotect.vantivcnp.com/eProtect/eProtect-api3.js', reviewed_on: '2026-09-23' },
188
+ { kind: 'official_documentation', reference: 'https://docs.worldpay.com/assets/pdf/Worldpay_eProtect_Integration_Guide.pdf', reviewed_on: '2026-09-23' },
189
+ ];
190
+ const eprotectScript = /^\/eProtect\/(?:eProtect|litle)-api[23]\.js$/;
191
+ RULES.push({ id: 'worldpay-eprotect-js-api', psp: 'worldpay_eprotect', kinds: ['script'], hostname: /^request\.eprotect\.vantivcnp\.com$/, pathname: eprotectScript,
192
+ origin: 'https://request.eprotect.vantivcnp.com', path_pattern: '/eProtect/{eProtect,litle}-api{2,3}.js', sources: eprotectSources }, { id: 'worldpay-eprotect-iframe-client', psp: 'worldpay_eprotect', kinds: ['script'], hostname: /^request\.eprotect\.vantivcnp\.com$/,
193
+ pathname: /^\/eProtect\/js\/(?:payframe|eProtect-iframe)-client[34](?:\.min)?\.js$/, origin: 'https://request.eprotect.vantivcnp.com',
194
+ path_pattern: '/eProtect/js/{payframe,eProtect-iframe}-client{3,4}[.min].js', sources: eprotectSources }, { id: 'worldpay-eprotect-payframe', psp: 'worldpay_eprotect', kinds: ['frame', 'iframe', 'document'], hostname: /^request\.eprotect\.vantivcnp\.com$/,
195
+ pathname: /^\/eProtect\/payframe_[A-Za-z0-9]{1,64}_[A-Za-z0-9_-]{1,96}\.html$/, origin: 'https://request.eprotect.vantivcnp.com',
196
+ path_pattern: '/eProtect/payframe_:paypageId_:style.html', sources: eprotectSources }, { id: 'worldpay-eprotect-merchant-domain', psp: 'worldpay_eprotect', kinds: ['script'], hostname: /^paypage\.bhphotovideo\.com$/, pathname: eprotectScript,
197
+ origin: 'https://paypage.bhphotovideo.com', path_pattern: '/eProtect/{eProtect,litle}-api{2,3}.js', sources: eprotectSources,
198
+ variant_unverified: 'This eProtect script is served from a merchant-named domain, not a Worldpay eProtect host; only Worldpay’s own eProtect hosts are covered.' });
199
+ // WSPay Components (WSPay's build of Monri Components), reviewed from the vendor's public bundles
200
+ // on 2026-09-23. The processor ships dark: until the bundled catalog serves wspay, a lone WSPay
201
+ // signal names the processor and stays unknown. Monri Components on ipg.monri.com and the WSPay
202
+ // Form hosted page identify their family and stay unknown through `variant_unverified`.
203
+ const wspaySource = (reference) => ({ kind: 'primary_source', reference, reviewed_on: '2026-09-23' });
204
+ RULES.push({ id: 'wspay-components-script', psp: 'wspay', kinds: ['script'], hostname: /^proxy\.wspay\.biz$/, pathname: /^\/dist\/(?:components|monri)\.js$/, origin: 'https://proxy.wspay.biz', path_pattern: '/dist/{components,monri}.js',
205
+ sources: [wspaySource('https://proxy.wspay.biz/dist/components.js'), wspaySource('https://proxy.wspay.biz/dist/monri.js')] }, { id: 'wspay-components-card-frame', psp: 'wspay', kinds: ['frame', 'iframe', 'document'], hostname: /^proxy\.wspay\.biz$/, pathname: /^\/v2\/js\/payment-method-component-dynamic\.html$/, origin: 'https://proxy.wspay.biz', path_pattern: '/v2/js/payment-method-component-dynamic.html',
206
+ sources: [wspaySource('https://proxy.wspay.biz/dist/components.js'), wspaySource('https://proxy.wspay.biz/v2/js/payment-method-component-dynamic.html')] }, { id: 'wspay-form-hosted-page', psp: 'wspay', kinds: ['document', 'frame', 'iframe', 'form'], hostname: /^form\.wspay\.biz$/, pathname: /^\/authorization(?:\.aspx)?$/, origin: 'https://form.wspay.biz', path_pattern: '/authorization{,.aspx}',
207
+ sources: [wspaySource('https://docs.wspay.info/wspayform')],
208
+ variant_unverified: 'The implemented WSPay adapter covers the WSPay Components card confirm on proxy.wspay.biz; the WSPay Form hosted page posts the card to form.wspay.biz and is not admitted.' }, { id: 'monri-components-script', psp: 'monri', kinds: ['script'], hostname: /^ipg\.monri\.com$/, pathname: /^\/dist\/(?:components|monri)\.js$/, origin: 'https://ipg.monri.com', path_pattern: '/dist/{components,monri}.js',
209
+ sources: [wspaySource('https://ipg.monri.com/en/documentation/components'), wspaySource('https://ipg.monri.com/dist/components.js')],
210
+ variant_unverified: 'Monri Components on ipg.monri.com confirm the card on Monri’s own hosts, which need the relay route; only the WSPay Components confirm on proxy.wspay.biz is implemented.' }, { id: 'monri-components-card-frame', psp: 'monri', kinds: ['frame', 'iframe', 'document'], hostname: /^ipg\.monri\.com$/, pathname: /^\/v2\/js\/payment-(?:method-component-dynamic|component)\.html$/, origin: 'https://ipg.monri.com', path_pattern: '/v2/js/payment-{method-component-dynamic,component}.html',
211
+ sources: [wspaySource('https://ipg.monri.com/dist/components.js')],
212
+ variant_unverified: 'Monri Components on ipg.monri.com confirm the card on Monri’s own hosts, which need the relay route; only the WSPay Components confirm on proxy.wspay.biz is implemented.' });
213
+ // Shiji STS behind the MyCheck Wallet V3 (dark: its processor declares a capability, so the bundled
214
+ // catalog does not list it and these signals stay unknown until a client opts in). The in-page
215
+ // wallet (main.js) and the STS proxy script identify the processor. The wallet's iframe integration
216
+ // (sdk.js, wallet-iframe.html) and Shiji's ps-js-apm library identify it too, but no Vault mode covers
217
+ // them, so each keeps the result unknown through `variant_unverified`. Sources: the reviewed bundles
218
+ // (sts.proxy.v2.1.js sha256 aee72b81...346ade84, wallet main.js 7d28c3bf...03580fdb).
219
+ const shijiSources = [
220
+ { kind: 'primary_source', reference: 'https://cdn.shijipayment.com/sts/sts.proxy.v2.1.js', reviewed_on: '2026-09-25' },
221
+ { kind: 'primary_source', reference: 'https://wallet-sdk-v3.mycheckapp.com/latest/static/js/main.js', reviewed_on: '2026-09-25' },
222
+ ];
223
+ RULES.push({ id: 'mycheck-wallet-v3-script', psp: 'shiji_sts', kinds: ['script'], hostname: /^wallet-sdk-v3\.mycheckapp\.com$/, pathname: /^\/[A-Za-z0-9._-]+\/static\/js\/main\.js$/, origin: 'https://wallet-sdk-v3.mycheckapp.com', path_pattern: '/:version/static/js/main.js',
224
+ sources: shijiSources }, { id: 'shiji-sts-proxy-script', psp: 'shiji_sts', kinds: ['script'], hostname: /^cdn\.shijipayment\.com$/, pathname: /^\/sts\/sts\.proxy\.v2\.1\.js$/, origin: 'https://cdn.shijipayment.com', path_pattern: '/sts/sts.proxy.v2.1.js',
225
+ sources: shijiSources }, { id: 'mycheck-wallet-v3-iframe-sdk', psp: 'shiji_sts', kinds: ['script'], hostname: /^wallet-sdk-v3\.mycheckapp\.com$/, pathname: /^\/[A-Za-z0-9._-]+\/sdk\.js$/, origin: 'https://wallet-sdk-v3.mycheckapp.com', path_pattern: '/:version/sdk.js',
226
+ sources: [{ kind: 'primary_source', reference: 'https://wallet-sdk-v3.mycheckapp.com/latest/sdk.js', reviewed_on: '2026-09-25' }],
227
+ variant_unverified: 'The MyCheck wallet iframe integration sends the card from MyCheck\'s own frame; only the in-page wallet (main.js) is admitted.' }, { id: 'mycheck-wallet-v3-iframe', psp: 'shiji_sts', kinds: ['frame', 'iframe', 'document'], hostname: /^wallet-sdk-v3\.mycheckapp\.com$/, pathname: /^\/wallet-iframe\.html$/, origin: 'https://wallet-sdk-v3.mycheckapp.com', path_pattern: '/wallet-iframe.html',
228
+ sources: [{ kind: 'primary_source', reference: 'https://wallet-sdk-v3.mycheckapp.com/wallet-iframe.html', reviewed_on: '2026-09-25' }],
229
+ variant_unverified: 'The MyCheck wallet iframe integration sends the card from MyCheck\'s own frame; only the in-page wallet (main.js) is admitted.' }, { id: 'shiji-ps-js-apm-script', psp: 'shiji_sts', kinds: ['script'], hostname: /^cdn\.shijipayment\.com$/, pathname: /^\/libraries\/shijipayments\.latest\.min\.js$/, origin: 'https://cdn.shijipayment.com', path_pattern: '/libraries/shijipayments.latest.min.js',
230
+ sources: [{ kind: 'primary_source', reference: 'https://cdn.shijipayment.com/libraries/shijipayments.latest.min.js', reviewed_on: '2026-09-25' }],
231
+ variant_unverified: 'Shiji\'s ps-js-apm library can take its STS key and URL from server configuration; only the MyCheck Wallet V3 path under the pinned key is admitted.' });
232
+ // Amadeus Payment Platform (Outpayce), reviewed from Amadeus's public Checkout Web SDK (the 7.1.0
233
+ // bundle, its form-field pages and user guide under prd.payment.amadeus.com/checkout/sdk/) and the
234
+ // Data Collection Page script on paypages.payment.amadeus.com on 2026-09-25. The SDK loads its tunnel,
235
+ // pan and cvv frames from the same versioned directory; the DCP page is framed from /ATPDCP/land/.
236
+ // The processor ships dark: until the bundled catalog serves amadeus_checkout, a lone Amadeus signal
237
+ // names the processor and stays unknown.
238
+ const amadeusSource = (reference) => ({ kind: 'primary_source', reference, reviewed_on: '2026-09-25' });
239
+ RULES.push({ id: 'amadeus-checkout-sdk-script', psp: 'amadeus_checkout', kinds: ['script'], hostname: /^prd\.payment\.amadeus\.com$/, pathname: /^\/checkout\/sdk\/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/sdk-es(?:5|2015|2022)\.js$/, origin: 'https://prd.payment.amadeus.com', path_pattern: '/checkout/sdk/:version/sdk-{es5,es2015,es2022}.js',
240
+ sources: [amadeusSource('https://prd.payment.amadeus.com/checkout/sdk/7.1.0/sdk-es2022.js'), amadeusSource('https://prd.payment.amadeus.com/checkout/sdk/manifest.json')] }, { id: 'amadeus-checkout-sdk-frame', psp: 'amadeus_checkout', kinds: ['document', 'frame', 'iframe'], hostname: /^prd\.payment\.amadeus\.com$/, pathname: /^\/checkout\/sdk\/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/form-fields\/(?:tunnel|pan|cvv)\.html$/, origin: 'https://prd.payment.amadeus.com', path_pattern: '/checkout/sdk/:version/form-fields/{tunnel,pan,cvv}.html',
241
+ sources: [amadeusSource('https://prd.payment.amadeus.com/checkout/sdk/7.1.0/form-fields/tunnel.html'), amadeusSource('https://github.com/outpaycelab/outpayce-checkout-sdk-web/blob/main/userguide.md')] }, { id: 'amadeus-data-collection-page', psp: 'amadeus_checkout', kinds: ['document', 'frame', 'iframe'], hostname: /^paypages\.payment\.amadeus\.com$/, pathname: /^\/1ASIATP\/ATPDCP\/land\/?$/, origin: 'https://paypages.payment.amadeus.com', path_pattern: '/1ASIATP/ATPDCP/land/',
242
+ sources: [amadeusSource('https://paypages.payment.amadeus.com/1ASIATP/ATPDCP/static/dcppages/standard/js/standard-acb53a79a0.min.js')] });
243
+ // Worldline Connect MyCheckout (dark: its processor declares a capability, so the bundled catalog
244
+ // does not list it and these signals stay unknown until a client opts in). The hosted payment page
245
+ // itself identifies the processor: /checkout/<hosted checkout> on the `payment.` subdomain of a
246
+ // data center (pay1 Europe, pay2 US), and its card form's action, /checkout. Read from Worldline's
247
+ // template bundle and a recorded MyCheckout card page (Aveda Belgium, Sep 2025).
248
+ const worldlineSources = [
249
+ { kind: 'primary_source', reference: 'https://assets.pay1.checkout.worldline-solutions.com/templates/generic/responsive/wro/html-footer.js', reviewed_on: '2026-09-30' },
250
+ { kind: 'official_documentation', reference: 'https://docs.connect.worldline-solutions.com/documentation/hosted-payment-pages/', reviewed_on: '2026-09-30' },
251
+ ];
252
+ RULES.push({ id: 'worldline-mycheckout-page', psp: 'worldline_mycheckout', kinds: ['document', 'frame', 'iframe'], hostname: /^payment\.pay1\.checkout\.worldline-solutions\.com$/,
253
+ pathname: /^\/checkout\/(?:payment-product-details\/)?[1-9][0-9]{0,9}-[0-9a-f]{32}:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}:[0-9a-f]{32}$/,
254
+ origin: 'https://payment.pay1.checkout.worldline-solutions.com', path_pattern: '/checkout/{payment-product-details/}:hosted_checkout', sources: worldlineSources }, { id: 'worldline-mycheckout-card-form', psp: 'worldline_mycheckout', kinds: ['form'], hostname: /^payment\.pay1\.checkout\.worldline-solutions\.com$/, pathname: /^\/checkout$/,
255
+ origin: 'https://payment.pay1.checkout.worldline-solutions.com', path_pattern: '/checkout', sources: worldlineSources });
256
+ // A processor that ships dark (its definition declares a capability) is left out of the bundled
257
+ // catalog. Datatrans's discovery rules wait with it: they join RULES only once KNOWN_PSPS, the
258
+ // bundled catalog's processors, lists its psp. Until then its assets are not evidence, so a page
259
+ // that loads them, alone or beside another processor's SDK, reads exactly as it did before the
260
+ // processor existed. (The dark GMO, CyberSource Flex, Juspay, Pelecard, ACI, CreditGuard,
261
+ // Primer, Payrails, Elavon Converge, Worldpay eProtect, WSPay, Shiji STS, Amadeus and Worldline
262
+ // MyCheckout rules above join RULES now, and their signals stay unknown.)
263
+ const SERVED_ONLY_RULES = [];
264
+ // Datatrans / PCI Proxy Secure Fields 2.0.0, reviewed from Datatrans's public library and iframe
265
+ // script (pay.datatrans.com/upp/payment/js/secure-fields-2.0.0.js and .min.js, field.js 3.24.602)
266
+ // and the PCI Proxy docs on 2026-09-25. The library loads the card and CVV iframes from the
267
+ // paymentField document on the same host. Dark behind datatrans_secure_fields_tokenize.
268
+ const datatransSource = (reference) => ({ kind: 'primary_source', reference, reviewed_on: '2026-09-25' });
269
+ for (const [suffix, hostname, origin] of [['', /^pay\.datatrans\.com$/, 'https://pay.datatrans.com'],
270
+ ['-sandbox', /^pay\.sandbox\.datatrans\.com$/, 'https://pay.sandbox.datatrans.com']]) {
271
+ SERVED_ONLY_RULES.push({ id: `datatrans-secure-fields-script${suffix}`, psp: 'datatrans', kinds: ['script'], hostname, pathname: /^\/upp\/payment\/js\/secure-fields-2\.0\.0(?:\.min)?\.js$/, origin, path_pattern: '/upp/payment/js/secure-fields-2.0.0{,.min}.js',
272
+ sources: [datatransSource('https://pay.datatrans.com/upp/payment/js/secure-fields-2.0.0.js'), datatransSource('https://docs.pci-proxy.com/docs/secure-fields-quick-start')] }, { id: `datatrans-secure-fields-frame${suffix}`, psp: 'datatrans', kinds: ['document', 'frame', 'iframe'], hostname, pathname: /^\/upp\/payment\/SecureFields\/paymentField$/, origin, path_pattern: '/upp/payment/SecureFields/paymentField',
273
+ sources: [datatransSource('https://pay.datatrans.com/upp/payment/SecureFields/field.js'), datatransSource('https://docs.datatrans.ch/docs/secure-fields')] });
274
+ }
275
+ RULES.push(...SERVED_ONLY_RULES.filter(rule => KNOWN_PSPS.includes(rule.psp)));
101
276
  // Keep sandbox evidence truthful instead of labelling it with a production origin.
102
277
  for (const [baseId, suffix, hostname, origin] of [
103
278
  ['gmo-mp-token-script', 'test', /^stg\.static\.mul-pay\.jp$/, 'https://stg.static.mul-pay.jp'],
@@ -106,6 +281,23 @@ for (const [baseId, suffix, hostname, origin] of [
106
281
  ['gmo-link-hosted-page', 'test', /^pt01\.mul-pay\.jp$/, 'https://pt01.mul-pay.jp'],
107
282
  ['cybersource-flex-microform-script', 'test', /^testflex\.cybersource\.com$/, 'https://testflex.cybersource.com'],
108
283
  ['cybersource-flex-microform-field', 'test', /^testflex\.cybersource\.com$/, 'https://testflex.cybersource.com'],
284
+ ['worldpay-eprotect-js-api', 'prelive', /^request\.eprotect\.vantivprelive\.com$/, 'https://request.eprotect.vantivprelive.com'],
285
+ ['worldpay-eprotect-iframe-client', 'prelive', /^request\.eprotect\.vantivprelive\.com$/, 'https://request.eprotect.vantivprelive.com'],
286
+ ['worldpay-eprotect-payframe', 'prelive', /^request\.eprotect\.vantivprelive\.com$/, 'https://request.eprotect.vantivprelive.com'],
287
+ ['mycheck-wallet-v3-script', 'sandbox', /^wallet-sdk-v3-sandbox\.mycheckapp\.com$/, 'https://wallet-sdk-v3-sandbox.mycheckapp.com'],
288
+ ['mycheck-wallet-v3-script', 'test', /^wallet-sdk-v3-test\.mycheckapp\.com$/, 'https://wallet-sdk-v3-test.mycheckapp.com'],
289
+ ['shiji-sts-proxy-script', 'dev', /^cdn\.shijipayment\.dev$/, 'https://cdn.shijipayment.dev'],
290
+ ['mycheck-wallet-v3-iframe-sdk', 'sandbox', /^wallet-sdk-v3-sandbox\.mycheckapp\.com$/, 'https://wallet-sdk-v3-sandbox.mycheckapp.com'],
291
+ ['mycheck-wallet-v3-iframe-sdk', 'test', /^wallet-sdk-v3-test\.mycheckapp\.com$/, 'https://wallet-sdk-v3-test.mycheckapp.com'],
292
+ ['mycheck-wallet-v3-iframe', 'sandbox', /^wallet-sdk-v3-sandbox\.mycheckapp\.com$/, 'https://wallet-sdk-v3-sandbox.mycheckapp.com'],
293
+ ['mycheck-wallet-v3-iframe', 'test', /^wallet-sdk-v3-test\.mycheckapp\.com$/, 'https://wallet-sdk-v3-test.mycheckapp.com'],
294
+ // MyCheckout's US data center and the pre-production twins of both.
295
+ ['worldline-mycheckout-page', 'pay2', /^payment\.pay2\.checkout\.worldline-solutions\.com$/, 'https://payment.pay2.checkout.worldline-solutions.com'],
296
+ ['worldline-mycheckout-page', 'preprod', /^payment\.pay1\.preprod\.checkout\.worldline-solutions\.com$/, 'https://payment.pay1.preprod.checkout.worldline-solutions.com'],
297
+ ['worldline-mycheckout-page', 'pay2-preprod', /^payment\.pay2\.preprod\.checkout\.worldline-solutions\.com$/, 'https://payment.pay2.preprod.checkout.worldline-solutions.com'],
298
+ ['worldline-mycheckout-card-form', 'pay2', /^payment\.pay2\.checkout\.worldline-solutions\.com$/, 'https://payment.pay2.checkout.worldline-solutions.com'],
299
+ ['worldline-mycheckout-card-form', 'preprod', /^payment\.pay1\.preprod\.checkout\.worldline-solutions\.com$/, 'https://payment.pay1.preprod.checkout.worldline-solutions.com'],
300
+ ['worldline-mycheckout-card-form', 'pay2-preprod', /^payment\.pay2\.preprod\.checkout\.worldline-solutions\.com$/, 'https://payment.pay2.preprod.checkout.worldline-solutions.com'],
109
301
  ['square-web-sdk', 'sandbox', /^sandbox\.web\.squarecdn\.com$/, 'https://sandbox.web.squarecdn.com'],
110
302
  ['paysafe-js', 'test', /^hosted\.test\.paysafe\.com$/, 'https://hosted.test.paysafe.com'],
111
303
  ['worldpay-checkout-sdk', 'try', /^try\.access\.worldpay\.com$/, 'https://try.access.worldpay.com'],
@@ -115,6 +307,11 @@ for (const [baseId, suffix, hostname, origin] of [
115
307
  ['authorize-net-sim-hosted-form', 'secure2', /^secure2\.authorize\.net$/, 'https://secure2.authorize.net'],
116
308
  ['worldpay-hosted-payment-page', 'test', /^secure-test\.worldpay\.com$/, 'https://secure-test.worldpay.com'],
117
309
  ['rapyd-hosted-checkout-page', 'sandbox', /^sandboxcheckout\.rapyd\.net$/, 'https://sandboxcheckout.rapyd.net'],
310
+ // The pdt and uat copies of the SDK are byte-identical to prd.
311
+ ['amadeus-checkout-sdk-script', 'pdt', /^pdt\.payment\.amadeus\.com$/, 'https://pdt.payment.amadeus.com'],
312
+ ['amadeus-checkout-sdk-script', 'uat', /^uat\.payment\.amadeus\.com$/, 'https://uat.payment.amadeus.com'],
313
+ ['amadeus-checkout-sdk-frame', 'pdt', /^pdt\.payment\.amadeus\.com$/, 'https://pdt.payment.amadeus.com'],
314
+ ['amadeus-checkout-sdk-frame', 'uat', /^uat\.payment\.amadeus\.com$/, 'https://uat.payment.amadeus.com'],
118
315
  // Adyen's regional live hosts (docs.adyen.com/development-resources/live-endpoints/).
119
316
  ['adyen-secured-fields-live', 'us', /^checkoutshopper-live-us\.adyen\.com$/, 'https://checkoutshopper-live-us.adyen.com'],
120
317
  ['adyen-secured-fields-live', 'au', /^checkoutshopper-live-au\.adyen\.com$/, 'https://checkoutshopper-live-au.adyen.com'],
@@ -125,6 +322,38 @@ for (const [baseId, suffix, hostname, origin] of [
125
322
  ['fiserv-commercehub-payment-fields', 'cert', /^commercehub-checkout-cert\.fiservapps\.com$/, 'https://commercehub-checkout-cert.fiservapps.com'],
126
323
  ['fiserv-commercehub-checkout-script', 'cert', /^commercehub-checkout-cert\.fiservapps\.com$/, 'https://commercehub-checkout-cert.fiservapps.com'],
127
324
  ['fiserv-secure-data-capture-frame', 'cert', /^commercehub-secure-data-capture-cert\.fiservapps\.com$/, 'https://commercehub-secure-data-capture-cert.fiservapps.com'],
325
+ // Verifone's other regions and its two sandboxes serve the same verifone.js.
326
+ ['verifone-secure-card-capture-script', 'emea', /^emea\.jsclient\.verifone\.cloud$/, 'https://emea.jsclient.verifone.cloud'],
327
+ ['verifone-secure-card-capture-script', 'uscst', /^uscst\.jsclient\.vficloud\.net$/, 'https://uscst.jsclient.vficloud.net'],
328
+ ['verifone-secure-card-capture-script', 'cst', /^cst\.jsclient\.vficloud\.net$/, 'https://cst.jsclient.vficloud.net'],
329
+ // Juspay's sandbox, and api.juspay.io, the host the Session API's own sample payment link uses.
330
+ ['juspay-hypercheckout-payment-page', 'sandbox', /^sandbox\.juspay\.in$/, 'https://sandbox.juspay.in'],
331
+ ['juspay-hypercheckout-payment-page', 'io', /^api\.juspay\.io$/, 'https://api.juspay.io'],
332
+ // Older Pelecard terminals serve the same page and scripts from gateway20 (live and test terminals alike).
333
+ ['pelecard-payment-page', 'gateway20', /^gateway20\.pelecard\.biz$/, 'https://gateway20.pelecard.biz'],
334
+ ['pelecard-payment-script', 'gateway20', /^gateway20\.pelecard\.biz$/, 'https://gateway20.pelecard.biz'],
335
+ // ACI serves the same widget from its second live host and its two INTEGRATOR_TEST hosts.
336
+ ['aci-copyandpay-widget-script', 'oppwa', /^oppwa\.com$/, 'https://oppwa.com'],
337
+ ['aci-copyandpay-widget-script', 'eu-test', /^eu-test\.oppwa\.com$/, 'https://eu-test.oppwa.com'],
338
+ ['aci-copyandpay-widget-script', 'test', /^test\.oppwa\.com$/, 'https://test.oppwa.com'],
339
+ ['aci-copyandpay-card-frame', 'oppwa', /^oppwa\.com$/, 'https://oppwa.com'],
340
+ ['aci-copyandpay-card-frame', 'eu-test', /^eu-test\.oppwa\.com$/, 'https://eu-test.oppwa.com'],
341
+ ['aci-copyandpay-card-frame', 'test', /^test\.oppwa\.com$/, 'https://test.oppwa.com'],
342
+ // CreditGuard's second production PPS host and its UAT host.
343
+ ['creditguard-pps-hosted-page', 'pps2', /^pps2\.creditguard\.co\.il$/, 'https://pps2.creditguard.co.il'],
344
+ ['creditguard-pps-template-script', 'pps2', /^pps2\.creditguard\.co\.il$/, 'https://pps2.creditguard.co.il'],
345
+ ['creditguard-pps-hosted-page', 'uat', /^ppsuat\.creditguard\.co\.il$/, 'https://ppsuat.creditguard.co.il'],
346
+ ['creditguard-pps-template-script', 'uat', /^ppsuat\.creditguard\.co\.il$/, 'https://ppsuat.creditguard.co.il'],
347
+ // Converge's demo environment serves the same page and bundles.
348
+ ['elavon-converge-hosted-payment-page', 'demo', /^api\.demo\.convergepay\.com$/, 'https://api.demo.convergepay.com'],
349
+ ['elavon-converge-hpp-bundle', 'demo', /^api\.demo\.convergepay\.com$/, 'https://api.demo.convergepay.com'],
350
+ ['elavon-converge-lightbox', 'demo', /^api\.demo\.convergepay\.com$/, 'https://api.demo.convergepay.com'],
351
+ ['elavon-converge-checkout-js', 'demo', /^api\.demo\.convergepay\.com$/, 'https://api.demo.convergepay.com'],
352
+ ['wspay-components-script', 'test', /^proxy-test\.wspay\.biz$/, 'https://proxy-test.wspay.biz'],
353
+ ['wspay-components-card-frame', 'test', /^proxy-test\.wspay\.biz$/, 'https://proxy-test.wspay.biz'],
354
+ ['wspay-form-hosted-page', 'test', /^formtest\.wspay\.biz$/, 'https://formtest.wspay.biz'],
355
+ ['monri-components-script', 'test', /^ipgtest\.monri\.com$/, 'https://ipgtest.monri.com'],
356
+ ['monri-components-card-frame', 'test', /^ipgtest\.monri\.com$/, 'https://ipgtest.monri.com'],
128
357
  ]) {
129
358
  RULES.push({ ...RULES.find(rule => rule.id === baseId), id: `${baseId}-${suffix}`, hostname, origin });
130
359
  }
@@ -577,14 +806,14 @@ export function getCheckoutPreflightSchemas() {
577
806
  schema_version: { const: 1 }, profile_version: text, catalog_version: { const: CHECKOUT_PREFLIGHT_CATALOG_VERSION }, integration,
578
807
  processor_entries: { type: 'array', maxItems: 256, items: {
579
808
  type: 'object', additionalProperties: false, required: ['psp', 'mode', 'scenario', 'status'], properties: {
580
- psp: { enum: KNOWN_PSPS }, mode: { enum: ['token', 'cse', 'hosted_form'] }, scenario: { enum: SCENARIOS }, status: { enum: ['supported', 'unsupported'] },
809
+ psp: { enum: KNOWN_PSPS }, mode: { enum: ['token', 'cse', 'hosted_form', 'device_encrypt'] }, scenario: { enum: SCENARIOS }, status: { enum: ['supported', 'unsupported'] },
581
810
  limitations: { type: 'array', maxItems: 16, items: { type: 'string', maxLength: 256, pattern: '^[^\\u0000-\\u001f]*$' } },
582
811
  },
583
812
  } },
584
813
  expires_at: { type: 'string', format: 'date-time', maxLength: 40 }, entries: { type: 'array', maxItems: 256, items: {
585
814
  type: 'object', additionalProperties: false, required: ['flow', 'operation', 'operation_version', 'mode', 'scenario', 'status'], properties: {
586
815
  flow: { enum: FLOWS.map(flow => flow.id) }, operation: { enum: FLOWS.map(flow => flow.operation) }, operation_version: { const: 1 },
587
- mode: { enum: ['token', 'cse', 'hosted_form'] }, scenario: { enum: SCENARIOS }, status: { enum: ['supported', 'unsupported'] },
816
+ mode: { enum: ['token', 'cse', 'hosted_form', 'device_encrypt'] }, scenario: { enum: SCENARIOS }, status: { enum: ['supported', 'unsupported'] },
588
817
  limitations: { type: 'array', maxItems: 16, items: { type: 'string', maxLength: 256, pattern: '^[^\\u0000-\\u001f]*$' } },
589
818
  },
590
819
  } },
@@ -598,7 +827,7 @@ export function getCheckoutPreflightSchemas() {
598
827
  const result = { $schema: 'https://json-schema.org/draft/2020-12/schema', type: 'object', additionalProperties: false,
599
828
  required: ['schema_version', 'catalog_version', 'integration', 'scenario', 'scenario_defaulted', 'psp', 'flow', 'mode', 'status', 'support_scope', 'checkout_flow_status', 'candidates', 'reason_codes', 'limitations', 'missing_evidence', 'observation', 'scope', 'merchant_confirmation_required'], properties: {
600
829
  schema_version: { const: 1 }, catalog_version: { const: CHECKOUT_PREFLIGHT_CATALOG_VERSION }, integration,
601
- scenario: { enum: SCENARIOS }, scenario_defaulted: { type: 'boolean' }, psp: { type: ['string', 'null'] }, flow: { type: ['string', 'null'] }, mode: { enum: ['token', 'cse', 'hosted_form', null] },
830
+ scenario: { enum: SCENARIOS }, scenario_defaulted: { type: 'boolean' }, psp: { type: ['string', 'null'] }, flow: { type: ['string', 'null'] }, mode: { enum: ['token', 'cse', 'hosted_form', 'device_encrypt', null] },
602
831
  support_scope: { enum: ['processor_integration', 'checkout_flow', null] }, checkout_flow_status: { enum: ['identified', 'unknown', 'ambiguous'] },
603
832
  status: { enum: ['supported', 'unsupported', 'unknown'] }, candidates: { type: 'array', items: { type: 'object', additionalProperties: false, required: ['psp', 'relevance', 'evidence'], properties: {
604
833
  psp: { type: 'string' }, relevance: { enum: ['active', 'undetermined'] }, evidence: { type: 'array', items: evidence },
@@ -14,8 +14,11 @@ export declare class PreparationGate {
14
14
  private expiryTimer?;
15
15
  constructor(opts: AttachOptions, lifecycle: CheckoutLifecycle, readDocumentUrl: () => Promise<string>);
16
16
  private prepare;
17
- /** Called for every recognized card mutation, before any await or local retry guard. */
18
- claim(requestUrl: string, requestBody?: string | null, requestHeaders?: Record<string, string>): PreparedCheckout | undefined;
17
+ /**
18
+ * Called for every recognized card request, before any await or local retry guard. The request's
19
+ * own method is what binds: a POST for most processors, the registration GET for Worldpay eProtect.
20
+ */
21
+ claim(requestUrl: string, requestMethod: string, requestBody?: string | null, requestHeaders?: Record<string, string>): PreparedCheckout | undefined;
19
22
  assertDocument(): Promise<void>;
20
23
  private readDocument;
21
24
  isEngaged(): boolean;
@@ -1,6 +1,6 @@
1
1
  import { CheckoutPreparationError } from './client.js';
2
- import { validAmountInput } from './client.js';
3
- import { matchesPreparation, validPreparationEnvironment, preparationEndpoint } from './prepared-processor.js';
2
+ import { amountRefusal, validAmountInput } from './client.js';
3
+ import { matchesPreparation, validPreparationEnvironment, preparationEndpoint, preparationBindsByShape, preparationRequestMethod, preparedRequestRefusal } from './prepared-processor.js';
4
4
  /** A local, one-use rendezvous. It never starts or retries a merchant request. */
5
5
  export class PreparationGate {
6
6
  opts;
@@ -41,7 +41,17 @@ export class PreparationGate {
41
41
  throw new CheckoutPreparationError(null, 'unsupported_processor');
42
42
  // A Fiserv checkout's merchantProfile names a key pin, which prepareCheckout checks: its
43
43
  // capture endpoint is checked below like any processor-hosted checkout's.
44
- if (options.merchantProfile !== undefined && options.psp !== 'fiserv') {
44
+ if (options.psp === 'verifone') {
45
+ // A Verifone merchant's own server: a profile the last sync served, which this
46
+ // attachment pauses, enabled for this client.
47
+ const profile = typeof this.opts.vault.verifoneProfile === 'function' && typeof options.merchantProfile === 'string'
48
+ ? this.opts.vault.verifoneProfile(options.merchantProfile) : null;
49
+ if (!profile)
50
+ throw new CheckoutPreparationError(null, 'processor_interception_unavailable');
51
+ if (profile.status !== 'enabled')
52
+ throw new CheckoutPreparationError(null, 'unsupported_checkout');
53
+ }
54
+ else if (options.merchantProfile !== undefined && options.psp !== 'fiserv') {
45
55
  // An Adyen merchant's own endpoint: a profile this build reviewed, which
46
56
  // this attachment pauses, and one Agentcard turned on for this client.
47
57
  const profile = typeof this.opts.vault.merchantProfile === 'function' && typeof options.merchantProfile === 'string'
@@ -55,11 +65,19 @@ export class PreparationGate {
55
65
  }
56
66
  else {
57
67
  const tokenizer = preparationEndpoint(options.psp, options.environment);
58
- if (!this.opts.vault.isCardRequest(tokenizer, 'POST'))
68
+ // ACI's card-number request names a checkout id the merchant mints at Pay time, and a GET card
69
+ // request (Worldpay eProtect) is recognized by its whole query, which the page has not written
70
+ // yet, so no prepared URL is ever their card request: ask whether the registry serves the
71
+ // processor at all instead. A preparation the adapters would never pause could never bind.
72
+ const interceptable = preparationBindsByShape(options.psp) || preparationRequestMethod(options.psp) === 'GET'
73
+ ? typeof this.opts.vault.recognizesProcessor === 'function' && this.opts.vault.recognizesProcessor(options.psp)
74
+ : this.opts.vault.isCardRequest(tokenizer, 'POST');
75
+ if (!interceptable)
59
76
  throw new CheckoutPreparationError(null, 'processor_interception_unavailable');
60
77
  }
61
- if (!validAmountInput(this.opts.amount) || this.opts.amount === 0 || !/^[a-z]{3}$/i.test(this.opts.currency ?? ''))
62
- throw new CheckoutPreparationError(null, 'amount_required');
78
+ if (!validAmountInput(this.opts.amount) || this.opts.amount === 0 || !/^[a-z]{3}$/i.test(this.opts.currency ?? '')) {
79
+ throw new CheckoutPreparationError(null, 'amount_required', undefined, this.opts.amount != null && !validAmountInput(this.opts.amount) ? amountRefusal(this.opts.amount, this.opts.currency) : undefined);
80
+ }
63
81
  if (signal.aborted)
64
82
  throw new CheckoutPreparationError(null, 'cancelled');
65
83
  this.documentUrl = await this.readDocument();
@@ -109,8 +127,11 @@ export class PreparationGate {
109
127
  }
110
128
  // Keep the signal listener after ready: caller cancellation retires the handle too.
111
129
  }
112
- /** Called for every recognized card mutation, before any await or local retry guard. */
113
- claim(requestUrl, requestBody, requestHeaders) {
130
+ /**
131
+ * Called for every recognized card request, before any await or local retry guard. The request's
132
+ * own method is what binds: a POST for most processors, the registration GET for Worldpay eProtect.
133
+ */
134
+ claim(requestUrl, requestMethod, requestBody, requestHeaders) {
114
135
  this.observedRequest = true;
115
136
  if (this.state === 'unused')
116
137
  return undefined;
@@ -121,8 +142,13 @@ export class PreparationGate {
121
142
  const prepared = this.prepared;
122
143
  // A merchant-hosted preparation claims only its profile's reviewed card request.
123
144
  // A Fiserv preparation claims only a capture under the key pin it names.
124
- if (Date.parse(prepared.expiresAt) <= Date.now() || !matchesPreparation(prepared, requestUrl, 'POST', requestBody, requestHeaders)) {
125
- const reason = Date.parse(prepared.expiresAt) <= Date.now() ? 'expired' : 'checkout_changed';
145
+ // A CreditGuard preparation claims only a submit to the page it framed.
146
+ // A Worldpay eProtect preparation claims only its registration GET naming the paypageId it carries.
147
+ if (Date.parse(prepared.expiresAt) <= Date.now() || !matchesPreparation(prepared, requestUrl, requestMethod, requestBody, requestHeaders)) {
148
+ // An Amadeus request payment-core refuses names its own reason (preparedRequestRefusal), so
149
+ // Air France's split expiry reads amadeus_merchant_held_expiry rather than a changed checkout.
150
+ const reason = Date.parse(prepared.expiresAt) <= Date.now() ? 'expired'
151
+ : preparedRequestRefusal(prepared.psp, prepared.environment, requestUrl, requestBody, requestHeaders, prepared.merchantOrigin);
126
152
  this.invalidate(reason);
127
153
  throw new CheckoutPreparationError(prepared.id, reason);
128
154
  }
@@ -1,23 +1,84 @@
1
- export type PreparationProcessor = 'square' | 'braintree' | 'worldpay' | 'bambora' | 'mercado_pago' | 'recurly' | 'spreedly' | 'adyen' | 'checkout_com' | 'paysafe' | 'fiserv' | 'cybersource_flex';
1
+ /**
2
+ * aci: prepared only. ACI's widget gives up on Pay after 60 seconds, too soon for a prompt that
3
+ * waits on a person, so the cardholder approves before the agent clicks Pay. Its environments are
4
+ * its live hosts (production) and its INTEGRATOR_TEST hosts (sandbox).
5
+ *
6
+ * worldpay_eprotect: prepared only. Its merchants give up on the registration 10 to 15 seconds
7
+ * after Pay (5 before the vendor script fails over), too soon for a prompt that waits on a person,
8
+ * so the cardholder approves before the agent clicks Pay. Its environments are its two card hosts:
9
+ * the production primary and the pre-live host (sandbox).
10
+ *
11
+ * amadeus_checkout: prepared only. Its SDK tunnel abandons the add after 30 seconds, too soon
12
+ * for an approval after Pay. Its environments are its hosts: paypages (production) and
13
+ * paypages.test (sandbox).
14
+ */
15
+ export type PreparationProcessor = 'square' | 'braintree' | 'worldpay' | 'bambora' | 'mercado_pago' | 'recurly' | 'spreedly' | 'adyen' | 'checkout_com' | 'paysafe' | 'fiserv' | 'cybersource_flex' | 'aci' | 'creditguard' | 'worldpay_eprotect' | 'amadeus_checkout' | 'verifone';
2
16
  export type PreparationEnvironment = 'production' | 'sandbox' | 'shared';
3
17
  /**
4
18
  * How the approved card reaches the processor: the device's own request (token), or
5
19
  * ciphertext the device produces for this browser to send (cse: Adyen's four encrypted
6
- * fields, or Fiserv's Secure Data Capture envelope under a key Agentcard pinned).
20
+ * fields, Fiserv's Secure Data Capture envelope under a key Agentcard pinned, or a
21
+ * verifone.js blob under one).
7
22
  */
8
23
  export type PreparationMode = 'token' | 'cse';
9
24
  export declare function preparationMode(psp: string): PreparationMode;
25
+ /** The method of the native card request a preparation binds: the registration GET for Worldpay eProtect, a POST for every other processor. */
26
+ export declare function preparationRequestMethod(psp: string): 'GET' | 'POST';
10
27
  /**
11
28
  * Shared endpoint processors cannot attest test/live mode from their URL or key prefix.
12
29
  * Adyen can: test and live are separate hosts and key prefixes. Fiserv's are separate
13
30
  * hosts too: connect (production) and connect-cert (sandbox). So are CyberSource
14
31
  * Flex's: flex.cybersource.com is live, testflex.cybersource.com is test, and each has
15
- * its own signing keys.
32
+ * its own signing keys. A Verifone preparation pays in the environment of the key its reviewed
33
+ * profile pins.
16
34
  */
17
35
  export declare function validPreparationEnvironment(psp: string, environment: string): boolean;
36
+ /**
37
+ * ACI's prepared endpoint, the literal the API names (backend checkout-prepared-processor.ts): its
38
+ * environment's primary widget host and a checkout id that can never be real, since the merchant
39
+ * mints the checkout only at Pay time. The bind matches the card-number request by host
40
+ * environment and shape instead (matchesPreparedRequest).
41
+ */
42
+ export declare function aciPreparationUrl(environment: PreparationEnvironment): string;
43
+ /**
44
+ * A processor whose card request names an id the merchant mints only at Pay time (ACI's checkout
45
+ * id), so no URL can be prepared in advance: whether the adapters can intercept it is asked of the
46
+ * registry (VaultClient.recognizesProcessor), not of the prepared endpoint.
47
+ */
48
+ export declare function preparationBindsByShape(psp: string): boolean;
49
+ /**
50
+ * The endpoint a CreditGuard preparation stands for, per environment, as the API advertises it: the
51
+ * PPS card submit on pps (production) or ppsuat (sandbox) under the nil transaction id. It only
52
+ * proves the synced registry recognizes CreditGuard. A real submit names the txId of the page the
53
+ * preparation framed and may be on pps2, so it is matched by shape (matchesPreparedRequest), never
54
+ * by equality with this URL.
55
+ */
56
+ export declare function creditguardPreparationUrl(environment: 'production' | 'sandbox'): string;
18
57
  export declare function preparationEndpoint(psp: PreparationProcessor, environment: PreparationEnvironment): string;
19
- /** Processor identity and environment are part of the device's prior consent. */
20
- export declare function matchesPreparedRequest(psp: PreparationProcessor, environment: PreparationEnvironment, requestUrl: string, method: string, body?: string | null, headers?: Record<string, string>): boolean;
58
+ /**
59
+ * What a preparation binds beyond its processor and environment. CreditGuard: the merchant page the
60
+ * cardholder approved (the submit's ppDomain names it) and the hosted page the checkout framed (the
61
+ * submit must pay that page's own transaction). Worldpay eProtect: the paypageId naming the Worldpay
62
+ * merchant the registration is for, fixed before its page sent anything. Every other processor
63
+ * ignores all three.
64
+ */
65
+ export interface PreparedRequestBinding {
66
+ merchantOrigin?: string;
67
+ paymentPageUrl?: string;
68
+ paypageId?: string | null;
69
+ }
70
+ /**
71
+ * The approved merchant page's host, with its port if it has one: what the Amadeus SDK sends in its
72
+ * Amadeus-Checkout-Sdk-Host header (location.host). Null for anything but an http(s) origin. The
73
+ * API's twin (checkout-prepared-processor.ts) reads the same value.
74
+ */
75
+ export declare function merchantHostOf(merchantOrigin: string | null | undefined): string | null;
76
+ /**
77
+ * Processor identity and environment are part of the device's prior consent. `binding` carries what
78
+ * the preparation fixed beyond them (PreparedRequestBinding); Amadeus binds its SDK's Host header to
79
+ * `binding.merchantOrigin`, the origin the cardholder approved, and fails without one.
80
+ */
81
+ export declare function matchesPreparedRequest(psp: PreparationProcessor, environment: PreparationEnvironment, requestUrl: string, method: string, body?: string | null, headers?: Record<string, string>, binding?: PreparedRequestBinding): boolean;
21
82
  /**
22
83
  * The one request a merchant-hosted preparation pays: the reviewed profile's
23
84
  * card request itself (classifyMerchantRequest pauses it), at the profile's exact
@@ -34,6 +95,11 @@ export declare function matchesPreparedMerchantRequest(profileId: string, reques
34
95
  * the one its envelope's key is pinned as for its endpoint and merchant, must be that
35
96
  * pin, as the API's bind requires. Two pins in one environment (a merchant's old and new
36
97
  * keys during a rotation) never spend each other's approval. No other processor names one.
98
+ * A CreditGuard preparation binds the merchant page it approved and the page it framed
99
+ * (merchantOrigin, paymentPageUrl), which matchesPreparedRequest holds the submit to.
100
+ * A Worldpay eProtect preparation names the paypageId its registration must carry.
101
+ * An Amadeus preparation binds its SDK's Host header to the page the cardholder approved
102
+ * (merchantOrigin), as the API does.
37
103
  */
38
104
  export declare function matchesPreparation(preparation: {
39
105
  psp: PreparationProcessor;
@@ -42,4 +108,17 @@ export declare function matchesPreparation(preparation: {
42
108
  sandboxDeclaration?: {
43
109
  endpoint: string;
44
110
  };
111
+ merchantOrigin?: string;
112
+ paymentPageUrl?: string;
113
+ paypageId?: string;
45
114
  }, requestUrl: string, method: string, body?: string | null, headers?: Record<string, string>): boolean;
115
+ /**
116
+ * The reason a claim reports for a request its preparation does not match. An Amadeus preparation
117
+ * names what payment-core's Amadeus check refused on its own environment's card URL, as
118
+ * `amadeus_<reason>`: Air France's and KLM's add, whose expiry their own form keeps, is
119
+ * `amadeus_merchant_held_expiry`, every Data Collection Page store is
120
+ * `amadeus_dcp_field_config_unreviewed` until a merchant's field config is reviewed, and a Host
121
+ * header that does not name the approved page is `amadeus_header_binding`. Everything else, another
122
+ * processor's request or the other environment's host included, is `checkout_changed`.
123
+ */
124
+ export declare function preparedRequestRefusal(psp: PreparationProcessor, environment: PreparationEnvironment, requestUrl: string, body?: string | null, headers?: Record<string, string>, merchantOrigin?: string | null): string;