@agent-cards/sdk 0.23.22 → 0.23.24

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 (54) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/PREFLIGHT.md +2 -0
  3. package/README.md +34 -4
  4. package/dist/aci.generated.js +3 -3
  5. package/dist/agent-amount.generated.d.ts +7 -0
  6. package/dist/agent-amount.generated.js +3 -0
  7. package/dist/amadeus.d.ts +5 -2
  8. package/dist/amadeus.js +18 -3
  9. package/dist/amazon-payment-services.d.ts +25 -0
  10. package/dist/amazon-payment-services.generated.d.ts +76 -0
  11. package/dist/amazon-payment-services.generated.js +883 -0
  12. package/dist/amazon-payment-services.js +53 -0
  13. package/dist/capabilities.generated.d.ts +2 -0
  14. package/dist/capabilities.generated.js +3 -0
  15. package/dist/card-fields.generated.js +1127 -25
  16. package/dist/cdp.js +116 -15
  17. package/dist/client.d.ts +107 -8
  18. package/dist/client.js +277 -128
  19. package/dist/hosted-entry.js +2 -1
  20. package/dist/hosted-form.d.ts +5 -0
  21. package/dist/hosted-form.js +5 -0
  22. package/dist/index.d.ts +1 -0
  23. package/dist/index.js +1 -0
  24. package/dist/openpay.generated.d.ts +67 -0
  25. package/dist/openpay.generated.js +446 -0
  26. package/dist/paddle-checkout-watch.d.ts +70 -0
  27. package/dist/paddle-checkout-watch.js +239 -0
  28. package/dist/paddle-tokenex.generated.d.ts +29 -1
  29. package/dist/paddle-tokenex.generated.js +175 -26
  30. package/dist/paytrail.d.ts +58 -0
  31. package/dist/paytrail.js +98 -0
  32. package/dist/pre-claim.d.ts +4 -0
  33. package/dist/pre-claim.js +46 -2
  34. package/dist/prepared-processor.d.ts +12 -4
  35. package/dist/prepared-processor.js +31 -5
  36. package/dist/primer.generated.js +1155 -53
  37. package/dist/registry.d.ts +4 -3
  38. package/dist/registry.js +12 -4
  39. package/dist/sbps.d.ts +57 -0
  40. package/dist/sbps.generated.d.ts +96 -0
  41. package/dist/sbps.generated.js +427 -0
  42. package/dist/sbps.js +90 -0
  43. package/dist/stripe-checkout.generated.js +458 -8
  44. package/dist/tap-payments.d.ts +43 -0
  45. package/dist/tap-payments.generated.d.ts +59 -0
  46. package/dist/tap-payments.generated.js +990 -0
  47. package/dist/tap-payments.js +72 -0
  48. package/dist/transbank.d.ts +33 -0
  49. package/dist/transbank.js +62 -0
  50. package/dist/url-mask-parts.d.ts +24 -0
  51. package/dist/url-mask-parts.js +22 -0
  52. package/dist/url-masks.generated.d.ts +3 -0
  53. package/dist/url-masks.generated.js +2 -0
  54. package/package.json +4 -4
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Paytrail's card method (the Visa and Mastercard method on the payment wall most Finnish webshops send the buyer
3
+ * to), as this SDK reads it.
4
+ *
5
+ * The merchant's page, or Paytrail's own wall, posts a card-free entry top-level to
6
+ * https://services.paytrail.com/payments/<transaction>/click-to-pay/loading-and-redirect: seven fields Paytrail signed
7
+ * for the merchant, and no card and no amount. Paytrail answers with a loading page whose one form posts the same
8
+ * fields to .../click-to-pay/initialize-payment, which sends the browser to Payment Highway's card page
9
+ * (v1.api.paymenthighway.io, Paytrail's card platform) under a session of its own. The entry is the one request this
10
+ * SDK pauses: the cardholder's device repeats it over the end-to-end TLS relay and follows it to the card page
11
+ * (payment-core processors/paytrail.js). Everything after it in the agent's browser leads to the card the agent
12
+ * typed: the loading page's own post opens the card page, and on Payment Highway's host the card post (/card), the
13
+ * Click to Pay posts (/visa, /mastercard), the 3-D Secure step (/continue), the older card form's post and the card
14
+ * page's lookup of the typed card's first digits (GET .../acquirerData?bin=...). This SDK aborts every one of them,
15
+ * so a placeholder card never reaches Payment Highway.
16
+ *
17
+ * The hosts are payment-core's PAYTRAIL_HOSTS and PAYMENT_HIGHWAY_HOSTS; paytrail.test.mjs pins the lists together.
18
+ */
19
+ export declare const PAYTRAIL_PSP = "paytrail";
20
+ export declare const PAYTRAIL_HOSTS: readonly string[];
21
+ export declare const PAYMENT_HIGHWAY_HOSTS: readonly string[];
22
+ /** Whether this URL is on Paytrail's entry host (https, no credentials, any port, a trailing dot or not). */
23
+ export declare function isPaytrailHost(url: string): boolean;
24
+ /** Whether this URL is on Payment Highway's card page host (https, no credentials, any port, a trailing dot or not). */
25
+ export declare function isPaymentHighwayHost(url: string): boolean;
26
+ /**
27
+ * The only request that is the merchant's entry: a POST to the card method's loading-and-redirect route for one
28
+ * transaction, written exactly as the method's form action writes it, with the transaction in lowercase and no port,
29
+ * query, fragment or credentials (payment-core isPaytrailEntryUrl). The entry the SDK pauses; the gate aborts every
30
+ * other post of the card method.
31
+ */
32
+ export declare function isPaytrailEntry(url: string, method: string): boolean;
33
+ /**
34
+ * Whether a request on Paytrail's host belongs to the card method (a /click-to-pay/ route of a payment, in any letter
35
+ * case): the entry, the loading page's post to initialize-payment, which opens Payment Highway's card page for the
36
+ * transaction, and any other spelling of either. Another method's form (a bank's) is not.
37
+ */
38
+ export declare function isPaytrailCardMethodUrl(url: string): boolean;
39
+ /**
40
+ * The card page's card lookup: a GET on Payment Highway's host to .../acquirerData, which names the first digits of
41
+ * the card typed so far in its `bin` query. Any other GET there (the card page itself, its scripts and images) is not
42
+ * a card request.
43
+ */
44
+ export declare function isPaymentHighwayCardLookup(url: string, method: string): boolean;
45
+ /** Whether this build's registry serves Paytrail's entry, asked with an entry on a transaction no payment holds. */
46
+ export declare function isPaytrailServed(vault: {
47
+ isCardRequest(url: string, method?: string): boolean;
48
+ }): boolean;
49
+ /**
50
+ * Whether an adapter must hand this request to the pre-claim gates: it is on Paytrail's host or Payment Highway's, and
51
+ * this build's registry serves Paytrail's entry. The loading page's post and Payment Highway's card requests are not
52
+ * the entry, so the registry's card-request test does not name them; the CDP adapter still pauses them through the
53
+ * recognizer's host and its abort host, and attachToPlaywright's route predicate asks this, so both adapters show the
54
+ * gates every request to either host once Paytrail is armed.
55
+ */
56
+ export declare function isArmedPaytrailUrl(vault: {
57
+ isCardRequest(url: string, method?: string): boolean;
58
+ }, url: string): boolean;
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Paytrail's card method (the Visa and Mastercard method on the payment wall most Finnish webshops send the buyer
3
+ * to), as this SDK reads it.
4
+ *
5
+ * The merchant's page, or Paytrail's own wall, posts a card-free entry top-level to
6
+ * https://services.paytrail.com/payments/<transaction>/click-to-pay/loading-and-redirect: seven fields Paytrail signed
7
+ * for the merchant, and no card and no amount. Paytrail answers with a loading page whose one form posts the same
8
+ * fields to .../click-to-pay/initialize-payment, which sends the browser to Payment Highway's card page
9
+ * (v1.api.paymenthighway.io, Paytrail's card platform) under a session of its own. The entry is the one request this
10
+ * SDK pauses: the cardholder's device repeats it over the end-to-end TLS relay and follows it to the card page
11
+ * (payment-core processors/paytrail.js). Everything after it in the agent's browser leads to the card the agent
12
+ * typed: the loading page's own post opens the card page, and on Payment Highway's host the card post (/card), the
13
+ * Click to Pay posts (/visa, /mastercard), the 3-D Secure step (/continue), the older card form's post and the card
14
+ * page's lookup of the typed card's first digits (GET .../acquirerData?bin=...). This SDK aborts every one of them,
15
+ * so a placeholder card never reaches Payment Highway.
16
+ *
17
+ * The hosts are payment-core's PAYTRAIL_HOSTS and PAYMENT_HIGHWAY_HOSTS; paytrail.test.mjs pins the lists together.
18
+ */
19
+ export const PAYTRAIL_PSP = 'paytrail';
20
+ export const PAYTRAIL_HOSTS = Object.freeze(['services.paytrail.com']);
21
+ export const PAYMENT_HIGHWAY_HOSTS = Object.freeze(['v1.api.paymenthighway.io']);
22
+ const UUID = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}';
23
+ const ENTRY_PATH = new RegExp(`^/payments/${UUID}/click-to-pay/loading-and-redirect$`);
24
+ // The card method's entry on a transaction no payment holds: the URL this build asks its registry about to learn
25
+ // whether the API serves Paytrail's recognizer, which takes any transaction (payment-core isPaytrailEntryUrl).
26
+ const ENTRY_PROBE = 'https://services.paytrail.com/payments/00000000-0000-4000-8000-000000000000/click-to-pay/loading-and-redirect';
27
+ function onHosts(url, hosts) {
28
+ let parsed;
29
+ try {
30
+ parsed = new URL(url);
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ return parsed.protocol === 'https:' && !parsed.username && !parsed.password
36
+ && hosts.includes(parsed.hostname.toLowerCase().replace(/\.$/, '')) ? parsed : null;
37
+ }
38
+ /** Whether this URL is on Paytrail's entry host (https, no credentials, any port, a trailing dot or not). */
39
+ export function isPaytrailHost(url) {
40
+ return onHosts(url, PAYTRAIL_HOSTS) !== null;
41
+ }
42
+ /** Whether this URL is on Payment Highway's card page host (https, no credentials, any port, a trailing dot or not). */
43
+ export function isPaymentHighwayHost(url) {
44
+ return onHosts(url, PAYMENT_HIGHWAY_HOSTS) !== null;
45
+ }
46
+ /**
47
+ * The only request that is the merchant's entry: a POST to the card method's loading-and-redirect route for one
48
+ * transaction, written exactly as the method's form action writes it, with the transaction in lowercase and no port,
49
+ * query, fragment or credentials (payment-core isPaytrailEntryUrl). The entry the SDK pauses; the gate aborts every
50
+ * other post of the card method.
51
+ */
52
+ export function isPaytrailEntry(url, method) {
53
+ if (String(method).toUpperCase() !== 'POST' || typeof url !== 'string')
54
+ return false;
55
+ let parsed;
56
+ try {
57
+ parsed = new URL(url);
58
+ }
59
+ catch {
60
+ return false;
61
+ }
62
+ return parsed.protocol === 'https:' && PAYTRAIL_HOSTS.includes(parsed.hostname) && ENTRY_PATH.test(parsed.pathname)
63
+ && !parsed.port && !parsed.username && !parsed.password && parsed.href === url && !/[?#]/.test(url);
64
+ }
65
+ /**
66
+ * Whether a request on Paytrail's host belongs to the card method (a /click-to-pay/ route of a payment, in any letter
67
+ * case): the entry, the loading page's post to initialize-payment, which opens Payment Highway's card page for the
68
+ * transaction, and any other spelling of either. Another method's form (a bank's) is not.
69
+ */
70
+ export function isPaytrailCardMethodUrl(url) {
71
+ const parsed = onHosts(url, PAYTRAIL_HOSTS);
72
+ return parsed !== null && /^\/payments\/[^/]+\/click-to-pay(?:\/|$)/i.test(parsed.pathname);
73
+ }
74
+ /**
75
+ * The card page's card lookup: a GET on Payment Highway's host to .../acquirerData, which names the first digits of
76
+ * the card typed so far in its `bin` query. Any other GET there (the card page itself, its scripts and images) is not
77
+ * a card request.
78
+ */
79
+ export function isPaymentHighwayCardLookup(url, method) {
80
+ if (String(method).toUpperCase() !== 'GET')
81
+ return false;
82
+ const parsed = onHosts(url, PAYMENT_HIGHWAY_HOSTS);
83
+ return parsed !== null && (/\/acquirerData\/?$/i.test(parsed.pathname) || parsed.searchParams.has('bin'));
84
+ }
85
+ /** Whether this build's registry serves Paytrail's entry, asked with an entry on a transaction no payment holds. */
86
+ export function isPaytrailServed(vault) {
87
+ return vault.isCardRequest(ENTRY_PROBE, 'POST');
88
+ }
89
+ /**
90
+ * Whether an adapter must hand this request to the pre-claim gates: it is on Paytrail's host or Payment Highway's, and
91
+ * this build's registry serves Paytrail's entry. The loading page's post and Payment Highway's card requests are not
92
+ * the entry, so the registry's card-request test does not name them; the CDP adapter still pauses them through the
93
+ * recognizer's host and its abort host, and attachToPlaywright's route predicate asks this, so both adapters show the
94
+ * gates every request to either host once Paytrail is armed.
95
+ */
96
+ export function isArmedPaytrailUrl(vault, url) {
97
+ return (isPaytrailHost(url) || isPaymentHighwayHost(url)) && isPaytrailServed(vault);
98
+ }
@@ -5,6 +5,7 @@ import { DatatransRepeats } from './datatrans.js';
5
5
  import { TokenexIframeRepeats } from './tokenex-iframe.js';
6
6
  import { type AciGate } from './aci.js';
7
7
  import type { EprotectGate } from './eprotect.js';
8
+ import type { SbpsGate } from './sbps.js';
8
9
  import { type ShijiStsCompanions } from './shiji-sts.js';
9
10
  import type { CheckoutLifecycle } from './lifecycle.js';
10
11
  import { type MerchantProfile } from './merchant-hosted.js';
@@ -148,6 +149,8 @@ export interface PreClaimContext {
148
149
  replacesNavigationBody?: () => Promise<boolean>;
149
150
  /** Worldpay eProtect's hosts; absent or inert until the registry serves eProtect. */
150
151
  eprotect?: EprotectGate;
152
+ /** SB Payment Service's token hosts; absent or inert until the registry serves SBPS. */
153
+ sbps?: SbpsGate;
151
154
  readDocumentUrl: () => Promise<string>;
152
155
  lifecycle: CheckoutLifecycle;
153
156
  /**
@@ -278,6 +281,7 @@ export declare function isArmedCreditguardCall(vault: {
278
281
  export declare const przelewy24PreClaim: PreClaimGate;
279
282
  export declare const ekashuPreClaim: PreClaimGate;
280
283
  export declare const transbankPreClaim: PreClaimGate;
284
+ export declare const paytrailPreClaim: PreClaimGate;
281
285
  export declare const redsysPreClaim: PreClaimGate;
282
286
  export declare const quickpayPreClaim: PreClaimGate;
283
287
  export declare const comgatePreClaim: PreClaimGate;
package/dist/pre-claim.js CHANGED
@@ -80,6 +80,7 @@ import { cardEndpointCarriesCard, cardEndpointDetail, cardEndpointFor, cardEndpo
80
80
  import { cardEndpointStoppedPage, refusedNavigationOutcome } from './card-endpoint-page.js';
81
81
  import { PAYRAILS_HOLDING_REASONS, PAYRAILS_SESSION_MESSAGE, isPayrailsHost, isPayrailsPaymentUrl, isPayrailsStaticHost, payrailsKeyRefusal, payrailsPaymentRefusal, payrailsRequestKind, payrailsSaveRefusal, } from './payrails.js';
82
82
  import { classifyVerifoneProfileRequest, verifoneTemplatedUrl } from './verifone.js';
83
+ import { isPaymentHighwayCardLookup, isPaymentHighwayHost, isPaytrailCardMethodUrl, isPaytrailEntry, isPaytrailServed } from './paytrail.js';
83
84
  import { ekashuEntryUrl, isEkashuEntry, isEkashuHost } from './ekashu.js';
84
85
  import { isArmedTransbankUrl } from './transbank.js';
85
86
  import { isRedsysEntry, isRedsysHost, redsysEntryUrl } from './redsys.js';
@@ -1509,6 +1510,23 @@ const eprotectPreClaim = (ctx) => {
1509
1510
  return eprotectFailoverAbort(ctx);
1510
1511
  return unsupportedAbort(ctx);
1511
1512
  };
1513
+ // SB Payment Service, once the registry serves it (a synced build that declares its capability, for
1514
+ // an org the API enabled); for every other client the gate defers on everything, so nothing changes.
1515
+ // On SBPS's token hosts:
1516
+ // - the token request GET the recognizer admits defers to the arbiter, which pauses it for the vault
1517
+ // claim flow; one the registry does not cover aborts as unsupported instead of reaching SBPS;
1518
+ // - any other request on /token/generateToken (another method, query or spelling) aborts as an
1519
+ // unsupported checkout, so the placeholder's ciphertext never leaves;
1520
+ // - everything else there (the scripts, the 3-D Secure info request) continues.
1521
+ // Synchronous for a token request, so it pauses in the microtask it paused in.
1522
+ const sbpsPreClaim = (ctx) => {
1523
+ const request = ctx.sbps?.classify(ctx.request.url, ctx.request.method);
1524
+ if (!request || request.kind === 'sibling')
1525
+ return undefined;
1526
+ if (request.kind === 'token_request')
1527
+ return ctx.vault.isCardRequest(ctx.request.url, ctx.request.method) ? undefined : unsupportedAbort(ctx);
1528
+ return unsupportedAbort(ctx);
1529
+ };
1512
1530
  async function eprotectFailoverAbort(ctx) {
1513
1531
  ctx.onEvent?.({ type: 'blocked', detail: 'eprotect_failover_aborted' });
1514
1532
  await ctx.effects.abort();
@@ -1699,6 +1717,32 @@ export const transbankPreClaim = (ctx) => {
1699
1717
  return undefined;
1700
1718
  return processorPageAbort(ctx);
1701
1719
  };
1720
+ // Paytrail's card method (paytrail.ts). Once this build's registry serves Paytrail's entry (a capability the API serves
1721
+ // only to a company Agentcard turned Paytrail on for), every request to Paytrail's entry host and to Payment Highway's
1722
+ // card page host pauses, and this gate judges the card method's posts and the card page's card lookup:
1723
+ // - the merchant's entry (the card method's loading-and-redirect route for one transaction, exactly) defers, and the
1724
+ // terminal arbiter pauses it for the claim flow like any card request: the cardholder's device pays it;
1725
+ // - every other post of the card method on Paytrail's host (the loading page's post to initialize-payment, which
1726
+ // opens Payment Highway's card page, or the entry in another spelling) aborts as an unsupported checkout, and so do
1727
+ // every POST to Payment Highway (the card post, the Click to Pay posts, the 3-D Secure step, the older card form's
1728
+ // post) and the card page's GET that looks up the typed card's first digits, so Payment Highway never sees the card
1729
+ // the agent typed. The agent's browser reaches Payment Highway only when the entry was not paused (an attachment
1730
+ // made too late, say), and then only the cardholder's device can pay.
1731
+ // Any other request (another payment method's form, the card page itself, its scripts and images) is not this gate's
1732
+ // and continues. With Paytrail not served, the entry is no card request, the gate defers, and every request continues
1733
+ // as before. Synchronous until it must abort, like every gate. Exported for the gate registry's tests.
1734
+ export const paytrailPreClaim = (ctx) => {
1735
+ const { url, method } = ctx.request;
1736
+ const post = String(method).toUpperCase() === 'POST';
1737
+ const paymentHighway = isPaymentHighwayHost(url) && (post || isPaymentHighwayCardLookup(url, method));
1738
+ if (!paymentHighway && !(post && isPaytrailCardMethodUrl(url)))
1739
+ return undefined;
1740
+ if (!isPaytrailServed(ctx.vault))
1741
+ return undefined;
1742
+ if (isPaytrailEntry(url, method))
1743
+ return undefined;
1744
+ return processorPageAbort(ctx);
1745
+ };
1702
1746
  // Redsys's hosted payment page (redsys.ts). Once this build's registry serves Redsys's entry (a
1703
1747
  // capability the API serves only to a company Agentcard turned Redsys on for), every request to
1704
1748
  // Redsys's hosts pauses, and this gate judges the POSTs:
@@ -2438,8 +2482,8 @@ async function unsupportedContinue(ctx) {
2438
2482
  * arbiter runs after all of them and is not part of this list. A gate appended
2439
2483
  * after Stripe is never offered a step Stripe claimed: Stripe answers, aborts or
2440
2484
  * pauses each one itself. */
2441
- export const PSP_PRE_CLAIM_GATES = [cardEndpointResendPreClaim, cardEndpointPreClaim, mercadoPreClaim, juspayPreClaim, braintreePreClaim, stripePreClaim, merchantHostedPreClaim, verifonePreClaim, fiservPreClaim, gmoPreClaim, cybersourceFlexPreClaim, datatransPreClaim, tokenexIframePreClaim, pelecardPreClaim, aciPreClaim, creditguardPreClaim, primerPreClaim, payrailsPreClaim, convergePreClaim, eprotectPreClaim, wspayPreClaim, shijiStsPreClaim, ekashuPreClaim, redsysPreClaim, quickpayPreClaim, comgatePreClaim, przelewy24PreClaim, transbankPreClaim, eximbayPreClaim, paypalHostedFieldsPreClaim,
2442
- paypalCardFormsPreClaim, cybersourceSecureAcceptancePreClaim, worldlineMyCheckoutPreClaim, paddleVgsPayPreClaim, ebanxPreClaim, payrexxPreClaim, hipayPreClaim];
2485
+ export const PSP_PRE_CLAIM_GATES = [cardEndpointResendPreClaim, cardEndpointPreClaim, mercadoPreClaim, juspayPreClaim, braintreePreClaim, stripePreClaim, merchantHostedPreClaim, verifonePreClaim, fiservPreClaim, gmoPreClaim, cybersourceFlexPreClaim, datatransPreClaim, tokenexIframePreClaim, pelecardPreClaim, aciPreClaim, creditguardPreClaim, primerPreClaim, payrailsPreClaim, convergePreClaim, eprotectPreClaim, sbpsPreClaim, wspayPreClaim, shijiStsPreClaim, ekashuPreClaim, redsysPreClaim, quickpayPreClaim, comgatePreClaim, przelewy24PreClaim, transbankPreClaim, eximbayPreClaim, paypalHostedFieldsPreClaim,
2486
+ paypalCardFormsPreClaim, cybersourceSecureAcceptancePreClaim, worldlineMyCheckoutPreClaim, paddleVgsPayPreClaim, ebanxPreClaim, payrexxPreClaim, hipayPreClaim, paytrailPreClaim];
2443
2487
  /** Run each gate in order; the first to return a decision wins. If none does,
2444
2488
  * the terminal arbiter decides between continue, abort (unsupported) and pause.
2445
2489
  * Returns synchronously while every gate defers synchronously (an ordinary card
@@ -32,8 +32,13 @@
32
32
  * hipay: prepared only. The merchant's page gives HiPay's hosted fields 20 seconds after Pay, too soon for an
33
33
  * approval after Pay. Its environments are its two vault hosts: secure2-vault (production) and
34
34
  * stage-secure2-vault (sandbox).
35
+ *
36
+ * openpay_bbva: prepared only. openpay.js abandons its token create 40 seconds after Pay, too soon for an
37
+ * approval after Pay. Its environments are its API hosts: api.openpay.<mx|co|pe> (production) and
38
+ * sandbox-api.openpay.<mx|co|pe> (sandbox). The token URL names the merchant in its path, so no URL is
39
+ * prepared in advance: the claim binds the request by its host's environment and its shape, as ACI's.
35
40
  */
36
- 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' | 'cybersource_secure_acceptance' | 'paddle_vgs' | 'wix_payments' | 'paygent' | 'hipay';
41
+ 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' | 'cybersource_secure_acceptance' | 'paddle_vgs' | 'wix_payments' | 'paygent' | 'hipay' | 'openpay_bbva';
37
42
  export type PreparationEnvironment = 'production' | 'sandbox' | 'shared';
38
43
  /**
39
44
  * How the approved card reaches the processor: the device's own request (token), or
@@ -71,7 +76,8 @@ export declare function preparedApprovalAnswersRetry(psp: string): boolean;
71
76
  * profile pins. CyberSource Secure Acceptance's are separate hosts too: secureacceptance is
72
77
  * live, testsecureacceptance is test. So are Paddle VGS's two card URLs: vault is live,
73
78
  * sandbox-vault is test. So are Paygent's two token hosts: token is live, sandbox is test. So are
74
- * HiPay's two vault hosts: secure2-vault is live, stage-secure2-vault is test.
79
+ * HiPay's two vault hosts: secure2-vault is live, stage-secure2-vault is test. So are Openpay's API
80
+ * hosts: api.openpay.<mx|co|pe> is live, sandbox-api.openpay.<mx|co|pe> is test.
75
81
  */
76
82
  export declare function validPreparationEnvironment(psp: string, environment: string): boolean;
77
83
  /**
@@ -83,8 +89,10 @@ export declare function validPreparationEnvironment(psp: string, environment: st
83
89
  export declare function aciPreparationUrl(environment: PreparationEnvironment): string;
84
90
  /**
85
91
  * A processor whose card request names an id the merchant mints only at Pay time (ACI's checkout
86
- * id), so no URL can be prepared in advance: whether the adapters can intercept it is asked of the
87
- * registry (VaultClient.recognizesProcessor), not of the prepared endpoint.
92
+ * id), or the merchant's own id (Openpay's token URL carries the merchant id in its path and the
93
+ * country in its host), so no URL can be prepared in advance: whether the adapters can intercept it
94
+ * is asked of the registry (VaultClient.recognizesProcessor), not of the prepared endpoint, which
95
+ * only names the preparation.
88
96
  */
89
97
  export declare function preparationBindsByShape(psp: string): boolean;
90
98
  /**
@@ -17,6 +17,7 @@ import { PADDLE_VGS_CARDS_URLS, isPreparedPaddleVgsRequest } from './paddle-vgs.
17
17
  import { WIX_PAYMENTS_TOKENIZE_URL, isPreparedWixPaymentsRequest } from './wix-payments.generated.js';
18
18
  import { paygentEnvironment, paygentPreparationUrl, paygentRequestRefusal } from './paygent.generated.js';
19
19
  import { HIPAY_TOKEN_URLS, hipayRequestRefusal, hipayTokenEnvironment, isPreparedHipayRequest } from './hipay.generated.js';
20
+ import { OPENPAY_PREPARATION_URLS, isPreparedOpenpayRequest, openpayRequestRefusal, openpayTokenEnvironment } from './openpay.generated.js';
20
21
  export function preparationMode(psp) {
21
22
  return psp === 'adyen' || psp === 'fiserv' || psp === 'verifone' ? 'cse' : 'token';
22
23
  }
@@ -52,7 +53,8 @@ export function preparedApprovalAnswersRetry(psp) {
52
53
  * profile pins. CyberSource Secure Acceptance's are separate hosts too: secureacceptance is
53
54
  * live, testsecureacceptance is test. So are Paddle VGS's two card URLs: vault is live,
54
55
  * sandbox-vault is test. So are Paygent's two token hosts: token is live, sandbox is test. So are
55
- * HiPay's two vault hosts: secure2-vault is live, stage-secure2-vault is test.
56
+ * HiPay's two vault hosts: secure2-vault is live, stage-secure2-vault is test. So are Openpay's API
57
+ * hosts: api.openpay.<mx|co|pe> is live, sandbox-api.openpay.<mx|co|pe> is test.
56
58
  */
57
59
  export function validPreparationEnvironment(psp, environment) {
58
60
  if (psp === 'bambora' || psp === 'mercado_pago' || psp === 'recurly' || psp === 'spreedly')
@@ -61,7 +63,7 @@ export function validPreparationEnvironment(psp, environment) {
61
63
  if (psp === 'wix_payments')
62
64
  return environment === 'production';
63
65
  return ['square', 'braintree', 'worldpay', 'adyen', 'checkout_com', 'paysafe', 'fiserv', 'cybersource_flex', 'aci', 'creditguard', 'worldpay_eprotect', 'amadeus_checkout', 'verifone',
64
- 'cybersource_secure_acceptance', 'paddle_vgs', 'paygent', 'hipay'].includes(psp) && ['production', 'sandbox'].includes(environment);
66
+ 'cybersource_secure_acceptance', 'paddle_vgs', 'paygent', 'hipay', 'openpay_bbva'].includes(psp) && ['production', 'sandbox'].includes(environment);
65
67
  }
66
68
  /**
67
69
  * ACI's prepared endpoint, the literal the API names (backend checkout-prepared-processor.ts): its
@@ -74,11 +76,13 @@ export function aciPreparationUrl(environment) {
74
76
  }
75
77
  /**
76
78
  * A processor whose card request names an id the merchant mints only at Pay time (ACI's checkout
77
- * id), so no URL can be prepared in advance: whether the adapters can intercept it is asked of the
78
- * registry (VaultClient.recognizesProcessor), not of the prepared endpoint.
79
+ * id), or the merchant's own id (Openpay's token URL carries the merchant id in its path and the
80
+ * country in its host), so no URL can be prepared in advance: whether the adapters can intercept it
81
+ * is asked of the registry (VaultClient.recognizesProcessor), not of the prepared endpoint, which
82
+ * only names the preparation.
79
83
  */
80
84
  export function preparationBindsByShape(psp) {
81
- return psp === 'aci';
85
+ return psp === 'aci' || psp === 'openpay_bbva';
82
86
  }
83
87
  /**
84
88
  * The endpoint a CreditGuard preparation stands for, per environment, as the API advertises it: the
@@ -115,6 +119,11 @@ export function preparationEndpoint(psp, environment) {
115
119
  // HiPay: the token create on the environment's vault, the only URL the claim takes for it.
116
120
  if (psp === 'hipay')
117
121
  return HIPAY_TOKEN_URLS[environment];
122
+ // Openpay: the literal the API names (backend checkout-prepared-processor.ts), on the environment's Mexican host. It
123
+ // only names the preparation: its "prepared" is shorter than any merchant id, so no card request is ever sent to it,
124
+ // and the claim binds the real token URL by environment and shape (matchesPreparedRequest), as ACI's.
125
+ if (psp === 'openpay_bbva')
126
+ return OPENPAY_PREPARATION_URLS[environment];
118
127
  // A Verifone endpoint is its reviewed profile's leg, never one per environment (verifone.ts).
119
128
  if (psp === 'verifone')
120
129
  throw new Error('unsupported_preparation_processor');
@@ -286,6 +295,15 @@ export function matchesPreparedRequest(psp, environment, requestUrl, method, bod
286
295
  // bind with too.
287
296
  if (psp === 'hipay')
288
297
  return isPreparedHipayRequest(requestUrl, method.toUpperCase(), body ?? null, environment, headers ?? {});
298
+ // Openpay: a token URL on one of the environment's API hosts and payment-core's whole request rule (openpay.js's JSON
299
+ // Content-Type and Accept, one public key under Basic, every header named once, and the caller's token body member by
300
+ // member), the rule the API and the Vault bind with too. The token URL names the merchant in its path, so the claim
301
+ // never compares it with the prepared endpoint, which only names the preparation. The method as the page sent it, as
302
+ // the API reads it. Which merchant id and public key a live request may name is the API's to judge at the bind and the
303
+ // Vault's before it writes the card, against the reviewed pin each of them holds for the approved checkout origin, so a
304
+ // merchant a later release reviews needs no new build of this library.
305
+ if (psp === 'openpay_bbva')
306
+ return isPreparedOpenpayRequest(requestUrl, method, body ?? null, environment, headers ?? {});
289
307
  if (psp === 'creditguard')
290
308
  return matchesPreparedCreditguard(environment, requestUrl, body, headers, binding);
291
309
  // A Verifone request is judged only through the profile its preparation names (matchesPreparation).
@@ -453,6 +471,14 @@ export function preparedRequestRefusal(psp, environment, requestUrl, body, heade
453
471
  return 'checkout_changed';
454
472
  return hipayRequestRefusal({ url: requestUrl, method: 'POST', headers, body: body ?? null }) ?? 'checkout_changed';
455
473
  }
474
+ // An Openpay token create on one of the prepared environment's API hosts names what payment-core's request rule
475
+ // refused (openpay_headers_refused, openpay_body_unsupported); another environment's host, a group's or a customer's
476
+ // path, a query, or any other request is `checkout_changed`.
477
+ if (psp === 'openpay_bbva') {
478
+ if (openpayTokenEnvironment(requestUrl) !== environment)
479
+ return 'checkout_changed';
480
+ return openpayRequestRefusal({ url: requestUrl, method: 'POST', headers, body: body ?? null }) ?? 'checkout_changed';
481
+ }
456
482
  if (psp !== 'amadeus_checkout' || amadeusEnvironment(requestUrl) !== environment)
457
483
  return 'checkout_changed';
458
484
  const merchantHost = merchantHostOf(merchantOrigin);