@agent-cards/sdk 0.23.27 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/PREFLIGHT.md +7 -1
  3. package/README.md +137 -99
  4. package/dist/aci.d.ts +52 -22
  5. package/dist/aci.js +79 -15
  6. package/dist/adyen-merchant-hosted.generated.d.ts +1 -1
  7. package/dist/adyen-merchant-hosted.generated.js +459 -21
  8. package/dist/agent-amount.generated.js +1 -1
  9. package/dist/agentcard.d.ts +4 -5
  10. package/dist/agentcard.js +4 -5
  11. package/dist/amadeus.d.ts +9 -3
  12. package/dist/amadeus.js +33 -4
  13. package/dist/api-module.d.ts +1 -7
  14. package/dist/api-module.js +3 -5
  15. package/dist/{voice-retry.js → api-retry.js} +1 -1
  16. package/dist/api-types.d.ts +53 -0
  17. package/dist/{voice-types.js → api-types.js} +7 -2
  18. package/dist/approvals.d.ts +166 -0
  19. package/dist/approvals.js +213 -0
  20. package/dist/buy.d.ts +20 -101
  21. package/dist/buy.js +19 -74
  22. package/dist/capabilities.generated.js +1 -1
  23. package/dist/card-fields.generated.js +1398 -106
  24. package/dist/cdp.d.ts +3 -13
  25. package/dist/cdp.js +231 -175
  26. package/dist/client.d.ts +104 -22
  27. package/dist/client.js +215 -40
  28. package/dist/creditguard.generated.d.ts +4 -4
  29. package/dist/datatrans.generated.js +22 -1
  30. package/dist/elavon-converge.generated.js +5 -3
  31. package/dist/hold.d.ts +8 -0
  32. package/dist/hold.js +43 -2
  33. package/dist/hosted-entry.js +2 -0
  34. package/dist/index.d.ts +9 -15
  35. package/dist/index.js +6 -10
  36. package/dist/juspay-gate.js +2 -2
  37. package/dist/juspay.generated.d.ts +2 -2
  38. package/dist/juspay.generated.js +174 -4
  39. package/dist/lifecycle.d.ts +9 -61
  40. package/dist/lifecycle.js +24 -10
  41. package/dist/merchant-card-endpoints.generated.d.ts +6 -1
  42. package/dist/merchant-card-endpoints.generated.js +344 -19
  43. package/dist/merchant-hosted.d.ts +8 -1
  44. package/dist/nike-order.d.ts +51 -0
  45. package/dist/nike-order.js +81 -0
  46. package/dist/oceanpayment.d.ts +38 -0
  47. package/dist/oceanpayment.js +70 -0
  48. package/dist/paddle-tokenex.generated.js +105 -10
  49. package/dist/payplug.d.ts +41 -0
  50. package/dist/payplug.js +71 -0
  51. package/dist/payrails.generated.js +27 -7
  52. package/dist/payrexx.generated.js +176 -2
  53. package/dist/pre-claim.d.ts +9 -0
  54. package/dist/pre-claim.js +86 -7
  55. package/dist/preflight-capabilities.generated.d.ts +0 -4
  56. package/dist/preflight-capabilities.generated.js +0 -5
  57. package/dist/preflight-catalog.json +46 -5
  58. package/dist/preflight-playwright.d.ts +2 -2
  59. package/dist/preflight-playwright.js +63 -14
  60. package/dist/preflight-schemas.json +4 -0
  61. package/dist/preflight.generated.d.ts +0 -4
  62. package/dist/preflight.generated.js +24 -1
  63. package/dist/prepared-processor.d.ts +18 -5
  64. package/dist/prepared-processor.js +48 -8
  65. package/dist/primer.generated.js +1418 -120
  66. package/dist/processout.generated.d.ts +61 -0
  67. package/dist/processout.generated.js +577 -0
  68. package/dist/requests.js +1 -1
  69. package/dist/shiji-sts.generated.js +105 -10
  70. package/dist/stripe-checkout.generated.js +1405 -234
  71. package/dist/substitutions.generated.js +460 -26
  72. package/dist/tap-payments.generated.js +105 -10
  73. package/dist/twoc2p.generated.js +105 -10
  74. package/dist/url-masks/bluesnap.d.ts +2 -0
  75. package/dist/url-masks/bluesnap.js +15 -0
  76. package/dist/url-masks/oceanpayment.d.ts +2 -0
  77. package/dist/url-masks/oceanpayment.js +13 -0
  78. package/dist/url-masks/payplug.d.ts +2 -0
  79. package/dist/url-masks/payplug.js +13 -0
  80. package/dist/url-masks/vtex_payments.d.ts +2 -0
  81. package/dist/url-masks/vtex_payments.js +12 -0
  82. package/dist/url-masks.generated.d.ts +1 -1
  83. package/dist/url-masks.generated.js +6 -2
  84. package/dist/verifone.generated.js +42 -2
  85. package/dist/vtex-payments.generated.d.ts +127 -0
  86. package/dist/vtex-payments.generated.js +544 -0
  87. package/dist/webhooks.d.ts +2 -2
  88. package/dist/webhooks.js +2 -2
  89. package/dist/wspay.generated.d.ts +1 -1
  90. package/dist/wspay.generated.js +175 -3
  91. package/examples/preflight/kernel-native/inventory.json +1 -1
  92. package/package.json +6 -8
  93. package/dist/languages.d.ts +0 -23
  94. package/dist/languages.js +0 -76
  95. package/dist/voice-pkce.d.ts +0 -49
  96. package/dist/voice-pkce.js +0 -147
  97. package/dist/voice-stream.generated.d.ts +0 -118
  98. package/dist/voice-stream.generated.js +0 -170
  99. package/dist/voice-types.d.ts +0 -735
  100. package/dist/voice.d.ts +0 -373
  101. package/dist/voice.js +0 -815
  102. package/readme.test.mjs +0 -53
  103. /package/dist/{voice-retry.d.ts → api-retry.d.ts} +0 -0
@@ -0,0 +1,61 @@
1
+ declare var PROCESSOUT_PSP: string;
2
+ declare var PROCESSOUT_CAPABILITY: string;
3
+ declare var PROCESSOUT_OPERATION: string;
4
+ declare var PROCESSOUT_API_HOST: string;
5
+ declare var PROCESSOUT_API_VERSION: string;
6
+ declare var PROCESSOUT_PREPARATION_URLS: Readonly<{
7
+ production: "https://api.processout.com/cards?project_id=proj_prepared";
8
+ sandbox: "https://api.processout.com/cards?project_id=test-proj_prepared";
9
+ }>;
10
+ declare var PROCESSOUT_REFUSAL_CODES: readonly string[];
11
+ declare var PROCESSOUT_CARD_KEYS: readonly string[];
12
+ declare function processoutCardTarget(url: any): Readonly<{
13
+ projectId: string;
14
+ environment: "production" | "sandbox";
15
+ }> | null;
16
+ declare function isProcessoutCardUrl(url: any): boolean;
17
+ declare function processoutEnvironment(url: any): "production" | "sandbox" | null;
18
+ declare function processoutBodyVerdict(body: any, url: any): Readonly<{
19
+ verdict: "refuse";
20
+ code: any;
21
+ }> | Readonly<{
22
+ verdict: "card";
23
+ }>;
24
+ declare function processoutRequestRefusal(request: any): any;
25
+ declare function processoutProjectId(request: any): string | null;
26
+ declare function isPreparedProcessoutRequest(url: any, method: any, body: any, environment: any, headers: any): boolean;
27
+ declare function processoutPinOriginUsable(origin: any): boolean;
28
+ declare var PROCESSOUT_MERCHANT_PINS: readonly never[];
29
+ declare function processoutOriginPin(merchantOrigin: any, pins?: readonly never[]): null;
30
+ declare function processoutPreparationRefusal(environment: any, merchantOrigin: any, pins?: readonly never[]): "unsupported_environment" | "processout_merchant_unreviewed" | null;
31
+ declare function processoutMerchantPin(merchantOrigin: any, request: any, pins?: readonly never[]): null;
32
+ declare function processoutMerchantRefusal(merchantOrigin: any, request: any, pins?: readonly never[]): "processout_url_refused" | "processout_merchant_unreviewed" | "processout_project_unreviewed" | null;
33
+ declare var PROCESSOUT_TEST_PANS: readonly string[];
34
+ declare function isProcessoutTestCard(number: any): boolean;
35
+ declare function processoutDeviceRefusal(request: any, card: any, options: any): any;
36
+ declare function processoutRefusalMessage(code: any): any;
37
+ declare function injectProcessoutCard(body: any, card: any): {
38
+ body: string;
39
+ where: string[];
40
+ };
41
+ declare function processoutRefusalCode(text: any): string | null;
42
+ declare function isProcessoutRefusalCode(code: any): boolean;
43
+ declare function processoutAnswerOutcome(status: any, text: any, card: any, template: any): {
44
+ outcome: string;
45
+ reason: string;
46
+ code?: undefined;
47
+ body?: undefined;
48
+ } | {
49
+ outcome: string;
50
+ code: string;
51
+ reason?: undefined;
52
+ body?: undefined;
53
+ } | {
54
+ outcome: string;
55
+ body: string;
56
+ reason?: undefined;
57
+ code?: undefined;
58
+ };
59
+ declare var processout_default: any;
60
+ declare var device: any;
61
+ export { PROCESSOUT_API_HOST, PROCESSOUT_API_VERSION, PROCESSOUT_CAPABILITY, PROCESSOUT_CARD_KEYS, PROCESSOUT_MERCHANT_PINS, PROCESSOUT_OPERATION, PROCESSOUT_PREPARATION_URLS, PROCESSOUT_PSP, PROCESSOUT_REFUSAL_CODES, PROCESSOUT_TEST_PANS, processout_default as default, device, injectProcessoutCard, isPreparedProcessoutRequest, isProcessoutCardUrl, isProcessoutRefusalCode, isProcessoutTestCard, processoutAnswerOutcome, processoutBodyVerdict, processoutCardTarget, processoutDeviceRefusal, processoutEnvironment, processoutMerchantPin, processoutMerchantRefusal, processoutOriginPin, processoutPinOriginUsable, processoutPreparationRefusal, processoutProjectId, processoutRefusalCode, processoutRefusalMessage, processoutRequestRefusal };
@@ -0,0 +1,577 @@
1
+ // @ts-nocheck
2
+ // Generated from @agent-cards/payment-core. Do not edit.
3
+ // artifact-sha256: b04e28b1a574ea60e62b721f13185f487aee8ed4c78fe9f3b35793df51bd9fe7
4
+ // src/deep-freeze.js
5
+ function deepFreeze(value) {
6
+ if (value && typeof value === "object" && !Object.isFrozen(value)) {
7
+ for (const child of Object.values(value))
8
+ deepFreeze(child);
9
+ Object.freeze(value);
10
+ }
11
+ return value;
12
+ }
13
+ // src/registration.js
14
+ var PARTS = {
15
+ psp: "id",
16
+ definitions: "list",
17
+ refusedOperations: "list",
18
+ settlementReadback: "any",
19
+ exactUrl: "rule",
20
+ bodyGate: "rule",
21
+ amount: "rule",
22
+ hostedEntry: "rule",
23
+ limitations: "sentences"
24
+ };
25
+ var DEVICE_PARTS = { psp: "id", testPans: "numbers", deviceCheck: "rule", fill: "rule", refusalCode: "rule", outcome: "rule", relayOnly: "flag" };
26
+ var PSP_ID = /^[a-z][a-z0-9_]*$/;
27
+ function problemsOf(spec, parts) {
28
+ if (!spec || typeof spec !== "object")
29
+ return ["a registration is an object"];
30
+ const psp = spec.psp;
31
+ if (typeof psp !== "string" || !PSP_ID.test(psp))
32
+ return [`${JSON.stringify(psp)} is not a processor id`];
33
+ const problems = Object.keys(spec).filter((key) => !(key in parts)).map((key) => `${psp}: ${key} is no registration part`);
34
+ for (const [key, kind] of Object.entries(parts)) {
35
+ const value = spec[key];
36
+ if (value === void 0)
37
+ continue;
38
+ if (kind === "rule" && typeof value !== "function")
39
+ problems.push(`${psp}: ${key} is not a function`);
40
+ if (kind === "flag" && value !== true)
41
+ problems.push(`${psp}: ${key} is not true`);
42
+ if (kind === "numbers" && !((Array.isArray(value) || value instanceof Set) && [...value].every((n) => typeof n === "string" && /^\d{12,19}$/.test(n)))) {
43
+ problems.push(`${psp}: ${key} is not a list of card numbers`);
44
+ }
45
+ if (kind === "sentences" && !(Array.isArray(value) && value.length > 0 && value.every((s) => typeof s === "string" && s.trim() !== ""))) {
46
+ problems.push(`${psp}: ${key} is not a list of sentences`);
47
+ }
48
+ }
49
+ if ("definitions" in parts) {
50
+ if (!Array.isArray(spec.definitions) || spec.definitions.length === 0)
51
+ problems.push(`${psp}: names no definition`);
52
+ else if (spec.definitions.some((definition) => definition?.psp !== psp))
53
+ problems.push(`${psp}: a definition names another processor`);
54
+ for (const id of spec.refusedOperations ?? []) {
55
+ if (typeof id !== "string" || !id.startsWith(`${psp}.`))
56
+ problems.push(`${psp}: ${JSON.stringify(id)} is not one of its operations`);
57
+ }
58
+ const pages = Array.isArray(spec.definitions) ? spec.definitions.filter((d) => d?.hostedForm?.cardIn === "processor_page") : [];
59
+ if (spec.hostedEntry !== void 0 && (pages.length === 0 || pages.some((d) => d.hostedForm.policy !== void 0))) {
60
+ problems.push(`${psp}: hostedEntry needs a definition whose hosted form takes the card on the processor's page and names no policy`);
61
+ }
62
+ }
63
+ return problems;
64
+ }
65
+ function registered(spec, parts) {
66
+ const problems = problemsOf(spec, parts);
67
+ if (problems.length)
68
+ throw new Error(`payment-core registration refused: ${problems.join("; ")}`);
69
+ return deepFreeze({ ...spec });
70
+ }
71
+ function registerProcessor(spec) {
72
+ return registered(spec, PARTS);
73
+ }
74
+ function registerDeviceRules(psp, rules) {
75
+ const checked = registered({ psp, ...rules }, DEVICE_PARTS);
76
+ return checked.testPans ? Object.freeze({ ...checked, testPans: new Set(checked.testPans) }) : checked;
77
+ }
78
+ // src/processors/processout.js
79
+ var PROCESSOUT_PSP = "processout";
80
+ var PROCESSOUT_CAPABILITY = "processout_card_token";
81
+ var PROCESSOUT_OPERATION = "processout.card_request";
82
+ var PROCESSOUT_API_HOST = "api.processout.com";
83
+ var PROCESSOUT_API_VERSION = "1.3.0.0";
84
+ var PROCESSOUT_PREPARATION_URLS = /* @__PURE__ */ Object.freeze({
85
+ production: "https://api.processout.com/cards?project_id=proj_prepared",
86
+ sandbox: "https://api.processout.com/cards?project_id=test-proj_prepared"
87
+ });
88
+ var PROCESSOUT_REFUSAL_CODES = /* @__PURE__ */ Object.freeze([
89
+ "processout_url_refused",
90
+ "processout_headers_refused",
91
+ "processout_body_unsupported",
92
+ "processout_merchant_unreviewed",
93
+ "processout_project_unreviewed",
94
+ "processout_live_row_required",
95
+ "processout_keep_on_file",
96
+ "processout_test_card_required"
97
+ ]);
98
+ var URL_LIMIT = 512;
99
+ var BODY_LIMIT = 4096;
100
+ var CARD_URL = /^https:\/\/api\.processout\.com\/cards\?legacyrequest=true&project_id=((?:test-)?proj_[A-Za-z0-9]{16,64})&x-Content-Type=application\/json&x-API-Version=1\.3\.0\.0&x-Authorization=Basic%20([A-Za-z0-9+/]{4,256}={0,2})$/;
101
+ var JSON_TYPE = /^application\/json(?:; ?charset=utf-8)?$/i;
102
+ var FOREIGN_HEADERS = /* @__PURE__ */ Object.freeze(["x-processout-client-secret", "idempotency-key"]);
103
+ var PAGE_KEYS = /* @__PURE__ */ Object.freeze(["name", "contact", "preferred_scheme"]);
104
+ var CONTACT_KEYS = /* @__PURE__ */ Object.freeze(["address1", "address2", "city", "state", "country_code", "zip"]);
105
+ var DEVICE_KEYS = /* @__PURE__ */ Object.freeze([
106
+ "request_origin",
107
+ "app_color_depth",
108
+ "app_language",
109
+ "app_screen_height",
110
+ "app_screen_width",
111
+ "app_timezone_offset",
112
+ "app_java_enabled"
113
+ ]);
114
+ var PROCESSOUT_CARD_KEYS = /* @__PURE__ */ Object.freeze(["number", "exp_month", "exp_year", "cvc2"]);
115
+ var BODY_KEYS = /* @__PURE__ */ new Set([...PAGE_KEYS, "device", ...DEVICE_KEYS, ...PROCESSOUT_CARD_KEYS]);
116
+ var NUMBER = /^[0-9]{12,19}$/;
117
+ var MONTH = /^(?:[1-9]|1[0-2])$/;
118
+ var YEAR = /^20[0-9]{2}$/;
119
+ var CODE = /^[0-9]{3,4}$/;
120
+ var TEXT_LIMIT = 256;
121
+ var SCHEME = /^[A-Za-z][A-Za-z0-9 _-]{0,31}$/;
122
+ var LANGUAGE = /^[A-Za-z]{1,8}(?:-[A-Za-z0-9]{1,8}){0,4}$/;
123
+ var PAN_LIKE = /(?:[0-9][^0-9A-Za-z]*){12,}/;
124
+ var record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
125
+ var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
126
+ var refuse = (code) => Object.freeze({ verdict: "refuse", code });
127
+ var CARD = /* @__PURE__ */ Object.freeze({ verdict: "card" });
128
+ var BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
129
+ function base64Of(text) {
130
+ let out = "";
131
+ for (let at = 0; at < text.length; at += 3) {
132
+ const a = text.charCodeAt(at);
133
+ const b = at + 1 < text.length ? text.charCodeAt(at + 1) : NaN;
134
+ const c = at + 2 < text.length ? text.charCodeAt(at + 2) : NaN;
135
+ out += BASE64[a >> 2] + BASE64[(a & 3) << 4 | (Number.isNaN(b) ? 0 : b >> 4)] + (Number.isNaN(b) ? "=" : BASE64[(b & 15) << 2 | (Number.isNaN(c) ? 0 : c >> 6)]) + (Number.isNaN(c) ? "=" : BASE64[c & 63]);
136
+ }
137
+ return out;
138
+ }
139
+ var basicOf = (projectId) => base64Of(`${projectId}:`);
140
+ function luhn(digits) {
141
+ let sum = 0;
142
+ for (let at = 0; at < digits.length; at += 1) {
143
+ let digit = Number(digits[digits.length - 1 - at]);
144
+ if (at % 2 === 1) {
145
+ digit *= 2;
146
+ if (digit > 9)
147
+ digit -= 9;
148
+ }
149
+ sum += digit;
150
+ }
151
+ return sum % 10 === 0;
152
+ }
153
+ function processoutCardTarget(url) {
154
+ if (typeof url !== "string" || url.length > URL_LIMIT)
155
+ return null;
156
+ const match = CARD_URL.exec(url);
157
+ if (!match || match[2] !== basicOf(match[1]))
158
+ return null;
159
+ return Object.freeze({ projectId: match[1], environment: match[1].startsWith("test-") ? "sandbox" : "production" });
160
+ }
161
+ function isProcessoutCardUrl(url) {
162
+ return processoutCardTarget(url) !== null;
163
+ }
164
+ function processoutEnvironment(url) {
165
+ const target = processoutCardTarget(url);
166
+ return target === null ? null : target.environment;
167
+ }
168
+ function readBody(body) {
169
+ if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT)
170
+ return null;
171
+ try {
172
+ const value = JSON.parse(body);
173
+ return record(value) && JSON.stringify(value) === body ? value : null;
174
+ }
175
+ catch {
176
+ return null;
177
+ }
178
+ }
179
+ var pageText = (value) => value === null || typeof value === "string" && value.length <= TEXT_LIMIT && !PAN_LIKE.test(value);
180
+ var DEVICE_RULES = /* @__PURE__ */ Object.freeze({
181
+ request_origin: (value) => value === "web",
182
+ app_color_depth: (value) => Number.isSafeInteger(value) && value >= 1 && value <= 64,
183
+ app_language: (value) => typeof value === "string" && value.length <= 64 && LANGUAGE.test(value),
184
+ app_screen_height: (value) => Number.isSafeInteger(value) && value >= 1 && value <= 1e5,
185
+ app_screen_width: (value) => Number.isSafeInteger(value) && value >= 1 && value <= 1e5,
186
+ app_timezone_offset: (value) => Number.isSafeInteger(value) && value >= -1440 && value <= 1440,
187
+ app_java_enabled: (value) => typeof value === "boolean"
188
+ });
189
+ function soundDevice(value) {
190
+ const device2 = value.device;
191
+ if (!record(device2) || !own(device2, "request_origin") || !own(device2, "app_timezone_offset"))
192
+ return false;
193
+ return DEVICE_KEYS.every((key) => own(device2, key) ? DEVICE_RULES[key](device2[key]) && own(value, key) && value[key] === device2[key] : !own(value, key)) && Object.keys(device2).every((key) => DEVICE_KEYS.includes(key));
194
+ }
195
+ function soundPageData(value) {
196
+ if (own(value, "name") && !pageText(value.name))
197
+ return false;
198
+ if (own(value, "preferred_scheme") && !(value.preferred_scheme === null || typeof value.preferred_scheme === "string" && SCHEME.test(value.preferred_scheme)))
199
+ return false;
200
+ const contact = value.contact;
201
+ return record(contact) && Object.keys(contact).every((key) => CONTACT_KEYS.includes(key) && pageText(contact[key]));
202
+ }
203
+ function processoutBodyVerdict(body, url) {
204
+ if (url !== void 0 && processoutCardTarget(url) === null)
205
+ return refuse("processout_url_refused");
206
+ const value = readBody(body);
207
+ if (value === null || !Object.keys(value).every((key) => BODY_KEYS.has(key)))
208
+ return refuse("processout_body_unsupported");
209
+ if (!PROCESSOUT_CARD_KEYS.every((key) => typeof value[key] === "string"))
210
+ return refuse("processout_body_unsupported");
211
+ if (!NUMBER.test(value.number) || !luhn(value.number) || !MONTH.test(value.exp_month) || !YEAR.test(value.exp_year) || !CODE.test(value.cvc2))
212
+ return refuse("processout_body_unsupported");
213
+ if (!soundPageData(value) || !soundDevice(value))
214
+ return refuse("processout_body_unsupported");
215
+ return CARD;
216
+ }
217
+ function headerMap(headers) {
218
+ const out = /* @__PURE__ */ new Map();
219
+ for (const [name, value] of Object.entries(record(headers) ? headers : {})) {
220
+ const lower = name.toLowerCase();
221
+ if (out.has(lower) || typeof value !== "string")
222
+ return null;
223
+ out.set(lower, value);
224
+ }
225
+ return out;
226
+ }
227
+ function processoutRequestRefusal(request) {
228
+ if (!record(request) || request.method !== "POST")
229
+ return "processout_url_refused";
230
+ const target = processoutCardTarget(request.url);
231
+ if (target === null)
232
+ return "processout_url_refused";
233
+ const map = headerMap(request.headers);
234
+ if (map === null || !JSON_TYPE.test(map.get("content-type") ?? "") || map.get("api-version") !== PROCESSOUT_API_VERSION || map.get("authorization") !== `Basic ${basicOf(target.projectId)}` || FOREIGN_HEADERS.some((name) => map.has(name)))
235
+ return "processout_headers_refused";
236
+ const verdict = processoutBodyVerdict(request.body);
237
+ return verdict.verdict === "card" ? null : verdict.code;
238
+ }
239
+ function processoutProjectId(request) {
240
+ return processoutRequestRefusal(request) === null ? processoutCardTarget(request.url).projectId : null;
241
+ }
242
+ function isPreparedProcessoutRequest(url, method, body, environment, headers) {
243
+ return (environment === "production" || environment === "sandbox") && processoutEnvironment(url) === environment && processoutRequestRefusal({ url, method, headers, body }) === null;
244
+ }
245
+ var PIN_ORIGIN = /^https:\/\/([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)+)$/;
246
+ var PROCESSOUT_DOMAIN = /(?:^|\.)processout\.(?:com|ninja|dev)$/;
247
+ var LIVE_PROJECT = /^proj_[A-Za-z0-9]{16,64}$/;
248
+ function processoutPinOriginUsable(origin) {
249
+ const host = typeof origin === "string" ? PIN_ORIGIN.exec(origin) : null;
250
+ return !!host && !PROCESSOUT_DOMAIN.test(host[1]);
251
+ }
252
+ var PROCESSOUT_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([]);
253
+ var usablePin = (entry) => record(entry) && typeof entry.merchant === "string" && entry.merchant !== "" && Array.isArray(entry.origins) && entry.origins.length > 0 && entry.origins.every(processoutPinOriginUsable) && Array.isArray(entry.projectIds) && entry.projectIds.length > 0 && entry.projectIds.every((id) => typeof id === "string" && LIVE_PROJECT.test(id));
254
+ function processoutOriginPin(merchantOrigin, pins = PROCESSOUT_MERCHANT_PINS) {
255
+ if (!processoutPinOriginUsable(merchantOrigin) || !Array.isArray(pins))
256
+ return null;
257
+ const found = pins.filter((entry) => usablePin(entry) && entry.origins.includes(merchantOrigin));
258
+ return found.length === 1 ? found[0] : null;
259
+ }
260
+ function processoutPreparationRefusal(environment, merchantOrigin, pins = PROCESSOUT_MERCHANT_PINS) {
261
+ if (environment === "sandbox")
262
+ return null;
263
+ if (environment !== "production")
264
+ return "unsupported_environment";
265
+ return processoutOriginPin(merchantOrigin, pins) ? null : "processout_merchant_unreviewed";
266
+ }
267
+ function processoutMerchantPin(merchantOrigin, request, pins = PROCESSOUT_MERCHANT_PINS) {
268
+ const target = record(request) ? processoutCardTarget(request.url) : null;
269
+ if (target === null || target.environment !== "production")
270
+ return null;
271
+ const found = processoutOriginPin(merchantOrigin, pins);
272
+ return found && found.projectIds.includes(target.projectId) ? found : null;
273
+ }
274
+ function processoutMerchantRefusal(merchantOrigin, request, pins = PROCESSOUT_MERCHANT_PINS) {
275
+ const target = record(request) ? processoutCardTarget(request.url) : null;
276
+ if (target === null)
277
+ return "processout_url_refused";
278
+ if (target.environment === "sandbox")
279
+ return null;
280
+ if (processoutOriginPin(merchantOrigin, pins) === null)
281
+ return "processout_merchant_unreviewed";
282
+ return processoutMerchantPin(merchantOrigin, request, pins) ? null : "processout_project_unreviewed";
283
+ }
284
+ var PROCESSOUT_TEST_PANS = /* @__PURE__ */ Object.freeze([
285
+ "4242424242424242",
286
+ "5555555555554444",
287
+ "378282246310005",
288
+ "30123456789019",
289
+ "3530111333300000",
290
+ "6011111111111117",
291
+ "4977830000000001",
292
+ "4360000001000005",
293
+ "5130290000000009",
294
+ "4658580000000008",
295
+ "4571730000000003",
296
+ "4023600000000002",
297
+ "4338300000000009",
298
+ "4835910000000003",
299
+ "4000000000000101",
300
+ "4000000000000119",
301
+ "4000000000000259",
302
+ "4000000000003238",
303
+ "4000000000003055",
304
+ "4000000000003063",
305
+ "4000000000003220",
306
+ "4000000000003253",
307
+ "4000000000003246",
308
+ "4000000000002180",
309
+ "4000000000002198",
310
+ "4000000000002206",
311
+ "4000000000002214",
312
+ "4000000000002222",
313
+ "4000000000002230",
314
+ "4000000000002248",
315
+ "4000000000002255",
316
+ "4000000000002263",
317
+ "4000000000002271",
318
+ "4000000000002289",
319
+ "4127969420587632",
320
+ "4000000000000002",
321
+ "4000000000000010",
322
+ "4000000000000127",
323
+ "4000000000000135",
324
+ "4000000000000028",
325
+ "4000000000000036",
326
+ "4000000000000044",
327
+ "4000000000000069",
328
+ "4000000000000077",
329
+ "4000000000000085",
330
+ "4000000000000093",
331
+ "4000000000000200",
332
+ "4000000000000309",
333
+ "4000000000001216",
334
+ "4000000000004004",
335
+ "4000000000006223",
336
+ "4000000000000531",
337
+ "4000000000003303",
338
+ "4000000000006009",
339
+ "4000000000004301",
340
+ "5337480000007168"
341
+ ]);
342
+ function isProcessoutTestCard(number) {
343
+ const digits = typeof number === "string" || Number.isSafeInteger(number) ? String(number).replace(/[ -]/g, "") : "";
344
+ return PROCESSOUT_TEST_PANS.includes(digits);
345
+ }
346
+ function processoutDeviceRefusal(request, card, options) {
347
+ const refusal = processoutRequestRefusal(request);
348
+ if (refusal)
349
+ return refusal;
350
+ if (processoutEnvironment(request.url) === "sandbox")
351
+ return record(card) && isProcessoutTestCard(card.number) ? null : "processout_test_card_required";
352
+ const settings = record(options) ? options : {};
353
+ if (typeof settings.merchantOrigin !== "string")
354
+ return "processout_merchant_unreviewed";
355
+ if (settings.sandbox !== false)
356
+ return "processout_live_row_required";
357
+ const merchant = processoutMerchantRefusal(settings.merchantOrigin, request);
358
+ if (merchant)
359
+ return merchant;
360
+ return settings.keepOnFile === true ? null : "processout_keep_on_file";
361
+ }
362
+ var UNREVIEWED = "Refusing to pay: this ProcessOut payment goes to a merchant account Agentcard has not reviewed. Nothing was sent.";
363
+ var REFUSAL_MESSAGES = /* @__PURE__ */ Object.freeze({
364
+ processout_url_refused: "Refusing to pay: this ProcessOut card request does not go to ProcessOut's card address exactly as ProcessOut's card fields send it. Nothing was sent.",
365
+ processout_headers_refused: "Refusing to pay: this ProcessOut card request does not carry the headers ProcessOut's card fields send. Nothing was sent.",
366
+ processout_body_unsupported: "Refusing to pay: this is not the card request of ProcessOut's card fields. Nothing was sent.",
367
+ // The device's refusals of a live or a sandbox request (processoutDeviceRefusal), in the sentences Openpay, Pin
368
+ // Payments and the shared sandbox rule ship.
369
+ processout_merchant_unreviewed: UNREVIEWED,
370
+ processout_project_unreviewed: UNREVIEWED,
371
+ processout_live_row_required: "Refusing to pay: Agentcard sends a card to a live ProcessOut checkout only for a live purchase, and this one is not live. Nothing was sent.",
372
+ processout_keep_on_file: "Refusing to pay: this ProcessOut payment would keep the card on file without your consent. Nothing was sent.",
373
+ processout_test_card_required: "Refusing to pay: a sandbox or test host accepts only the processor's documented test cards, not a real card."
374
+ });
375
+ function processoutRefusalMessage(code) {
376
+ return own(REFUSAL_MESSAGES, code) ? REFUSAL_MESSAGES[code] : REFUSAL_MESSAGES.processout_body_unsupported;
377
+ }
378
+ var FILL_FAILED = "Could not fill the card fields for ProcessOut. Nothing was sent.";
379
+ var AMEX = /^3[47]/;
380
+ var whole = (value) => {
381
+ if (Number.isSafeInteger(value) && value >= 0)
382
+ return value;
383
+ return typeof value === "string" && /^[0-9]{1,4}$/.test(value) ? Number(value) : NaN;
384
+ };
385
+ function cardValues(card) {
386
+ const usable = (value) => typeof value === "string" || Number.isSafeInteger(value);
387
+ if (!record(card) || !usable(card.number) || !usable(card.cvc))
388
+ return null;
389
+ const number = String(card.number);
390
+ const cvc = String(card.cvc);
391
+ const month = whole(card.month);
392
+ const stated = whole(card.year);
393
+ const year = stated >= 0 && stated <= 99 ? 2e3 + stated : stated;
394
+ if (!NUMBER.test(number) || !luhn(number) || !(month >= 1 && month <= 12) || !(year >= 2e3 && year <= 2099))
395
+ return null;
396
+ if (!new RegExp(`^[0-9]{${AMEX.test(number) ? 4 : 3}}$`).test(cvc))
397
+ return null;
398
+ return { number, exp_month: String(month), exp_year: String(year), cvc2: cvc };
399
+ }
400
+ var withoutCard = (value) => JSON.stringify(Object.fromEntries(Object.entries(value).filter(([key]) => !PROCESSOUT_CARD_KEYS.includes(key))));
401
+ function injectProcessoutCard(body, card) {
402
+ const verdict = processoutBodyVerdict(body);
403
+ if (verdict.verdict !== "card")
404
+ throw new Error(processoutRefusalMessage(verdict.code));
405
+ const values = cardValues(card);
406
+ if (!values)
407
+ throw new Error(FILL_FAILED);
408
+ const page = JSON.parse(body);
409
+ const value = JSON.parse(body);
410
+ for (const key of PROCESSOUT_CARD_KEYS)
411
+ value[key] = values[key];
412
+ const filled = JSON.stringify(value);
413
+ if (processoutBodyVerdict(filled).verdict !== "card" || withoutCard(JSON.parse(filled)) !== withoutCard(page))
414
+ throw new Error(FILL_FAILED);
415
+ return { body: filled, where: [...PROCESSOUT_CARD_KEYS] };
416
+ }
417
+ var ANSWER_LIMIT = 65536;
418
+ var CARD_TOKEN = /^card_[A-Za-z0-9]{8,64}$/;
419
+ var CARD_FACTS = /* @__PURE__ */ Object.freeze([
420
+ "id",
421
+ "project_id",
422
+ "scheme",
423
+ "co_scheme",
424
+ "preferred_scheme",
425
+ "type",
426
+ "bank_name",
427
+ "brand",
428
+ "category",
429
+ "iin",
430
+ "last_4_digits",
431
+ "exp_month",
432
+ "exp_year",
433
+ "expires_soon",
434
+ "sandbox"
435
+ ]);
436
+ var LAST_FOUR = /^[0-9]{4}$/;
437
+ var IIN = /^[0-9]{6}$/;
438
+ var ERROR_TYPE = /^[a-z][a-z0-9_-]*(?:\.[a-z0-9_-]+)+$/;
439
+ var TYPE_LIMIT = 53;
440
+ var UNSETTLED_TYPE = /(?:pending|timeout|internal-error|network-error|network-failed|unknown-error)$/;
441
+ var MAX_CODE_DIGITS = 11;
442
+ var OUTCOMES = /* @__PURE__ */ Object.freeze(["success", "failed", "pending"]);
443
+ var REFUSAL_CODE = /^(?:processout_refused|processout_[a-z][a-z0-9_-]*(?:\.[a-z0-9_-]+)+|http_4[0-9]{2})$/;
444
+ var digitCount = (text) => (text.match(/[0-9]/g) ?? []).length;
445
+ function readAnswer(text) {
446
+ if (typeof text !== "string" || text === "" || text.length > ANSWER_LIMIT)
447
+ return null;
448
+ try {
449
+ const value = JSON.parse(text);
450
+ return record(value) ? value : null;
451
+ }
452
+ catch {
453
+ return null;
454
+ }
455
+ }
456
+ var outcomeOf = (answer) => OUTCOMES.includes(answer.outcome) ? answer.outcome : answer.success === true ? "success" : "failed";
457
+ var explicitRefusal = (answer) => !own(answer, "card") && !own(answer, "customer_action") && (answer.outcome === "failed" || !own(answer, "outcome") && answer.success === false);
458
+ var unsettledRefusal = (answer) => explicitRefusal(answer) && typeof answer.error_type === "string" && UNSETTLED_TYPE.test(answer.error_type);
459
+ var unfinished = (answer) => own(answer, "customer_action") || typeof answer.error_type === "string" && UNSETTLED_TYPE.test(answer.error_type);
460
+ function processoutRefusalCode(text) {
461
+ const answer = readAnswer(text);
462
+ if (answer === null || !explicitRefusal(answer) || unsettledRefusal(answer))
463
+ return null;
464
+ const type = answer.error_type;
465
+ return typeof type === "string" && type.length <= TYPE_LIMIT && ERROR_TYPE.test(type) && digitCount(type) <= MAX_CODE_DIGITS ? `processout_${type}` : null;
466
+ }
467
+ function isProcessoutRefusalCode(code) {
468
+ return typeof code === "string" && code.length <= 64 && REFUSAL_CODE.test(code) && !UNSETTLED_TYPE.test(code) && digitCount(code) <= MAX_CODE_DIGITS;
469
+ }
470
+ var fact = (value) => value === null || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value) || typeof value === "string" && value.length <= TEXT_LIMIT;
471
+ var dateFact = (value) => whole(value);
472
+ function tokenAnswer(answer) {
473
+ if (answer.success !== true || own(answer, "outcome") && answer.outcome !== "success" || own(answer, "customer_action") || own(answer, "error_type") || !record(answer.card))
474
+ return null;
475
+ const source = answer.card;
476
+ if (typeof source.id !== "string" || !CARD_TOKEN.test(source.id) || typeof source.last_4_digits !== "string" || !LAST_FOUR.test(source.last_4_digits) || !(dateFact(source.exp_month) >= 1 && dateFact(source.exp_month) <= 12) || !(dateFact(source.exp_year) >= 2e3))
477
+ return null;
478
+ const card = {};
479
+ for (const key of CARD_FACTS) {
480
+ if (!own(source, key))
481
+ continue;
482
+ if (!fact(source[key]))
483
+ return null;
484
+ if (key === "iin" && !(typeof source.iin === "string" && IIN.test(source.iin)))
485
+ continue;
486
+ card[key] = source[key];
487
+ }
488
+ return { success: true, card };
489
+ }
490
+ function processoutAnswerOutcome(status, text, card, template) {
491
+ if (!Number.isInteger(status))
492
+ return { outcome: "unknown", reason: "processout_unconfirmed" };
493
+ if (status >= 500)
494
+ return { outcome: "unknown", reason: "server_error" };
495
+ const answer = readAnswer(text);
496
+ const refused = answer !== null && explicitRefusal(answer);
497
+ if (answer !== null && unfinished(answer))
498
+ return { outcome: "unknown", reason: "processout_unconfirmed" };
499
+ if (status >= 400 && status < 500) {
500
+ if (answer !== null && !refused && (own(answer, "card") || outcomeOf(answer) !== "failed"))
501
+ return { outcome: "unknown", reason: "processout_unconfirmed" };
502
+ return { outcome: "refused", code: processoutRefusalCode(text) ?? `http_${status}` };
503
+ }
504
+ if (status !== 200 && status !== 201)
505
+ return { outcome: "unknown", reason: "processout_unconfirmed" };
506
+ if (answer === null)
507
+ return { outcome: "unknown", reason: "processout_unconfirmed" };
508
+ if (refused)
509
+ return { outcome: "refused", code: processoutRefusalCode(text) ?? "processout_refused" };
510
+ if (outcomeOf(answer) === "pending")
511
+ return { outcome: "unknown", reason: "processout_pending" };
512
+ const token = tokenAnswer(answer);
513
+ if (token === null)
514
+ return { outcome: "unknown", reason: "processout_unconfirmed" };
515
+ const target = record(template) ? processoutCardTarget(template.url) : null;
516
+ if (target && (own(token.card, "project_id") && token.card.project_id !== target.projectId || own(token.card, "sandbox") && token.card.sandbox !== (target.environment === "sandbox"))) {
517
+ return { outcome: "unknown", reason: "processout_token_mismatch" };
518
+ }
519
+ const body = JSON.stringify(token);
520
+ if (card) {
521
+ const number = String(card.number ?? "").replace(/[^0-9]/g, "");
522
+ const holdsCard = (raw) => raw.replace(/[^0-9]/g, "").includes(number);
523
+ if (number && (holdsCard(text) || holdsCard(body)))
524
+ return { outcome: "unknown", reason: "processout_unsafe_response" };
525
+ const facts = token.card;
526
+ if (facts.last_4_digits !== number.slice(-4) || dateFact(facts.exp_month) !== Number(card.month) || dateFact(facts.exp_year) % 100 !== Number(card.year) % 100 || own(facts, "iin") && !number.startsWith(facts.iin)) {
527
+ return { outcome: "unknown", reason: "processout_token_mismatch" };
528
+ }
529
+ }
530
+ return { outcome: "approved", body };
531
+ }
532
+ var processout_default = /* @__PURE__ */ registerProcessor({
533
+ psp: PROCESSOUT_PSP,
534
+ definitions: [
535
+ {
536
+ psp: "processout",
537
+ // ProcessOut.js's card request, as the header above reads it. One host serves every project, live and sandbox
538
+ // alike, so no sandbox host is marked: the project id names the environment, and the device sends a sandbox
539
+ // project only ProcessOut's documented test cards (processoutDeviceRefusal). The page gives up 20 seconds after
540
+ // its tokenize message, so the lane is prepared only (preparationRequired). The match reads the host and the path,
541
+ // and ends where the path does, as Pin Payments' does: a card's own record under /cards/, where the code refresh
542
+ // goes, is never paused. The exact-URL rule below holds the query, the project id and its Basic credential among it.
543
+ // Ships dark: served only to a client that declares `processout_card_token`, and gated off for every org until
544
+ // the backend's gate names one.
545
+ capability: "processout_card_token",
546
+ match: "api\\.processout\\.com/cards(?![\\w/.%-])",
547
+ hosts: ["^api\\.processout\\.com$"],
548
+ preparationRequired: true,
549
+ encoding: "json",
550
+ // ProcessOut.js's own headers: the project's Basic credential and the API version. Origin, Referer and cookies
551
+ // never ride.
552
+ passthroughHeaders: ["^authorization$", "^api-version$"],
553
+ jsonCardFields: [["number"]]
554
+ }
555
+ ],
556
+ // Only the cardholder's device sends a card, after a person approves; no reviewed list names processout.
557
+ refusedOperations: [PROCESSOUT_OPERATION],
558
+ // Not surveyed: the card request mints a token and moves no money; the store's server charges it under its own
559
+ // secret key, which Agentcard never holds.
560
+ settlementReadback: "not_surveyed",
561
+ exactUrl: isProcessoutCardUrl,
562
+ bodyGate: (url, body) => processoutBodyVerdict(body, url)
563
+ });
564
+ var device = /* @__PURE__ */ registerDeviceRules(PROCESSOUT_PSP, {
565
+ // The whole request, then the project: a pinned live one with consent to a kept card, or a sandbox one with a test
566
+ // card, before any card is written (processoutDeviceRefusal), from the settings and the card device-replay.js hands
567
+ // every registered processor (deviceCheckArguments).
568
+ deviceCheck: (request, settings, card) => {
569
+ const refusal = processoutDeviceRefusal(request, card, settings);
570
+ return refusal ? processoutRefusalMessage(refusal) : null;
571
+ },
572
+ fill: injectProcessoutCard,
573
+ // Only a bounded code leaves as a fact, never ProcessOut's message, which can echo what was sent.
574
+ refusalCode: (text) => processoutRefusalCode(text),
575
+ outcome: (status, text, template, card) => processoutAnswerOutcome(status, text, card, template)
576
+ });
577
+ export { PROCESSOUT_API_HOST, PROCESSOUT_API_VERSION, PROCESSOUT_CAPABILITY, PROCESSOUT_CARD_KEYS, PROCESSOUT_MERCHANT_PINS, PROCESSOUT_OPERATION, PROCESSOUT_PREPARATION_URLS, PROCESSOUT_PSP, PROCESSOUT_REFUSAL_CODES, PROCESSOUT_TEST_PANS, processout_default as default, device, injectProcessoutCard, isPreparedProcessoutRequest, isProcessoutCardUrl, isProcessoutRefusalCode, isProcessoutTestCard, processoutAnswerOutcome, processoutBodyVerdict, processoutCardTarget, processoutDeviceRefusal, processoutEnvironment, processoutMerchantPin, processoutMerchantRefusal, processoutOriginPin, processoutPinOriginUsable, processoutPreparationRefusal, processoutProjectId, processoutRefusalCode, processoutRefusalMessage, processoutRequestRefusal };
package/dist/requests.js CHANGED
@@ -1,4 +1,4 @@
1
- import { AgentcardError } from './voice-types.js';
1
+ import { AgentcardError } from './api-types.js';
2
2
  /** The placeholder card every builder puts in the request; the Vault replaces it at approval. */
3
3
  const PLACEHOLDER = { number: '4242424242424242', exp_month: '12', exp_year: '2030', cvc: '123' };
4
4
  /** The paused Stripe request for an order: `POST /v1/payment_intents/{pi}/confirm` with a placeholder card. */