@agent-cards/checkout 0.19.0 → 0.21.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 (106) hide show
  1. package/README.md +6 -753
  2. package/cdp.d.ts +1 -0
  3. package/cdp.js +2 -0
  4. package/index.d.ts +1 -0
  5. package/index.js +2 -0
  6. package/package.json +33 -33
  7. package/playwright.d.ts +1 -0
  8. package/playwright.js +2 -0
  9. package/preflight.d.ts +1 -0
  10. package/preflight.js +2 -0
  11. package/CHANGELOG.md +0 -132
  12. package/PREFLIGHT.md +0 -312
  13. package/dist/adyen-merchant-hosted.generated.d.ts +0 -277
  14. package/dist/adyen-merchant-hosted.generated.js +0 -1902
  15. package/dist/adyen.generated.d.ts +0 -24
  16. package/dist/adyen.generated.js +0 -64
  17. package/dist/attachment.d.ts +0 -11
  18. package/dist/attachment.js +0 -50
  19. package/dist/braintree.d.ts +0 -2
  20. package/dist/braintree.generated.d.ts +0 -10
  21. package/dist/braintree.generated.js +0 -302
  22. package/dist/braintree.js +0 -2
  23. package/dist/builtin-registry.generated.d.ts +0 -2
  24. package/dist/builtin-registry.generated.js +0 -1
  25. package/dist/card-fields.generated.d.ts +0 -3
  26. package/dist/card-fields.generated.js +0 -46
  27. package/dist/cdp.d.ts +0 -192
  28. package/dist/cdp.js +0 -2393
  29. package/dist/checkout-com.generated.d.ts +0 -4
  30. package/dist/checkout-com.generated.js +0 -183
  31. package/dist/client.d.ts +0 -849
  32. package/dist/client.js +0 -1754
  33. package/dist/cse-body.d.ts +0 -25
  34. package/dist/cse-body.js +0 -41
  35. package/dist/fiserv.d.ts +0 -65
  36. package/dist/fiserv.generated.d.ts +0 -73
  37. package/dist/fiserv.generated.js +0 -830
  38. package/dist/fiserv.js +0 -104
  39. package/dist/hosted-form.d.ts +0 -44
  40. package/dist/hosted-form.js +0 -78
  41. package/dist/index.d.ts +0 -18
  42. package/dist/index.js +0 -10
  43. package/dist/lifecycle.d.ts +0 -179
  44. package/dist/lifecycle.js +0 -395
  45. package/dist/mercado-checkout.d.ts +0 -20
  46. package/dist/mercado-checkout.generated.d.ts +0 -52
  47. package/dist/mercado-checkout.generated.js +0 -198
  48. package/dist/mercado-checkout.js +0 -108
  49. package/dist/merchant-handoff.d.ts +0 -54
  50. package/dist/merchant-handoff.js +0 -100
  51. package/dist/merchant-hosted.d.ts +0 -140
  52. package/dist/merchant-hosted.js +0 -170
  53. package/dist/merchant-total-watch.d.ts +0 -115
  54. package/dist/merchant-total-watch.js +0 -268
  55. package/dist/merchant-total.d.ts +0 -257
  56. package/dist/merchant-total.js +0 -383
  57. package/dist/owned-shop.generated.d.ts +0 -24
  58. package/dist/owned-shop.generated.js +0 -108
  59. package/dist/paysafe.generated.d.ts +0 -12
  60. package/dist/paysafe.generated.js +0 -87
  61. package/dist/playwright.d.ts +0 -3
  62. package/dist/playwright.js +0 -3
  63. package/dist/pre-claim.d.ts +0 -123
  64. package/dist/pre-claim.js +0 -386
  65. package/dist/preflight-capabilities.generated.d.ts +0 -1253
  66. package/dist/preflight-capabilities.generated.js +0 -1929
  67. package/dist/preflight-catalog.json +0 -4727
  68. package/dist/preflight-playwright.d.ts +0 -34
  69. package/dist/preflight-playwright.js +0 -355
  70. package/dist/preflight-schemas.json +0 -1122
  71. package/dist/preflight.d.ts +0 -1
  72. package/dist/preflight.generated.d.ts +0 -1965
  73. package/dist/preflight.generated.js +0 -570
  74. package/dist/preflight.js +0 -2
  75. package/dist/preparation.d.ts +0 -38
  76. package/dist/preparation.js +0 -191
  77. package/dist/prepared-processor.d.ts +0 -43
  78. package/dist/prepared-processor.js +0 -172
  79. package/dist/recurly.generated.d.ts +0 -1
  80. package/dist/recurly.generated.js +0 -87
  81. package/dist/registry.d.ts +0 -121
  82. package/dist/registry.js +0 -310
  83. package/dist/spreedly.generated.d.ts +0 -10
  84. package/dist/spreedly.generated.js +0 -332
  85. package/dist/stripe-checkout.d.ts +0 -81
  86. package/dist/stripe-checkout.generated.d.ts +0 -82
  87. package/dist/stripe-checkout.generated.js +0 -1093
  88. package/dist/stripe-checkout.js +0 -140
  89. package/dist/substitute.d.ts +0 -38
  90. package/dist/substitute.js +0 -23
  91. package/dist/substitutions.generated.d.ts +0 -11
  92. package/dist/substitutions.generated.js +0 -818
  93. package/examples/existing-browser.mjs +0 -63
  94. package/examples/preflight/classify-direct.mjs +0 -21
  95. package/examples/preflight/classify-kernel.mjs +0 -30
  96. package/examples/preflight/inspect-browser.mjs +0 -44
  97. package/examples/preflight/kernel-native/README.md +0 -112
  98. package/examples/preflight/kernel-native/documented-adapters.json +0 -113
  99. package/examples/preflight/kernel-native/inventory.json +0 -233
  100. package/examples/preflight/kernel-native/qualification.mjs +0 -182
  101. package/examples/preflight/kernel-profile.empty.json +0 -11
  102. package/examples/preflight/mollie-hosted.observations.json +0 -23
  103. package/examples/preflight/mollie-hosted.result.json +0 -103
  104. package/examples/preflight/stripe-script.direct.result.json +0 -92
  105. package/examples/preflight/stripe-script.observations.json +0 -16
  106. package/examples/preflight/stripe-script.result.json +0 -87
@@ -1,24 +0,0 @@
1
- /** Adyen Web Sessions payments request, before it consumes an approval.
2
- * adyen-web (Drop-in and the Card component in the Sessions flow) posts one
3
- * JSON body to /checkoutshopper/v1/sessions/{id}/payments on the merchant's
4
- * Adyen host, with `clientKey` as its only query parameter, and carries the
5
- * card as four JWE blobs under paymentMethod. Those four blobs are what the
6
- * cardholder's device replaces; nothing else in the body is rewritten. Test
7
- * and live are separate host families AND separate client-key prefixes, so a
8
- * preparation names one of them and the request must agree on both. A body
9
- * that pays with a stored card, carries a single encrypted blob, or asks
10
- * Adyen to store the card is not the purchase the person approved and never
11
- * consumes readiness. This module never rewrites a body.
12
- */
13
- export type AdyenPreparationEnvironment = 'production' | 'sandbox';
14
- export declare const ADYEN_ENCRYPTED_CARD_FIELDS: readonly ["encryptedCardNumber", "encryptedExpiryMonth", "encryptedExpiryYear", "encryptedSecurityCode"];
15
- /** Which preparation environment a hostname belongs to: Adyen's test host, one of its live host families, or neither. */
16
- export declare function adyenPreparationEnvironment(hostname: string): AdyenPreparationEnvironment | null;
17
- /** The URL a preparation advertises for the approved host family: every registry recognizes it, and it is never a real session. */
18
- export declare function adyenPreparationUrl(environment: AdyenPreparationEnvironment): string;
19
- /** A Sessions payments URL on the approved host family whose only query is a client key of that same environment. */
20
- export declare function isPreparedAdyenUrl(rawUrl: string, environment: AdyenPreparationEnvironment): boolean;
21
- /** A fresh scheme card carrying the four encrypted fields the device replaces; stored cards, single-blob encryption and store requests never consume consent. */
22
- export declare function isPreparedAdyenBody(body: string | null | undefined): boolean;
23
- /** Processor identity, environment and request shape are part of the device's prior consent. */
24
- export declare function isPreparedAdyenRequest(rawUrl: string, method: string, body: string | null | undefined, environment: AdyenPreparationEnvironment): boolean;
@@ -1,64 +0,0 @@
1
- export const ADYEN_ENCRYPTED_CARD_FIELDS = ['encryptedCardNumber', 'encryptedExpiryMonth', 'encryptedExpiryYear', 'encryptedSecurityCode'];
2
- const SESSIONS_PAYMENTS = /^\/checkoutshopper\/v1\/sessions\/[A-Za-z0-9_-]{1,256}\/payments$/;
3
- const TEST_HOST = /^checkoutshopper-test\.adyen\.com$/;
4
- const LIVE_HOST = /^(?:checkoutshopper-live(?:-[a-z]+)?\.adyen\.com|(?:[a-z0-9-]+\.)*adyenpayments\.com)$/;
5
- const CLIENT_KEY = /^(test|live)_[A-Za-z0-9]{32}$/;
6
- const record = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
7
- const text = (value, max = 4096) => typeof value === 'string' && value.length > 0 && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
8
- /** Which preparation environment a hostname belongs to: Adyen's test host, one of its live host families, or neither. */
9
- export function adyenPreparationEnvironment(hostname) {
10
- const host = hostname.toLowerCase();
11
- if (TEST_HOST.test(host))
12
- return 'sandbox';
13
- if (LIVE_HOST.test(host))
14
- return 'production';
15
- return null;
16
- }
17
- /** The URL a preparation advertises for the approved host family: every registry recognizes it, and it is never a real session. */
18
- export function adyenPreparationUrl(environment) {
19
- return `https://checkoutshopper-${environment === 'production' ? 'live' : 'test'}.adyen.com/checkoutshopper/v1/sessions/prepared/payments`;
20
- }
21
- /** A Sessions payments URL on the approved host family whose only query is a client key of that same environment. */
22
- export function isPreparedAdyenUrl(rawUrl, environment) {
23
- let url;
24
- try {
25
- url = new URL(rawUrl);
26
- }
27
- catch {
28
- return false;
29
- }
30
- if (url.protocol !== 'https:' || url.port || url.username || url.password || url.hash)
31
- return false;
32
- if (adyenPreparationEnvironment(url.hostname) !== environment || !SESSIONS_PAYMENTS.test(url.pathname))
33
- return false;
34
- const names = [...url.searchParams.keys()];
35
- if (names.length !== 1 || names[0] !== 'clientKey')
36
- return false;
37
- const key = url.searchParams.get('clientKey') ?? '';
38
- const match = CLIENT_KEY.exec(key);
39
- return !!match && match[0] === key && (match[1] === 'live') === (environment === 'production');
40
- }
41
- /** A fresh scheme card carrying the four encrypted fields the device replaces; stored cards, single-blob encryption and store requests never consume consent. */
42
- export function isPreparedAdyenBody(body) {
43
- if (typeof body !== 'string' || !body || body.length > 65536)
44
- return false;
45
- let parsed;
46
- try {
47
- parsed = JSON.parse(body);
48
- }
49
- catch {
50
- return false;
51
- }
52
- if (!record(parsed) || parsed.storePaymentMethod === true)
53
- return false;
54
- const method = parsed.paymentMethod;
55
- if (!record(method) || method.type !== 'scheme')
56
- return false;
57
- if ('storedPaymentMethodId' in method || 'encryptedCard' in method || 'recurringDetailReference' in method)
58
- return false;
59
- return ADYEN_ENCRYPTED_CARD_FIELDS.every(field => text(method[field]));
60
- }
61
- /** Processor identity, environment and request shape are part of the device's prior consent. */
62
- export function isPreparedAdyenRequest(rawUrl, method, body, environment) {
63
- return method.toUpperCase() === 'POST' && isPreparedAdyenUrl(rawUrl, environment) && isPreparedAdyenBody(body);
64
- }
@@ -1,11 +0,0 @@
1
- /** An attachment failure has no payment or browser credentials in its message. */
2
- export declare class CheckoutAttachmentError extends Error {
3
- readonly reason: 'timeout' | 'closed' | 'unavailable';
4
- readonly code = "checkout_attachment_failed";
5
- constructor(reason: 'timeout' | 'closed' | 'unavailable');
6
- }
7
- /** Preserve a known setup cause without exposing raw transport errors. */
8
- export declare function attachmentFailure(error: unknown): CheckoutAttachmentError;
9
- export declare function attachmentDeadline(value: number | undefined): number;
10
- /** Stop waiting, then reject every late continuation before its next command. */
11
- export declare function withinAttachmentDeadline(arm: (assertActive: () => void) => Promise<void>, timeoutMs: number, signal: AbortSignal): Promise<void>;
@@ -1,50 +0,0 @@
1
- /** An attachment failure has no payment or browser credentials in its message. */
2
- export class CheckoutAttachmentError extends Error {
3
- reason;
4
- code = 'checkout_attachment_failed';
5
- constructor(reason) {
6
- super('Could not attach checkout interception. Close this checkout page and retry in a fresh browser context.');
7
- this.reason = reason;
8
- this.name = 'CheckoutAttachmentError';
9
- }
10
- }
11
- /** Preserve a known setup cause without exposing raw transport errors. */
12
- export function attachmentFailure(error) {
13
- return error instanceof CheckoutAttachmentError ? error : new CheckoutAttachmentError('unavailable');
14
- }
15
- export function attachmentDeadline(value) {
16
- if (value === undefined)
17
- return 30_000;
18
- if (!Number.isSafeInteger(value) || value <= 0 || value > 300_000) {
19
- throw new Error('attachmentTimeoutMs must be an integer between 1 and 300000.');
20
- }
21
- return value;
22
- }
23
- /** Stop waiting, then reject every late continuation before its next command. */
24
- export async function withinAttachmentDeadline(arm, timeoutMs, signal) {
25
- let stopped;
26
- let timer;
27
- let onAbort = () => { };
28
- const assertActive = () => { if (stopped)
29
- throw stopped; };
30
- const deadline = new Promise((_resolve, reject) => {
31
- const stop = (failure) => { stopped ??= failure; reject(stopped); };
32
- onAbort = () => stop(attachmentFailure(signal.reason));
33
- signal.addEventListener('abort', onAbort, { once: true });
34
- if (signal.aborted)
35
- onAbort();
36
- else
37
- timer = setTimeout(() => stop(new CheckoutAttachmentError('timeout')), timeoutMs);
38
- });
39
- try {
40
- await Promise.race([deadline, Promise.resolve().then(() => { assertActive(); return arm(assertActive); })]);
41
- }
42
- catch (error) {
43
- stopped ??= attachmentFailure(error);
44
- throw stopped;
45
- }
46
- finally {
47
- clearTimeout(timer);
48
- signal.removeEventListener('abort', onAbort);
49
- }
50
- }
@@ -1,2 +0,0 @@
1
- export { braintreeEnvironment, classifyBraintreeRequest, isPreparedBraintreeRequest, readTokenizationJson } from './braintree.generated.js';
2
- export type { BraintreeEnvironment, BraintreeRequestKind } from './braintree.generated.js';
@@ -1,10 +0,0 @@
1
- /** Classify native Braintree GraphQL requests without changing their bytes. */
2
- export type BraintreeEnvironment = 'production' | 'sandbox';
3
- export type BraintreeRequestKind = 'configuration' | 'tokenization' | 'invalid';
4
- export declare function braintreeEnvironment(url: string): BraintreeEnvironment | undefined;
5
- /** Bounded duplicate-aware JSON for fresh-card preparation bodies. */
6
- export declare function readTokenizationJson(body: string | null): Record<string, unknown> | null;
7
- /** Undefined belongs to another processor; invalid Braintree requests stay blocked. */
8
- export declare function classifyBraintreeRequest(url: string, method: string, body: string | null): BraintreeRequestKind | undefined;
9
- /** Preparation accepts guest tokenization only; ordinary interception stays broader. */
10
- export declare function isPreparedBraintreeRequest(body: string | null): boolean;
@@ -1,302 +0,0 @@
1
- const PRODUCTION = 'https://payments.braintree-api.com/graphql';
2
- const SANDBOX = 'https://payments.sandbox.braintree-api.com/graphql';
3
- const MAX_BODY_LENGTH = 128 * 1024;
4
- const MAX_DEPTH = 32;
5
- const MAX_NODES = 10_000;
6
- export function braintreeEnvironment(url) {
7
- return url === PRODUCTION ? 'production' : url === SANDBOX ? 'sandbox' : undefined;
8
- }
9
- function invalid() { throw new Error('invalid_braintree_request'); }
10
- function record(value) {
11
- return value !== null && typeof value === 'object' && !Array.isArray(value);
12
- }
13
- /** JSON.parse discards duplicate keys, so validate keys before using any value. */
14
- class JsonReader {
15
- text;
16
- at = 0;
17
- nodes = 0;
18
- constructor(text) {
19
- this.text = text;
20
- }
21
- read() {
22
- const value = this.value(0);
23
- this.space();
24
- if (this.at !== this.text.length)
25
- invalid();
26
- return value;
27
- }
28
- space() {
29
- while (' \t\r\n'.includes(this.text[this.at] ?? '\0'))
30
- this.at++;
31
- }
32
- take(expected) {
33
- this.space();
34
- if (this.text[this.at++] !== expected)
35
- invalid();
36
- }
37
- string() {
38
- this.space();
39
- const start = this.at;
40
- if (this.text[this.at++] !== '"')
41
- invalid();
42
- while (this.at < this.text.length) {
43
- const char = this.text[this.at++];
44
- if (char === '\\') {
45
- this.at++;
46
- continue;
47
- }
48
- if (char === '"')
49
- return JSON.parse(this.text.slice(start, this.at));
50
- }
51
- return invalid();
52
- }
53
- value(depth) {
54
- if (depth > MAX_DEPTH || ++this.nodes > MAX_NODES)
55
- invalid();
56
- this.space();
57
- const char = this.text[this.at];
58
- if (char === '"')
59
- return this.string();
60
- if (char === '{') {
61
- this.at++;
62
- const result = Object.create(null);
63
- const keys = new Set();
64
- this.space();
65
- if (this.text[this.at] === '}') {
66
- this.at++;
67
- return result;
68
- }
69
- while (true) {
70
- const key = this.string();
71
- if (keys.has(key))
72
- invalid();
73
- keys.add(key);
74
- this.take(':');
75
- result[key] = this.value(depth + 1);
76
- this.space();
77
- const next = this.text[this.at++];
78
- if (next === '}')
79
- return result;
80
- if (next !== ',')
81
- invalid();
82
- }
83
- }
84
- if (char === '[') {
85
- this.at++;
86
- const result = [];
87
- this.space();
88
- if (this.text[this.at] === ']') {
89
- this.at++;
90
- return result;
91
- }
92
- while (true) {
93
- result.push(this.value(depth + 1));
94
- this.space();
95
- const next = this.text[this.at++];
96
- if (next === ']')
97
- return result;
98
- if (next !== ',')
99
- invalid();
100
- }
101
- }
102
- for (const [literal, value] of [['true', true], ['false', false], ['null', null]]) {
103
- if (this.text.startsWith(literal, this.at)) {
104
- this.at += literal.length;
105
- return value;
106
- }
107
- }
108
- const number = /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/.exec(this.text.slice(this.at));
109
- if (!number)
110
- invalid();
111
- this.at += number[0].length;
112
- const value = Number(number[0]);
113
- if (!Number.isFinite(value))
114
- invalid();
115
- return value;
116
- }
117
- }
118
- /** Bounded duplicate-aware JSON for fresh-card preparation bodies. */
119
- export function readTokenizationJson(body) {
120
- if (typeof body !== 'string' || body.length === 0 || body.length > MAX_BODY_LENGTH)
121
- return null;
122
- try {
123
- const value = new JsonReader(body).read();
124
- return record(value) ? value : null;
125
- }
126
- catch {
127
- return null;
128
- }
129
- }
130
- /** Native operations need names, punctuation and variables, never literals. */
131
- function lex(query) {
132
- const tokens = [];
133
- let at = 0;
134
- while (at < query.length) {
135
- const char = query[at];
136
- if (' \t\r\n,'.includes(char)) {
137
- at++;
138
- continue;
139
- }
140
- if ('!$():{}'.includes(char)) {
141
- tokens.push(char);
142
- at++;
143
- }
144
- else if (/[A-Za-z_]/.test(char)) {
145
- const start = at++;
146
- while (at < query.length && /[A-Za-z_0-9]/.test(query[at]))
147
- at++;
148
- tokens.push(query.slice(start, at));
149
- }
150
- else
151
- invalid(); // Includes comments, strings, fragments and directives.
152
- if (tokens.length > MAX_NODES)
153
- invalid();
154
- }
155
- return tokens;
156
- }
157
- class GraphqlReader {
158
- tokens;
159
- at = 0;
160
- constructor(tokens) {
161
- this.tokens = tokens;
162
- }
163
- peek() { return this.tokens[this.at]; }
164
- take(expected) {
165
- if (this.tokens[this.at++] !== expected)
166
- invalid();
167
- }
168
- name() {
169
- const value = this.tokens[this.at++];
170
- if (!value || !/^[A-Za-z_][A-Za-z_0-9]*$/.test(value))
171
- invalid();
172
- return value;
173
- }
174
- read() {
175
- const kind = this.name();
176
- const name = this.name();
177
- let inputDefinition = false;
178
- if (this.peek() === '(') {
179
- // No defaults, alternate types, unused variables or duplicate definitions.
180
- for (const token of ['(', '$', 'input', ':', 'TokenizeCreditCardInput', '!', ')'])
181
- this.take(token);
182
- inputDefinition = true;
183
- }
184
- const fields = this.selection(0);
185
- if (this.at !== this.tokens.length)
186
- invalid();
187
- return { kind, name, inputDefinition, fields };
188
- }
189
- selection(depth) {
190
- if (depth > MAX_DEPTH)
191
- invalid();
192
- this.take('{');
193
- const fields = [];
194
- const names = new Set();
195
- while (this.peek() !== '}') {
196
- const name = this.name();
197
- if (names.has(name))
198
- invalid();
199
- names.add(name);
200
- const args = [];
201
- if (this.peek() === '(') {
202
- if (depth !== 0)
203
- invalid();
204
- this.take('(');
205
- const argument = this.name();
206
- this.take(':');
207
- this.take('$');
208
- args.push({ name: argument, variable: this.name() });
209
- this.take(')');
210
- }
211
- const children = this.peek() === '{' ? this.selection(depth + 1) : [];
212
- fields.push({ name, arguments: args, fields: children });
213
- // Aliases, directives and other punctuation cannot begin the next field.
214
- }
215
- this.take('}');
216
- if (fields.length === 0)
217
- invalid();
218
- return fields;
219
- }
220
- }
221
- /** Undefined belongs to another processor; invalid Braintree requests stay blocked. */
222
- export function classifyBraintreeRequest(url, method, body) {
223
- let hostname;
224
- try {
225
- hostname = new URL(url).hostname;
226
- }
227
- catch {
228
- return undefined;
229
- }
230
- if (hostname !== 'payments.braintree-api.com' && hostname !== 'payments.sandbox.braintree-api.com')
231
- return undefined;
232
- if (!braintreeEnvironment(url) || method !== 'POST' || typeof body !== 'string' || body.length === 0 || body.length > MAX_BODY_LENGTH)
233
- return 'invalid';
234
- try {
235
- const envelope = new JsonReader(body).read();
236
- if (!record(envelope) || typeof envelope.query !== 'string' || typeof envelope.operationName !== 'string')
237
- return 'invalid';
238
- if (Object.keys(envelope).some(key => !['query', 'operationName', 'variables', 'clientSdkMetadata'].includes(key)))
239
- return 'invalid';
240
- if (envelope.clientSdkMetadata !== undefined && !record(envelope.clientSdkMetadata))
241
- return 'invalid';
242
- const operation = new GraphqlReader(lex(envelope.query)).read();
243
- if (operation.name !== envelope.operationName || operation.fields.length !== 1)
244
- return 'invalid';
245
- const root = operation.fields[0];
246
- if (root.fields.length === 0)
247
- return 'invalid';
248
- const variables = envelope.variables === undefined ? Object.create(null) : envelope.variables;
249
- if (!record(variables))
250
- return 'invalid';
251
- if (operation.kind === 'query' && ['ClientConfiguration', 'ClientConfigurationQuery'].includes(operation.name)
252
- && !operation.inputDefinition && root.name === 'clientConfiguration' && root.arguments.length === 0
253
- && Object.keys(variables).length === 0)
254
- return 'configuration';
255
- if (operation.kind !== 'mutation' || operation.name !== 'TokenizeCreditCard' || !operation.inputDefinition
256
- || root.name !== 'tokenizeCreditCard' || root.arguments.length !== 1
257
- || root.arguments[0].name !== 'input' || root.arguments[0].variable !== 'input'
258
- || Object.keys(variables).length !== 1 || !record(variables.input) || !record(variables.input.creditCard))
259
- return 'invalid';
260
- const card = variables.input.creditCard;
261
- if (!['number', 'expirationMonth', 'expirationYear'].every(key => typeof card[key] === 'string' && card[key].trim().length > 0))
262
- return 'invalid';
263
- if (card.cvv !== undefined && (typeof card.cvv !== 'string' || card.cvv.trim().length === 0))
264
- return 'invalid';
265
- return 'tokenization';
266
- }
267
- catch {
268
- return 'invalid';
269
- }
270
- }
271
- /** Preparation accepts guest tokenization only; ordinary interception stays broader. */
272
- export function isPreparedBraintreeRequest(body) {
273
- if (classifyBraintreeRequest(PRODUCTION, 'POST', body) !== 'tokenization')
274
- return false;
275
- try {
276
- const envelope = new JsonReader(body).read();
277
- const variables = envelope.variables;
278
- const input = variables.input;
279
- if (Object.keys(input).some(key => key !== 'creditCard' && key !== 'options'))
280
- return false;
281
- const card = input.creditCard;
282
- if (Object.keys(card).some(key => !['number', 'expirationMonth', 'expirationYear', 'cvv', 'cardholderName', 'billingAddress'].includes(key)))
283
- return false;
284
- if (Object.entries(card).some(([key, value]) => key !== 'billingAddress' && typeof value !== 'string'))
285
- return false;
286
- if (card.billingAddress !== undefined) {
287
- if (!record(card.billingAddress))
288
- return false;
289
- const addressKeys = ['postalCode', 'firstName', 'lastName', 'company', 'streetAddress', 'extendedAddress',
290
- 'locality', 'region', 'countryCodeNumeric', 'countryCodeAlpha2', 'countryCodeAlpha3', 'countryName'];
291
- if (Object.entries(card.billingAddress).some(([key, value]) => !addressKeys.includes(key) || typeof value !== 'string'))
292
- return false;
293
- }
294
- // Fingerprint authorization defaults validation on when the option is absent.
295
- // Preparation permits only an explicit request for a transient card token.
296
- return record(input.options) && Object.keys(input.options).every(key => key === 'validate')
297
- && input.options.validate === false;
298
- }
299
- catch {
300
- return false;
301
- }
302
- }
package/dist/braintree.js DELETED
@@ -1,2 +0,0 @@
1
- // The generated projection keeps the public SDK free of runtime dependencies.
2
- export { braintreeEnvironment, classifyBraintreeRequest, isPreparedBraintreeRequest, readTokenizationJson } from './braintree.generated.js';
@@ -1,2 +0,0 @@
1
- import type { Recognizer } from './registry.js';
2
- export declare const BUILTIN_REGISTRY: Recognizer[];
@@ -1 +0,0 @@
1
- export const BUILTIN_REGISTRY = [{ "psp": "spreedly", "match": /core\.spreedly\.com\/v1\/payment_methods\/restricted\.json/i, "hosts": ["^core\\.spreedly\\.com$"], "encoding": "json", "passthroughHeaders": [/^spreedly-environment-key$/i] }, { "psp": "shopify", "match": /(checkout\.pci\.shopifyinc\.com|deposit\.[a-z0-9-]+\.shopifycs\.com)\/sessions/i, "hosts": ["^checkout\\.pci\\.shopifyinc\\.com$", "^deposit\\.[a-z0-9-]+\\.shopifycs\\.com$"], "encoding": "json", "passthroughHeaders": [/^shopify-identification-signature$/i] }, { "psp": "stripe", "match": /api\.stripe\.com\/v1\/(payment_methods|tokens|sources|confirmation_tokens|setup_intents\/seti_\w+\/confirm|payment_intents\/pi_\w+\/confirm|payment_pages\/cs_(?:test|live)_\w+\/confirm)/i, "hosts": ["^api\\.stripe\\.com$"], "encoding": "form", "passthroughHeaders": [/^authorization$/i, /^stripe-version$/i, /^x-stripe-client-user-agent$/i], "cardFields": ["card[number]", "payment_method_data[card][number]"], "passWithoutCard": "api\\.stripe\\.com/v1/(sources|confirmation_tokens|payment_pages/cs_(?:test|live)_\\w+/confirm)" }, { "psp": "braintree", "match": /payments(\.sandbox)?\.braintree-api\.com\/graphql/i, "hosts": ["^payments\\.braintree-api\\.com$", "^payments\\.sandbox\\.braintree-api\\.com$"], "sandboxHosts": ["^payments\\.sandbox\\.braintree-api\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i, /^braintree-version$/i] }, { "psp": "checkout_com", "match": /(api|card-acquisition-gateway)(\.sandbox)?\.checkout\.com\/tokens/i, "hosts": ["^api\\.checkout\\.com$", "^api\\.sandbox\\.checkout\\.com$", "^card-acquisition-gateway\\.checkout\\.com$", "^card-acquisition-gateway\\.sandbox\\.checkout\\.com$"], "sandboxHosts": ["^api\\.sandbox\\.checkout\\.com$", "^card-acquisition-gateway\\.sandbox\\.checkout\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i] }, { "psp": "adyen", "match": /(checkoutshopper-(test|live(-[a-z]+)?)\.adyen\.com|([a-z0-9-]+\.)*adyenpayments\.com)\/checkoutshopper\/v1\/sessions\/[A-Za-z0-9_-]+\/payments/i, "hosts": ["^checkoutshopper-(test|live(-[a-z]+)?)\\.adyen\\.com$", "^([a-z0-9-]+\\.)*adyenpayments\\.com$"], "sandboxHosts": ["^checkoutshopper-test\\.adyen\\.com$"], "encoding": "json", "passthroughHeaders": [], "clientSideEncrypted": true, "mode": "cse" }, { "psp": "tranzila", "match": /(direct\.tranzila\.com\/process\/n\/|directng\.tranzila\.com\/process\/?)/i, "hosts": ["^direct\\.tranzila\\.com$", "^directng\\.tranzila\\.com$"], "encoding": "form", "passthroughHeaders": [], "mode": "hosted_form" }, { "psp": "square", "match": /pci-connect\.squareup(?:sandbox)?\.com\/v2\/card-nonce/i, "hosts": ["^pci-connect\\.squareup\\.com$", "^pci-connect\\.squareupsandbox\\.com$"], "sandboxHosts": ["^pci-connect\\.squareupsandbox\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "authorize_net", "match": /(api2|apitest)\.authorize\.net\/xml\/v1\/request\.api/i, "hosts": ["^api2\\.authorize\\.net$", "^apitest\\.authorize\\.net$"], "sandboxHosts": ["^apitest\\.authorize\\.net$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "worldpay", "match": /(try\.)?access\.worldpay\.com\/(sessions\/card|verifiedTokens\/sessions)/i, "hosts": ["^access\\.worldpay\\.com$", "^try\\.access\\.worldpay\\.com$"], "sandboxHosts": ["^try\\.access\\.worldpay\\.com$"], "encoding": "json", "passthroughHeaders": [/^accept$/i] }, { "psp": "nuvei", "match": /(secure|ppp-test)\.safecharge\.com\/ppp\/api\/v1\/(?:cardTokenization|clientPayment|websdk\/initPaymentWithCardTokenization)\.do/i, "hosts": ["^secure\\.safecharge\\.com$", "^ppp-test\\.safecharge\\.com$"], "sandboxHosts": ["^ppp-test\\.safecharge\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "airwallex", "match": /(checkout(\.sandbox)?\.airwallex\.com|pci-api(\.sandbox)?\.airwallex\.com)\/api\/v1\/pa\/(payment_intents\/[^/?#]+\/confirm|payment_consents\/[^/?#]+\/verify|payment_methods\/create)(\?|$)/i, "hosts": ["^checkout\\.airwallex\\.com$", "^checkout\\.sandbox\\.airwallex\\.com$", "^pci-api\\.airwallex\\.com$", "^pci-api\\.sandbox\\.airwallex\\.com$"], "sandboxHosts": ["^checkout\\.sandbox\\.airwallex\\.com$", "^pci-api\\.sandbox\\.airwallex\\.com$"], "encoding": "json", "passthroughHeaders": [/^client-secret$/i, /^authorization$/i, /^x-auth-token$/i, /^x-on-behalf-of$/i, /^x-api-version$/i] }, { "psp": "rapyd", "match": /(api|sandboxapi)\.rapyd\.net\/v1\/(?:hosted\/collect\/card\/[^/?#]+\/payment_method|checkout\/checkout_[A-Za-z0-9]+)(?:[?#]|$)/i, "hosts": ["^api\\.rapyd\\.net$", "^sandboxapi\\.rapyd\\.net$"], "sandboxHosts": ["^sandboxapi\\.rapyd\\.net$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "dlocal", "match": /ppmcc(-sandbox)?\.dlocal\.com\/cvault\/credit-card\/temporal/i, "hosts": ["^ppmcc\\.dlocal\\.com$", "^ppmcc-sandbox\\.dlocal\\.com$"], "sandboxHosts": ["^ppmcc-sandbox\\.dlocal\\.com$"], "encoding": "json", "passthroughHeaders": [/^x-fields-api-key$/i, /^x-uow$/i, /^x-dlocal-infrav2$/i] }, { "psp": "ebanx", "match": /(?:(?:customer-frontier|customer|api-local-latam|api|sandbox-local-latam|sandbox)\.ebanx\.com|(?:api-diamond|api|sandbox)\.ebanxpay\.com)\/ws\/token/i, "hosts": ["^customer\\.ebanx\\.com$", "^customer-frontier\\.ebanx\\.com$", "^api\\.ebanx\\.com$", "^sandbox\\.ebanx\\.com$", "^api-local-latam\\.ebanx\\.com$", "^sandbox-local-latam\\.ebanx\\.com$", "^api-diamond\\.ebanxpay\\.com$", "^api\\.ebanxpay\\.com$", "^sandbox\\.ebanxpay\\.com$"], "sandboxHosts": ["^sandbox\\.ebanx\\.com$", "^sandbox-local-latam\\.ebanx\\.com$", "^sandbox\\.ebanxpay\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "mercado_pago", "match": /api\.mercadopago\.com\/v1\/card_tokens(?![\w/-])/i, "hosts": ["^api\\.mercadopago\\.com$"], "encoding": "json", "passthroughHeaders": [/^x-product-id$/i] }, { "psp": "payu", "match": /(secure\.payu\.com|(merch-prod|secure)\.snd\.payu\.com)\/api\/front\/tokens/i, "hosts": ["^secure\\.payu\\.com$", "^(merch-prod|secure)\\.snd\\.payu\\.com$"], "sandboxHosts": ["^(merch-prod|secure)\\.snd\\.payu\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i] }, { "psp": "razorpay", "match": /api\.razorpay\.com\/v1\/(?:standard_checkout\/)?payments\/create\/(?:ajax|checkout|fees)/i, "hosts": ["^api\\.razorpay\\.com$"], "encoding": "form", "passthroughHeaders": [/^x-razorpay-sessionid$/i, /^x-customer-access-token$/i] }, { "psp": "mollie", "match": /api\.cc\.mollie\.com\/v1\/card-tokens/i, "hosts": ["^api\\.cc\\.mollie\\.com$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "paysafe", "match": /(?:api(\.test)?\.paysafe\.com\/(?:paymenthub\/v1\/singleusepaymenthandles|js\/api\/v1\/tokenize)|hosted(\.test)?\.paysafe\.com\/checkout\/api\/v1\/tokenize)(?![\w/-])/i, "hosts": ["^api\\.paysafe\\.com$", "^api\\.test\\.paysafe\\.com$", "^hosted\\.paysafe\\.com$", "^hosted\\.test\\.paysafe\\.com$"], "sandboxHosts": ["^api\\.test\\.paysafe\\.com$", "^hosted\\.test\\.paysafe\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i, /^x-paysafe-credentials$/i, /^correlationid$/i] }, { "psp": "recurly", "match": /api(\.eu)?\.recurly\.com\/js\/v1\/token(?![\w-])/i, "hosts": ["^api\\.recurly\\.com$", "^api\\.eu\\.recurly\\.com$"], "encoding": "form", "passthroughHeaders": [/^recurly-credential-checkout-hostname$/i] }, { "psp": "moneris", "match": /(www3|esqa|gateway|gatewayqa|gatewayt|gatewaydev)\.moneris\.com\/HPPtoken\/request\.php/i, "hosts": ["^www3\\.moneris\\.com$", "^esqa\\.moneris\\.com$", "^gateway\\.moneris\\.com$", "^gatewayqa\\.moneris\\.com$", "^gatewayt\\.moneris\\.com$", "^gatewaydev\\.moneris\\.com$"], "sandboxHosts": ["^esqa\\.moneris\\.com$", "^gatewayqa\\.moneris\\.com$", "^gatewayt\\.moneris\\.com$", "^gatewaydev\\.moneris\\.com$"], "encoding": "form", "passthroughHeaders": [] }, { "psp": "bambora", "match": /(api\.na\.bambora\.com|api\.bam\.shift4api\.net)\/scripts\/tokenization\/tokens/i, "hosts": ["^api\\.na\\.bambora\\.com$", "^api\\.bam\\.shift4api\\.net$"], "encoding": "json", "passthroughHeaders": [] }, { "psp": "global_payments", "match": /(?:api\.heartlandportico\.com\/SecureSubmit\.v1\/api\/token|cert\.api2\.heartlandportico\.com\/Hps\.Exchange\.PosGateway\.Hpf\.v1\/api\/token|apis(?:\.sandbox)?(?:\.eu)?\.globalpay\.com\/ucp\/(?:merchants\/[^/]+\/)?payment-methods)/i, "hosts": ["^api\\.heartlandportico\\.com$", "^cert\\.api2\\.heartlandportico\\.com$", "^apis\\.globalpay\\.com$", "^apis\\.sandbox\\.globalpay\\.com$", "^apis\\.eu\\.globalpay\\.com$", "^apis\\.sandbox\\.eu\\.globalpay\\.com$"], "sandboxHosts": ["^cert\\.api2\\.heartlandportico\\.com$", "^apis\\.sandbox\\.globalpay\\.com$", "^apis\\.sandbox\\.eu\\.globalpay\\.com$"], "encoding": "json", "passthroughHeaders": [/^authorization$/i, /^x-gp-version$/i] }];
@@ -1,3 +0,0 @@
1
- declare function carriesCardFields(recognizer: any, body: any): boolean;
2
- declare function requestWithoutCard(recognizer: any, url: any, body: any): "continue" | "refuse" | null;
3
- export { carriesCardFields, requestWithoutCard };
@@ -1,46 +0,0 @@
1
- // @ts-nocheck
2
- // Generated from @agent-cards/payment-core. Do not edit.
3
- // artifact-sha256: ac6967df3f29912d12c310418d06b6583529d5a4d5346c362ef0a7987fd4f2ab
4
- // src/card-fields.js
5
- function carriesCardFields(recognizer, body) {
6
- const fields = recognizer && recognizer.cardFields;
7
- if (!Array.isArray(fields) || fields.length === 0)
8
- return true;
9
- if (recognizer.encoding !== "form")
10
- return true;
11
- if (typeof body !== "string" || body === "")
12
- return false;
13
- for (const chunk of body.split("&")) {
14
- const eq = chunk.indexOf("=");
15
- if (eq <= 0 || eq === chunk.length - 1)
16
- continue;
17
- let key;
18
- try {
19
- key = decodeURIComponent(chunk.slice(0, eq).replace(/\+/g, " "));
20
- }
21
- catch {
22
- continue;
23
- }
24
- if (fields.includes(key))
25
- return true;
26
- }
27
- return false;
28
- }
29
- function requestWithoutCard(recognizer, url, body) {
30
- if (carriesCardFields(recognizer, body))
31
- return null;
32
- const pass = recognizer && recognizer.passWithoutCard;
33
- if (typeof pass === "string" && pass !== "") {
34
- let parsed;
35
- try {
36
- parsed = new URL(url);
37
- }
38
- catch {
39
- return "refuse";
40
- }
41
- if (new RegExp(`^(?:${pass})$`, "i").test(`${parsed.hostname.toLowerCase()}${parsed.pathname}`))
42
- return "continue";
43
- }
44
- return "refuse";
45
- }
46
- export { carriesCardFields, requestWithoutCard };