@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
package/dist/sbps.js ADDED
@@ -0,0 +1,90 @@
1
+ // SB Payment Service (SBPS): the adapters' side of its one-time token request.
2
+ //
3
+ // SBPS's token script (com_sbps_system_token.js) encrypts the card in the merchant's page and sends it
4
+ // as ONE JSONP <script> GET to /token/generateToken on token.sps-system.com (stbtoken.sps-system.com
5
+ // for SBPS's test environment); the answer is JavaScript that calls the request's own callback with
6
+ // {"tokenRes": {...}}. The rules that judge that request (the exact URL the browser writes for the
7
+ // script's <script>, the merchant pins, the answer judge) live in payment-core and reach this SDK as
8
+ // sbps.generated.ts. This module holds only what an attachment decides from them:
9
+ // - which request on SBPS's token hosts is the card token request to pause for the vault;
10
+ // - which is a variant of it this SDK does not complete (aborted, so the placeholder's ciphertext
11
+ // never reaches SBPS);
12
+ // - the script answer the paused request gets once the cardholder's device sent the real card: the
13
+ // token Agentcard stored, wrapped in the callback the paused URL named.
14
+ // The 3-D Secure info request on the same host (/token/generateTds2Token: the buyer's name, phone and
15
+ // email, no card) and the scripts continue untouched.
16
+ import { SBPS_ANSWER_CONTENT_TYPE, SBPS_TOKEN_HOSTS, SBPS_TOKEN_PATH, isSbpsRequest, isSbpsTokenRequest, sbpsJsonp, sbpsOutcome, sbpsRequestFacts } from './sbps.generated.js';
17
+ /** The processor id, as the registry and the API name it. */
18
+ export const SBPS_PSP = 'sb_payment_service';
19
+ /** The dark-launch capability the API serves the SBPS recognizer behind (payment-core definitions.js). */
20
+ export const SBPS_CAPABILITY = 'sbps_token_jsonp';
21
+ /** What the paused <script> is answered with. */
22
+ export { SBPS_ANSWER_CONTENT_TYPE };
23
+ const SBPS_HOSTNAMES = [SBPS_TOKEN_HOSTS.production, SBPS_TOKEN_HOSTS.sandbox];
24
+ /** Which SBPS request this is, or null for a URL that is not on one of SBPS's token hosts. */
25
+ export function classifySbpsRequest(url, method) {
26
+ let parsed;
27
+ try {
28
+ parsed = new URL(url);
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ if (parsed.protocol !== 'https:' || parsed.port || parsed.username || parsed.password
34
+ || !SBPS_HOSTNAMES.includes(parsed.hostname.toLowerCase().replace(/\.$/, '')))
35
+ return null;
36
+ // Every spelling of the token path belongs to the token request family: the exact request carries the
37
+ // card, and any neighbour of it is nothing this SDK completes. generateTds2Token is not a neighbour.
38
+ if (parsed.pathname.toLowerCase().startsWith(SBPS_TOKEN_PATH.toLowerCase())) {
39
+ return typeof method === 'string' && isSbpsTokenRequest(url, method.toUpperCase()) ? { kind: 'token_request' } : { kind: 'unsupported' };
40
+ }
41
+ return { kind: 'sibling' };
42
+ }
43
+ /** The token request GET exactly as payment-core admits it: its URL alone, with no body. */
44
+ export function isSbpsTokenGet(request) {
45
+ return (request.method ?? 'POST').toUpperCase() === 'GET' && isSbpsRequest({ url: request.url, method: 'GET', body: request.body ?? '' });
46
+ }
47
+ /**
48
+ * The answer a paused token request gets, or null when the stored answer is not one to hand the page:
49
+ * SBPS's own shape, `<callback>(<tokenRes>)` under a script type, with the callback the paused URL
50
+ * named. The answer must be one payment-core's judge accepts for that exact URL (result OK and the
51
+ * five token fields), byte for byte what the API stored after running the same judge.
52
+ */
53
+ export function sbpsScriptAnswer(templateUrl, response) {
54
+ const facts = sbpsRequestFacts(templateUrl);
55
+ if (!facts || response.status !== 200 || typeof response.body !== 'string')
56
+ return null;
57
+ let body;
58
+ try {
59
+ body = sbpsJsonp(facts.callback, response.body);
60
+ }
61
+ catch {
62
+ return null;
63
+ }
64
+ const verdict = sbpsOutcome(200, body, templateUrl, undefined);
65
+ if (verdict.outcome !== 'token' || verdict.sanitizedJson !== response.body)
66
+ return null;
67
+ return { status: 200, headers: { 'content-type': SBPS_ANSWER_CONTENT_TYPE }, body };
68
+ }
69
+ /**
70
+ * One attachment's view of SBPS's token hosts. Inert (classify returns null) until the registry serves
71
+ * SBPS, which a client reaches only by syncing with the capability for an org the API enabled, so a
72
+ * build, an org or an API that never served it leaves every SBPS request exactly as before.
73
+ */
74
+ export class SbpsGate {
75
+ vault;
76
+ constructor(vault) {
77
+ this.vault = vault;
78
+ }
79
+ /** What this request is, when the registry serves SBPS and the URL is on its token hosts; null leaves it to the other gates. */
80
+ classify(url, method) {
81
+ if (typeof this.vault?.recognizesProcessor !== 'function' || !this.vault.recognizesProcessor(SBPS_PSP))
82
+ return null;
83
+ return classifySbpsRequest(url, method);
84
+ }
85
+ /** Playwright's route predicate sees only the URL: route the token request family, never the scripts or the 3-D Secure info request. */
86
+ matches(url) {
87
+ const request = this.classify(url, 'GET');
88
+ return request !== null && request.kind !== 'sibling';
89
+ }
90
+ }
@@ -1,6 +1,6 @@
1
1
  // @ts-nocheck
2
2
  // Generated from @agent-cards/payment-core. Do not edit.
3
- // artifact-sha256: 360d9805357acc5244c3beafbb16a6da782e933b506db49c2d63df06ac23f7b4
3
+ // artifact-sha256: 4c352f016f43f7758a725419b405e045be30972b855e6400ae2dd3823c5265ab
4
4
  // src/deep-freeze.js
5
5
  function deepFreeze(value) {
6
6
  if (value && typeof value === "object" && !Object.isFrozen(value)) {
@@ -10,6 +10,158 @@ function deepFreeze(value) {
10
10
  }
11
11
  return value;
12
12
  }
13
+ // src/registration.js
14
+ var PARTS = { psp: "id", definitions: "list", refusedOperations: "list", settlementReadback: "any", exactUrl: "rule", bodyGate: "rule", amount: "rule" };
15
+ var PSP_ID = /^[a-z][a-z0-9_]*$/;
16
+ var registrationProblems = (spec) => problemsOf(spec, PARTS);
17
+ function problemsOf(spec, parts) {
18
+ if (!spec || typeof spec !== "object")
19
+ return ["a registration is an object"];
20
+ const psp = spec.psp;
21
+ if (typeof psp !== "string" || !PSP_ID.test(psp))
22
+ return [`${JSON.stringify(psp)} is not a processor id`];
23
+ const problems2 = Object.keys(spec).filter((key) => !(key in parts)).map((key) => `${psp}: ${key} is no registration part`);
24
+ for (const [key, kind] of Object.entries(parts)) {
25
+ const value = spec[key];
26
+ if (value === void 0)
27
+ continue;
28
+ if (kind === "rule" && typeof value !== "function")
29
+ problems2.push(`${psp}: ${key} is not a function`);
30
+ if (kind === "numbers" && !((Array.isArray(value) || value instanceof Set) && [...value].every((n) => typeof n === "string" && /^\d{12,19}$/.test(n)))) {
31
+ problems2.push(`${psp}: ${key} is not a list of card numbers`);
32
+ }
33
+ }
34
+ if ("definitions" in parts) {
35
+ if (!Array.isArray(spec.definitions) || spec.definitions.length === 0)
36
+ problems2.push(`${psp}: names no definition`);
37
+ else if (spec.definitions.some((definition) => definition?.psp !== psp))
38
+ problems2.push(`${psp}: a definition names another processor`);
39
+ for (const id of spec.refusedOperations ?? []) {
40
+ if (typeof id !== "string" || !id.startsWith(`${psp}.`))
41
+ problems2.push(`${psp}: ${JSON.stringify(id)} is not one of its operations`);
42
+ }
43
+ }
44
+ return problems2;
45
+ }
46
+ function registered(spec, parts) {
47
+ const problems2 = problemsOf(spec, parts);
48
+ if (problems2.length)
49
+ throw new Error(`payment-core registration refused: ${problems2.join("; ")}`);
50
+ return deepFreeze({ ...spec });
51
+ }
52
+ function registerProcessor(spec) {
53
+ return registered(spec, PARTS);
54
+ }
55
+ // src/processors/midtrans.js
56
+ var MIDTRANS_PSP = "midtrans";
57
+ var MIDTRANS_OPERATION = "midtrans.card_request";
58
+ var MIDTRANS_TOKEN_URL = "https://api.midtrans.com/v2/token";
59
+ var MIDTRANS_SANDBOX_TOKEN_URL = "https://api.sandbox.midtrans.com/v2/token";
60
+ var MIDTRANS_TOKEN_KEYS = /* @__PURE__ */ Object.freeze(["card_cvv", "card_number", "card_exp_month", "card_exp_year", "installment_term"]);
61
+ var BODY_LIMIT = 4096;
62
+ var CARD_NUMBER = /^[0-9]{12,19}$/;
63
+ var SECURITY_CODE = /^[0-9]{3,4}$/;
64
+ var MONTH = /^(?:0[1-9]|1[0-2])$/;
65
+ var YEAR = /^20[0-9]{2}$/;
66
+ var TERM = /^[0-9]{1,3}$/;
67
+ var record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
68
+ var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
69
+ var inOrder = (value, keys) => {
70
+ let at = 0;
71
+ for (const name of Object.keys(value)) {
72
+ while (at < keys.length && keys[at] !== name)
73
+ at += 1;
74
+ if (at === keys.length)
75
+ return false;
76
+ at += 1;
77
+ }
78
+ return true;
79
+ };
80
+ var refuse = (code) => Object.freeze({ verdict: "refuse", code });
81
+ var CARD = /* @__PURE__ */ Object.freeze({ verdict: "card" });
82
+ function isMidtransTokenUrl(url) {
83
+ return url === MIDTRANS_TOKEN_URL || url === MIDTRANS_SANDBOX_TOKEN_URL;
84
+ }
85
+ function readBody(body) {
86
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT)
87
+ return null;
88
+ let value;
89
+ try {
90
+ value = JSON.parse(body);
91
+ if (!record(value) || JSON.stringify(value) !== body)
92
+ return null;
93
+ }
94
+ catch {
95
+ return null;
96
+ }
97
+ return value;
98
+ }
99
+ function midtransBodyVerdict(body) {
100
+ const value = readBody(body);
101
+ if (value === null || !inOrder(value, MIDTRANS_TOKEN_KEYS)) {
102
+ if (record(value) && (own(value, "token_id") || own(value, "two_click")) && !own(value, "card_number"))
103
+ return refuse("midtrans_saved_card");
104
+ return refuse("midtrans_body_unsupported");
105
+ }
106
+ if (!own(value, "card_cvv") || !own(value, "card_number") || !own(value, "card_exp_month") || !own(value, "card_exp_year")) {
107
+ return refuse("midtrans_body_unsupported");
108
+ }
109
+ if (typeof value.card_cvv !== "string" || !SECURITY_CODE.test(value.card_cvv) || typeof value.card_number !== "string" || !CARD_NUMBER.test(value.card_number) || typeof value.card_exp_month !== "string" || !MONTH.test(value.card_exp_month) || typeof value.card_exp_year !== "string" || !YEAR.test(value.card_exp_year))
110
+ return refuse("midtrans_body_unsupported");
111
+ if (own(value, "installment_term") && (typeof value.installment_term !== "string" || !TERM.test(value.installment_term)))
112
+ return refuse("midtrans_body_unsupported");
113
+ return CARD;
114
+ }
115
+ var midtrans_default = /* @__PURE__ */ registerProcessor({
116
+ psp: MIDTRANS_PSP,
117
+ definitions: [
118
+ {
119
+ psp: "midtrans",
120
+ // Snap's token request, as the header above reads it. Sandbox has its own host, so the device sends a
121
+ // test-mode request only Midtrans' documented test cards (hostEnvironmentPinned, device-replay.js S7).
122
+ // Ships dark: served only to a client that declares `midtrans_card_token`, gated off for every org until an
123
+ // operator lists one (`midtrans:<org>`), and the backend's gate serves only Agentcard's own company until the
124
+ // token's publishable key is bound to the merchant (backend config.ts MIDTRANS_KEY_BOUND_TO_MERCHANT).
125
+ capability: "midtrans_card_token",
126
+ match: "api\\.(?:sandbox\\.)?midtrans\\.com/v2/token",
127
+ hosts: ["^api\\.midtrans\\.com$", "^api\\.sandbox\\.midtrans\\.com$"],
128
+ sandboxHosts: ["^api\\.sandbox\\.midtrans\\.com$"],
129
+ hostEnvironmentPinned: true,
130
+ encoding: "json",
131
+ // Snap's own headers: the publishable client key (Authorization Basic) and X-Service. Origin, Referer and
132
+ // cookies never ride.
133
+ passthroughHeaders: ["^authorization$", "^x-service$"],
134
+ jsonCardFields: [["card_number"]]
135
+ }
136
+ ],
137
+ // Only the cardholder's device sends a token, after a person approves; no reviewed list names midtrans.
138
+ refusedOperations: [MIDTRANS_OPERATION],
139
+ // Not surveyed: the token moves no money, and the merchant's own charge names its status by the order id alone.
140
+ settlementReadback: "not_surveyed",
141
+ exactUrl: isMidtransTokenUrl,
142
+ bodyGate: (url, body) => url !== void 0 && !isMidtransTokenUrl(url) ? { verdict: "refuse", code: "midtrans_url_refused" } : midtransBodyVerdict(body)
143
+ });
144
+ // src/processors/index.generated.js
145
+ var REGISTERED_MODULES = Object.freeze({
146
+ midtrans: midtrans_default
147
+ });
148
+ // src/registry.js
149
+ var REGISTERED_PROCESSORS = Object.values(REGISTERED_MODULES);
150
+ var ids = REGISTERED_PROCESSORS.map((processor) => processor.psp);
151
+ var problems = REGISTERED_PROCESSORS.flatMap(registrationProblems);
152
+ for (const [name, processor] of Object.entries(REGISTERED_MODULES)) {
153
+ if (processor.psp !== name)
154
+ problems.push(`processors/${name}.js registers ${JSON.stringify(processor.psp)}`);
155
+ }
156
+ if (ids.some((id, i) => i > 0 && ids[i - 1] >= id))
157
+ problems.push(`registered processors out of id order: ${ids.join(", ")}`);
158
+ if (problems.length)
159
+ throw new Error(`payment-core registry refused: ${problems.join("; ")}`);
160
+ var BY_PSP = new Map(REGISTERED_PROCESSORS.map((processor) => [processor.psp, processor]));
161
+ var REGISTERED_IDS = Object.freeze(ids);
162
+ var REGISTERED_DEFINITIONS = Object.freeze(REGISTERED_PROCESSORS.flatMap((processor) => processor.definitions));
163
+ var REGISTERED_REFUSED_OPERATIONS = Object.freeze(REGISTERED_PROCESSORS.flatMap((processor) => processor.refusedOperations ?? []));
164
+ var REGISTERED_SETTLEMENT_READBACK = Object.freeze(REGISTERED_PROCESSORS.filter((processor) => processor.settlementReadback !== void 0).map((processor) => [processor.psp, processor.settlementReadback]));
13
165
  // src/definitions.js
14
166
  var PROCESSOR_DEFINITIONS = deepFreeze([
15
167
  {
@@ -563,8 +715,9 @@ var PROCESSOR_DEFINITIONS = deepFreeze([
563
715
  // posts the card there in that same session, and the runtime resolves the paused navigation with the
564
716
  // hosted_form notice. Only the entry path is matched, exactly (processors/paytrail.js isPaytrailEntryUrl:
565
717
  // a query would reach Paytrail's server beside the signed body). The card page and its card, wallet and
566
- // card-number lookups live on Payment Highway's host, which no recognizer takes; the SDK's pause, a later
567
- // change, refuses them in the agent's browser, so no dummy card reaches Payment Highway. The entry names no amount: Paytrail
718
+ // card-number lookups live on Payment Highway's host, which no recognizer takes: it is an abort host, armed in
719
+ // the SDK's adapters so the SDK's Paytrail gate refuses every card request the agent's browser sends there,
720
+ // and no dummy card reaches Payment Highway. The entry names no amount: Paytrail
568
721
  // holds it, so the cardholder approves the agent's amount and the device holds it to the amount the card
569
722
  // page names. Paytrail's public test merchant shares this host, so the host marks no environment. Dark:
570
723
  // served only to a client that declares the capability, and gated off for every org the operator has not
@@ -572,6 +725,9 @@ var PROCESSOR_DEFINITIONS = deepFreeze([
572
725
  capability: "paytrail_hosted_payment_page",
573
726
  match: "services\\.paytrail\\.com/payments/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/click-to-pay/loading-and-redirect",
574
727
  hosts: ["^services\\.paytrail\\.com$"],
728
+ // Payment Highway's live host (processors/paytrail.js PAYMENT_HIGHWAY_HOSTS), which no recognizer takes: an SDK that
729
+ // declares the capability arms it so its gate can refuse the card posts the agent's browser sends there.
730
+ abortHosts: ["^v1\\.api\\.paymenthighway\\.io$"],
575
731
  encoding: "form",
576
732
  passthroughHeaders: [],
577
733
  mode: "hosted_form",
@@ -2752,7 +2908,127 @@ var PROCESSOR_DEFINITIONS = deepFreeze([
2752
2908
  // Referer and cookies never ride.
2753
2909
  passthroughHeaders: ["^authorization$", "^client-type$", "^client-version$", "^client-id$"],
2754
2910
  jsonCardFields: [["card_data", "account_number"]]
2755
- }
2911
+ },
2912
+ {
2913
+ psp: "sb_payment_service",
2914
+ // SB Payment Service (SBPS), SoftBank's card gateway: its one-time token script on the merchant's
2915
+ // page (com_sbps_system_token.js) encrypts the card in the page and sends it as ONE JSONP <script>
2916
+ // GET to /token/generateToken on token.sps-system.com (stbtoken.sps-system.com for SBPS's test
2917
+ // environment), the card in the query: val is AES-256-CBC of "number:YYYYMM:code" under a PBKDF2 key
2918
+ // over the merchant and service ids, and key is the salt and iv RSA-wrapped under SBPS's key in the
2919
+ // script. sbps.js holds the request rule the pause decision, the API's create and the device all
2920
+ // read: the exact URL the browser writes for the script's <script>, so the 3-D Secure info request
2921
+ // on the same host (/token/generateTds2Token, the buyer's details and no card) is never recognized.
2922
+ // Nothing can be written into the paused ciphertext: the cardholder's device rebuilds key and val
2923
+ // with the real card under the key payment-core pins, and sends the GET through the checkout relay,
2924
+ // since the host answers no browser origin and answers with JavaScript.
2925
+ // Ships dark: served only to a client that declares `sbps_token_jsonp`, gated off for every org until
2926
+ // an operator lists one (`sb_payment_service:<org>`), held to the merchants sbps.js pins per checkout
2927
+ // origin, and autopilot never sends this request (autopilot.js DEVICE_REPLAY_REFUSED_OPERATIONS). The
2928
+ // environment is pinned (S7): stbtoken only on test rows and only with documented test cards.
2929
+ capability: "sbps_token_jsonp",
2930
+ // The path has a right-edge guard for the SDK's unanchored test.
2931
+ match: "(?:stb)?token\\.sps-system\\.com/token/generateToken(?![\\w/.-])",
2932
+ hosts: ["^token\\.sps-system\\.com$", "^stbtoken\\.sps-system\\.com$"],
2933
+ sandboxHosts: ["^stbtoken\\.sps-system\\.com$"],
2934
+ hostEnvironmentPinned: true,
2935
+ // `encoding` describes the query, since the request has no body. No captured header is ever
2936
+ // replayed, and the card rides in the query of one GET whose answer is JSONP.
2937
+ encoding: "form",
2938
+ passthroughHeaders: [],
2939
+ request: { method: "GET", cardIn: "query", response: "jsonp" }
2940
+ },
2941
+ {
2942
+ psp: "tappay",
2943
+ // TapPay (Cherri Tech, Taiwan): TapPay Fields, the card iframes every TPDirect integration mounts from
2944
+ // js.tappaysdk.com (confirmed live 2026-10-17). TPDirect.card.getPrime makes TapPay's own api iframe
2945
+ // (js.tappaysdk.com/sdk/tpdirect/api/html/<version>) read the three field iframes and POST one request:
2946
+ // POST https://js.tappaysdk.com/payment/tpdirect/production/getprime
2947
+ // Content-Type: application/x-www-form-urlencoded, x-api-key: <the merchant's TapPay app key>
2948
+ // jsonString={"cardnumber":...,"cardduedate":"<YYYYMM>","appid":...,"appkey":...,"appname":...,
2949
+ // "url":...,"port":...,"protocol":...,"tappay_sdk_version":...,"cardholder_info":{...}[,"cardccv":...][,"device_id":...]}
2950
+ // The one form field jsonString holds the whole card request as the SDK's JSON.stringify. tappay.js
2951
+ // holds the request rule, the pause decision, the device fill and the answer judge; the card sits at
2952
+ // cardnumber, cardduedate (TapPay's "20"+YY+MM, so YYYYMM) and the optional cardccv. The request names no
2953
+ // amount and mints a prime (one-time token, 90-second TTL) the merchant's server charges with Pay by
2954
+ // Prime, where 3-D Secure runs (three_domain_secure), never in this request. The api iframe posts same
2955
+ // origin, so a replay from the Vault's origin is cross-origin and its x-api-key preflight is refused
2956
+ // (OPTIONS to getprime drew 403 with no Access-Control-Allow-Origin, 2026-10-17), so the card leaves the
2957
+ // cardholder's device only through the checkout relay, and tappayAnswerOutcome judges the answer, since
2958
+ // TapPay reports a refusal inside HTTP 200 with a non-zero status. One host serves every merchant, so a
2959
+ // live card is tokenized only for a checkout origin a reviewed pin lists (tappay.js tappayMerchantRefusal)
2960
+ // and the approval names that merchant. TapPay's sandbox is the same host with the /sandbox/ path and so
2961
+ // cannot be told from production by host (hostEnvironment is host based): this lane recognizes production
2962
+ // only, as Wix Payments does, and a sandbox test run is a later change.
2963
+ // Ships dark: served only to a client that declares `tappay_prime`, gated off for every org until an
2964
+ // operator lists one (`tappay:<org>`), and autopilot never sends this request (autopilot.js
2965
+ // DEVICE_REPLAY_REFUSED_OPERATIONS).
2966
+ capability: "tappay_prime",
2967
+ match: "js\\.tappaysdk\\.com/payment/tpdirect/production/getprime",
2968
+ hosts: ["^js\\.tappaysdk\\.com$"],
2969
+ encoding: "form",
2970
+ passthroughHeaders: ["^x-api-key$"]
2971
+ },
2972
+ {
2973
+ psp: "paymob",
2974
+ // Paymob's own checkout (Egypt, the UAE, Saudi Arabia, Oman): Unified Checkout, the hosted page every
2975
+ // Paymob payment link, PayMe handle, WooCommerce plugin and Shopify redirect app opens, and Pixel, the
2976
+ // card frame a merchant's own page embeds. Pay sends the card in one JSON POST to the Paymob API of the
2977
+ // merchant's country, /api/acceptance/payments/pay on accept., uae., ksa. or oman.paymob.com (and
2978
+ // accept.paymobsolutions.com, Paymob Egypt's older name for the same API): {source: {identifier,
2979
+ // sourceholder_name, subtype: "CARD", expiry_month, expiry_year, cvn, ...}, payment_token, ...}.
2980
+ // Unencrypted. The request names no amount of its own: its payment key, Paymob's signed JWT for the
2981
+ // merchant's intention, names the amount and currency Paymob charges. paymob.js holds the rule the
2982
+ // pause decision reads: the exact URL, a JSON content type, and the card form's payment, key by key,
2983
+ // with a saved Paymob card, a payment that keeps the card, pays in installments, splits, converts or
2984
+ // names a Paymob account, and any other card shape refused. Every other method of the checkout
2985
+ // (wallets, Apple Pay, Google Pay, KNET, valU, cash) carries no card on the same URL and continues
2986
+ // untouched (passWithoutCard). The API answers any origin's preflight, so the cardholder's device
2987
+ // sends the card itself; no header is needed beside the content type. 3-D Secure follows the answer,
2988
+ // with no card. Test and live modes share the hosts (test keys and integrations separate them), so no
2989
+ // sandbox host is marked.
2990
+ // Ships dark: served only to a client that declares `paymob_checkout_pay`, gated off for every org
2991
+ // until an operator lists one (`paymob:<org>`), and autopilot never sends this request
2992
+ // (autopilot.js DEVICE_REPLAY_REFUSED_OPERATIONS).
2993
+ capability: "paymob_checkout_pay",
2994
+ match: "(?:accept|uae|ksa|oman)\\.paymob\\.com/api/acceptance/payments/pay|accept\\.paymobsolutions\\.com/api/acceptance/payments/pay",
2995
+ hosts: ["^accept\\.paymob\\.com$", "^uae\\.paymob\\.com$", "^ksa\\.paymob\\.com$", "^oman\\.paymob\\.com$", "^accept\\.paymobsolutions\\.com$"],
2996
+ encoding: "json",
2997
+ passthroughHeaders: [],
2998
+ jsonCardFields: [["source", "identifier"]],
2999
+ passWithoutCard: "(?:accept|uae|ksa|oman)\\.paymob\\.com/api/acceptance/payments/pay|accept\\.paymobsolutions\\.com/api/acceptance/payments/pay"
3000
+ },
3001
+ {
3002
+ psp: "payu_latam",
3003
+ // PayU Latam's WebCheckout (Colombia, Mexico, Chile, Peru, Panama), the hosted page a PayU Latam
3004
+ // merchant's payment form, button, link or cart plugin opens at checkout.payulatam.com. Its card form
3005
+ // posts the whole checkout transaction as JSON to /ppp-web-gateway-payu/checkout/submit/<country>
3006
+ // /credit_card/<session key> on the page's own host, the card in checkoutCreditCard: the number as the
3007
+ // field's mask spells it, the code, and the month and two-digit year as numbers. The body copies the
3008
+ // order PayU holds for the session, but PayU charges its own, so the amount is the agent's (no request
3009
+ // amount in backend.js). payu-latam.js holds the rule the
3010
+ // pause decision reads: the exact URL with a country this lane read, and the card form's own body, with
3011
+ // the box that has PayU keep the card, a card PayU saved, a wallet, installments and a test order on
3012
+ // the live host refused. The page's BIN lookup (checkout/card_info/) and its 3-D Secure redirect use
3013
+ // other paths, which `match` leaves out; `(?![\w/;.%-])` ends the key for a consumer that tests `match`
3014
+ // unanchored. The submit answers a CORS preflight from any origin, so the cardholder's device can send
3015
+ // the card itself. Ships dark: served only to a client that declares
3016
+ // `payu_latam_webcheckout_card`, gated off for every org until an operator lists one
3017
+ // (`payu_latam:<org>`), and autopilot never sends this request (autopilot.js
3018
+ // DEVICE_REPLAY_REFUSED_OPERATIONS). The environment is pinned (S7): sandbox.checkout.payulatam.com
3019
+ // only on test rows and only with documented test cards.
3020
+ capability: "payu_latam_webcheckout_card",
3021
+ match: "(?:sandbox\\.)?checkout\\.payulatam\\.com/ppp-web-gateway-payu/checkout/submit/(?:ar|br|cl|co|mx|pa|pe)/credit_card/[0-9a-f]{32}(?![\\w/;.%-])",
3022
+ hosts: ["^checkout\\.payulatam\\.com$", "^sandbox\\.checkout\\.payulatam\\.com$"],
3023
+ sandboxHosts: ["^sandbox\\.checkout\\.payulatam\\.com$"],
3024
+ hostEnvironmentPinned: true,
3025
+ encoding: "json",
3026
+ // AngularJS's Accept, which the page sends on every $http call. Cookies, Origin and Referer never ride.
3027
+ passthroughHeaders: ["^accept$"],
3028
+ jsonCardFields: [["checkoutCreditCard", "number"]]
3029
+ },
3030
+ // Every processor registered since this list froze, in id order (registry.js).
3031
+ ...REGISTERED_DEFINITIONS
2756
3032
  ]);
2757
3033
  var PSP_RECOGNIZERS = deepFreeze(PROCESSOR_DEFINITIONS.map(({ compose, encryptedCardFields, deviceSteps, deviceEncrypt, ...definition }) => definition));
2758
3034
  var PSP_CLIENT_TABLE = deepFreeze(PROCESSOR_DEFINITIONS.map((definition) => ({
@@ -2992,7 +3268,7 @@ var HIPAY_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
2992
3268
  pin6({ id: "happybulle", merchant: "HappyBulle", origins: ["https://www.happybulle.com"], usernames: ["94683309.secure-gateway.hipay-tpp.com"] })
2993
3269
  ]);
2994
3270
  // src/amazon-payment-services.js
2995
- var BODY_LIMIT = 32 * 1024;
3271
+ var BODY_LIMIT2 = 32 * 1024;
2996
3272
  var ANSWER_LIMIT = 64 * 1024;
2997
3273
  // src/clover.js
2998
3274
  var REQUIRED_KEYS = /* @__PURE__ */ Object.freeze(["encrypted_pan", "exp_month", "exp_year", "cvv", "first6", "last4", "brand"]);
@@ -3204,7 +3480,8 @@ var CARDCOM_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
3204
3480
  var TOAST_SUBSTITUTION = /* @__PURE__ */ Object.freeze({ at: "card", fields: Object.freeze(["cardData"]) });
3205
3481
  // src/fastspring.js
3206
3482
  var FASTSPRING_STORE_PINS = /* @__PURE__ */ Object.freeze([
3207
- Object.freeze({ environment: "production", store: "daisydisk", storefront: "", merchant: "DaisyDisk" })
3483
+ Object.freeze({ environment: "production", store: "daisydisk", storefront: "", merchant: "DaisyDisk" }),
3484
+ Object.freeze({ environment: "production", store: "stardock", storefront: "/popup-store", merchant: "Stardock" })
3208
3485
  ]);
3209
3486
  var STORE = "[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?";
3210
3487
  var CARD_URL = new RegExp(`^https://(${STORE})(\\.test)?\\.onfastspring\\.com((?:/(?:popup|embedded)-[A-Za-z0-9_-]{1,64})?)/session/([A-Za-z0-9_-]{16,64})/payment$`);
@@ -3215,6 +3492,159 @@ var OMISE_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
3215
3492
  pin10({ id: "socialgiver", merchant: "Socialgiver", origins: ["https://www.socialgiver.com"], keys: ["pkey_5d5o2iahksmyrkybemg"] }),
3216
3493
  pin10({ id: "thireq_pecko_links", merchant: "Thireq Pecko", origins: ["https://linksplus.omise.co"], keys: ["pkey_65w70xniwsinf0gm680"] })
3217
3494
  ]);
3495
+ // src/payu-latam.js
3496
+ var PAYU_LATAM_HOSTS = /* @__PURE__ */ Object.freeze({
3497
+ production: Object.freeze(["checkout.payulatam.com"]),
3498
+ sandbox: Object.freeze(["sandbox.checkout.payulatam.com"])
3499
+ });
3500
+ var ADDRESS = ["street1", "street2", "street3", "city", "state", "country", "postalCode", "phone"];
3501
+ var PERSON = [
3502
+ "fullName",
3503
+ "emailAddress",
3504
+ "contactPhone",
3505
+ "phoneCountryCode",
3506
+ "dniNumber",
3507
+ "isDniNumberEncrypt",
3508
+ "dniType",
3509
+ "personType",
3510
+ "businessName",
3511
+ "cnpj",
3512
+ "gender"
3513
+ ];
3514
+ var MONEY = ["value", "symbol", "currency"];
3515
+ var RECORD_MEMBERS = /* @__PURE__ */ Object.freeze({
3516
+ payer: [...PERSON, "merchantBuyerId", "billingAddress", "birthDate", "identificationNumber", "identificationType"],
3517
+ "payer.billingAddress": ADDRESS,
3518
+ order: [
3519
+ "id",
3520
+ "referenceCode",
3521
+ "airlineCode",
3522
+ "description",
3523
+ "isTest",
3524
+ "signature",
3525
+ "language",
3526
+ "buyer",
3527
+ "shipment",
3528
+ "state",
3529
+ "status",
3530
+ "paymentApprovalDate",
3531
+ "creationDate",
3532
+ "accountId",
3533
+ "amount",
3534
+ "tax",
3535
+ "totalPurchase",
3536
+ "currency",
3537
+ "amountConvertedValue",
3538
+ "taxConvertedValue",
3539
+ "taxReturnBase",
3540
+ "taxReturnBaseConvertedValue",
3541
+ "additionalValue",
3542
+ "administrativeFee",
3543
+ "taxAdministrativeFee",
3544
+ "taxAdministrativeFeeReturnBase",
3545
+ "enabledPaymentMethods",
3546
+ "enabledInstallments",
3547
+ "enabledPaymentMethodTypes",
3548
+ "enabledIin",
3549
+ "enabledPseBanks",
3550
+ "enabledKhipuBanks",
3551
+ "paymentMethodsDescription",
3552
+ "urlEncodedId",
3553
+ "shippingValue",
3554
+ "paymentRequestLinkId",
3555
+ "airlineDescription",
3556
+ "displayShipping",
3557
+ "displayBuyerComments",
3558
+ "buyerCommentsLabel",
3559
+ "extraParameters",
3560
+ "dispersion"
3561
+ ],
3562
+ "order.buyer": [...PERSON, "merchantBuyerId", "buyerAddress", "comments"],
3563
+ "order.buyer.buyerAddress": ADDRESS,
3564
+ "order.shipment": [...PERSON, "merchantShipmentId", "shippingAddress", "comments"],
3565
+ "order.shipment.shippingAddress": ADDRESS,
3566
+ "order.amount": MONEY,
3567
+ "order.tax": MONEY,
3568
+ "order.totalPurchase": MONEY,
3569
+ "order.amountConvertedValue": MONEY,
3570
+ "order.taxConvertedValue": MONEY,
3571
+ "order.taxReturnBase": MONEY,
3572
+ "order.taxReturnBaseConvertedValue": MONEY,
3573
+ shippingInfo: [
3574
+ "userLogin",
3575
+ "id",
3576
+ "reference",
3577
+ "description",
3578
+ "currency",
3579
+ "deliveryCity",
3580
+ "deliveryCityName",
3581
+ "deliveryAddress1",
3582
+ "deliveryAddress2",
3583
+ "deliveryAddress3",
3584
+ "postalCode",
3585
+ "fullName",
3586
+ "documentType",
3587
+ "document",
3588
+ "phoneNumber",
3589
+ "observationsReceivingShipment",
3590
+ "destinationState",
3591
+ "destinationStateName",
3592
+ "destinationCountry",
3593
+ "destinationEmail",
3594
+ "originFullName",
3595
+ "originIdentificationType",
3596
+ "originIdentification",
3597
+ "originCity",
3598
+ "originState",
3599
+ "originCountry",
3600
+ "originAddress",
3601
+ "originZipCode",
3602
+ "originPhone",
3603
+ "originEmail",
3604
+ "kilogramWeight",
3605
+ "volumetricWeight",
3606
+ "totalValue",
3607
+ "declaredValue",
3608
+ "shippingValue",
3609
+ "guideNumber",
3610
+ "enlistmentApplies",
3611
+ "deliveryDate",
3612
+ "deliveryDays",
3613
+ "minDeliveryDays",
3614
+ "packageHeight",
3615
+ "packageWidth",
3616
+ "packageLength",
3617
+ "shippingProvider",
3618
+ "shippingState",
3619
+ "creationDate",
3620
+ "lastUpdateDate",
3621
+ "expirationDate",
3622
+ "signature",
3623
+ "strCreationDate",
3624
+ "comment",
3625
+ "warehouseId",
3626
+ "additionalDeliveryDays",
3627
+ "shippingMerchantValue"
3628
+ ],
3629
+ // PayU's own ten, as transaction/create names them, and the merchant's extra1 to extra4 (the payment form's
3630
+ // optional fields), each text or nothing.
3631
+ "order.extraParameters": [
3632
+ "CURRENCY",
3633
+ "LANGUAGE",
3634
+ "ACCOUNT_ID",
3635
+ "ALGORITHM_SIGNATURE",
3636
+ "CHECKOUT_VERSION",
3637
+ "RESPONSE_URL",
3638
+ "IS_TEST",
3639
+ "SIGNATURE",
3640
+ "NOTIFY_URL",
3641
+ "IP_COUNTRY",
3642
+ "EXTRA1",
3643
+ "EXTRA2",
3644
+ "EXTRA3",
3645
+ "EXTRA4"
3646
+ ]
3647
+ });
3218
3648
  // src/cybersource-secure-acceptance.js
3219
3649
  var SA_BODY_LIMIT = 32 * 1024;
3220
3650
  var SA_REPLY_LIMIT = 64 * 1024;
@@ -3550,7 +3980,8 @@ var TRANSBANK_MERCHANTS = Object.freeze([
3550
3980
  fantasyName: null,
3551
3981
  merchant: "Teleférico Santiago",
3552
3982
  hosts: Object.freeze(["telefericosantiago.cl"]),
3553
- returnHost: "telefericosantiago.cl"
3983
+ returnHost: "telefericosantiago.cl",
3984
+ returnUrl: null
3554
3985
  })
3555
3986
  ]);
3556
3987
  var MAX_PAGE5 = 64 * 1024;
@@ -3568,7 +3999,9 @@ var PAYTRAIL_ENTRY_FIELDS = Object.freeze([
3568
3999
  "checkout-nonce",
3569
4000
  "signature"
3570
4001
  ]);
3571
- var PAYTRAIL_MERCHANTS = Object.freeze([]);
4002
+ var PAYTRAIL_MERCHANTS = Object.freeze([
4003
+ Object.freeze({ account: "1076015", merchant: "DofE Finland", paytrailName: "Avartti-säätiö", returnHost: "dofe.fi" })
4004
+ ]);
3572
4005
  var UUID_SOURCE = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
3573
4006
  var UUID2 = new RegExp(`^${UUID_SOURCE}$`);
3574
4007
  var ENTRY_PATH = new RegExp(`^/payments/(${UUID_SOURCE})/click-to-pay/loading-and-redirect$`);
@@ -3673,6 +4106,23 @@ var DECLINE_CODES = Object.freeze([
3673
4106
  "AccountSuspended"
3674
4107
  ]);
3675
4108
  var FRICTIONLESS_STATUSES = Object.freeze([0, 5, 7]);
4109
+ // src/sbps.js
4110
+ var pin11 = (fields) => /* @__PURE__ */ Object.freeze({
4111
+ ...fields,
4112
+ origins: Object.freeze([...fields.origins]),
4113
+ accounts: Object.freeze(fields.accounts.map((account) => Object.freeze({ ...account })))
4114
+ });
4115
+ var SBPS_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
4116
+ /* @__PURE__ */ pin11({
4117
+ id: "boss_ezo_fukuoka",
4118
+ merchant: `BOSS E${ /* @__PURE__ */String.fromCharCode(12539)}ZO FUKUOKA`,
4119
+ origins: ["https://ticket.e-zofukuoka.com"],
4120
+ accounts: [{ merchantId: "75082", serviceId: "001" }]
4121
+ })
4122
+ ]);
4123
+ var ERROR_TYPES = /* @__PURE__ */ Object.freeze(["03", "04", "05", "07", "99"]);
4124
+ var ERROR_FIELDS = /* @__PURE__ */ Object.freeze(["001", "002", "003", "004", "005", "999"]);
4125
+ var SBPS_REFUSAL_CODES = /* @__PURE__ */ Object.freeze(ERROR_TYPES.flatMap((type) => ERROR_FIELDS.map((field) => `${type}${field}`)));
3676
4126
  // src/recognition.js
3677
4127
  var PATTERN_WITHOUT_CARD_FIELDS = Object.freeze({
3678
4128
  stripe: "api\\.stripe\\.com/v1/(payment_methods|tokens|setup_intents/seti_\\w+/confirm|payment_intents/pi_\\w+/confirm)"