@agent-cards/sdk 0.20.0 → 0.22.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 (111) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/PREFLIGHT.md +34 -0
  3. package/README.md +1217 -15
  4. package/dist/aci.d.ts +173 -0
  5. package/dist/aci.generated.d.ts +87 -0
  6. package/dist/aci.generated.js +306 -0
  7. package/dist/aci.js +371 -0
  8. package/dist/adyen-merchant-hosted.generated.d.ts +3 -3
  9. package/dist/adyen-merchant-hosted.generated.js +283 -49
  10. package/dist/agentcard.d.ts +9 -2
  11. package/dist/agentcard.js +4 -2
  12. package/dist/amadeus-checkout.generated.d.ts +57 -0
  13. package/dist/amadeus-checkout.generated.js +549 -0
  14. package/dist/amadeus.d.ts +41 -0
  15. package/dist/amadeus.js +81 -0
  16. package/dist/builtin-registry.generated.js +1 -1
  17. package/dist/card-endpoint.d.ts +177 -0
  18. package/dist/card-endpoint.js +286 -0
  19. package/dist/card-fields.generated.d.ts +5 -3
  20. package/dist/card-fields.generated.js +284 -7
  21. package/dist/cdp.d.ts +6 -1
  22. package/dist/cdp.js +983 -147
  23. package/dist/client.d.ts +493 -13
  24. package/dist/client.js +1100 -82
  25. package/dist/creditguard.generated.d.ts +79 -0
  26. package/dist/creditguard.generated.js +662 -0
  27. package/dist/cse-body.js +11 -1
  28. package/dist/cybersource-flex.d.ts +183 -0
  29. package/dist/cybersource-flex.generated.d.ts +92 -0
  30. package/dist/cybersource-flex.generated.js +689 -0
  31. package/dist/cybersource-flex.js +275 -0
  32. package/dist/datatrans.d.ts +96 -0
  33. package/dist/datatrans.generated.d.ts +64 -0
  34. package/dist/datatrans.generated.js +426 -0
  35. package/dist/datatrans.js +178 -0
  36. package/dist/elavon-converge.d.ts +37 -0
  37. package/dist/elavon-converge.generated.d.ts +49 -0
  38. package/dist/elavon-converge.generated.js +439 -0
  39. package/dist/elavon-converge.js +84 -0
  40. package/dist/eprotect.d.ts +152 -0
  41. package/dist/eprotect.generated.d.ts +77 -0
  42. package/dist/eprotect.generated.js +498 -0
  43. package/dist/eprotect.js +222 -0
  44. package/dist/gmo.d.ts +63 -0
  45. package/dist/gmo.generated.d.ts +60 -0
  46. package/dist/gmo.generated.js +586 -0
  47. package/dist/gmo.js +119 -0
  48. package/dist/hosted-form.d.ts +3 -2
  49. package/dist/hosted-form.js +3 -2
  50. package/dist/index.d.ts +19 -3
  51. package/dist/index.js +6 -1
  52. package/dist/juspay-gate.d.ts +82 -0
  53. package/dist/juspay-gate.js +126 -0
  54. package/dist/juspay.generated.d.ts +89 -0
  55. package/dist/juspay.generated.js +705 -0
  56. package/dist/lifecycle.d.ts +62 -6
  57. package/dist/lifecycle.js +123 -8
  58. package/dist/merchant-card-endpoints.generated.d.ts +63 -0
  59. package/dist/merchant-card-endpoints.generated.js +1103 -0
  60. package/dist/merchant-hosted.d.ts +4 -1
  61. package/dist/merchant-hosted.js +5 -2
  62. package/dist/merchant-session-probe.d.ts +48 -0
  63. package/dist/merchant-session-probe.js +53 -0
  64. package/dist/merchant-session.generated.d.ts +69 -0
  65. package/dist/merchant-session.generated.js +919 -0
  66. package/dist/payrails.d.ts +133 -0
  67. package/dist/payrails.generated.d.ts +73 -0
  68. package/dist/payrails.generated.js +596 -0
  69. package/dist/payrails.js +305 -0
  70. package/dist/pelecard.d.ts +32 -0
  71. package/dist/pelecard.generated.d.ts +32 -0
  72. package/dist/pelecard.generated.js +283 -0
  73. package/dist/pelecard.js +42 -0
  74. package/dist/pre-claim.d.ts +84 -3
  75. package/dist/pre-claim.js +987 -9
  76. package/dist/preflight-catalog.json +2310 -263
  77. package/dist/preflight-schemas.json +187 -6
  78. package/dist/preflight.generated.d.ts +1 -1
  79. package/dist/preflight.generated.js +247 -4
  80. package/dist/preparation.d.ts +5 -2
  81. package/dist/preparation.js +36 -10
  82. package/dist/prepared-processor.d.ts +86 -5
  83. package/dist/prepared-processor.js +157 -6
  84. package/dist/primer.d.ts +53 -0
  85. package/dist/primer.generated.d.ts +38 -0
  86. package/dist/primer.generated.js +624 -0
  87. package/dist/primer.js +82 -0
  88. package/dist/registry.d.ts +114 -12
  89. package/dist/registry.js +85 -11
  90. package/dist/shiji-sts.d.ts +144 -0
  91. package/dist/shiji-sts.generated.d.ts +72 -0
  92. package/dist/shiji-sts.generated.js +913 -0
  93. package/dist/shiji-sts.js +222 -0
  94. package/dist/stripe-checkout.generated.d.ts +1 -1
  95. package/dist/stripe-checkout.generated.js +735 -10
  96. package/dist/stripe-setup.d.ts +16 -0
  97. package/dist/stripe-setup.js +61 -0
  98. package/dist/substitutions.generated.js +187 -29
  99. package/dist/verifone.d.ts +68 -0
  100. package/dist/verifone.generated.d.ts +51 -0
  101. package/dist/verifone.generated.js +1401 -0
  102. package/dist/verifone.js +119 -0
  103. package/dist/voice-types.d.ts +27 -0
  104. package/dist/voice.d.ts +6 -1
  105. package/dist/voice.js +6 -1
  106. package/dist/wspay.d.ts +41 -0
  107. package/dist/wspay.generated.d.ts +41 -0
  108. package/dist/wspay.generated.js +370 -0
  109. package/dist/wspay.js +65 -0
  110. package/examples/preflight/kernel-native/inventory.json +1 -1
  111. package/package.json +3 -3
@@ -0,0 +1,275 @@
1
+ // CyberSource Flex Microform v2 in the checkout SDK (design cybersource_flex, revised).
2
+ //
3
+ // The card field is CyberSource's own iframe, and the request it sends (a POST of a compact JWE
4
+ // to /flex/v2/tokens) is sealed under a capture context the merchant minted for this checkout.
5
+ // The paused body is ciphertext of the agent's placeholder card, so nothing in it can be swapped:
6
+ // the cardholder's device seals the real card itself under the same context and sends it to
7
+ // CyberSource, and the transient token that comes back answers the paused request. The context
8
+ // lives only in the field iframe's URL fragment, so this module reads it there, verifies it
9
+ // offline against the signing keys payment-core pins (no network), and hands it to authorize()
10
+ // beside the paused request. The API and the device verify it again.
11
+ //
12
+ // Recognition is not coverage: Microform v0.x and Flex API direct traffic post to the same URL.
13
+ // A POST pauses only when it comes from a Microform v2 card field of a reviewed version whose
14
+ // committed document URL this attachment read, sealed under the context that URL carries. A check
15
+ // (eCheck) Microform carries no card and continues untouched; everything else is refused before
16
+ // any authorization exists.
17
+ //
18
+ // The API serves the Flex recognizer only to an org Agentcard enabled for CyberSource Flex, so
19
+ // for every other org nothing here runs: the SDK never recognizes a Flex host and the field's
20
+ // request goes through untouched, as it did before this build.
21
+ import { assertCybersourceFlexTemplate, cybersourceFlexHostEnvironment, cybersourceFlexTemplateKid, isCybersourceFlexRequest, parseMicroformFragment, verifyCaptureContext, } from './cybersource-flex.generated.js';
22
+ /** The processor id, as the registry and the API name it. */
23
+ export const CYBERSOURCE_FLEX_PSP = 'cybersource_flex';
24
+ /**
25
+ * The dark-launch capability the Flex recognizer names: the capture-context sidecar a create
26
+ * must carry. syncRegistry declares it (SUPPORTED_CAPABILITIES), because this build reads the
27
+ * context and sends it; the API serves the recognizer only to a client that does.
28
+ */
29
+ export const CYBERSOURCE_FLEX_CAPABILITY = 'capture_context';
30
+ const MICROFORM_FIELDS = ['number', 'securityCode'];
31
+ /** An https URL on flex.cybersource.com or testflex.cybersource.com, with no port or credentials. */
32
+ export function isCybersourceFlexHost(url) {
33
+ try {
34
+ const parsed = new URL(url);
35
+ return parsed.protocol === 'https:' && !parsed.port && !parsed.username && !parsed.password
36
+ && cybersourceFlexHostEnvironment(parsed.hostname) !== null;
37
+ }
38
+ catch {
39
+ return false;
40
+ }
41
+ }
42
+ /**
43
+ * How an adapter fails a card request it will not let through: a CyberSource Flex request as a
44
+ * network error (Playwright 'failed', CDP 'Failed', net::ERR_FAILED), every other request as an
45
+ * abort (net::ERR_ABORTED). Microform 2.12.1's field reports a failed request to the merchant's page
46
+ * at once (createToken's callback gets CREATE_TOKEN_XHR_ERROR), so the page runs its own error path:
47
+ * a message, a retry under the same capture context, or GetPay's reload under a new one. It never
48
+ * reports an aborted request, so after a refusal or a decline the page's createToken would wait with
49
+ * no answer. Both were observed with the real field on CyberSource's sandbox.
50
+ */
51
+ export function refusedRequestFailure(url) {
52
+ return isCybersourceFlexHost(url) ? 'failed' : 'aborted';
53
+ }
54
+ function frameOf(url) {
55
+ if (typeof url !== 'string' || !url)
56
+ return null;
57
+ try {
58
+ return parseMicroformFragment(url);
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ }
64
+ /** payment-core's own clock allowance on a context's exp. */
65
+ const CLOCK_SKEW_MS = 60_000;
66
+ const MAX_CONTEXTS = 32;
67
+ const MAX_FRAMES = 64;
68
+ function causeOf(error) {
69
+ const reason = error?.reason;
70
+ return typeof reason === 'string' && /^[a-z_]{1,32}$/.test(reason) ? reason : 'crypto';
71
+ }
72
+ /**
73
+ * Each capture context verified once, offline, against the keys payment-core pins, and
74
+ * remembered for the attachment. The adapters start a context's check when its field iframe
75
+ * loads, so by the time the page sends its card the answer is usually settled and the pause
76
+ * stays synchronous. Bounded: the oldest context is dropped past 32.
77
+ */
78
+ export class CaptureContexts {
79
+ entries = new Map();
80
+ verify(jwt) {
81
+ let entry = this.entries.get(jwt);
82
+ if (!entry) {
83
+ if (this.entries.size >= MAX_CONTEXTS)
84
+ this.entries.delete(this.entries.keys().next().value);
85
+ const created = { promise: Promise.resolve({ ok: false, cause: 'crypto' }) };
86
+ created.promise = Promise.resolve()
87
+ .then(() => verifyCaptureContext(jwt, { crypto: globalThis.crypto }))
88
+ .then((context) => (created.settled = { ok: true, context: context }), (error) => (created.settled = { ok: false, cause: causeOf(error) }));
89
+ this.entries.set(jwt, created);
90
+ entry = created;
91
+ }
92
+ return entry.settled ?? entry.promise;
93
+ }
94
+ /** Start the check of a card field iframe's capture context from the frame's URL, when it is one. */
95
+ warm(url) {
96
+ const frame = frameOf(url);
97
+ if (frame && frame.microformType === 'card' && frame.reviewed)
98
+ void this.verify(frame.captureContext);
99
+ }
100
+ }
101
+ /**
102
+ * The fields that loaded for the issuing frame's Microform: every frame sharing its capture
103
+ * context, microform id, version, host and type. Null when they are not a number field plus an
104
+ * optional security code field, which is all the device can rebuild.
105
+ */
106
+ function fieldsOf(issuing, frames) {
107
+ const types = new Set([issuing.fieldType]);
108
+ for (const frame of frames) {
109
+ if (frame.captureContext === issuing.captureContext && frame.microformId === issuing.microformId
110
+ && frame.version === issuing.version && frame.environment === issuing.environment
111
+ && frame.microformType === issuing.microformType)
112
+ types.add(frame.fieldType);
113
+ }
114
+ if (!types.has('number') || [...types].some((type) => !MICROFORM_FIELDS.includes(type)))
115
+ return null;
116
+ return MICROFORM_FIELDS.filter((field) => types.has(field));
117
+ }
118
+ function afterVerification(request, issuing, fields, verification) {
119
+ if (!verification.ok)
120
+ return { kind: 'refuse', reason: 'capture_context_invalid', cause: verification.cause };
121
+ const context = verification.context;
122
+ if (!(context.exp * 1000 > Date.now() - CLOCK_SKEW_MS))
123
+ return { kind: 'refuse', reason: 'capture_context_invalid', cause: 'expired' };
124
+ if (context.url !== request.url || context.environment !== issuing.environment) {
125
+ return { kind: 'refuse', reason: 'capture_context_invalid', cause: 'url_mismatch' };
126
+ }
127
+ try {
128
+ assertCybersourceFlexTemplate(request.body, context);
129
+ }
130
+ catch {
131
+ return { kind: 'refuse', reason: 'capture_context_mismatch' };
132
+ }
133
+ const trigger = issuing.fieldType;
134
+ return {
135
+ kind: 'pause',
136
+ flex: {
137
+ sidecar: { capture_context: issuing.captureContext, microform: { version: issuing.version, fields, trigger } },
138
+ shape: `jwe:${issuing.microformType}:${fields.join(',')}:${cybersourceFlexTemplateKid(request.body)}:${issuing.captureContext}`,
139
+ },
140
+ };
141
+ }
142
+ /**
143
+ * Judge one POST to a Flex host, given the frame that sent it and every Microform frame this
144
+ * attachment knows. `issuing` is that frame read as a Microform field: `undefined` when its URL
145
+ * could not be read at all, `null` when it was read and is no Microform v2 field (the merchant's
146
+ * own page or frame, which is where Flex API direct traffic comes from). In order:
147
+ * 1. a check (eCheck) Microform: continue, it carries no card;
148
+ * 2. a body the adapter could not read: refuse this request;
149
+ * 3. not a field iframe's sealed card (application/jwt, a Microform JWE, the exact tokens
150
+ * URL): unsupported, Microform v0.x and Flex API direct post here too;
151
+ * 4. a frame that could not be read: refuse this request, since the read can fail for a
152
+ * reason the page's next request does not repeat (a missed event, a slow frame tree read);
153
+ * 5. a frame read and found to be no Microform field, an unreviewed version, or fields the
154
+ * device cannot rebuild: unsupported, as the page's next request repeats each of them;
155
+ * 6. a capture context that does not verify, has expired, names another URL or host, or did
156
+ * not seal this body: refuse this request;
157
+ * 7. otherwise pause, with the sidecar the create carries.
158
+ * Returns synchronously when the context's verification already settled.
159
+ */
160
+ export function judgeMicroformRequest(request, issuing, frames, contexts) {
161
+ if (issuing && issuing.microformType !== 'card')
162
+ return { kind: 'continue' };
163
+ if (request.body === null)
164
+ return { kind: 'refuse', reason: 'request_body_unreadable' };
165
+ if (!isCybersourceFlexRequest(request.url, 'POST', request.body, request.headers)) {
166
+ return { kind: 'unsupported', reason: 'microform_request_unrecognized' };
167
+ }
168
+ if (issuing === undefined)
169
+ return { kind: 'refuse', reason: 'microform_frame_unread' };
170
+ if (issuing === null)
171
+ return { kind: 'unsupported', reason: 'microform_request_unrecognized' };
172
+ if (!issuing.reviewed)
173
+ return { kind: 'unsupported', reason: 'microform_version_unreviewed' };
174
+ const fields = fieldsOf(issuing, frames);
175
+ if (!fields || !MICROFORM_FIELDS.includes(issuing.fieldType)) {
176
+ return { kind: 'unsupported', reason: 'microform_fields_unsupported' };
177
+ }
178
+ const withBody = request;
179
+ const verification = contexts.verify(issuing.captureContext);
180
+ return verification instanceof Promise
181
+ ? verification.then((settled) => afterVerification(withBody, issuing, fields, settled))
182
+ : afterVerification(withBody, issuing, fields, verification);
183
+ }
184
+ /**
185
+ * The CDP adapter's record of Microform field iframes, keyed by frame id (an out-of-process
186
+ * iframe's target id is its frame id). Fed only from CDP sources that report a document the
187
+ * frame COMMITTED, with its fragment: Page.frameNavigated (the child's own session for an
188
+ * out-of-process iframe, the parent's for an in-process one), the iframe target's url on
189
+ * Target.attachedToTarget when the SDK attaches to a form that already rendered, and the
190
+ * pausing session's Page.getFrameTree as a last read. A document request (Network.
191
+ * requestWillBeSent, Fetch.requestPaused) is only a hint that warms the context's check: a page
192
+ * can start a navigation to a genuine field URL in a frame it scripts and stop it before it
193
+ * commits, and that frame then still runs the page's own document. A frame that navigates
194
+ * elsewhere or detaches is forgotten. Bounded to the 64 most recent frames.
195
+ */
196
+ export class MicroformFrames {
197
+ frames = new Map();
198
+ contexts = new CaptureContexts();
199
+ /** Start the capture context's check from a navigation that has not committed; records nothing. */
200
+ warm(url) {
201
+ this.contexts.warm(url);
202
+ }
203
+ /** A frame's committed document URL, fragment included. A URL that is not a field iframe's forgets the frame. */
204
+ observe(frameId, url) {
205
+ if (typeof frameId !== 'string' || !frameId || frameId.length > 256)
206
+ return;
207
+ const frame = frameOf(url);
208
+ if (!frame) {
209
+ if (typeof url === 'string' && url)
210
+ this.frames.delete(frameId);
211
+ return;
212
+ }
213
+ this.frames.delete(frameId);
214
+ if (this.frames.size >= MAX_FRAMES)
215
+ this.frames.delete(this.frames.keys().next().value);
216
+ this.frames.set(frameId, frame);
217
+ // Warm the verification so the card request's pause stays synchronous.
218
+ if (frame.microformType === 'card' && frame.reviewed)
219
+ void this.contexts.verify(frame.captureContext);
220
+ }
221
+ forget(frameId) {
222
+ if (typeof frameId === 'string')
223
+ this.frames.delete(frameId);
224
+ }
225
+ /**
226
+ * Judge a POST the frame `frameId` sent. When that frame is not on record, `reread` reads the
227
+ * pausing session's frame tree once (recording what it finds) and resolves to the frame's
228
+ * committed URL, or undefined when the frame was not found or the read failed: a frame read and
229
+ * found to be no field is judged as such, one never read is refused for this request alone.
230
+ */
231
+ judge(request, frameId, reread) {
232
+ const issuing = frameId ? this.frames.get(frameId) : undefined;
233
+ if (!issuing && frameId && reread) {
234
+ return reread().catch(() => undefined).then((url) => judgeMicroformRequest(request, this.frames.get(frameId) ?? (url === undefined ? undefined : frameOf(url)), this.frames.values(), this.contexts));
235
+ }
236
+ return judgeMicroformRequest(request, issuing, this.frames.values(), this.contexts);
237
+ }
238
+ }
239
+ /**
240
+ * The Playwright adapter's judge: Playwright keeps a frame's fragment in frame.url() (checked in
241
+ * cybersource-flex-browser.test.mjs) and moves frame.url() only when a navigation commits, so the
242
+ * issuing frame and its siblings are read at pause time. `issuingUrl` is undefined when the
243
+ * request's frame could not be read at all.
244
+ */
245
+ export function judgeMicroformFrameUrls(request, issuingUrl, frameUrls, contexts) {
246
+ const frames = [];
247
+ for (const url of frameUrls) {
248
+ const frame = frameOf(url);
249
+ if (frame)
250
+ frames.push(frame);
251
+ }
252
+ return judgeMicroformRequest(request, issuingUrl === undefined ? undefined : frameOf(issuingUrl), frames, contexts);
253
+ }
254
+ /**
255
+ * Whether a create's sidecar has the shape the API admits (routes/api/v2/checkout.ts
256
+ * createSchema): a capture context of 1 to 16384 characters, and a Microform version with a
257
+ * number field, an optional security code field and a trigger among them. authorize() checks
258
+ * it before any create, so a hand-built request fails locally rather than at the API.
259
+ */
260
+ export function validCybersourceFlexSidecar(captureContext, microform) {
261
+ if (typeof captureContext !== 'string' || captureContext.length < 1 || captureContext.length > 16384)
262
+ return false;
263
+ if (!microform || typeof microform !== 'object' || Array.isArray(microform))
264
+ return false;
265
+ const value = microform;
266
+ if (Object.keys(value).some((key) => !['version', 'fields', 'trigger'].includes(key)))
267
+ return false;
268
+ if (typeof value.version !== 'string' || !/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/.test(value.version))
269
+ return false;
270
+ const fields = value.fields;
271
+ if (!Array.isArray(fields) || fields.length < 1 || fields.length > 2 || new Set(fields).size !== fields.length
272
+ || fields.some((field) => !MICROFORM_FIELDS.includes(field)) || !fields.includes('number'))
273
+ return false;
274
+ return value.trigger === undefined || fields.includes(value.trigger);
275
+ }
@@ -0,0 +1,96 @@
1
+ import { DATATRANS_CARD_ON_FILE_REFUSED, DATATRANS_INVALID_REQUEST } from './datatrans.generated.js';
2
+ import type { ReplayResponse } from './client.js';
3
+ export declare const DATATRANS_PSP = "datatrans";
4
+ /** The dark-launch capability the API serves the datatrans recognizer behind. */
5
+ export declare const DATATRANS_CAPABILITY = "datatrans_secure_fields_tokenize";
6
+ /**
7
+ * Why the SDK refuses a Datatrans card post before anything is claimed, created or prompted. The
8
+ * API answers the same two codes at create, so a refusal here only saves the round trip:
9
+ * - `invalid_datatrans_request`: not a sound Secure Fields TOKENIZE card post. That covers
10
+ * another mode, a payment or 3-D Secure post (`transactionId`, `3D`, `dccSelected`), a key
11
+ * field.js never sends, a URL variant (a query, a case or dot spelling) or a content type that
12
+ * is not jQuery's form type. The cardholder's device could never fill it.
13
+ * - `datatrans_card_on_file_refused`: a sound post that asks PCI Proxy to keep the card on file
14
+ * (usage=REGISTRATION: a reusable alias plus a network token, so the merchant could charge the
15
+ * card again later), while the card-on-file policy the API served refuses that
16
+ * (datatransCardOnFilePolicy). British Airways's Nexus checkout sends it for every new card.
17
+ */
18
+ export type DatatransRefusalReason = typeof DATATRANS_INVALID_REQUEST | typeof DATATRANS_CARD_ON_FILE_REFUSED;
19
+ /** True when the URL's host is one of Datatrans's two pay hosts. */
20
+ export declare function isDatatransHost(url: string): boolean;
21
+ /**
22
+ * The card-on-file policy this build applies to a Datatrans card post: the one the API served with
23
+ * the datatrans recognizer (Recognizer.cardOnFile, VaultClient.cardOnFilePolicy) when payment-core
24
+ * defines it (`refuse`, `disclose`, `agentcard_single_use`), and `refuse` for anything else, an entry
25
+ * that names none included. The decision is payment-core's DATATRANS_REGISTRATION_POLICY, which the
26
+ * API reads each time it serves the catalog and again at create, so a change to that one line
27
+ * reaches every build already published at its next syncRegistry(), with no SDK release.
28
+ */
29
+ export declare function datatransCardOnFilePolicy(served: unknown): string;
30
+ /**
31
+ * The pause decision for a POST the registry recognized on a Datatrans pay host, by payment-core's
32
+ * classifyDatatransRequest under the card-on-file policy the API served (datatransCardOnFilePolicy):
33
+ * 'card' the exact card URL with jQuery's form type and a sound TOKENIZE card body: it pauses. A
34
+ * usage=REGISTRATION post is one too once the served policy allows card on file, and the
35
+ * API and the cardholder's device then apply that policy;
36
+ * a DatatransRefusalReason: it is refused in the browser;
37
+ * null no card in the body (a wallet, bank-account or CVV-only post) or not the card path:
38
+ * the SDK's ordinary handling decides, and such a post continues untouched.
39
+ */
40
+ export declare function datatransPauseDecision(request: {
41
+ url: string;
42
+ headers: Record<string, string>;
43
+ body: string | null;
44
+ }, servedPolicy?: unknown): 'card' | DatatransRefusalReason | null;
45
+ /**
46
+ * How long an approved Datatrans answer is replayed to its own frame: the token's own lifetime
47
+ * (PCI Proxy keeps a tokenization readable for 30 minutes). Past it the stored transactionId names a
48
+ * token the merchant can no longer read, so a later post is a new question.
49
+ */
50
+ export declare const DATATRANS_REPEAT_WINDOW_MS: number;
51
+ /**
52
+ * How long a stored answer waits for its form's next post. British Airways re-submits while the agent
53
+ * finishes the card form, right after the approved answer. A form that posts nothing for this long has
54
+ * moved on: the order was placed or abandoned, which the SDK cannot tell apart without reconcile(). Its
55
+ * next post is a new approval. Each answered re-submit restarts the wait, and the token's lifetime
56
+ * still ends every answer.
57
+ */
58
+ export declare const DATATRANS_REPEAT_IDLE_MS: number;
59
+ /** A stored answer handed to a repeat, with the approval it came from. */
60
+ export interface DatatransRepeatAnswer {
61
+ authorizationId: string;
62
+ response: {
63
+ status: number;
64
+ headers: Record<string, string>;
65
+ body: string;
66
+ };
67
+ }
68
+ /**
69
+ * The approved Datatrans answers one attachment handed to a card post, per frame. `frame` is the
70
+ * adapter's identity for the request's frame (the CDP frameId, the Playwright Frame); a request
71
+ * whose frame is unknown is never remembered and never answered. Only an answer payment-core reads
72
+ * as approved ({transactionId, cardInfo}) is kept: an error answer leaves the next post a new
73
+ * question, so the page can try again.
74
+ */
75
+ export declare class DatatransRepeats {
76
+ private readonly windowMs;
77
+ private readonly now;
78
+ private readonly idleMs;
79
+ private remembered;
80
+ constructor(windowMs?: number, now?: () => number, idleMs?: number);
81
+ /**
82
+ * Keep the answer a token replay handed to this card post, when Datatrans approved it. Called
83
+ * after the answer reached the browser, so it never throws: a failure here only leaves the
84
+ * page's next post a new question.
85
+ */
86
+ remember(frame: unknown, url: string, body: string | null, replay: ReplayResponse): void;
87
+ /**
88
+ * The stored answer for a repeat of an answered card post from the same frame, or null. Only an
89
+ * answer from `authorizationId`, the approval the attachment is handing off now, is handed out,
90
+ * and every answer from another approval is dropped: a later authorization ends the window of
91
+ * every earlier one. An answer whose form stayed quiet past the idle bound is dropped too, and
92
+ * handing one out restarts that bound.
93
+ */
94
+ answerFor(frame: unknown, url: string, body: string | null, authorizationId: string | null): DatatransRepeatAnswer | null;
95
+ private prune;
96
+ }
@@ -0,0 +1,64 @@
1
+ declare var DATATRANS_HOSTS: readonly string[];
2
+ declare var DATATRANS_TOKENIZE_PATH: string;
3
+ declare var DATATRANS_REFUSAL_REASONS: readonly string[];
4
+ declare var DATATRANS_INVALID_REQUEST: string;
5
+ declare var DATATRANS_CARD_ON_FILE_REFUSED: string;
6
+ declare var DATATRANS_REGISTRATION_POLICIES: readonly string[];
7
+ declare var DATATRANS_REGISTRATION_POLICY: string;
8
+ declare var DATATRANS_REVIEWED_MERCHANT_IDS: Readonly<{
9
+ "pay.datatrans.com": readonly never[];
10
+ "pay.sandbox.datatrans.com": readonly string[];
11
+ }>;
12
+ declare var DATATRANS_PAYMENT_METHODS: readonly string[];
13
+ declare var DATATRANS_TEST_PANS: readonly string[];
14
+ declare function encodeDatatransFormValue(value: any): string;
15
+ declare function parseDatatransForm(body: any): {
16
+ key: string;
17
+ value: string;
18
+ rawKey: string;
19
+ raw: string;
20
+ }[] | null;
21
+ declare function serializeDatatransForm(pairs: any): any;
22
+ declare function isDatatransTokenizeUrl(url: any, method?: string): boolean;
23
+ declare function datatransRegistrationRefusal(usage: any, card: any, policy?: string): "card_on_file" | null;
24
+ declare function datatransCardOnFileDisclosure(body: any, policy?: string): boolean;
25
+ declare function datatransBodyRefusal(body: any, card: any, policy?: string): "unsupported" | "card_on_file" | null;
26
+ declare function datatransMerchantId(body: any): string | null | undefined;
27
+ declare function classifyDatatransRequest(url: any, method: any, body: any, headers: any, policy?: string): "card" | "unsupported" | "card_on_file" | null;
28
+ declare function datatransTokenizeRefusal(request: any, card: any, policy?: string): "unsupported" | "card_on_file" | null;
29
+ declare function isDatatransTokenizeRequest(request: any, card: any): boolean;
30
+ declare function datatransMerchantRefusal(url: any, body: any, merchants?: Readonly<{
31
+ "pay.datatrans.com": readonly never[];
32
+ "pay.sandbox.datatrans.com": readonly string[];
33
+ }>): "unregistered_merchant" | null;
34
+ declare function datatransDeviceRefusal(request: any, card: any, policy?: string, merchants?: Readonly<{
35
+ "pay.datatrans.com": readonly never[];
36
+ "pay.sandbox.datatrans.com": readonly string[];
37
+ }>): "unsupported" | "card_on_file" | "brand_mismatch" | "unregistered_merchant" | null;
38
+ declare function datatransRefusalMessage(reason: any): string;
39
+ declare function datatransCardBrand(number: any): "VIS" | "ECA" | "AMX" | null;
40
+ declare function datatransBrandRefusal(body: any, card: any): "unsupported" | "brand_mismatch" | null;
41
+ declare function injectDatatransCard(body: any, card: any, policy?: string): {
42
+ body: string;
43
+ where: string[];
44
+ };
45
+ declare function datatransErrorCode(message: any): string | RegExp;
46
+ declare function datatransResponseOutcome(status: any, body: any, card: any): {
47
+ outcome: string;
48
+ reason: string;
49
+ code?: undefined;
50
+ } | {
51
+ outcome: string;
52
+ code: string | RegExp;
53
+ reason?: undefined;
54
+ } | {
55
+ outcome: string;
56
+ reason?: undefined;
57
+ code?: undefined;
58
+ };
59
+ declare function sanitizeDatatransTokenResponse(body: any): string;
60
+ declare function datatransFacts(status: any, body: any): {
61
+ outcome: string;
62
+ refusalCode: string | RegExp | null | undefined;
63
+ };
64
+ export { DATATRANS_CARD_ON_FILE_REFUSED, DATATRANS_HOSTS, DATATRANS_INVALID_REQUEST, DATATRANS_PAYMENT_METHODS, DATATRANS_REFUSAL_REASONS, DATATRANS_REGISTRATION_POLICIES, DATATRANS_REGISTRATION_POLICY, DATATRANS_REVIEWED_MERCHANT_IDS, DATATRANS_TEST_PANS, DATATRANS_TOKENIZE_PATH, classifyDatatransRequest, datatransBodyRefusal, datatransBrandRefusal, datatransCardBrand, datatransCardOnFileDisclosure, datatransDeviceRefusal, datatransErrorCode, datatransFacts, datatransMerchantId, datatransMerchantRefusal, datatransRefusalMessage, datatransRegistrationRefusal, datatransResponseOutcome, datatransTokenizeRefusal, encodeDatatransFormValue, injectDatatransCard, isDatatransTokenizeRequest, isDatatransTokenizeUrl, parseDatatransForm, sanitizeDatatransTokenResponse, serializeDatatransForm };