@agent-cards/sdk 0.24.0 → 0.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +61 -4
  3. package/dist/adyen-merchant-hosted.generated.d.ts +1 -1
  4. package/dist/adyen-merchant-hosted.generated.js +128 -35
  5. package/dist/agent-amount.generated.js +1 -1
  6. package/dist/aurus.d.ts +33 -0
  7. package/dist/aurus.js +75 -0
  8. package/dist/builtin-registry.generated.js +1 -1
  9. package/dist/capabilities.generated.js +1 -1
  10. package/dist/card-fields.generated.js +1756 -433
  11. package/dist/cardlink-vpos.d.ts +43 -0
  12. package/dist/cardlink-vpos.js +90 -0
  13. package/dist/cdp.js +13 -0
  14. package/dist/checkout-com.generated.js +5 -1
  15. package/dist/client.d.ts +66 -0
  16. package/dist/client.js +66 -0
  17. package/dist/cybersource-flex.generated.d.ts +39 -1
  18. package/dist/cybersource-flex.generated.js +100 -11
  19. package/dist/eghl.d.ts +40 -0
  20. package/dist/eghl.js +72 -0
  21. package/dist/gmo.generated.js +7 -2
  22. package/dist/hosted-entry.js +2 -0
  23. package/dist/paddle-tokenex.generated.js +7 -2
  24. package/dist/payrails.generated.js +7 -2
  25. package/dist/pre-claim.d.ts +2 -0
  26. package/dist/pre-claim.js +46 -2
  27. package/dist/preflight-catalog.json +154 -1
  28. package/dist/preflight-schemas.json +14 -0
  29. package/dist/preflight.generated.d.ts +5 -0
  30. package/dist/preflight.generated.js +40 -3
  31. package/dist/preparation.d.ts +7 -0
  32. package/dist/preparation.js +21 -0
  33. package/dist/primer.generated.js +1778 -455
  34. package/dist/shiji-sts.generated.js +7 -2
  35. package/dist/stripe-checkout.generated.js +1741 -470
  36. package/dist/substitutions.generated.js +94 -1
  37. package/dist/tap-payments.generated.js +7 -2
  38. package/dist/twoc2p.generated.js +7 -2
  39. package/examples/preflight/kernel-native/inventory.json +1 -1
  40. package/package.json +2 -2
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Cardlink's VPOS (the redirect payment page Greek banks give their merchants: Eurobank's paycenter on
3
+ * vpos.eurocommerce.gr, Cardlink's own on ecommerce.cardlink.gr, Nexi Greece's on www.alphaecommerce.gr), as this SDK
4
+ * reads it.
5
+ *
6
+ * The merchant's order page posts a signed entry form, top-level, to https://<host>/vpos/shophandlermpi, and the VPOS
7
+ * answers with its card page, whose form posts the card back to that same URL. The entry carries no card, and it is the
8
+ * one request this SDK pauses: the cardholder's device repeats it over the end-to-end TLS relay and fills the card into
9
+ * the page the VPOS returns to it (payment-core processors/cardlink_vpos.js). Every other POST the agent's browser makes
10
+ * to these hosts carries a card the agent typed or leads to a page that asks for one: the card page's own post and its
11
+ * card check, which share the entry's URL and carry the page's own fields, and anything posted to Cardlink's test
12
+ * hosts. This SDK aborts every one of them, so a placeholder card never reaches the VPOS.
13
+ *
14
+ * CARDLINK_VPOS_ENTRY_HOSTS is payment-core's CARDLINK_VPOS_HOSTS, and isCardlinkVposEntryUrl is payment-core's
15
+ * isCardlinkVposEntryUrl; cardlink-vpos.test.mjs pins both to payment-core.
16
+ */
17
+ export declare const CARDLINK_VPOS_PSP = "cardlink_vpos";
18
+ export declare const CARDLINK_VPOS_ENTRY_HOSTS: readonly string[];
19
+ export declare const CARDLINK_VPOS_TEST_HOSTS: readonly string[];
20
+ /**
21
+ * Whether a URL is an entry exactly as a merchant's form action writes it: https, one of the three live hosts in lower
22
+ * case, the default port, no credentials, the path /vpos/shophandlermpi, and no query or fragment, not even an empty one.
23
+ */
24
+ export declare function isCardlinkVposEntryUrl(raw: unknown): boolean;
25
+ /** Whether a URL is on one of the VPOS's hosts, live or test: https, no credentials, any port, any case, a trailing dot or not. */
26
+ export declare function isCardlinkVposHost(raw: string): boolean;
27
+ /**
28
+ * Whether a body reads as a merchant's entry and never as the card page's post: a form whose every pair decodes, that
29
+ * names a mid and a digest, and that carries none of the card page's fields or a card field. payment-core's entry rules
30
+ * judge the rest at create.
31
+ */
32
+ export declare function isCardlinkVposEntryBody(body: string | null | undefined): boolean;
33
+ /** The one request on the VPOS's hosts this SDK pauses: a POST of an entry body to an entry URL. */
34
+ export declare function isCardlinkVposEntry(url: string, method: string, body: string | null | undefined): boolean;
35
+ /**
36
+ * Whether an adapter must hand this request to the pre-claim gates: it is on one of the VPOS's hosts and this build's
37
+ * registry serves the entry. The card page's posts share the entry's URL, so the CDP adapter pauses them through the
38
+ * recognizer's host patterns, and attachToPlaywright's route predicate asks this, so both adapters show the gates every
39
+ * request to a VPOS host once the lane is armed.
40
+ */
41
+ export declare function isArmedCardlinkVposUrl(vault: {
42
+ isCardRequest(url: string, method?: string): boolean;
43
+ } | undefined, url: string): boolean;
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Cardlink's VPOS (the redirect payment page Greek banks give their merchants: Eurobank's paycenter on
3
+ * vpos.eurocommerce.gr, Cardlink's own on ecommerce.cardlink.gr, Nexi Greece's on www.alphaecommerce.gr), as this SDK
4
+ * reads it.
5
+ *
6
+ * The merchant's order page posts a signed entry form, top-level, to https://<host>/vpos/shophandlermpi, and the VPOS
7
+ * answers with its card page, whose form posts the card back to that same URL. The entry carries no card, and it is the
8
+ * one request this SDK pauses: the cardholder's device repeats it over the end-to-end TLS relay and fills the card into
9
+ * the page the VPOS returns to it (payment-core processors/cardlink_vpos.js). Every other POST the agent's browser makes
10
+ * to these hosts carries a card the agent typed or leads to a page that asks for one: the card page's own post and its
11
+ * card check, which share the entry's URL and carry the page's own fields, and anything posted to Cardlink's test
12
+ * hosts. This SDK aborts every one of them, so a placeholder card never reaches the VPOS.
13
+ *
14
+ * CARDLINK_VPOS_ENTRY_HOSTS is payment-core's CARDLINK_VPOS_HOSTS, and isCardlinkVposEntryUrl is payment-core's
15
+ * isCardlinkVposEntryUrl; cardlink-vpos.test.mjs pins both to payment-core.
16
+ */
17
+ export const CARDLINK_VPOS_PSP = 'cardlink_vpos';
18
+ export const CARDLINK_VPOS_ENTRY_HOSTS = Object.freeze(['vpos.eurocommerce.gr', 'ecommerce.cardlink.gr', 'www.alphaecommerce.gr']);
19
+ export const CARDLINK_VPOS_TEST_HOSTS = Object.freeze(['eurocommerce-test.cardlink.gr', 'ecommerce-test.cardlink.gr',
20
+ 'alphaecommerce-test.cardlink.gr']);
21
+ const ENTRY_PATH = '/vpos/shophandlermpi';
22
+ // An entry URL, for asking whether this build's registry serves the entry.
23
+ const PROBE = 'https://vpos.eurocommerce.gr/vpos/shophandlermpi';
24
+ // A field of the card page's form or of its card check, or any card field: an entry never carries one.
25
+ const PAGE_FIELD = /^(?:card[._]|cvv|cmd$|trid$|st$|paystep$|paymentmethod$|startbonus$|bonusdata$|what$|tds2_)/i;
26
+ /**
27
+ * Whether a URL is an entry exactly as a merchant's form action writes it: https, one of the three live hosts in lower
28
+ * case, the default port, no credentials, the path /vpos/shophandlermpi, and no query or fragment, not even an empty one.
29
+ */
30
+ export function isCardlinkVposEntryUrl(raw) {
31
+ if (typeof raw !== 'string' || raw.length > 256 || raw.includes('?') || raw.includes('#'))
32
+ return false;
33
+ let url;
34
+ try {
35
+ url = new URL(raw);
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ return url.href === raw && url.protocol === 'https:' && !url.port && !url.username && !url.password
41
+ && CARDLINK_VPOS_ENTRY_HOSTS.includes(url.hostname) && url.pathname === ENTRY_PATH;
42
+ }
43
+ /** Whether a URL is on one of the VPOS's hosts, live or test: https, no credentials, any port, any case, a trailing dot or not. */
44
+ export function isCardlinkVposHost(raw) {
45
+ let url;
46
+ try {
47
+ url = new URL(raw);
48
+ }
49
+ catch {
50
+ return false;
51
+ }
52
+ const host = url.hostname.toLowerCase().replace(/\.$/, '');
53
+ return url.protocol === 'https:' && !url.username && !url.password && (CARDLINK_VPOS_ENTRY_HOSTS.includes(host) || CARDLINK_VPOS_TEST_HOSTS.includes(host));
54
+ }
55
+ /**
56
+ * Whether a body reads as a merchant's entry and never as the card page's post: a form whose every pair decodes, that
57
+ * names a mid and a digest, and that carries none of the card page's fields or a card field. payment-core's entry rules
58
+ * judge the rest at create.
59
+ */
60
+ export function isCardlinkVposEntryBody(body) {
61
+ if (typeof body !== 'string' || body === '')
62
+ return false;
63
+ const names = [];
64
+ for (const chunk of body.split('&')) {
65
+ const eq = chunk.indexOf('=');
66
+ if (eq < 1)
67
+ return false;
68
+ try {
69
+ names.push(decodeURIComponent(chunk.slice(0, eq).replace(/\+/g, ' ')));
70
+ decodeURIComponent(chunk.slice(eq + 1).replace(/\+/g, ' '));
71
+ }
72
+ catch {
73
+ return false;
74
+ }
75
+ }
76
+ return names.includes('mid') && names.includes('digest') && !names.some((name) => PAGE_FIELD.test(name));
77
+ }
78
+ /** The one request on the VPOS's hosts this SDK pauses: a POST of an entry body to an entry URL. */
79
+ export function isCardlinkVposEntry(url, method, body) {
80
+ return String(method).toUpperCase() === 'POST' && isCardlinkVposEntryUrl(url) && isCardlinkVposEntryBody(body);
81
+ }
82
+ /**
83
+ * Whether an adapter must hand this request to the pre-claim gates: it is on one of the VPOS's hosts and this build's
84
+ * registry serves the entry. The card page's posts share the entry's URL, so the CDP adapter pauses them through the
85
+ * recognizer's host patterns, and attachToPlaywright's route predicate asks this, so both adapters show the gates every
86
+ * request to a VPOS host once the lane is armed.
87
+ */
88
+ export function isArmedCardlinkVposUrl(vault, url) {
89
+ return isCardlinkVposHost(url) && typeof vault?.isCardRequest === 'function' && vault.isCardRequest(PROBE, 'POST');
90
+ }
package/dist/cdp.js CHANGED
@@ -27,6 +27,8 @@ import { isArmedRedsysUrl } from './redsys.js';
27
27
  import { isArmedPrzelewy24Url } from './przelewy24.js';
28
28
  import { isArmedBarionUrl } from './barion.js';
29
29
  import { isArmedPayplugUrl } from './payplug.js';
30
+ import { isArmedCardlinkVposUrl } from './cardlink-vpos.js';
31
+ import { isArmedEghlUrl } from './eghl.js';
30
32
  import { isArmedQuickpayUrl } from './quickpay.js';
31
33
  import { COMGATE_CARD_PATTERNS, isArmedComgateUrl, servesComgate } from './comgate.js';
32
34
  import { isArmedEximbayUrl } from './eximbay.js';
@@ -2453,6 +2455,11 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
2453
2455
  && params?.frameId === pageTargetId && typeof params?.url === 'string') {
2454
2456
  committedTopUrl = params.url.split('#')[0];
2455
2457
  }
2458
+ // A history update that leaves the prepared page's origin, path and query as they were (a single-page
2459
+ // checkout's replaceState to its own URL, a hash change) is the same document, and keeps the preparation.
2460
+ if (method === 'Page.navigatedWithinDocument' && sessionId === pageSessionId && preparationFrameId && params?.frameId === preparationFrameId
2461
+ && preparationGate.keepsDocument(params.url))
2462
+ return;
2456
2463
  if (((method === 'Page.frameNavigated' && !params.frame?.parentId) || (method === 'Page.navigatedWithinDocument' && preparationFrameId && params.frameId === preparationFrameId)) && sessionId === pageSessionId) {
2457
2464
  preparationGate.invalidate('merchant_document_changed');
2458
2465
  mercadoCheckout.invalidate();
@@ -4029,6 +4036,12 @@ export async function attachToPlaywright(page, opts) {
4029
4036
  // Every request to PayPlug's page host once its entry is served (payplug.ts): the page's card post reaches the
4030
4037
  // PayPlug gate and fails.
4031
4038
  || isArmedPayplugUrl(opts.vault, url.toString())
4039
+ // Every request to the VPOS's hosts once its entry is served (cardlink-vpos.ts): the card page's post, which shares
4040
+ // the entry's URL, reaches the Cardlink gate and fails.
4041
+ || isArmedCardlinkVposUrl(opts.vault, url.toString())
4042
+ // Every request to eGHL's hosts once its entry is served (eghl.ts): the card page's post, which shares the entry's
4043
+ // address, reaches the eGHL gate and fails.
4044
+ || isArmedEghlUrl(opts.vault, url.toString())
4032
4045
  // Every request to an NMI host whose entry is served (ekashu.ts), as attachToCdp arms the
4033
4046
  // host: the card page's post and its 3-D Secure calls reach the NMI gate and fail.
4034
4047
  || isArmedEkashuUrl(opts.vault, url.toString())
@@ -1,11 +1,12 @@
1
1
  // @ts-nocheck
2
2
  // Generated from @agent-cards/payment-core. Do not edit.
3
- // artifact-sha256: aaa2f76129db849a23bf8bb44043f5cff2b45e853b16b5de4d61a1f6a10cd392
3
+ // artifact-sha256: a4f45fd0e69b19e8cb2da463b865012950ae5bcc9971c01d3e348a7de1a255ef
4
4
  // src/checkout-com.js
5
5
  var ENDPOINTS = Object.freeze({
6
6
  production: ["https://api.checkout.com/tokens", "https://card-acquisition-gateway.checkout.com/tokens"],
7
7
  sandbox: ["https://api.sandbox.checkout.com/tokens", "https://card-acquisition-gateway.sandbox.checkout.com/tokens"]
8
8
  });
9
+ var MERCHANT_ENDPOINT = /^https:\/\/(?:[a-z0-9]+\.)?(?:api(\.sandbox)?\.checkout\.com\/tokens|devices\.api(\.sandbox)?\.checkout\.com\/(?:cag\/)?tokens)$/;
9
10
  var record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
10
11
  var own = (value, name) => Object.prototype.hasOwnProperty.call(value, name);
11
12
  var keys = (value, allowed) => record(value) && Object.keys(value).every((name) => allowed.includes(name));
@@ -123,6 +124,9 @@ function checkoutComEnvironment(url) {
123
124
  return "production";
124
125
  if (ENDPOINTS.sandbox.includes(url))
125
126
  return "sandbox";
127
+ const merchant = typeof url === "string" ? MERCHANT_ENDPOINT.exec(url) : null;
128
+ if (merchant?.[0] === url)
129
+ return merchant[1] || merchant[2] ? "sandbox" : "production";
126
130
  return void 0;
127
131
  }
128
132
  var ADDRESS_TEXT = ["address_line1", "address_line2", "city", "state", "zip", "name"];
package/dist/client.d.ts CHANGED
@@ -507,6 +507,34 @@ export declare const SUPPORTED_REGISTRY_FEATURES: readonly string[];
507
507
  * authorize() needs the agent's pair, and the API holds its amount to the price. Served on the same
508
508
  * terms, and the API holds the lane to Agentcard's own company.
509
509
  *
510
+ * `aurus_one_time_token`: the card request Aurus Pay's ecom card frame (O'Reilly Auto Parts) sends to
511
+ * pecst<NN>.aurusepay.com/storeservices/ecom/oneTimeToken, the card sealed in the frame under a public key its own
512
+ * script carries. This build pauses it only when Aurus's card frame sent it (aurus.ts aurusPreClaim); the same
513
+ * request from the store's page or another frame fails in the browser before anything is created. The request
514
+ * names no amount, so authorize() needs the agent's pair, above zero. The cardholder's device does not seal for
515
+ * Aurus yet (payment-core processors/aurus.js), so a paused request opens no approval that pays.
516
+ *
517
+ * `viva_smart_checkout_chargetoken`: the card request Viva Wallet's Smart Checkout page sends as one
518
+ * JSON request to www.vivapayments.com/web2/checkout/v2/chargetokens (demo.vivapayments.com in test),
519
+ * on Pay, after the page's own reCAPTCHA run. This build pauses only the page's own card body at that
520
+ * exact URL (payment-core processors/viva_wallet.js); a body that keeps the card, pays with a stored
521
+ * card, converts the currency or is the page's second try after a decline fails in the browser before
522
+ * anything is created. The cardholder's device sends the card through Agentcard's checkout relay, since
523
+ * the page's request answers no other origin, and the page gets Viva's single-use charge token as
524
+ * payment-core's judge rebuilt it; the page then charges that token card free. The body names its
525
+ * amount, which the API holds to the agent's pair, and the API pays a live token only for an order
526
+ * payment-core pins. Served on the same terms, and the API holds the lane to Agentcard's own company.
527
+ *
528
+ * `paystack_pinned_key`: the charge Paystack's hosted checkout sends as one form POST to
529
+ * standard.paystack.co/charge/, the card only as `clientdata`, RSA ciphertext under the one key
530
+ * Paystack's page carries. This build pauses only the card page's own charge at that exact URL
531
+ * (payment-core processors/paystack.js); a charge that keeps the card, starts a plan or carries a PIN
532
+ * fails in the browser before anything is created. The cardholder's device encrypts the real card under
533
+ * the same pinned key and sends the charge itself, and the page gets Paystack's answer: paid, declined,
534
+ * or the issuer's 3-D Secure step, which the page then runs in the agent's browser. The charge names
535
+ * no amount, so authorize() needs the agent's pair, above zero. Served on the same terms, and the API
536
+ * holds the lane to Agentcard's own company.
537
+ *
510
538
  * `usaepay_payment_key`: the card request USAePay's Pay.js card frame sends as one JSON request to
511
539
  * www.usaepay.com/api/v2/pub/payment_keys (secure.usaepay.com alike; sandbox.usaepay.com in test), under
512
540
  * the merchant's public key in its Authorization. This build pauses only the frame's own card body at
@@ -555,6 +583,31 @@ export declare const SUPPORTED_REGISTRY_FEATURES: readonly string[];
555
583
  * approves. Served on the same terms: only to a build that lists it, for a company Agentcard turned
556
584
  * ProcessOut on for.
557
585
  *
586
+ * `monei_card_token`: the card request MONEI's card frame sends from MONEI's payment page
587
+ * (secure.monei.com/payments/<id>) to api.monei.com/v1/tokens, with the payment's id and the card. This
588
+ * build pauses only the frame's own body for a payment at that exact URL (payment-core
589
+ * processors/monei.js); MONEI's account flow, Click to Pay and a wallet on the same URL fail in the
590
+ * browser before anything is created. The request names neither the merchant nor the amount, so the API
591
+ * reads MONEI's own record of the payment and holds the agent's pair, above zero
592
+ * (agent-amount-processors.json), to MONEI's amount exactly. The cardholder's device sends the card to
593
+ * MONEI itself and the frame gets back MONEI's payment token alone, rebuilt by payment-core's judge.
594
+ * Served on the same terms: only to a build that lists it, for a company Agentcard turned MONEI on for.
595
+ *
596
+ * `frisbii_card_token`: the card request Frisbii Checkout's hosted payment page (checkout.reepay.com or
597
+ * checkout.frisbii.com, as an overlay, an embedded frame or a full window) sends to
598
+ * card.reepay.com or card.frisbii.com /v1/token/?session=<id>, with the merchant's public key and the
599
+ * card. This build pauses only the page's own body at that exact URL (payment-core
600
+ * processors/frisbii.js); any other body on it, one that keeps the card on file included, fails in the
601
+ * browser before anything is created. The page's two other card paths, a stored card's token
602
+ * (/v1/token/cof/) and Click to Pay (/v1/token/create_click_to_pay), are held and refused whatever
603
+ * their body, so neither leaves the browser either. The request names the amount only when
604
+ * the session carries 3-D Secure data, so the agent's pair is required, above zero
605
+ * (agent-amount-processors.json), and the API refuses it when it differs from the page's own. The
606
+ * cardholder's device sends the card to Frisbii
607
+ * itself and the page gets back Frisbii's card token or 3-D Secure step alone, rebuilt by payment-core's
608
+ * judge. Served on the same terms: only to a build that lists it, for a company Agentcard turned Frisbii
609
+ * on for.
610
+ *
558
611
  * `aps_custom_merchant_page`: Amazon Payment Services' custom merchant page, whose own card form
559
612
  * posts top-level to /FortAPI/paymentPage on checkout.payfort.com (sbcheckout.payfort.com on APS's
560
613
  * sandbox) with service_command=TOKENIZATION. This build pauses that navigation; the cardholder's
@@ -598,6 +651,19 @@ export declare const SUPPORTED_REGISTRY_FEATURES: readonly string[];
598
651
  * zero. Served only to a build that lists it, and the API turns PayPlug on for Agentcard's own
599
652
  * company alone.
600
653
  *
654
+ * `cardlink_vpos_hosted_payment_page`: Cardlink's VPOS, the payment page of Eurobank, Cardlink and Nexi
655
+ * Greece, whose card-free signed entry (a form post to /vpos/shophandlermpi on one of the three hosts) this build
656
+ * pauses for the cardholder's device, and whose card page's post and card check on the same URL this build never
657
+ * lets the agent's browser send (pre-claim.ts, cardlink-vpos.ts). Served only to a build that lists it, and the API
658
+ * turns the lane on for Agentcard's own company alone.
659
+ *
660
+ * `eghl_hosted_payment_page`: eGHL's payment page (ADAPTIS, formerly eGHL, on securepay.e-ghl.com), whose card-free
661
+ * entry (a GET of /IPG/payment.aspx with the payment in its query, which the merchant's checkout or eGHL's Shopify app
662
+ * sends the buyer to) this build pauses for the cardholder's device by its exact URL (hosted-entry.ts), and whose card
663
+ * page's post to the same address this build never lets the agent's browser send (pre-claim.ts, eghl.ts). The entry
664
+ * names its amount, and the API holds the agent's pair to it exactly. Served only to a build that lists it, and the API
665
+ * turns the lane on for Agentcard's own company alone.
666
+ *
601
667
  * `paymob_checkout_pay`: the card payment Paymob's own checkout sends, from Unified Checkout
602
668
  * (<country>.checkout.paymob.com) or from the Pixel card frame a merchant's page embeds, as JSON to
603
669
  * https://<accept|uae|ksa|oman>.paymob.com/api/acceptance/payments/pay. This build pauses only the
package/dist/client.js CHANGED
@@ -501,6 +501,34 @@ export const SUPPORTED_REGISTRY_FEATURES = ['card_fields', 'checkout_sessions'];
501
501
  * authorize() needs the agent's pair, and the API holds its amount to the price. Served on the same
502
502
  * terms, and the API holds the lane to Agentcard's own company.
503
503
  *
504
+ * `aurus_one_time_token`: the card request Aurus Pay's ecom card frame (O'Reilly Auto Parts) sends to
505
+ * pecst<NN>.aurusepay.com/storeservices/ecom/oneTimeToken, the card sealed in the frame under a public key its own
506
+ * script carries. This build pauses it only when Aurus's card frame sent it (aurus.ts aurusPreClaim); the same
507
+ * request from the store's page or another frame fails in the browser before anything is created. The request
508
+ * names no amount, so authorize() needs the agent's pair, above zero. The cardholder's device does not seal for
509
+ * Aurus yet (payment-core processors/aurus.js), so a paused request opens no approval that pays.
510
+ *
511
+ * `viva_smart_checkout_chargetoken`: the card request Viva Wallet's Smart Checkout page sends as one
512
+ * JSON request to www.vivapayments.com/web2/checkout/v2/chargetokens (demo.vivapayments.com in test),
513
+ * on Pay, after the page's own reCAPTCHA run. This build pauses only the page's own card body at that
514
+ * exact URL (payment-core processors/viva_wallet.js); a body that keeps the card, pays with a stored
515
+ * card, converts the currency or is the page's second try after a decline fails in the browser before
516
+ * anything is created. The cardholder's device sends the card through Agentcard's checkout relay, since
517
+ * the page's request answers no other origin, and the page gets Viva's single-use charge token as
518
+ * payment-core's judge rebuilt it; the page then charges that token card free. The body names its
519
+ * amount, which the API holds to the agent's pair, and the API pays a live token only for an order
520
+ * payment-core pins. Served on the same terms, and the API holds the lane to Agentcard's own company.
521
+ *
522
+ * `paystack_pinned_key`: the charge Paystack's hosted checkout sends as one form POST to
523
+ * standard.paystack.co/charge/, the card only as `clientdata`, RSA ciphertext under the one key
524
+ * Paystack's page carries. This build pauses only the card page's own charge at that exact URL
525
+ * (payment-core processors/paystack.js); a charge that keeps the card, starts a plan or carries a PIN
526
+ * fails in the browser before anything is created. The cardholder's device encrypts the real card under
527
+ * the same pinned key and sends the charge itself, and the page gets Paystack's answer: paid, declined,
528
+ * or the issuer's 3-D Secure step, which the page then runs in the agent's browser. The charge names
529
+ * no amount, so authorize() needs the agent's pair, above zero. Served on the same terms, and the API
530
+ * holds the lane to Agentcard's own company.
531
+ *
504
532
  * `usaepay_payment_key`: the card request USAePay's Pay.js card frame sends as one JSON request to
505
533
  * www.usaepay.com/api/v2/pub/payment_keys (secure.usaepay.com alike; sandbox.usaepay.com in test), under
506
534
  * the merchant's public key in its Authorization. This build pauses only the frame's own card body at
@@ -549,6 +577,31 @@ export const SUPPORTED_REGISTRY_FEATURES = ['card_fields', 'checkout_sessions'];
549
577
  * approves. Served on the same terms: only to a build that lists it, for a company Agentcard turned
550
578
  * ProcessOut on for.
551
579
  *
580
+ * `monei_card_token`: the card request MONEI's card frame sends from MONEI's payment page
581
+ * (secure.monei.com/payments/<id>) to api.monei.com/v1/tokens, with the payment's id and the card. This
582
+ * build pauses only the frame's own body for a payment at that exact URL (payment-core
583
+ * processors/monei.js); MONEI's account flow, Click to Pay and a wallet on the same URL fail in the
584
+ * browser before anything is created. The request names neither the merchant nor the amount, so the API
585
+ * reads MONEI's own record of the payment and holds the agent's pair, above zero
586
+ * (agent-amount-processors.json), to MONEI's amount exactly. The cardholder's device sends the card to
587
+ * MONEI itself and the frame gets back MONEI's payment token alone, rebuilt by payment-core's judge.
588
+ * Served on the same terms: only to a build that lists it, for a company Agentcard turned MONEI on for.
589
+ *
590
+ * `frisbii_card_token`: the card request Frisbii Checkout's hosted payment page (checkout.reepay.com or
591
+ * checkout.frisbii.com, as an overlay, an embedded frame or a full window) sends to
592
+ * card.reepay.com or card.frisbii.com /v1/token/?session=<id>, with the merchant's public key and the
593
+ * card. This build pauses only the page's own body at that exact URL (payment-core
594
+ * processors/frisbii.js); any other body on it, one that keeps the card on file included, fails in the
595
+ * browser before anything is created. The page's two other card paths, a stored card's token
596
+ * (/v1/token/cof/) and Click to Pay (/v1/token/create_click_to_pay), are held and refused whatever
597
+ * their body, so neither leaves the browser either. The request names the amount only when
598
+ * the session carries 3-D Secure data, so the agent's pair is required, above zero
599
+ * (agent-amount-processors.json), and the API refuses it when it differs from the page's own. The
600
+ * cardholder's device sends the card to Frisbii
601
+ * itself and the page gets back Frisbii's card token or 3-D Secure step alone, rebuilt by payment-core's
602
+ * judge. Served on the same terms: only to a build that lists it, for a company Agentcard turned Frisbii
603
+ * on for.
604
+ *
552
605
  * `aps_custom_merchant_page`: Amazon Payment Services' custom merchant page, whose own card form
553
606
  * posts top-level to /FortAPI/paymentPage on checkout.payfort.com (sbcheckout.payfort.com on APS's
554
607
  * sandbox) with service_command=TOKENIZATION. This build pauses that navigation; the cardholder's
@@ -592,6 +645,19 @@ export const SUPPORTED_REGISTRY_FEATURES = ['card_fields', 'checkout_sessions'];
592
645
  * zero. Served only to a build that lists it, and the API turns PayPlug on for Agentcard's own
593
646
  * company alone.
594
647
  *
648
+ * `cardlink_vpos_hosted_payment_page`: Cardlink's VPOS, the payment page of Eurobank, Cardlink and Nexi
649
+ * Greece, whose card-free signed entry (a form post to /vpos/shophandlermpi on one of the three hosts) this build
650
+ * pauses for the cardholder's device, and whose card page's post and card check on the same URL this build never
651
+ * lets the agent's browser send (pre-claim.ts, cardlink-vpos.ts). Served only to a build that lists it, and the API
652
+ * turns the lane on for Agentcard's own company alone.
653
+ *
654
+ * `eghl_hosted_payment_page`: eGHL's payment page (ADAPTIS, formerly eGHL, on securepay.e-ghl.com), whose card-free
655
+ * entry (a GET of /IPG/payment.aspx with the payment in its query, which the merchant's checkout or eGHL's Shopify app
656
+ * sends the buyer to) this build pauses for the cardholder's device by its exact URL (hosted-entry.ts), and whose card
657
+ * page's post to the same address this build never lets the agent's browser send (pre-claim.ts, eghl.ts). The entry
658
+ * names its amount, and the API holds the agent's pair to it exactly. Served only to a build that lists it, and the API
659
+ * turns the lane on for Agentcard's own company alone.
660
+ *
595
661
  * `paymob_checkout_pay`: the card payment Paymob's own checkout sends, from Unified Checkout
596
662
  * (<country>.checkout.paymob.com) or from the Pixel card frame a merchant's page embeds, as JSON to
597
663
  * https://<accept|uae|ksa|oman>.paymob.com/api/acceptance/payments/pay. This build pauses only the
@@ -12,6 +12,19 @@ declare var CybersourceFlexError: {
12
12
  };
13
13
  declare function isVerifiedCaptureContext(value: any): boolean;
14
14
  declare function flexHostEnvironment(hostname: any): "production" | "sandbox" | null;
15
+ declare var UNIFIED_CHECKOUT_HOSTS: Readonly<{
16
+ production: "up.cybersource.com";
17
+ sandbox: "testup.cybersource.com";
18
+ }>;
19
+ declare var UNIFIED_CHECKOUT_REVIEWED_CLIENT_VERSIONS: readonly string[];
20
+ declare var UNIFIED_CHECKOUT_FRAMES: readonly string[];
21
+ declare function unifiedCheckoutHostEnvironment(hostname: any): "production" | "sandbox" | null;
22
+ declare function parseUnifiedCheckoutFrame(rawUrl: any): Readonly<{
23
+ environment: "production" | "sandbox";
24
+ frame: string;
25
+ asset: string;
26
+ captureContext: string;
27
+ }> | null;
15
28
  declare var CYBERSOURCE_FLEX_PSP: string;
16
29
  declare var CYBERSOURCE_FLEX_CONTENT_TYPE: string;
17
30
  declare var CYBERSOURCE_FLEX_TOKENS_URLS: Readonly<{
@@ -38,6 +51,7 @@ declare function verifyCaptureContext(jwt: any, { crypto, now }?: {}): Promise<R
38
51
  modulusBytes: number;
39
52
  index: any;
40
53
  contextType: any;
54
+ clientVersion: any;
41
55
  allowedCardNetworks: readonly any[] | null;
42
56
  targetOrigins: readonly any[];
43
57
  iat: any;
@@ -76,6 +90,29 @@ declare function buildCardPlaintext(verified: any, card: any, { fields, trigger,
76
90
  trigger?: string | undefined;
77
91
  }): string;
78
92
  declare function sealForContext(verified: any, plaintext: any, { crypto }?: {}): Promise<string>;
93
+ declare function verifyUnifiedCheckoutContext(jwt: any, { crypto, now }?: {}): Promise<Readonly<{
94
+ raw: any;
95
+ signingKid: any;
96
+ environment: any;
97
+ origin: string;
98
+ path: string;
99
+ url: string;
100
+ jwk: Readonly<{
101
+ kty: "RSA";
102
+ n: any;
103
+ e: any;
104
+ kid: any;
105
+ }>;
106
+ modulusBytes: number;
107
+ index: any;
108
+ contextType: any;
109
+ clientVersion: any;
110
+ allowedCardNetworks: readonly any[] | null;
111
+ targetOrigins: readonly any[];
112
+ iat: any;
113
+ exp: any;
114
+ }>>;
115
+ declare function buildUnifiedCheckoutPlaintext(verified: any, card: any, { billTo, now }?: {}): string;
79
116
  declare var CYBERSOURCE_FLEX_REFUSAL_REASONS: readonly string[];
80
117
  declare function cybersourceFlexRefusalCode(text: any): string | null;
81
118
  declare function isCybersourceFlexTokenShape(text: any): boolean;
@@ -107,6 +144,7 @@ declare function admitCybersourceFlexPreparation(prepared: any, { crypto, now }?
107
144
  modulusBytes: number;
108
145
  index: any;
109
146
  contextType: any;
147
+ clientVersion: any;
110
148
  allowedCardNetworks: readonly any[] | null;
111
149
  targetOrigins: readonly any[];
112
150
  iat: any;
@@ -115,4 +153,4 @@ declare function admitCybersourceFlexPreparation(prepared: any, { crypto, now }?
115
153
  fields: readonly string[];
116
154
  }>>;
117
155
  declare function sameCybersourceFlexPreparation(prepared: any, request: any): boolean;
118
- export { CYBERSOURCE_FLEX_CAPTURE_CONTEXT_MAX_LENGTH, CYBERSOURCE_FLEX_CONTENT_TYPE, CYBERSOURCE_FLEX_PRESEAL_TRIGGER, CYBERSOURCE_FLEX_PSP, CYBERSOURCE_FLEX_REFUSAL_REASONS, CYBERSOURCE_FLEX_REVIEWED_IFRAME_VERSIONS, CYBERSOURCE_FLEX_RULES_SOURCE, CYBERSOURCE_FLEX_SIGNING_KEYS, CYBERSOURCE_FLEX_TEST_PANS, CYBERSOURCE_FLEX_TOKENS_URLS, CybersourceFlexError, admitCybersourceFlexPreparation, assertCybersourceFlexTemplate, buildCardPlaintext, cybersourceFlexEnvironment, flexHostEnvironment as cybersourceFlexHostEnvironment, cybersourceFlexPreparationUrl, cybersourceFlexRefusalCode, cybersourceFlexTemplateKid, detectCardTypes, isCybersourceFlexMediaType, isCybersourceFlexRequest, isCybersourceFlexTemplateBody, isCybersourceFlexTokenShape, isPreparedCybersourceFlexRequest, isVerifiedCaptureContext, parseMicroformFragment, sameCybersourceFlexPreparation, sealForContext, transientTokenFacts, transientTokenSigned, verifyCaptureContext };
156
+ export { CYBERSOURCE_FLEX_CAPTURE_CONTEXT_MAX_LENGTH, CYBERSOURCE_FLEX_CONTENT_TYPE, CYBERSOURCE_FLEX_PRESEAL_TRIGGER, CYBERSOURCE_FLEX_PSP, CYBERSOURCE_FLEX_REFUSAL_REASONS, CYBERSOURCE_FLEX_REVIEWED_IFRAME_VERSIONS, CYBERSOURCE_FLEX_RULES_SOURCE, CYBERSOURCE_FLEX_SIGNING_KEYS, CYBERSOURCE_FLEX_TEST_PANS, CYBERSOURCE_FLEX_TOKENS_URLS, CybersourceFlexError, UNIFIED_CHECKOUT_FRAMES, UNIFIED_CHECKOUT_HOSTS, UNIFIED_CHECKOUT_REVIEWED_CLIENT_VERSIONS, admitCybersourceFlexPreparation, assertCybersourceFlexTemplate, buildCardPlaintext, buildUnifiedCheckoutPlaintext, cybersourceFlexEnvironment, flexHostEnvironment as cybersourceFlexHostEnvironment, cybersourceFlexPreparationUrl, cybersourceFlexRefusalCode, cybersourceFlexTemplateKid, detectCardTypes, isCybersourceFlexMediaType, isCybersourceFlexRequest, isCybersourceFlexTemplateBody, isCybersourceFlexTokenShape, isPreparedCybersourceFlexRequest, isVerifiedCaptureContext, parseMicroformFragment, parseUnifiedCheckoutFrame, sameCybersourceFlexPreparation, sealForContext, transientTokenFacts, transientTokenSigned, unifiedCheckoutHostEnvironment, verifyCaptureContext, verifyUnifiedCheckoutContext };
@@ -1,6 +1,6 @@
1
1
  // @ts-nocheck
2
2
  // Generated from @agent-cards/payment-core. Do not edit.
3
- // artifact-sha256: c6a711b5dc964dbeb45863780001d99b79090f919b282fed9ae6fc06b4839681
3
+ // artifact-sha256: a9a624dbdd5a025d710f99e5ce83a985e4561b4db6d3e60dc427b5e406e4b653
4
4
  // src/cybersource-flex-rules.js
5
5
  var CYBERSOURCE_FLEX_RULES_SOURCE = Object.freeze({ version: "2.12.1", sha256: "8429ebae83e9745cd53ad8ff0d9ba69bee0087c1435ed0695a25444bed418327" });
6
6
  var CYBERSOURCE_FLEX_RULES = [
@@ -201,6 +201,7 @@ async function sealCompactJwe(jwk, plaintext, { crypto }) {
201
201
  }
202
202
  // src/cybersource-flex-context.js
203
203
  var FLEX_TOKENS_PATH = "/flex/v2/tokens";
204
+ var UNIFIED_CHECKOUT_TOKENS_PATH = "/flex/v2/tokens/uc";
204
205
  var FLEX_HOSTS = Object.freeze({ production: "flex.cybersource.com", sandbox: "testflex.cybersource.com" });
205
206
  var CAPTURE_CONTEXT_MAX_LENGTH = 16384;
206
207
  var CLOCK_SKEW_MS = 6e4;
@@ -233,7 +234,8 @@ function origins(value) {
233
234
  return Object.freeze([]);
234
235
  return Object.freeze(value.filter((origin) => typeof origin === "string" && origin.length <= 2048).slice(0, 16));
235
236
  }
236
- async function verifyContextWithKeys(jwt, keys, { crypto, now } = {}) {
237
+ async function verifyContextWithKeys(jwt, keys, { crypto, now, kind = "microform" } = {}) {
238
+ const unified = kind === "unified_checkout";
237
239
  const [encodedHeader] = compactParts(jwt, 3, CAPTURE_CONTEXT_MAX_LENGTH, "format");
238
240
  const peek = jsonFromBytes(base64UrlToBytes(encodedHeader), "format");
239
241
  const kid = peek.kid;
@@ -254,8 +256,9 @@ async function verifyContextWithKeys(jwt, keys, { crypto, now } = {}) {
254
256
  if (!record(flx))
255
257
  refuse("format", "the capture context has no Flex section.");
256
258
  const origin = `https://${host}`;
257
- const url = `${origin}${FLEX_TOKENS_PATH}`;
258
- if (flx.origin !== origin || flx.path !== FLEX_TOKENS_PATH || own(flx, "tokensUrl") && flx.tokensUrl !== url) {
259
+ const path = unified ? UNIFIED_CHECKOUT_TOKENS_PATH : FLEX_TOKENS_PATH;
260
+ const url = `${origin}${path}`;
261
+ if (unified ? flx.origin !== origin || flx.tokensUrl !== url || own(flx, "path") : flx.origin !== origin || flx.path !== FLEX_TOKENS_PATH || own(flx, "tokensUrl") && flx.tokensUrl !== url) {
259
262
  refuse("url_mismatch", `the capture context does not send the card to ${url}.`);
260
263
  }
261
264
  const jwk = flx.jwk;
@@ -271,21 +274,22 @@ async function verifyContextWithKeys(jwt, keys, { crypto, now } = {}) {
271
274
  refuse("expired", "the capture context has expired.");
272
275
  }
273
276
  const ctx = Array.isArray(payload.ctx) ? payload.ctx : [];
274
- const index = ctx.findIndex((entry) => record(entry) && typeof entry.type === "string" && /^mf-/.test(entry.type));
277
+ const index = ctx.findIndex((entry) => record(entry) && typeof entry.type === "string" && (unified ? /^uc-/ : /^mf-/).test(entry.type));
275
278
  if (index < 0)
276
- refuse("microform", "the capture context is not a Microform context.");
279
+ refuse("microform", unified ? "the capture context is not a Unified Checkout context." : "the capture context is not a Microform context.");
277
280
  const data = record(ctx[index].data) ? ctx[index].data : {};
278
281
  const context = Object.freeze({
279
282
  raw: jwt,
280
283
  signingKid: kid,
281
284
  environment,
282
285
  origin,
283
- path: FLEX_TOKENS_PATH,
286
+ path,
284
287
  url,
285
288
  jwk: Object.freeze({ kty: "RSA", n: jwk.n, e: jwk.e, kid: jwk.kid }),
286
289
  modulusBytes: Math.ceil(bits / 8),
287
290
  index,
288
291
  contextType: ctx[index].type,
292
+ clientVersion: unified && typeof data.clientVersion === "string" && data.clientVersion.length <= 32 ? data.clientVersion : null,
289
293
  allowedCardNetworks: networks(data.allowedCardNetworks),
290
294
  targetOrigins: origins(data.targetOrigins),
291
295
  iat: Number.isFinite(payload.iat) ? payload.iat : null,
@@ -294,6 +298,51 @@ async function verifyContextWithKeys(jwt, keys, { crypto, now } = {}) {
294
298
  VERIFIED.add(context);
295
299
  return context;
296
300
  }
301
+ // src/cybersource-unified-checkout.js
302
+ var UNIFIED_CHECKOUT_HOSTS = Object.freeze({ production: "up.cybersource.com", sandbox: "testup.cybersource.com" });
303
+ var UNIFIED_CHECKOUT_REVIEWED_CLIENT_VERSIONS = Object.freeze(["1.8.2"]);
304
+ var UNIFIED_CHECKOUT_FRAMES = Object.freeze(["mce", "orc", "ga"]);
305
+ var FRAME_PATH = /^\/uc\/v1\/assets\/([A-Za-z0-9_-]{16,1024})\/(mce|orc|ga)\/(mce|orc|ga)\.html$/;
306
+ var FRAGMENT_MAX_LENGTH = CAPTURE_CONTEXT_MAX_LENGTH + 4096;
307
+ function unifiedCheckoutHostEnvironment(hostname) {
308
+ const host = String(hostname ?? "").toLowerCase();
309
+ if (host === UNIFIED_CHECKOUT_HOSTS.production)
310
+ return "production";
311
+ if (host === UNIFIED_CHECKOUT_HOSTS.sandbox)
312
+ return "sandbox";
313
+ return null;
314
+ }
315
+ function parseUnifiedCheckoutFrame(rawUrl) {
316
+ if (typeof rawUrl !== "string" || rawUrl.length > FRAGMENT_MAX_LENGTH + 2048)
317
+ return null;
318
+ let url;
319
+ try {
320
+ url = new URL(rawUrl);
321
+ }
322
+ catch {
323
+ return null;
324
+ }
325
+ const environment = unifiedCheckoutHostEnvironment(url.hostname);
326
+ const path = FRAME_PATH.exec(url.pathname);
327
+ if (url.protocol !== "https:" || url.port || url.username || url.password || !environment || !path || path[2] !== path[3])
328
+ return null;
329
+ const fragment = url.hash.slice(1);
330
+ if (!fragment || fragment.length > FRAGMENT_MAX_LENGTH)
331
+ return null;
332
+ let value;
333
+ try {
334
+ value = JSON.parse(decodeURIComponent(fragment));
335
+ }
336
+ catch {
337
+ return null;
338
+ }
339
+ if (!value || typeof value !== "object" || Array.isArray(value))
340
+ return null;
341
+ const ctx = value.ctx;
342
+ if (typeof ctx !== "string" || ctx.length < 1 || ctx.length > CAPTURE_CONTEXT_MAX_LENGTH)
343
+ return null;
344
+ return Object.freeze({ environment, frame: path[2], asset: path[1], captureContext: ctx });
345
+ }
297
346
  // src/cybersource-flex.js
298
347
  var CYBERSOURCE_FLEX_PSP = "cybersource_flex";
299
348
  var CYBERSOURCE_FLEX_CONTENT_TYPE = "application/jwt; charset=utf-8";
@@ -343,11 +392,11 @@ function cybersourceFlexEnvironment(url) {
343
392
  return "sandbox";
344
393
  return void 0;
345
394
  }
346
- var FRAGMENT_MAX_LENGTH = 16384;
395
+ var FRAGMENT_MAX_LENGTH2 = 16384;
347
396
  var IFRAME_PATH = /^\/microform\/bundle\/v(\d+\.\d+\.\d+)\/iframe\.html$/;
348
397
  var FIELD_TYPES = Object.freeze(["number", "securityCode"]);
349
398
  function parseMicroformFragment(rawUrl) {
350
- if (typeof rawUrl !== "string" || rawUrl.length > FRAGMENT_MAX_LENGTH + 2048)
399
+ if (typeof rawUrl !== "string" || rawUrl.length > FRAGMENT_MAX_LENGTH2 + 2048)
351
400
  return null;
352
401
  let url;
353
402
  try {
@@ -361,7 +410,7 @@ function parseMicroformFragment(rawUrl) {
361
410
  if (url.protocol !== "https:" || url.port || url.username || url.password || !environment || !path)
362
411
  return null;
363
412
  const fragment = url.hash.slice(1);
364
- if (!fragment || fragment.length > FRAGMENT_MAX_LENGTH)
413
+ if (!fragment || fragment.length > FRAGMENT_MAX_LENGTH2)
365
414
  return null;
366
415
  let value;
367
416
  try {
@@ -556,6 +605,46 @@ async function sealForContext(verified, plaintext, { crypto } = {}) {
556
605
  refuse("context", "the capture context was not verified on this device.");
557
606
  return sealCompactJwe(verified.jwk, plaintext, { crypto });
558
607
  }
608
+ function verifyUnifiedCheckoutContext(jwt, { crypto, now } = {}) {
609
+ return verifyContextWithKeys(jwt, CYBERSOURCE_FLEX_SIGNING_KEYS, { crypto, now, kind: "unified_checkout" });
610
+ }
611
+ var BILL_TO_NAME = /^[^\u0000-\u001f\u007f<>]{1,60}$/;
612
+ var BILL_TO_EMAIL = /^[^\s@<>]{1,64}@[^\s@<>]{1,190}$/;
613
+ function buildUnifiedCheckoutPlaintext(verified, card, { billTo, now } = {}) {
614
+ if (!isVerifiedCaptureContext(verified) || !/^uc-/.test(verified.contextType))
615
+ refuse("context", "the capture context was not verified as a Unified Checkout context on this device.");
616
+ if (!UNIFIED_CHECKOUT_REVIEWED_CLIENT_VERSIONS.includes(verified.clientVersion))
617
+ refuse("microform_version", "this Unified Checkout client version was not reviewed.");
618
+ const first = billTo?.firstName;
619
+ const last = billTo?.lastName;
620
+ const email = billTo?.email;
621
+ if (typeof first !== "string" || !BILL_TO_NAME.test(first) || typeof last !== "string" || !BILL_TO_NAME.test(last) || email !== void 0 && (typeof email !== "string" || !BILL_TO_EMAIL.test(email)))
622
+ refuse("fields", "the billing name or email is not one the card entry takes.");
623
+ const normalized = flexCard(card, typeof now === "function" ? now() : Date.now());
624
+ const detected = detectCardTypes(normalized.number, verified.allowedCardNetworks ?? void 0);
625
+ if (detected.codes.length === 0)
626
+ refuse("card_network", "this merchant's CyberSource form does not accept this card network.");
627
+ if (!detected.valid)
628
+ refuse("card_invalid", "the card number fails its network's length or check digit.");
629
+ if (detected.securityCode.required && !new RegExp(`^[0-9]{${detected.securityCode.length}}$`).test(normalized.cvc)) {
630
+ refuse("card_security_code", "the security code has the wrong length for this card.");
631
+ }
632
+ const data = {
633
+ PANENTRY: {
634
+ orderInformation: { billTo: { firstName: first, lastName: last, ...email !== void 0 ? { email } : {} } },
635
+ paymentInformation: { card: {
636
+ number: normalized.number,
637
+ expirationMonth: normalized.expirationMonth,
638
+ expirationYear: normalized.expirationYear,
639
+ securityCode: normalized.cvc,
640
+ type: detected.codes[0]
641
+ } }
642
+ }
643
+ };
644
+ const plaintext = JSON.stringify({ data, context: verified.raw, index: 0 }).replace(/[\u0080-\uffff]/g, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`);
645
+ asciiBytes(plaintext, "card_ascii");
646
+ return plaintext;
647
+ }
559
648
  var TOKEN_MAX_LENGTH = 8192;
560
649
  var CYBERSOURCE_FLEX_REFUSAL_REASONS = Object.freeze([
561
650
  "VALIDATION_ERROR",
@@ -728,4 +817,4 @@ function sameCybersourceFlexPreparation(prepared, request) {
728
817
  const theirs = new Set(two.fields);
729
818
  return mine.size === one.fields.length && theirs.size === two.fields.length && mine.size === theirs.size && [...mine].every((field) => theirs.has(field));
730
819
  }
731
- export { CYBERSOURCE_FLEX_CAPTURE_CONTEXT_MAX_LENGTH, CYBERSOURCE_FLEX_CONTENT_TYPE, CYBERSOURCE_FLEX_PRESEAL_TRIGGER, CYBERSOURCE_FLEX_PSP, CYBERSOURCE_FLEX_REFUSAL_REASONS, CYBERSOURCE_FLEX_REVIEWED_IFRAME_VERSIONS, CYBERSOURCE_FLEX_RULES_SOURCE, CYBERSOURCE_FLEX_SIGNING_KEYS, CYBERSOURCE_FLEX_TEST_PANS, CYBERSOURCE_FLEX_TOKENS_URLS, CybersourceFlexError, admitCybersourceFlexPreparation, assertCybersourceFlexTemplate, buildCardPlaintext, cybersourceFlexEnvironment, flexHostEnvironment as cybersourceFlexHostEnvironment, cybersourceFlexPreparationUrl, cybersourceFlexRefusalCode, cybersourceFlexTemplateKid, detectCardTypes, isCybersourceFlexMediaType, isCybersourceFlexRequest, isCybersourceFlexTemplateBody, isCybersourceFlexTokenShape, isPreparedCybersourceFlexRequest, isVerifiedCaptureContext, parseMicroformFragment, sameCybersourceFlexPreparation, sealForContext, transientTokenFacts, transientTokenSigned, verifyCaptureContext };
820
+ export { CYBERSOURCE_FLEX_CAPTURE_CONTEXT_MAX_LENGTH, CYBERSOURCE_FLEX_CONTENT_TYPE, CYBERSOURCE_FLEX_PRESEAL_TRIGGER, CYBERSOURCE_FLEX_PSP, CYBERSOURCE_FLEX_REFUSAL_REASONS, CYBERSOURCE_FLEX_REVIEWED_IFRAME_VERSIONS, CYBERSOURCE_FLEX_RULES_SOURCE, CYBERSOURCE_FLEX_SIGNING_KEYS, CYBERSOURCE_FLEX_TEST_PANS, CYBERSOURCE_FLEX_TOKENS_URLS, CybersourceFlexError, UNIFIED_CHECKOUT_FRAMES, UNIFIED_CHECKOUT_HOSTS, UNIFIED_CHECKOUT_REVIEWED_CLIENT_VERSIONS, admitCybersourceFlexPreparation, assertCybersourceFlexTemplate, buildCardPlaintext, buildUnifiedCheckoutPlaintext, cybersourceFlexEnvironment, flexHostEnvironment as cybersourceFlexHostEnvironment, cybersourceFlexPreparationUrl, cybersourceFlexRefusalCode, cybersourceFlexTemplateKid, detectCardTypes, isCybersourceFlexMediaType, isCybersourceFlexRequest, isCybersourceFlexTemplateBody, isCybersourceFlexTokenShape, isPreparedCybersourceFlexRequest, isVerifiedCaptureContext, parseMicroformFragment, parseUnifiedCheckoutFrame, sameCybersourceFlexPreparation, sealForContext, transientTokenFacts, transientTokenSigned, unifiedCheckoutHostEnvironment, verifyCaptureContext, verifyUnifiedCheckoutContext };