@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 +1 @@
1
- export const BUILTIN_REGISTRY = [{ "psp": "spreedly", "match": /core\.spreedly\.com\/v1\/payment_methods\/restricted\.json/i, "hosts": ["^core\\.spreedly\\.com$"], "encoding": "json", "passthroughHeaders": [/^spreedly-environment-key$/i] }, { "psp": "shopify", "match": /(checkout\.pci\.shopifyinc\.com|deposit\.[a-z0-9-]+\.shopifycs\.com)\/sessions/i, "hosts": ["^checkout\\.pci\\.shopifyinc\\.com$", "^deposit\\.[a-z0-9-]+\\.shopifycs\\.com$"], "encoding": "json", "passthroughHeaders": [/^shopify-identification-signature$/i] }, { "psp": "stripe", "match": /api\.stripe\.com\/v1\/(payment_methods|tokens|sources|confirmation_tokens|setup_intents\/seti_\w+\/confirm|payment_intents\/pi_\w+\/confirm|payment_pages\/cs_(?:test|live)_\w+\/confirm)/i, "hosts": ["^api\\.stripe\\.com$"], "encoding": "form", "passthroughHeaders": [/^authorization$/i, /^stripe-version$/i, /^x-stripe-client-user-agent$/i], "cardFields": ["card[number]", "payment_method_data[card][number]"], "passWithoutCard": "api\\.stripe\\.com/v1/(sources|confirmation_tokens|payment_pages/cs_(?:test|live)_\\w+/confirm)" }, { "psp": "braintree", "match": /payments(\.sandbox)?\.braintree-api\.com\/graphql/i, "hosts": ["^payments\\.braintree-api\\.com$", "^payments\\.sandbox\\.braintree-api\\.com$"], "sandboxHosts": ["^payments\\.sandbox\\.braintree-api\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i, /^braintree-version$/i] }, { "psp": "checkout_com", "match": /(api|card-acquisition-gateway)(\.sandbox)?\.checkout\.com\/tokens/i, "hosts": ["^api\\.checkout\\.com$", "^api\\.sandbox\\.checkout\\.com$", "^card-acquisition-gateway\\.checkout\\.com$", "^card-acquisition-gateway\\.sandbox\\.checkout\\.com$"], "sandboxHosts": ["^api\\.sandbox\\.checkout\\.com$", "^card-acquisition-gateway\\.sandbox\\.checkout\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i] }, { "psp": "adyen", "match": /(checkoutshopper-(test|live(-[a-z]+)?)\.adyen\.com|([a-z0-9-]+\.)*adyenpayments\.com)\/checkoutshopper\/v1\/sessions\/[A-Za-z0-9_-]+\/payments/i, "hosts": ["^checkoutshopper-(test|live(-[a-z]+)?)\\.adyen\\.com$", "^([a-z0-9-]+\\.)*adyenpayments\\.com$"], "sandboxHosts": ["^checkoutshopper-test\\.adyen\\.com$"], "encoding": "json", "passthroughHeaders": [], "clientSideEncrypted": true, "mode": "cse" }, { "psp": "tranzila", "match": /(direct\.tranzila\.com\/process\/n\/|directng\.tranzila\.com\/process\/?)/i, "hosts": ["^direct\\.tranzila\\.com$", "^directng\\.tranzila\\.com$"], "encoding": "form", "passthroughHeaders": [], "mode": "hosted_form" }, { "psp": "square", "match": /pci-connect\.squareup(?:sandbox)?\.com\/v2\/card-nonce/i, "hosts": ["^pci-connect\\.squareup\\.com$", "^pci-connect\\.squareupsandbox\\.com$"], "sandboxHosts": ["^pci-connect\\.squareupsandbox\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "authorize_net", "match": /(api2|apitest)\.authorize\.net\/xml\/v1\/request\.api/i, "hosts": ["^api2\\.authorize\\.net$", "^apitest\\.authorize\\.net$"], "sandboxHosts": ["^apitest\\.authorize\\.net$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "worldpay", "match": /(try\.)?access\.worldpay\.com\/(sessions\/card|verifiedTokens\/sessions)/i, "hosts": ["^access\\.worldpay\\.com$", "^try\\.access\\.worldpay\\.com$"], "sandboxHosts": ["^try\\.access\\.worldpay\\.com$"], "encoding": "json", "passthroughHeaders": [/^accept$/i] }, { "psp": "nuvei", "match": /(secure|ppp-test)\.safecharge\.com\/ppp\/api\/v1\/(?:cardTokenization|clientPayment|websdk\/initPaymentWithCardTokenization)\.do/i, "hosts": ["^secure\\.safecharge\\.com$", "^ppp-test\\.safecharge\\.com$"], "sandboxHosts": ["^ppp-test\\.safecharge\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "airwallex", "match": /(checkout(\.sandbox)?\.airwallex\.com|pci-api(\.sandbox)?\.airwallex\.com)\/api\/v1\/pa\/(payment_intents\/[^/?#]+\/confirm|payment_consents\/[^/?#]+\/verify|payment_methods\/create)(\?|$)/i, "hosts": ["^checkout\\.airwallex\\.com$", "^checkout\\.sandbox\\.airwallex\\.com$", "^pci-api\\.airwallex\\.com$", "^pci-api\\.sandbox\\.airwallex\\.com$"], "sandboxHosts": ["^checkout\\.sandbox\\.airwallex\\.com$", "^pci-api\\.sandbox\\.airwallex\\.com$"], "encoding": "json", "passthroughHeaders": [/^client-secret$/i, /^authorization$/i, /^x-auth-token$/i, /^x-on-behalf-of$/i, /^x-api-version$/i] }, { "psp": "rapyd", "match": /(api|sandboxapi)\.rapyd\.net\/v1\/(?:hosted\/collect\/card\/[^/?#]+\/payment_method|checkout\/checkout_[A-Za-z0-9]+)(?:[?#]|$)/i, "hosts": ["^api\\.rapyd\\.net$", "^sandboxapi\\.rapyd\\.net$"], "sandboxHosts": ["^sandboxapi\\.rapyd\\.net$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "dlocal", "match": /ppmcc(-sandbox)?\.dlocal\.com\/cvault\/credit-card\/temporal/i, "hosts": ["^ppmcc\\.dlocal\\.com$", "^ppmcc-sandbox\\.dlocal\\.com$"], "sandboxHosts": ["^ppmcc-sandbox\\.dlocal\\.com$"], "encoding": "json", "passthroughHeaders": [/^x-fields-api-key$/i, /^x-uow$/i, /^x-dlocal-infrav2$/i] }, { "psp": "ebanx", "match": /(?:(?:customer-frontier|customer|api-local-latam|api|sandbox-local-latam|sandbox)\.ebanx\.com|(?:api-diamond|api|sandbox)\.ebanxpay\.com)\/ws\/token/i, "hosts": ["^customer\\.ebanx\\.com$", "^customer-frontier\\.ebanx\\.com$", "^api\\.ebanx\\.com$", "^sandbox\\.ebanx\\.com$", "^api-local-latam\\.ebanx\\.com$", "^sandbox-local-latam\\.ebanx\\.com$", "^api-diamond\\.ebanxpay\\.com$", "^api\\.ebanxpay\\.com$", "^sandbox\\.ebanxpay\\.com$"], "sandboxHosts": ["^sandbox\\.ebanx\\.com$", "^sandbox-local-latam\\.ebanx\\.com$", "^sandbox\\.ebanxpay\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "mercado_pago", "match": /api\.mercadopago\.com\/v1\/card_tokens(?![\w/-])/i, "hosts": ["^api\\.mercadopago\\.com$"], "encoding": "json", "passthroughHeaders": [/^x-product-id$/i] }, { "psp": "payu", "match": /(secure\.payu\.com|(merch-prod|secure)\.snd\.payu\.com)\/api\/front\/tokens/i, "hosts": ["^secure\\.payu\\.com$", "^(merch-prod|secure)\\.snd\\.payu\\.com$"], "sandboxHosts": ["^(merch-prod|secure)\\.snd\\.payu\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i] }, { "psp": "razorpay", "match": /api\.razorpay\.com\/v1\/(?:standard_checkout\/)?payments\/create\/(?:ajax|checkout|fees)/i, "hosts": ["^api\\.razorpay\\.com$"], "encoding": "form", "passthroughHeaders": [/^x-razorpay-sessionid$/i, /^x-customer-access-token$/i] }, { "psp": "mollie", "match": /api\.cc\.mollie\.com\/v1\/card-tokens/i, "hosts": ["^api\\.cc\\.mollie\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "paysafe", "match": /(?:api(\.test)?\.paysafe\.com\/(?:paymenthub\/v1\/singleusepaymenthandles|js\/api\/v1\/tokenize)|hosted(\.test)?\.paysafe\.com\/checkout\/api\/v1\/tokenize)(?![\w/-])/i, "hosts": ["^api\\.paysafe\\.com$", "^api\\.test\\.paysafe\\.com$", "^hosted\\.paysafe\\.com$", "^hosted\\.test\\.paysafe\\.com$"], "sandboxHosts": ["^api\\.test\\.paysafe\\.com$", "^hosted\\.test\\.paysafe\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i, /^x-paysafe-credentials$/i, /^correlationid$/i] }, { "psp": "recurly", "match": /api(\.eu)?\.recurly\.com\/js\/v1\/token(?![\w-])/i, "hosts": ["^api\\.recurly\\.com$", "^api\\.eu\\.recurly\\.com$"], "encoding": "form", "passthroughHeaders": [/^recurly-credential-checkout-hostname$/i] }, { "psp": "moneris", "match": /(www3|esqa|gateway|gatewayqa|gatewayt|gatewaydev)\.moneris\.com\/HPPtoken\/request\.php/i, "hosts": ["^www3\\.moneris\\.com$", "^esqa\\.moneris\\.com$", "^gateway\\.moneris\\.com$", "^gatewayqa\\.moneris\\.com$", "^gatewayt\\.moneris\\.com$", "^gatewaydev\\.moneris\\.com$"], "sandboxHosts": ["^esqa\\.moneris\\.com$", "^gatewayqa\\.moneris\\.com$", "^gatewayt\\.moneris\\.com$", "^gatewaydev\\.moneris\\.com$"], "encoding": "form", "passthroughHeaders": [] }, { "psp": "bambora", "match": /(api\.na\.bambora\.com|api\.bam\.shift4api\.net)\/scripts\/tokenization\/tokens/i, "hosts": ["^api\\.na\\.bambora\\.com$", "^api\\.bam\\.shift4api\\.net$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "global_payments", "match": /(?:api\.heartlandportico\.com\/SecureSubmit\.v1\/api\/token|cert\.api2\.heartlandportico\.com\/Hps\.Exchange\.PosGateway\.Hpf\.v1\/api\/token|apis(?:\.sandbox)?(?:\.eu)?\.globalpay\.com\/ucp\/(?:merchants\/[^/]+\/)?payment-methods)/i, "hosts": ["^api\\.heartlandportico\\.com$", "^cert\\.api2\\.heartlandportico\\.com$", "^apis\\.globalpay\\.com$", "^apis\\.sandbox\\.globalpay\\.com$", "^apis\\.eu\\.globalpay\\.com$", "^apis\\.sandbox\\.eu\\.globalpay\\.com$"], "sandboxHosts": ["^cert\\.api2\\.heartlandportico\\.com$", "^apis\\.sandbox\\.globalpay\\.com$", "^apis\\.sandbox\\.eu\\.globalpay\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i, /^x-gp-version$/i] }, { "psp": "gravy", "match": /api(\.sandbox)?\.[a-z0-9-]+\.gr4vy\.app\/checkout\/sessions\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/fields/i, "hosts": ["^api\\.[a-z0-9-]+\\.gr4vy\\.app$", "^api\\.sandbox\\.[a-z0-9-]+\\.gr4vy\\.app$"], "sandboxHosts": ["^api\\.sandbox\\.[a-z0-9-]+\\.gr4vy\\.app$"], "encoding": "json", "passthroughHeaders": [] }];
1
+ export const BUILTIN_REGISTRY = [{ "psp": "spreedly", "match": /core\.spreedly\.com\/v1\/payment_methods\/restricted\.json/i, "hosts": ["^core\\.spreedly\\.com$"], "encoding": "json", "passthroughHeaders": [/^spreedly-environment-key$/i] }, { "psp": "shopify", "match": /(checkout\.pci\.shopifyinc\.com|deposit\.[a-z0-9-]+\.shopifycs\.com)\/sessions/i, "hosts": ["^checkout\\.pci\\.shopifyinc\\.com$", "^deposit\\.[a-z0-9-]+\\.shopifycs\\.com$"], "encoding": "json", "passthroughHeaders": [/^shopify-identification-signature$/i] }, { "psp": "stripe", "match": /api\.stripe\.com\/v1\/(payment_methods|tokens|sources|confirmation_tokens|setup_intents\/seti_\w+\/confirm|payment_intents\/pi_\w+\/confirm|payment_pages\/cs_(?:test|live)_\w+\/confirm)/i, "hosts": ["^api\\.stripe\\.com$"], "encoding": "form", "passthroughHeaders": [/^authorization$/i, /^stripe-version$/i, /^x-stripe-client-user-agent$/i], "cardFields": ["card[number]", "payment_method_data[card][number]"], "passWithoutCard": "api\\.stripe\\.com/v1/(sources|confirmation_tokens|payment_pages/cs_(?:test|live)_\\w+/confirm)" }, { "psp": "braintree", "match": /payments(\.sandbox)?\.braintree-api\.com\/graphql/i, "hosts": ["^payments\\.braintree-api\\.com$", "^payments\\.sandbox\\.braintree-api\\.com$"], "sandboxHosts": ["^payments\\.sandbox\\.braintree-api\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i, /^braintree-version$/i] }, { "psp": "checkout_com", "match": /(api|card-acquisition-gateway)(\.sandbox)?\.checkout\.com\/tokens/i, "hosts": ["^api\\.checkout\\.com$", "^api\\.sandbox\\.checkout\\.com$", "^card-acquisition-gateway\\.checkout\\.com$", "^card-acquisition-gateway\\.sandbox\\.checkout\\.com$"], "sandboxHosts": ["^api\\.sandbox\\.checkout\\.com$", "^card-acquisition-gateway\\.sandbox\\.checkout\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i] }, { "psp": "adyen", "match": /(checkoutshopper-(test|live(-[a-z]+)?)\.adyen\.com|([a-z0-9-]+\.)*adyenpayments\.com)\/checkoutshopper\/v1\/sessions\/[A-Za-z0-9_-]+\/payments/i, "hosts": ["^checkoutshopper-(test|live(-[a-z]+)?)\\.adyen\\.com$", "^([a-z0-9-]+\\.)*adyenpayments\\.com$"], "sandboxHosts": ["^checkoutshopper-test\\.adyen\\.com$"], "encoding": "json", "passthroughHeaders": [], "clientSideEncrypted": true, "mode": "cse" }, { "psp": "tranzila", "match": /(direct\.tranzila\.com\/process\/n\/|directng\.tranzila\.com\/process\/?)/i, "hosts": ["^direct\\.tranzila\\.com$", "^directng\\.tranzila\\.com$"], "encoding": "form", "passthroughHeaders": [], "mode": "hosted_form" }, { "psp": "square", "match": /pci-connect\.squareup(?:sandbox)?\.com\/v2\/card-nonce/i, "hosts": ["^pci-connect\\.squareup\\.com$", "^pci-connect\\.squareupsandbox\\.com$"], "sandboxHosts": ["^pci-connect\\.squareupsandbox\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "authorize_net", "match": /(api2|apitest)\.authorize\.net\/xml\/v1\/request\.api/i, "hosts": ["^api2\\.authorize\\.net$", "^apitest\\.authorize\\.net$"], "sandboxHosts": ["^apitest\\.authorize\\.net$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "worldpay", "match": /(try\.)?access\.worldpay\.com\/(sessions\/card|verifiedTokens\/sessions)/i, "hosts": ["^access\\.worldpay\\.com$", "^try\\.access\\.worldpay\\.com$"], "sandboxHosts": ["^try\\.access\\.worldpay\\.com$"], "encoding": "json", "passthroughHeaders": [/^accept$/i] }, { "psp": "nuvei", "match": /(secure|ppp-test)\.safecharge\.com\/ppp\/api\/v1\/(?:cardTokenization|clientPayment|websdk\/initPaymentWithCardTokenization)\.do/i, "hosts": ["^secure\\.safecharge\\.com$", "^ppp-test\\.safecharge\\.com$"], "sandboxHosts": ["^ppp-test\\.safecharge\\.com$"], "encoding": "json", "passthroughHeaders": [], "jsonCardFields": [["paymentOption", "card", "cardNumber"], ["cardData", "cardNumber"]], "passWithoutCard": "(?:secure|ppp-test)\\.safecharge\\.com/ppp/api/v1/(?:clientPayment|websdk/initPaymentWithCardTokenization)\\.do" }, { "psp": "airwallex", "match": /(checkout(\.sandbox)?\.airwallex\.com|pci-api(\.sandbox)?\.airwallex\.com)\/api\/v1\/pa\/(payment_intents\/[^/?#]+\/confirm|payment_consents\/[^/?#]+\/verify|payment_methods\/create)(\?|$)/i, "hosts": ["^checkout\\.airwallex\\.com$", "^checkout\\.sandbox\\.airwallex\\.com$", "^pci-api\\.airwallex\\.com$", "^pci-api\\.sandbox\\.airwallex\\.com$"], "sandboxHosts": ["^checkout\\.sandbox\\.airwallex\\.com$", "^pci-api\\.sandbox\\.airwallex\\.com$"], "encoding": "json", "passthroughHeaders": [/^client-secret$/i, /^authorization$/i, /^x-auth-token$/i, /^x-on-behalf-of$/i, /^x-api-version$/i] }, { "psp": "rapyd", "match": /(api|sandboxapi)\.rapyd\.net\/v1\/(?:hosted\/collect\/card\/[^/?#]+\/payment_method|checkout\/checkout_[A-Za-z0-9]+)(?:[?#]|$)/i, "hosts": ["^api\\.rapyd\\.net$", "^sandboxapi\\.rapyd\\.net$"], "sandboxHosts": ["^sandboxapi\\.rapyd\\.net$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "dlocal", "match": /ppmcc(-sandbox)?\.dlocal\.com\/cvault\/credit-card\/temporal/i, "hosts": ["^ppmcc\\.dlocal\\.com$", "^ppmcc-sandbox\\.dlocal\\.com$"], "sandboxHosts": ["^ppmcc-sandbox\\.dlocal\\.com$"], "encoding": "json", "passthroughHeaders": [/^x-fields-api-key$/i, /^x-uow$/i, /^x-dlocal-infrav2$/i] }, { "psp": "ebanx", "match": /(?:(?:customer-frontier|customer|api-local-latam|api|sandbox-local-latam|sandbox)\.ebanx\.com|(?:api-diamond|api|sandbox)\.ebanxpay\.com)\/ws\/token/i, "hosts": ["^customer\\.ebanx\\.com$", "^customer-frontier\\.ebanx\\.com$", "^api\\.ebanx\\.com$", "^sandbox\\.ebanx\\.com$", "^api-local-latam\\.ebanx\\.com$", "^sandbox-local-latam\\.ebanx\\.com$", "^api-diamond\\.ebanxpay\\.com$", "^api\\.ebanxpay\\.com$", "^sandbox\\.ebanxpay\\.com$"], "sandboxHosts": ["^sandbox\\.ebanx\\.com$", "^sandbox-local-latam\\.ebanx\\.com$", "^sandbox\\.ebanxpay\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "mercado_pago", "match": /api\.mercadopago\.com\/v1\/card_tokens(?![\w/-])/i, "hosts": ["^api\\.mercadopago\\.com$"], "encoding": "json", "passthroughHeaders": [/^x-product-id$/i] }, { "psp": "payu", "match": /(secure\.payu\.com|(merch-prod|secure)\.snd\.payu\.com)\/api\/front\/tokens/i, "hosts": ["^secure\\.payu\\.com$", "^(merch-prod|secure)\\.snd\\.payu\\.com$"], "sandboxHosts": ["^(merch-prod|secure)\\.snd\\.payu\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i] }, { "psp": "razorpay", "match": /api\.razorpay\.com\/v1\/(?:standard_checkout\/)?payments\/create\/(?:ajax|checkout|fees)/i, "hosts": ["^api\\.razorpay\\.com$"], "encoding": "form", "passthroughHeaders": [/^x-razorpay-sessionid$/i, /^x-customer-access-token$/i] }, { "psp": "mollie", "match": /api\.cc\.mollie\.com\/v1\/card-tokens/i, "hosts": ["^api\\.cc\\.mollie\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "paysafe", "match": /(?:api(\.test)?\.paysafe\.com\/(?:paymenthub\/v1\/singleusepaymenthandles|js\/api\/v1\/tokenize)|hosted(\.test)?\.paysafe\.com\/checkout\/api\/v1\/tokenize)(?![\w/-])/i, "hosts": ["^api\\.paysafe\\.com$", "^api\\.test\\.paysafe\\.com$", "^hosted\\.paysafe\\.com$", "^hosted\\.test\\.paysafe\\.com$"], "sandboxHosts": ["^api\\.test\\.paysafe\\.com$", "^hosted\\.test\\.paysafe\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i, /^x-paysafe-credentials$/i, /^correlationid$/i] }, { "psp": "recurly", "match": /api(\.eu)?\.recurly\.com\/js\/v1\/token(?![\w-])/i, "hosts": ["^api\\.recurly\\.com$", "^api\\.eu\\.recurly\\.com$"], "encoding": "form", "passthroughHeaders": [/^recurly-credential-checkout-hostname$/i] }, { "psp": "moneris", "match": /(www3|esqa|gateway|gatewayqa|gatewayt|gatewaydev)\.moneris\.com\/HPPtoken\/request\.php/i, "hosts": ["^www3\\.moneris\\.com$", "^esqa\\.moneris\\.com$", "^gateway\\.moneris\\.com$", "^gatewayqa\\.moneris\\.com$", "^gatewayt\\.moneris\\.com$", "^gatewaydev\\.moneris\\.com$"], "sandboxHosts": ["^esqa\\.moneris\\.com$", "^gatewayqa\\.moneris\\.com$", "^gatewayt\\.moneris\\.com$", "^gatewaydev\\.moneris\\.com$"], "encoding": "form", "passthroughHeaders": [] }, { "psp": "bambora", "match": /(api\.na\.bambora\.com|api\.bam\.shift4api\.net)\/scripts\/tokenization\/tokens/i, "hosts": ["^api\\.na\\.bambora\\.com$", "^api\\.bam\\.shift4api\\.net$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "global_payments", "match": /(?:api\.heartlandportico\.com\/SecureSubmit\.v1\/api\/token|cert\.api2\.heartlandportico\.com\/Hps\.Exchange\.PosGateway\.Hpf\.v1\/api\/token|apis(?:\.sandbox)?(?:\.eu)?\.globalpay\.com\/ucp\/(?:merchants\/[^/]+\/)?payment-methods)/i, "hosts": ["^api\\.heartlandportico\\.com$", "^cert\\.api2\\.heartlandportico\\.com$", "^apis\\.globalpay\\.com$", "^apis\\.sandbox\\.globalpay\\.com$", "^apis\\.eu\\.globalpay\\.com$", "^apis\\.sandbox\\.eu\\.globalpay\\.com$"], "sandboxHosts": ["^cert\\.api2\\.heartlandportico\\.com$", "^apis\\.sandbox\\.globalpay\\.com$", "^apis\\.sandbox\\.eu\\.globalpay\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i, /^x-gp-version$/i] }, { "psp": "gravy", "match": /api(\.sandbox)?\.[a-z0-9-]+\.gr4vy\.app\/checkout\/sessions\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/fields/i, "hosts": ["^api\\.[a-z0-9-]+\\.gr4vy\\.app$", "^api\\.sandbox\\.[a-z0-9-]+\\.gr4vy\\.app$"], "sandboxHosts": ["^api\\.sandbox\\.[a-z0-9-]+\\.gr4vy\\.app$"], "encoding": "json", "passthroughHeaders": [] }];
@@ -0,0 +1,177 @@
1
+ /** The SDK's view of a reviewed card endpoint profile: where its card request goes and what may travel with it. */
2
+ export interface CardEndpointProfile {
3
+ readonly id: string;
4
+ readonly merchant: string;
5
+ readonly status: 'observe' | 'enabled';
6
+ /** The exact https origin of the page the card is typed into. */
7
+ readonly checkout: string;
8
+ /** The exact https origin the card request goes to. */
9
+ readonly endpoint: string;
10
+ readonly method: 'POST';
11
+ readonly path: string;
12
+ readonly query: Readonly<Record<string, string>>;
13
+ readonly encoding: 'json' | 'form' | 'multipart';
14
+ readonly session: {
15
+ readonly cookies: boolean;
16
+ readonly headers: readonly string[];
17
+ readonly required: readonly string[];
18
+ };
19
+ readonly response: {
20
+ readonly headers: readonly string[];
21
+ };
22
+ }
23
+ /** One cookie of the endpoint's jar, name and value only. */
24
+ export interface CardEndpointCookie {
25
+ name: string;
26
+ value: string;
27
+ }
28
+ /**
29
+ * What the adapters capture from a paused card request and hand to the create: the
30
+ * URL, the origin of the page it was paused on, the profile's session headers, the
31
+ * endpoint's cookies for a cookie profile, a Referer on the checkout page, and the
32
+ * body, which holds only the placeholder card the agent typed. Never a real card,
33
+ * always cardholder data: it travels only in `merchant_card_endpoint.session`.
34
+ */
35
+ export interface CardEndpointSession {
36
+ url: string;
37
+ page_origin: string;
38
+ headers: Record<string, string>;
39
+ cookies?: CardEndpointCookie[];
40
+ referer?: string;
41
+ body: string;
42
+ }
43
+ /** The psp and mode a card endpoint authorization carries; neither is a processor. */
44
+ export declare const CARD_ENDPOINT_PSP: string;
45
+ export declare const CARD_ENDPOINT_MODE: "card_endpoint";
46
+ /**
47
+ * Why a card endpoint payment was refused before anything was created or sent. Nothing
48
+ * was charged, and the message names no URL, body or session value.
49
+ *
50
+ * - `not_enabled`: this build's copy of the profile does not take payments yet.
51
+ * - `amount_required`: the attachment names no amount; the agent's amount is the only authority here.
52
+ * - `approval_required`: the attachment asks for Autopilot; every payment here needs the cardholder's approval.
53
+ * - `preparation_unsupported`: a prepared checkout cannot pay a merchant's own card endpoint.
54
+ * - `request_unsupported`: the paused request is not the card request Agentcard reviewed
55
+ * (`detail` says what, naming fields, never values).
56
+ *
57
+ * Every reason but `request_unsupported` answers the same way for every request on the
58
+ * attachment, so the adapters stop asking; `request_unsupported` refuses only the
59
+ * request it is about.
60
+ */
61
+ export type CardEndpointRefusal = 'not_enabled' | 'amount_required' | 'approval_required' | 'preparation_unsupported' | 'request_unsupported';
62
+ export declare class CardEndpointRefusedError extends Error {
63
+ readonly profile: string;
64
+ readonly reason: CardEndpointRefusal;
65
+ readonly detail: string | null;
66
+ constructor(profile: string, reason: CardEndpointRefusal, detail?: string | null);
67
+ /** True when every later request on the attachment would be refused the same way. */
68
+ get permanent(): boolean;
69
+ }
70
+ /** The reviewed profile (any status) whose card request `url` and `method` are exactly, or null. */
71
+ export declare function cardEndpointFor(url: string, method: string): CardEndpointProfile | null;
72
+ /** The reviewed profile with this id, or null. */
73
+ export declare function cardEndpointById(id: string): CardEndpointProfile | null;
74
+ /** Whether this build's copy of the profile takes payments (enabled, nothing pending, a reviewed HAR, not recurring). */
75
+ export declare function cardEndpointLive(profile: CardEndpointProfile | string): boolean;
76
+ /** What an event may say about a card endpoint request: the profile and the endpoint origin, never the URL's path or query. */
77
+ export declare function cardEndpointDetail(profile: CardEndpointProfile): {
78
+ profile: string;
79
+ endpoint: string;
80
+ };
81
+ /**
82
+ * Fetch.enable patterns covering every profile's card request, in any status: its
83
+ * origin and path with each `:name` segment and the query as wildcards. A coarse
84
+ * pre-filter, like cardUrlPatterns for processors; cardEndpointFor is the exact check
85
+ * each paused request is held to, and anything it refuses continues untouched.
86
+ */
87
+ export declare function cardEndpointPatterns(): string[];
88
+ /** What an adapter reads off a paused card endpoint request. */
89
+ export interface CardEndpointCapture {
90
+ url: string;
91
+ /** The paused request's headers as the browser reports them; the jar's cookies are never among them. */
92
+ headers: Record<string, string> | undefined;
93
+ /** The paused body: the placeholder card the agent typed and the rest of the merchant's fields. */
94
+ body: string;
95
+ /** The origin of the top-level page the request was paused on, when it could be read. */
96
+ pageOrigin: string | undefined;
97
+ /** The endpoint's cookie jar for this URL (HttpOnly included). Read only for a cookie profile. */
98
+ cookies: () => Promise<CardEndpointCookie[]>;
99
+ }
100
+ /**
101
+ * The session the create carries for a paused card endpoint request: the profile's own
102
+ * header names and nothing else, the Referer only when it is a page on the checkout
103
+ * origin, the endpoint's cookies only for a cookie profile, and the body. Checked with
104
+ * the same rules the API and the device run (payment-core
105
+ * merchantCardEndpointSessionRefusal), so a request they would refuse never leaves this
106
+ * process: a CardEndpointRefusedError (`request_unsupported`) instead, naming no value.
107
+ */
108
+ export declare function captureCardEndpointSession(profile: CardEndpointProfile, capture: CardEndpointCapture): Promise<CardEndpointSession>;
109
+ /**
110
+ * The headers the paused request is answered with: the profile's answer headers the
111
+ * merchant sent, and never Set-Cookie (cookies reach the browser through
112
+ * cardEndpointCookies, on the endpoint host only).
113
+ */
114
+ export declare function cardEndpointAnswerHeaders(profile: CardEndpointProfile, headers: Record<string, string>): Record<string, string>;
115
+ /**
116
+ * The fixed answer a paused request gets when the cardholder's device withheld the
117
+ * merchant's answer (it carried the card, or a compressed stream the device cannot
118
+ * read): an error the merchant's page stops on. The card request was sent; whether
119
+ * the merchant took the payment is unknown until the order is checked.
120
+ */
121
+ export declare const CARD_ENDPOINT_WITHHELD_ANSWER: Readonly<{
122
+ status: number;
123
+ headers: Readonly<Record<string, string>>;
124
+ body: string;
125
+ }>;
126
+ /**
127
+ * A Set-Cookie value from the merchant's answer, as an adapter writes it into the
128
+ * agent's browser: host-only on the endpoint host, or on the parent domain its Domain
129
+ * attribute names when that is a rotation of a cookie the browser already holds there
130
+ * (`domain`), at the cookie's path, Secure whatever the merchant said (the endpoint is
131
+ * https-only, so no cookie the SDK writes ever travels over plain http), with its other
132
+ * flags and expiry. `expires` is seconds since the epoch, absent for a session cookie,
133
+ * and 1 for a cookie the merchant expired, which the browser then removes.
134
+ */
135
+ export interface CardEndpointSetCookie {
136
+ name: string;
137
+ value: string;
138
+ /** The endpoint's origin, which a host-only cookie is written for. */
139
+ origin: string;
140
+ /** The endpoint's host name. */
141
+ host: string;
142
+ /**
143
+ * The domain (no leading dot) the cookie is written on as a domain cookie: set only
144
+ * when the merchant's Domain attribute names the endpoint host or a parent of it and
145
+ * the browser already sends the endpoint a cookie of this name on that domain, so the
146
+ * write replaces that cookie. Absent for every other cookie, which is host-only.
147
+ */
148
+ domain?: string;
149
+ path: string;
150
+ /** True for every cookie the SDK writes: see above. */
151
+ secure: boolean;
152
+ httpOnly: boolean;
153
+ sameSite?: 'Strict' | 'Lax' | 'None';
154
+ expires?: number;
155
+ }
156
+ /**
157
+ * One cookie the browser sends to the endpoint, as the adapters read the jar
158
+ * (Network.getCookies or context.cookies()): its name and its domain, which a leading
159
+ * dot marks as a domain cookie.
160
+ */
161
+ export interface CardEndpointJarCookie {
162
+ name: string;
163
+ domain: string;
164
+ }
165
+ /**
166
+ * The merchant's Set-Cookie values as cookies to write (parseSetCookie), and how many
167
+ * could not be written as one (a malformed line, a prefix or a Domain the browser would
168
+ * refuse, a Domain with the jar unread). `jar` is the endpoint's cookies as the adapter
169
+ * read them, null when the read failed. Only a profile whose answer may carry cookies
170
+ * has any.
171
+ */
172
+ export declare function cardEndpointCookies(profile: CardEndpointProfile, requestUrl: string, setCookies: readonly string[], nowMs?: number, jar?: readonly CardEndpointJarCookie[] | null): {
173
+ cookies: CardEndpointSetCookie[];
174
+ skipped: number;
175
+ };
176
+ /** Why a session is not one the profile lets travel (payment-core merchantCardEndpointSessionRefusal), or null. Names no value. */
177
+ export declare function cardEndpointSessionRefusal(profile: CardEndpointProfile, session: unknown): string | null;
@@ -0,0 +1,286 @@
1
+ // A reviewed merchant's own card endpoint: the SDK's half of the card endpoint mode.
2
+ //
3
+ // Some merchants post the typed card from their own checkout page straight to their
4
+ // own server, with no processor in between (AT&T, Italo, Universal Orlando, Target
5
+ // Optical, Opus Virtual Offices). Agentcard reviews each one and pins it as a profile
6
+ // in the payment core (merchant-card-endpoints.generated.ts, the SDK's copy of the
7
+ // same rules the API and the Vault run): the page the card is typed into, the exact
8
+ // origin, path and query of the card request, which session headers and cookies it
9
+ // needs, and which answer headers may travel back.
10
+ //
11
+ // The adapters arm every profile's endpoint. A POST that is exactly a profile's card
12
+ // request pauses. While this build's copy of the profile does not take payments
13
+ // (observe, a fact only a partner HAR can pin, no reviewed HAR, a recurring charge)
14
+ // the request is aborted as an unsupported checkout and nothing is created. Otherwise
15
+ // the adapter captures the request's session (the profile's own header list, the
16
+ // endpoint's cookie jar for a cookie profile, a Referer on the checkout page) and
17
+ // hands it with the paused body, which holds only the placeholder card the agent
18
+ // typed, to the create. The cardholder's device sends the real card request to the
19
+ // merchant itself, over the checkout relay, and reports the merchant's answer; the
20
+ // adapter writes its Set-Cookie values into the agent's browser on the endpoint host
21
+ // (or on the parent domain of a cookie the browser already holds there, which the
22
+ // write replaces) and answers the paused request with it. The real card never reaches
23
+ // this process or the agent's page.
24
+ //
25
+ // The endpoint URL (it carries cart, booking and instance ids), the paused body, the
26
+ // session and the answer are cardholder data even with no real card in them: no
27
+ // event, error or log line from this module names any of them. Events name the
28
+ // profile id and the endpoint origin only.
29
+ import { MERCHANT_CARD_ENDPOINT_MODE as SHARED_MODE, MERCHANT_CARD_ENDPOINT_PSP as SHARED_PSP, MERCHANT_CARD_ENDPOINT_RECOGNIZERS as SHARED_RECOGNIZERS, matchMerchantCardEndpoint as sharedMatch, merchantCardEndpointLive as sharedLive, merchantCardEndpointSessionRefusal as sharedSessionRefusal, } from './merchant-card-endpoints.generated.js';
30
+ /** The psp and mode a card endpoint authorization carries; neither is a processor. */
31
+ export const CARD_ENDPOINT_PSP = SHARED_PSP;
32
+ export const CARD_ENDPOINT_MODE = SHARED_MODE;
33
+ const PROFILES = SHARED_RECOGNIZERS;
34
+ export class CardEndpointRefusedError extends Error {
35
+ profile;
36
+ reason;
37
+ detail;
38
+ constructor(profile, reason, detail = null) {
39
+ super(`refused a payment to the ${profile} card endpoint (${reason})${detail ? `: ${detail}` : ''}. Nothing was created and nothing was charged.`);
40
+ this.profile = profile;
41
+ this.reason = reason;
42
+ this.detail = detail;
43
+ this.name = 'CardEndpointRefusedError';
44
+ }
45
+ /** True when every later request on the attachment would be refused the same way. */
46
+ get permanent() { return this.reason !== 'request_unsupported'; }
47
+ }
48
+ /** The reviewed profile (any status) whose card request `url` and `method` are exactly, or null. */
49
+ export function cardEndpointFor(url, method) {
50
+ try {
51
+ return sharedMatch(url, method, undefined) ?? null;
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ /** The reviewed profile with this id, or null. */
58
+ export function cardEndpointById(id) {
59
+ return PROFILES.find((profile) => profile.id === id) ?? null;
60
+ }
61
+ /** Whether this build's copy of the profile takes payments (enabled, nothing pending, a reviewed HAR, not recurring). */
62
+ export function cardEndpointLive(profile) {
63
+ return sharedLive(typeof profile === 'string' ? profile : profile.id) === true;
64
+ }
65
+ /** What an event may say about a card endpoint request: the profile and the endpoint origin, never the URL's path or query. */
66
+ export function cardEndpointDetail(profile) {
67
+ return { profile: profile.id, endpoint: profile.endpoint };
68
+ }
69
+ // A CDP URL pattern treats '*' and '?' as wildcards and '\' as their escape.
70
+ const globEscape = (text) => text.replace(/[\\*?]/g, (char) => `\\${char}`);
71
+ /**
72
+ * Fetch.enable patterns covering every profile's card request, in any status: its
73
+ * origin and path with each `:name` segment and the query as wildcards. A coarse
74
+ * pre-filter, like cardUrlPatterns for processors; cardEndpointFor is the exact check
75
+ * each paused request is held to, and anything it refuses continues untouched.
76
+ */
77
+ export function cardEndpointPatterns() {
78
+ return [...new Set(PROFILES.map((profile) => `${globEscape(profile.endpoint)}${profile.path.split('/').map((segment) => (segment.startsWith(':') ? '*' : globEscape(segment))).join('/')}*`))];
79
+ }
80
+ // Header names a capture never keeps, whatever a profile lists: the device's transport
81
+ // writes Cookie, Origin and Host itself, the connection's own headers are its own, and
82
+ // the Referer travels in its own member. payment-core's session check refuses the same.
83
+ const NEVER_KEPT = /^(?:cookie|cookie2|set-cookie|origin|referer|host|content-length|transfer-encoding|connection|keep-alive|upgrade|te|trailer|expect|proxy-.*|:.*)$/;
84
+ /** The paused request's Referer when it is a page on the profile's checkout origin, written as a browser serializes it; else nothing. */
85
+ function keptReferer(profile, value) {
86
+ if (typeof value !== 'string' || value.includes('#'))
87
+ return undefined;
88
+ try {
89
+ const url = new URL(value);
90
+ return url.origin === profile.checkout && url.href === value && !url.username && !url.password ? value : undefined;
91
+ }
92
+ catch {
93
+ return undefined;
94
+ }
95
+ }
96
+ /**
97
+ * The session the create carries for a paused card endpoint request: the profile's own
98
+ * header names and nothing else, the Referer only when it is a page on the checkout
99
+ * origin, the endpoint's cookies only for a cookie profile, and the body. Checked with
100
+ * the same rules the API and the device run (payment-core
101
+ * merchantCardEndpointSessionRefusal), so a request they would refuse never leaves this
102
+ * process: a CardEndpointRefusedError (`request_unsupported`) instead, naming no value.
103
+ */
104
+ export async function captureCardEndpointSession(profile, capture) {
105
+ const headers = {};
106
+ const seen = new Set();
107
+ let referer;
108
+ for (const [name, value] of Object.entries(capture.headers ?? {})) {
109
+ const lower = name.toLowerCase();
110
+ if (seen.has(lower))
111
+ throw new CardEndpointRefusedError(profile.id, 'request_unsupported', 'the paused request names one header twice');
112
+ seen.add(lower);
113
+ if (lower === 'referer') {
114
+ referer = keptReferer(profile, value);
115
+ continue;
116
+ }
117
+ if (NEVER_KEPT.test(lower) || !profile.session.headers.includes(lower))
118
+ continue;
119
+ headers[lower] = typeof value === 'string' ? value : String(value);
120
+ }
121
+ const session = { url: capture.url, page_origin: capture.pageOrigin ?? '', headers, body: capture.body };
122
+ if (profile.session.cookies) {
123
+ const jar = await capture.cookies();
124
+ session.cookies = (Array.isArray(jar) ? jar : []).map(({ name, value }) => ({ name, value }));
125
+ }
126
+ if (referer !== undefined)
127
+ session.referer = referer;
128
+ const refusal = sharedSessionRefusal(profile.id, session);
129
+ if (refusal)
130
+ throw new CardEndpointRefusedError(profile.id, 'request_unsupported', refusal);
131
+ return session;
132
+ }
133
+ /**
134
+ * The headers the paused request is answered with: the profile's answer headers the
135
+ * merchant sent, and never Set-Cookie (cookies reach the browser through
136
+ * cardEndpointCookies, on the endpoint host only).
137
+ */
138
+ export function cardEndpointAnswerHeaders(profile, headers) {
139
+ const out = {};
140
+ for (const [name, value] of Object.entries(headers)) {
141
+ const lower = name.toLowerCase();
142
+ if (lower === 'set-cookie' || !profile.response.headers.includes(lower) || typeof value !== 'string' || !/^[\x20-\x7e\t]*$/.test(value))
143
+ continue;
144
+ out[lower] = value;
145
+ }
146
+ return out;
147
+ }
148
+ /**
149
+ * The fixed answer a paused request gets when the cardholder's device withheld the
150
+ * merchant's answer (it carried the card, or a compressed stream the device cannot
151
+ * read): an error the merchant's page stops on. The card request was sent; whether
152
+ * the merchant took the payment is unknown until the order is checked.
153
+ */
154
+ export const CARD_ENDPOINT_WITHHELD_ANSWER = Object.freeze({
155
+ status: 502,
156
+ headers: Object.freeze({ 'content-type': 'application/json', 'cache-control': 'no-store' }),
157
+ body: JSON.stringify({ error: { code: 'agentcard_answer_withheld', message: 'The merchant answered, and Agentcard withheld the answer because it could carry card data. Check the order with the merchant before trying again.' } }),
158
+ });
159
+ // RFC 6265 cookie-name (a token) and cookie-value, as payment-core checks a session cookie.
160
+ const COOKIE_NAME = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]{1,256}$/;
161
+ const COOKIE_VALUE = /^(?:[\x21\x23-\x2b\x2d-\x3a\x3c-\x5b\x5d-\x7e]*|"[\x21\x23-\x2b\x2d-\x3a\x3c-\x5b\x5d-\x7e]*")$/;
162
+ const COOKIE_PATH = /^\/[\x21-\x3a\x3c-\x7e]{0,1023}$/;
163
+ // Browsers keep a cookie for at most 400 days.
164
+ const MAX_COOKIE_AGE_S = 400 * 24 * 60 * 60;
165
+ /** RFC 6265 5.1.4: the directory of the request path, the path a cookie with no Path attribute gets. */
166
+ function defaultCookiePath(requestUrl) {
167
+ let path;
168
+ try {
169
+ path = new URL(requestUrl).pathname;
170
+ }
171
+ catch {
172
+ return '/';
173
+ }
174
+ const last = path.lastIndexOf('/');
175
+ return last <= 0 ? '/' : path.slice(0, last);
176
+ }
177
+ /**
178
+ * One Set-Cookie line as the cookie to write, or null when a browser would not store it
179
+ * or it cannot be written safely. `jar` is the endpoint's cookies (null when they could
180
+ * not be read). A Domain attribute the endpoint host does not belong to drops the cookie
181
+ * (RFC 6265 5.3), as a browser does. One the host belongs to puts the cookie on that
182
+ * domain when the jar already holds a domain cookie of this name there, so the rotation
183
+ * replaces it; otherwise the cookie stays host-only. With the jar unread, a cookie that
184
+ * names a Domain is not written, since its write could leave two cookies of one name.
185
+ */
186
+ function parseSetCookie(profile, requestUrl, line, nowS, jar) {
187
+ if (typeof line !== 'string' || line.length > 8192 || /[\x00-\x08\x0a-\x1f\x7f]/.test(line))
188
+ return null;
189
+ const [pair, ...attributes] = line.split(';');
190
+ const eq = pair.indexOf('=');
191
+ if (eq <= 0)
192
+ return null;
193
+ const name = pair.slice(0, eq).trim();
194
+ const value = pair.slice(eq + 1).trim();
195
+ if (!COOKIE_NAME.test(name) || !COOKIE_VALUE.test(value))
196
+ return null;
197
+ let path = defaultCookiePath(requestUrl);
198
+ let secure = false;
199
+ let httpOnly = false;
200
+ let sameSite;
201
+ let expires;
202
+ let maxAge;
203
+ let named;
204
+ for (const attribute of attributes) {
205
+ const at = attribute.indexOf('=');
206
+ const key = (at === -1 ? attribute : attribute.slice(0, at)).trim().toLowerCase();
207
+ const text = at === -1 ? '' : attribute.slice(at + 1).trim();
208
+ if (key === 'path') {
209
+ if (COOKIE_PATH.test(text))
210
+ path = text;
211
+ }
212
+ else if (key === 'secure')
213
+ secure = true;
214
+ else if (key === 'httponly')
215
+ httpOnly = true;
216
+ else if (key === 'samesite') {
217
+ const lower = text.toLowerCase();
218
+ sameSite = lower === 'strict' ? 'Strict' : lower === 'lax' ? 'Lax' : lower === 'none' ? 'None' : undefined;
219
+ }
220
+ else if (key === 'max-age') {
221
+ if (/^-?\d{1,12}$/.test(text))
222
+ maxAge = Number(text);
223
+ }
224
+ else if (key === 'expires') {
225
+ const at = Date.parse(text);
226
+ if (Number.isFinite(at))
227
+ expires = Math.floor(at / 1000);
228
+ }
229
+ // RFC 6265 5.2.3: the last non-empty Domain counts, without a leading dot, in lower case.
230
+ else if (key === 'domain') {
231
+ const domain = text.replace(/^\./, '').toLowerCase();
232
+ if (domain !== '')
233
+ named = domain;
234
+ }
235
+ }
236
+ if (maxAge !== undefined)
237
+ expires = maxAge <= 0 ? 1 : nowS + Math.min(maxAge, MAX_COOKIE_AGE_S);
238
+ else if (expires !== undefined)
239
+ expires = expires <= nowS ? 1 : Math.min(expires, nowS + MAX_COOKIE_AGE_S);
240
+ // The prefixes a browser enforces on the merchant's own line: __Secure- needs Secure,
241
+ // __Host- also needs Path=/.
242
+ if ((name.startsWith('__Secure-') || name.startsWith('__Host-')) && !secure)
243
+ return null;
244
+ if (name.startsWith('__Host-') && path !== '/')
245
+ return null;
246
+ const host = new URL(profile.endpoint).hostname;
247
+ let domain;
248
+ if (named !== undefined) {
249
+ // __Host- cookies never name a Domain; a Domain the endpoint host is not inside is refused by a browser.
250
+ if (name.startsWith('__Host-') || (host !== named && !host.endsWith(`.${named}`)))
251
+ return null;
252
+ if (jar === null)
253
+ return null;
254
+ if (jar.some((held) => held.name === name && String(held.domain).toLowerCase() === `.${named}`))
255
+ domain = named;
256
+ }
257
+ return {
258
+ name, value, origin: profile.endpoint, host, ...(domain !== undefined ? { domain } : {}), path, secure: true, httpOnly,
259
+ ...(sameSite ? { sameSite } : {}), ...(expires !== undefined ? { expires } : {}),
260
+ };
261
+ }
262
+ /**
263
+ * The merchant's Set-Cookie values as cookies to write (parseSetCookie), and how many
264
+ * could not be written as one (a malformed line, a prefix or a Domain the browser would
265
+ * refuse, a Domain with the jar unread). `jar` is the endpoint's cookies as the adapter
266
+ * read them, null when the read failed. Only a profile whose answer may carry cookies
267
+ * has any.
268
+ */
269
+ export function cardEndpointCookies(profile, requestUrl, setCookies, nowMs = Date.now(), jar = []) {
270
+ if (!profile.response.headers.includes('set-cookie'))
271
+ return { cookies: [], skipped: setCookies.length };
272
+ const cookies = [];
273
+ let skipped = 0;
274
+ for (const line of setCookies) {
275
+ const cookie = parseSetCookie(profile, requestUrl, line, Math.floor(nowMs / 1000), jar);
276
+ if (cookie)
277
+ cookies.push(cookie);
278
+ else
279
+ skipped += 1;
280
+ }
281
+ return { cookies, skipped };
282
+ }
283
+ /** Why a session is not one the profile lets travel (payment-core merchantCardEndpointSessionRefusal), or null. Names no value. */
284
+ export function cardEndpointSessionRefusal(profile, session) {
285
+ return sharedSessionRefusal(profile.id, session) ?? null;
286
+ }
@@ -1,3 +1,5 @@
1
- declare function carriesCardFields(recognizer: any, body: any): boolean;
2
- declare function requestWithoutCard(recognizer: any, url: any, body: any): "continue" | "refuse" | null;
3
- export { carriesCardFields, requestWithoutCard };
1
+ declare function carriesCardFields(recognizer: any, body: any): any;
2
+ declare function splitCardLeg(recognizer: any, body: any): "absorb" | "pass" | null;
3
+ declare function requestWithoutCard(recognizer: any, url: any, body: any): "refuse" | "continue" | null;
4
+ declare function cardRequestRefusal(recognizer: any, url: any, body: any): any;
5
+ export { cardRequestRefusal, carriesCardFields, requestWithoutCard, splitCardLeg };