@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.
- package/README.md +6 -753
- package/cdp.d.ts +1 -0
- package/cdp.js +2 -0
- package/index.d.ts +1 -0
- package/index.js +2 -0
- package/package.json +33 -33
- package/playwright.d.ts +1 -0
- package/playwright.js +2 -0
- package/preflight.d.ts +1 -0
- package/preflight.js +2 -0
- package/CHANGELOG.md +0 -132
- package/PREFLIGHT.md +0 -312
- package/dist/adyen-merchant-hosted.generated.d.ts +0 -277
- package/dist/adyen-merchant-hosted.generated.js +0 -1902
- package/dist/adyen.generated.d.ts +0 -24
- package/dist/adyen.generated.js +0 -64
- package/dist/attachment.d.ts +0 -11
- package/dist/attachment.js +0 -50
- package/dist/braintree.d.ts +0 -2
- package/dist/braintree.generated.d.ts +0 -10
- package/dist/braintree.generated.js +0 -302
- package/dist/braintree.js +0 -2
- package/dist/builtin-registry.generated.d.ts +0 -2
- package/dist/builtin-registry.generated.js +0 -1
- package/dist/card-fields.generated.d.ts +0 -3
- package/dist/card-fields.generated.js +0 -46
- package/dist/cdp.d.ts +0 -192
- package/dist/cdp.js +0 -2393
- package/dist/checkout-com.generated.d.ts +0 -4
- package/dist/checkout-com.generated.js +0 -183
- package/dist/client.d.ts +0 -849
- package/dist/client.js +0 -1754
- package/dist/cse-body.d.ts +0 -25
- package/dist/cse-body.js +0 -41
- package/dist/fiserv.d.ts +0 -65
- package/dist/fiserv.generated.d.ts +0 -73
- package/dist/fiserv.generated.js +0 -830
- package/dist/fiserv.js +0 -104
- package/dist/hosted-form.d.ts +0 -44
- package/dist/hosted-form.js +0 -78
- package/dist/index.d.ts +0 -18
- package/dist/index.js +0 -10
- package/dist/lifecycle.d.ts +0 -179
- package/dist/lifecycle.js +0 -395
- package/dist/mercado-checkout.d.ts +0 -20
- package/dist/mercado-checkout.generated.d.ts +0 -52
- package/dist/mercado-checkout.generated.js +0 -198
- package/dist/mercado-checkout.js +0 -108
- package/dist/merchant-handoff.d.ts +0 -54
- package/dist/merchant-handoff.js +0 -100
- package/dist/merchant-hosted.d.ts +0 -140
- package/dist/merchant-hosted.js +0 -170
- package/dist/merchant-total-watch.d.ts +0 -115
- package/dist/merchant-total-watch.js +0 -268
- package/dist/merchant-total.d.ts +0 -257
- package/dist/merchant-total.js +0 -383
- package/dist/owned-shop.generated.d.ts +0 -24
- package/dist/owned-shop.generated.js +0 -108
- package/dist/paysafe.generated.d.ts +0 -12
- package/dist/paysafe.generated.js +0 -87
- package/dist/playwright.d.ts +0 -3
- package/dist/playwright.js +0 -3
- package/dist/pre-claim.d.ts +0 -123
- package/dist/pre-claim.js +0 -386
- package/dist/preflight-capabilities.generated.d.ts +0 -1253
- package/dist/preflight-capabilities.generated.js +0 -1929
- package/dist/preflight-catalog.json +0 -4727
- package/dist/preflight-playwright.d.ts +0 -34
- package/dist/preflight-playwright.js +0 -355
- package/dist/preflight-schemas.json +0 -1122
- package/dist/preflight.d.ts +0 -1
- package/dist/preflight.generated.d.ts +0 -1965
- package/dist/preflight.generated.js +0 -570
- package/dist/preflight.js +0 -2
- package/dist/preparation.d.ts +0 -38
- package/dist/preparation.js +0 -191
- package/dist/prepared-processor.d.ts +0 -43
- package/dist/prepared-processor.js +0 -172
- package/dist/recurly.generated.d.ts +0 -1
- package/dist/recurly.generated.js +0 -87
- package/dist/registry.d.ts +0 -121
- package/dist/registry.js +0 -310
- package/dist/spreedly.generated.d.ts +0 -10
- package/dist/spreedly.generated.js +0 -332
- package/dist/stripe-checkout.d.ts +0 -81
- package/dist/stripe-checkout.generated.d.ts +0 -82
- package/dist/stripe-checkout.generated.js +0 -1093
- package/dist/stripe-checkout.js +0 -140
- package/dist/substitute.d.ts +0 -38
- package/dist/substitute.js +0 -23
- package/dist/substitutions.generated.d.ts +0 -11
- package/dist/substitutions.generated.js +0 -818
- package/examples/existing-browser.mjs +0 -63
- package/examples/preflight/classify-direct.mjs +0 -21
- package/examples/preflight/classify-kernel.mjs +0 -30
- package/examples/preflight/inspect-browser.mjs +0 -44
- package/examples/preflight/kernel-native/README.md +0 -112
- package/examples/preflight/kernel-native/documented-adapters.json +0 -113
- package/examples/preflight/kernel-native/inventory.json +0 -233
- package/examples/preflight/kernel-native/qualification.mjs +0 -182
- package/examples/preflight/kernel-profile.empty.json +0 -11
- package/examples/preflight/mollie-hosted.observations.json +0 -23
- package/examples/preflight/mollie-hosted.result.json +0 -103
- package/examples/preflight/stripe-script.direct.result.json +0 -92
- package/examples/preflight/stripe-script.observations.json +0 -16
- package/examples/preflight/stripe-script.result.json +0 -87
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
// Generated from @agent-cards/payment-core. Do not edit.
|
|
3
|
-
// artifact-sha256: 0ea817a75d86052699eeaa7546950e6c046bb0d7a96e4a18dfcd3a0fdd2afc99
|
|
4
|
-
// src/mercado-checkout.js
|
|
5
|
-
var MERCADO_CHECKOUT_ORIGIN = "https://www.mercadopago.com.mx";
|
|
6
|
-
var MERCADO_CONFIGURATION_URL = MERCADO_CHECKOUT_ORIGIN + "/checkout/v1/payment/api/bricks/card-form/tokenization";
|
|
7
|
-
var MERCADO_CHECKOUT_PATTERN = MERCADO_CHECKOUT_ORIGIN + "/checkout/v1/payment/api/*";
|
|
8
|
-
var reject = () => {
|
|
9
|
-
throw new Error("mercado_checkout_context_invalid");
|
|
10
|
-
};
|
|
11
|
-
var object = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
12
|
-
var only = (v, keys) => object(v) && Object.keys(v).every((k) => keys.includes(k));
|
|
13
|
-
var exact = (v, keys) => only(v, keys) && keys.every((k) => Object.hasOwn(v, k));
|
|
14
|
-
var text = (v, max = 200) => typeof v === "string" && v.length > 0 && v.length <= max && !/[\u0000-\u001f\u007f]/.test(v);
|
|
15
|
-
var id = (v) => typeof v === "string" && /^[A-Za-z0-9_-]{1,128}$/.test(v);
|
|
16
|
-
var numberId = (v) => typeof v === "string" && /^\d{1,20}$/.test(v);
|
|
17
|
-
var label = (v) => text(v, 120) && /\p{L}/u.test(v) && !/[<>]|\d(?:[ -]*\d){5}|https?:|javascript:|data:/i.test(v);
|
|
18
|
-
var digest = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v);
|
|
19
|
-
var METHODS = ["visa", "master", "amex"];
|
|
20
|
-
var TYPES = ["credit_card", "debit_card", "prepaid_card"];
|
|
21
|
-
function checkedUrl(raw) {
|
|
22
|
-
let url;
|
|
23
|
-
try {
|
|
24
|
-
url = new URL(raw);
|
|
25
|
-
}
|
|
26
|
-
catch {
|
|
27
|
-
reject();
|
|
28
|
-
}
|
|
29
|
-
if (!text(raw, 4096) || url.href !== raw || url.origin !== MERCADO_CHECKOUT_ORIGIN || url.username || url.password || url.hash)
|
|
30
|
-
reject();
|
|
31
|
-
return url;
|
|
32
|
-
}
|
|
33
|
-
function mercadoCheckoutDocument(raw) {
|
|
34
|
-
const url = checkedUrl(raw);
|
|
35
|
-
const match = /^\/checkout\/v1\/payment\/redirect\/([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})\/card-form\/$/.exec(url.pathname);
|
|
36
|
-
const keys = [...url.searchParams.keys()];
|
|
37
|
-
if (!match || keys.length !== 3 || new Set(keys).size !== 3 || keys.some((k) => !["preference-id", "router-request-id", "p"].includes(k)) || !id(url.searchParams.get("preference-id")) || !id(url.searchParams.get("router-request-id")) || !text(url.searchParams.get("p"), 2048))
|
|
38
|
-
reject();
|
|
39
|
-
return { flowId: match[1], preferenceId: url.searchParams.get("preference-id"), query: url.search.slice(1) };
|
|
40
|
-
}
|
|
41
|
-
function initialization(value) {
|
|
42
|
-
const keys = [
|
|
43
|
-
"callerId",
|
|
44
|
-
"collectorId",
|
|
45
|
-
"allowThirdPartyCard",
|
|
46
|
-
"clientId",
|
|
47
|
-
"flowId",
|
|
48
|
-
"checkoutId",
|
|
49
|
-
"scope",
|
|
50
|
-
"excludedPaymentTypesAndIds",
|
|
51
|
-
"locale",
|
|
52
|
-
"siteId",
|
|
53
|
-
"serviceRoutePrefix",
|
|
54
|
-
"productId",
|
|
55
|
-
"marketplace",
|
|
56
|
-
"platform",
|
|
57
|
-
"cardDetails"
|
|
58
|
-
];
|
|
59
|
-
if (!exact(value, keys) || !numberId(value.callerId) || !numberId(value.collectorId) || !numberId(value.clientId) || value.allowThirdPartyCard !== true || value.flowId !== "checkout-pro-payment" || value.checkoutId !== "cow" || value.scope !== "prod" || value.locale !== "es-MX" || value.siteId !== "MLM" || value.serviceRoutePrefix !== "/checkout/v1/payment/api" || !id(value.productId) || value.marketplace !== "NONE" || value.platform !== "MP" || !Array.isArray(value.excludedPaymentTypesAndIds) || value.excludedPaymentTypesAndIds.length !== 0 || !exact(value.cardDetails, ["fieldsSetting", "identificationTypes", "additionalSteps"]) || !Array.isArray(value.cardDetails.identificationTypes) || value.cardDetails.identificationTypes.length !== 0 || JSON.stringify(value.cardDetails.additionalSteps) !== '["name"]')
|
|
60
|
-
reject();
|
|
61
|
-
const fields = value.cardDetails.fieldsSetting;
|
|
62
|
-
if (!Array.isArray(fields) || fields.length !== 5 || new Set(fields.map((f) => f?.name)).size !== 5)
|
|
63
|
-
reject();
|
|
64
|
-
for (const field of fields) {
|
|
65
|
-
if (!only(field, ["name", "type", "title", "placeholder", "length", "validationMessages", "mask", "hintMessage", "validationPattern", "autocomplete", "tooltipMessage"]) || !["card_number", "name", "expiration", "security_code", "identification_types"].includes(field.name) || field.type !== (field.name === "name" ? "text" : "number") || !text(field.title) || field.placeholder !== void 0 && !text(field.placeholder) || ["hintMessage", "validationPattern", "tooltipMessage"].some((k) => field[k] !== void 0 && !text(field[k], 1024)) || field.autocomplete !== void 0 && typeof field.autocomplete !== "boolean" || field.length !== void 0 && (!Number.isInteger(field.length) || field.length < 1 || field.length > 40) || field.mask !== void 0 && (!text(field.mask, 30) || !/^[ $/]+$/.test(field.mask)) || !only(field.validationMessages, ["emptyField", "incompleteField", "invalidField"]) || Object.values(field.validationMessages).some((v) => !text(v)))
|
|
66
|
-
reject();
|
|
67
|
-
}
|
|
68
|
-
if (JSON.stringify(value).length > 12e3)
|
|
69
|
-
reject();
|
|
70
|
-
return value;
|
|
71
|
-
}
|
|
72
|
-
function parseMercadoCheckoutContext(value) {
|
|
73
|
-
if (!exact(value, ["version", "documentUrl", "initializationData"]) || value.version !== 1)
|
|
74
|
-
reject();
|
|
75
|
-
mercadoCheckoutDocument(value.documentUrl);
|
|
76
|
-
initialization(value.initializationData);
|
|
77
|
-
return JSON.parse(JSON.stringify(value));
|
|
78
|
-
}
|
|
79
|
-
function captureMercadoCheckoutContext(url, method, body, documentUrl) {
|
|
80
|
-
if (url !== MERCADO_CONFIGURATION_URL || method !== "POST" || typeof body !== "string" || body.length > 16e3)
|
|
81
|
-
reject();
|
|
82
|
-
let parsed;
|
|
83
|
-
try {
|
|
84
|
-
parsed = JSON.parse(body);
|
|
85
|
-
}
|
|
86
|
-
catch {
|
|
87
|
-
reject();
|
|
88
|
-
}
|
|
89
|
-
if (!exact(parsed, ["cardBin", "initializationData"]) || typeof parsed.cardBin !== "string" || !/^\d{8}$/.test(parsed.cardBin))
|
|
90
|
-
reject();
|
|
91
|
-
return parseMercadoCheckoutContext({ version: 1, documentUrl, initializationData: parsed.initializationData });
|
|
92
|
-
}
|
|
93
|
-
function isMercadoTokenRequest(url, method) {
|
|
94
|
-
try {
|
|
95
|
-
const value = new URL(url), names = [...value.searchParams.keys()];
|
|
96
|
-
return method === "POST" && value.href === url && value.origin === "https://api.mercadopago.com" && value.pathname === "/v1/card_tokens" && !value.username && !value.password && !value.hash && new Set(names).size === names.length && names.every((n) => ["public_key", "locale", "js_version", "referer"].includes(n)) && id(value.searchParams.get("public_key"));
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
async function mercadoDigest(value) {
|
|
103
|
-
const bytes = new TextEncoder().encode(value);
|
|
104
|
-
return Array.from(new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", bytes)), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
105
|
-
}
|
|
106
|
-
function canonical(value) {
|
|
107
|
-
return Array.isArray(value) ? value.map(canonical) : object(value) ? Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonical(value[key])])) : value;
|
|
108
|
-
}
|
|
109
|
-
async function mercadoContextDigest(context, tokenUrl) {
|
|
110
|
-
if (!isMercadoTokenRequest(tokenUrl, "POST"))
|
|
111
|
-
reject();
|
|
112
|
-
return mercadoDigest(JSON.stringify(canonical({ context: parseMercadoCheckoutContext(context), tokenUrl })));
|
|
113
|
-
}
|
|
114
|
-
function prepareMercadoConfiguration(context, card) {
|
|
115
|
-
const parsed = parseMercadoCheckoutContext(context);
|
|
116
|
-
const number = card?.number;
|
|
117
|
-
if (typeof number !== "string" || !/^\d{12,19}$/.test(number))
|
|
118
|
-
reject();
|
|
119
|
-
return { url: MERCADO_CONFIGURATION_URL, body: JSON.stringify({ cardBin: number.slice(0, 8), initializationData: parsed.initializationData }) };
|
|
120
|
-
}
|
|
121
|
-
function parseMercadoConfiguration(value) {
|
|
122
|
-
const method = value?.paymentMethod, issuers = value?.issuersSettings;
|
|
123
|
-
if (!object(value) || !exact(method, ["paymentMethodId", "paymentTypeId", "name"]) || !METHODS.includes(method.paymentMethodId) || !TYPES.includes(method.paymentTypeId) || !label(method.name) || !Array.isArray(issuers) || issuers.length !== 1 || !object(issuers[0]) || !label(issuers[0].name))
|
|
124
|
-
reject();
|
|
125
|
-
const issuerId = String(issuers[0].id);
|
|
126
|
-
if (!/^\d{1,11}$/.test(issuerId) || typeof issuers[0].id !== "string" && !Number.isSafeInteger(issuers[0].id))
|
|
127
|
-
reject();
|
|
128
|
-
const cvc = Array.isArray(value.fieldsSetting) ? value.fieldsSetting.filter((f) => f?.name === "security_code") : [];
|
|
129
|
-
const amex = method.paymentMethodId === "amex";
|
|
130
|
-
if (cvc.length !== 1 || cvc[0].type !== "number" || cvc[0].length !== (amex ? 4 : 3) || value.securityCodeSettings?.mode !== "mandatory" || value.securityCodeSettings?.location !== (amex ? "front" : "back"))
|
|
131
|
-
reject();
|
|
132
|
-
return {
|
|
133
|
-
paymentMethodId: method.paymentMethodId,
|
|
134
|
-
paymentTypeId: method.paymentTypeId,
|
|
135
|
-
paymentMethodName: method.name,
|
|
136
|
-
issuerId,
|
|
137
|
-
issuerName: issuers[0].name
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
function tokenIdentity(body) {
|
|
141
|
-
let value;
|
|
142
|
-
try {
|
|
143
|
-
value = JSON.parse(body);
|
|
144
|
-
}
|
|
145
|
-
catch {
|
|
146
|
-
reject();
|
|
147
|
-
}
|
|
148
|
-
if (!object(value) || value.live_mode === false || typeof value.id !== "string" || !/^[A-Za-z0-9_-]{8,256}$/.test(value.id))
|
|
149
|
-
reject();
|
|
150
|
-
return value.id;
|
|
151
|
-
}
|
|
152
|
-
async function createMercadoProcessorContext(configuration, context, tokenUrl, tokenBody) {
|
|
153
|
-
return {
|
|
154
|
-
version: 1,
|
|
155
|
-
psp: "mercado_pago",
|
|
156
|
-
source: "checkout_pro_bin8",
|
|
157
|
-
contextDigest: await mercadoContextDigest(context, tokenUrl),
|
|
158
|
-
tokenDigest: await mercadoDigest(tokenIdentity(tokenBody)),
|
|
159
|
-
...parseMercadoConfiguration(configuration)
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
async function validateMercadoProcessorContext(value, context, tokenUrl, tokenBody) {
|
|
163
|
-
if (!exact(value, ["version", "psp", "source", "contextDigest", "tokenDigest", "paymentMethodId", "paymentTypeId", "paymentMethodName", "issuerId", "issuerName"]) || value.version !== 1 || value.psp !== "mercado_pago" || value.source !== "checkout_pro_bin8" || !digest(value.contextDigest) || !digest(value.tokenDigest) || !METHODS.includes(value.paymentMethodId) || !TYPES.includes(value.paymentTypeId) || !label(value.paymentMethodName) || !numberId(value.issuerId) || value.issuerId.length > 11 || !label(value.issuerName) || value.contextDigest !== await mercadoContextDigest(context, tokenUrl) || value.tokenDigest !== await mercadoDigest(tokenIdentity(tokenBody)))
|
|
164
|
-
reject();
|
|
165
|
-
return { ...value };
|
|
166
|
-
}
|
|
167
|
-
async function createMercadoAssociationGate({ context, tokenUrl, tokenBody, processorContext }) {
|
|
168
|
-
const checked = parseMercadoCheckoutContext(context), metadata = await validateMercadoProcessorContext(processorContext, checked, tokenUrl, tokenBody);
|
|
169
|
-
const document = mercadoCheckoutDocument(checked.documentUrl), token = tokenIdentity(tokenBody);
|
|
170
|
-
let claimed = false;
|
|
171
|
-
return { take({ url, method, body, documentUrl }) {
|
|
172
|
-
if (claimed)
|
|
173
|
-
reject();
|
|
174
|
-
const target = checkedUrl(url);
|
|
175
|
-
if (method !== "PUT" || documentUrl !== checked.documentUrl || target.pathname !== "/checkout/v1/payment/api/flow/" + document.flowId || target.search || typeof body !== "string" || body.length > 64e3)
|
|
176
|
-
reject();
|
|
177
|
-
let parsed;
|
|
178
|
-
try {
|
|
179
|
-
parsed = JSON.parse(body);
|
|
180
|
-
}
|
|
181
|
-
catch {
|
|
182
|
-
reject();
|
|
183
|
-
}
|
|
184
|
-
if (!only(parsed, ["id", "values", "type", "featureFlags", "version", "prev_step", "urlParams"]) || parsed.id !== "next_step" || parsed.type !== "redirect" || parsed.version !== "checkout" || parsed.prev_step !== "card_form" || parsed.urlParams !== document.query || !only(parsed.values, ["payment_method", "card_token", "card_ui_settings", "captchaToken"]) || parsed.values.card_token !== token || !object(parsed.values.card_ui_settings) || !only(parsed.values.payment_method, ["id", "type", "name", "issuer"]) || parsed.values.payment_method.id !== metadata.paymentMethodId || parsed.values.payment_method.type !== metadata.paymentTypeId)
|
|
185
|
-
reject();
|
|
186
|
-
claimed = true;
|
|
187
|
-
parsed.values.payment_method = {
|
|
188
|
-
id: metadata.paymentMethodId,
|
|
189
|
-
type: metadata.paymentTypeId,
|
|
190
|
-
name: metadata.paymentMethodName,
|
|
191
|
-
issuer: { id: Number(metadata.issuerId), name: metadata.issuerName }
|
|
192
|
-
};
|
|
193
|
-
return JSON.stringify(parsed);
|
|
194
|
-
}, get claimed() {
|
|
195
|
-
return claimed;
|
|
196
|
-
} };
|
|
197
|
-
}
|
|
198
|
-
export { MERCADO_CHECKOUT_ORIGIN, MERCADO_CHECKOUT_PATTERN, MERCADO_CONFIGURATION_URL, captureMercadoCheckoutContext, createMercadoAssociationGate, createMercadoProcessorContext, isMercadoTokenRequest, mercadoCheckoutDocument, mercadoContextDigest, mercadoDigest, parseMercadoCheckoutContext, parseMercadoConfiguration, prepareMercadoConfiguration, validateMercadoProcessorContext };
|
package/dist/mercado-checkout.js
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { captureMercadoCheckoutContext, createMercadoAssociationGate, isMercadoTokenRequest, MERCADO_CONFIGURATION_URL, MERCADO_CHECKOUT_ORIGIN, parseMercadoCheckoutContext } from './mercado-checkout.generated.js';
|
|
2
|
-
/** Capture only the native Checkout Pro configuration. A late configuration,
|
|
3
|
-
* navigation or repeated token cannot replace the context of an issued token.
|
|
4
|
-
* Final payment requests retain the attachment's existing payment guards.
|
|
5
|
-
*/
|
|
6
|
-
export class MercadoCheckoutGate {
|
|
7
|
-
context = null;
|
|
8
|
-
started = false;
|
|
9
|
-
stopped = false;
|
|
10
|
-
sequence = 0;
|
|
11
|
-
associatedFlow = null;
|
|
12
|
-
association = null;
|
|
13
|
-
matches(url) {
|
|
14
|
-
try {
|
|
15
|
-
const parsed = new URL(url);
|
|
16
|
-
return parsed.origin === MERCADO_CHECKOUT_ORIGIN
|
|
17
|
-
&& (parsed.pathname === new URL(MERCADO_CONFIGURATION_URL).pathname || parsed.pathname.startsWith('/checkout/v1/payment/api/flow/'));
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
requiresDocument(url, method) {
|
|
24
|
-
try {
|
|
25
|
-
const parsed = new URL(url);
|
|
26
|
-
return method.toUpperCase() === 'POST'
|
|
27
|
-
&& parsed.origin === 'https://api.mercadopago.com' && /^\/v1\/card_tokens$/i.test(parsed.pathname);
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
invalidate() {
|
|
34
|
-
if (!this.context && !this.started && this.sequence === 0)
|
|
35
|
-
return;
|
|
36
|
-
this.stopped = true;
|
|
37
|
-
this.context = null;
|
|
38
|
-
this.association = null;
|
|
39
|
-
this.sequence++;
|
|
40
|
-
}
|
|
41
|
-
async configuration(url, method, body, readDocument) {
|
|
42
|
-
if (url !== MERCADO_CONFIGURATION_URL || method !== 'POST')
|
|
43
|
-
return false;
|
|
44
|
-
if (this.started || this.stopped)
|
|
45
|
-
throw new Error('mercado_checkout_configuration_changed');
|
|
46
|
-
const sequence = ++this.sequence;
|
|
47
|
-
this.context = null;
|
|
48
|
-
const documentUrl = await readDocument();
|
|
49
|
-
// A newer native BIN lookup owns the context; the older harmless lookup
|
|
50
|
-
// still continues, but cannot erase or invalidate that newer capture.
|
|
51
|
-
if (sequence !== this.sequence && !this.stopped)
|
|
52
|
-
return true;
|
|
53
|
-
const context = captureMercadoCheckoutContext(url, method, body, documentUrl);
|
|
54
|
-
if (sequence !== this.sequence || this.started || this.stopped)
|
|
55
|
-
throw new Error('mercado_checkout_configuration_changed');
|
|
56
|
-
this.context = context;
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
claimToken(url, method, documentUrl) {
|
|
60
|
-
if (!this.requiresDocument(url, method))
|
|
61
|
-
return undefined;
|
|
62
|
-
// Other Mercado products remain on their existing tokenization path.
|
|
63
|
-
if (!documentUrl.startsWith(MERCADO_CHECKOUT_ORIGIN + '/checkout/'))
|
|
64
|
-
return undefined;
|
|
65
|
-
if (!isMercadoTokenRequest(url, method) || this.started || this.stopped || !this.context || this.context.documentUrl !== documentUrl)
|
|
66
|
-
throw new Error('mercado_checkout_configuration_unavailable');
|
|
67
|
-
this.started = true;
|
|
68
|
-
return parseMercadoCheckoutContext(this.context);
|
|
69
|
-
}
|
|
70
|
-
async arm(replay, tokenUrl) {
|
|
71
|
-
if (!this.started)
|
|
72
|
-
return;
|
|
73
|
-
if (this.stopped || !this.context || replay.mode !== 'token' || replay.status !== 201 || !replay.processorContext)
|
|
74
|
-
throw new Error('mercado_checkout_metadata_unavailable');
|
|
75
|
-
const context = this.context;
|
|
76
|
-
const association = await createMercadoAssociationGate({ context, tokenUrl, tokenBody: replay.body, processorContext: replay.processorContext });
|
|
77
|
-
if (this.stopped || this.context !== context)
|
|
78
|
-
throw new Error('mercado_checkout_context_changed');
|
|
79
|
-
this.association = association;
|
|
80
|
-
}
|
|
81
|
-
associationBody(url, method, body, documentUrl) {
|
|
82
|
-
if (['GET', 'HEAD', 'OPTIONS'].includes(method) || !this.matches(url) || url === MERCADO_CONFIGURATION_URL)
|
|
83
|
-
return undefined;
|
|
84
|
-
let parsed;
|
|
85
|
-
try {
|
|
86
|
-
parsed = JSON.parse(body);
|
|
87
|
-
}
|
|
88
|
-
catch {
|
|
89
|
-
if (this.started)
|
|
90
|
-
throw new Error('mercado_checkout_association_invalid');
|
|
91
|
-
return undefined;
|
|
92
|
-
}
|
|
93
|
-
// The observed Pay request keeps the existing payment guards, including
|
|
94
|
-
// after the native document navigates to review. Every card association
|
|
95
|
-
// must use the checked shape; changing prev_step cannot bypass correction.
|
|
96
|
-
const cardAssociation = parsed?.id === 'next_step' || parsed?.prev_step === 'card_form'
|
|
97
|
-
|| (parsed?.values && ('card_token' in parsed.values || 'payment_method' in parsed.values));
|
|
98
|
-
if (!cardAssociation && parsed?.id === 'pay' && parsed?.prev_step === 'review' && this.associatedFlow === url)
|
|
99
|
-
return undefined;
|
|
100
|
-
if (!cardAssociation && !this.started)
|
|
101
|
-
return undefined;
|
|
102
|
-
if (!this.started || this.stopped || !this.association)
|
|
103
|
-
throw new Error('mercado_checkout_association_unavailable');
|
|
104
|
-
const corrected = this.association.take({ url, method, body, documentUrl });
|
|
105
|
-
this.associatedFlow = url;
|
|
106
|
-
return corrected;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import type { CheckoutLifecycle } from './lifecycle.js';
|
|
2
|
-
/** onEvent is ordinary integrator telemetry; the shape matches AttachOptions.onEvent. */
|
|
3
|
-
type HandoffEvent = {
|
|
4
|
-
type: string;
|
|
5
|
-
detail?: unknown;
|
|
6
|
-
};
|
|
7
|
-
/**
|
|
8
|
-
* A merchant-hosted card request after hand-off, shared by the CDP and
|
|
9
|
-
* Playwright adapters so both read it the same way.
|
|
10
|
-
*
|
|
11
|
-
* The browser continued the merchant's own request with the Vault's ciphertext in
|
|
12
|
-
* it; the merchant's server now charges the card through Adyen and answers its own
|
|
13
|
-
* page. Nothing Agentcard holds says whether it did. Two things after hand-off are
|
|
14
|
-
* therefore an unknown outcome, never a failure to retry:
|
|
15
|
-
* - the continued request answers 5xx or fails in the network: the merchant may
|
|
16
|
-
* have charged the card, and its page may never learn that it did;
|
|
17
|
-
* - the page sends the card request again before an answer arrived (Dick's
|
|
18
|
-
* retries on a network error or a 500, ATG on anything not OK): its retry
|
|
19
|
-
* carries the agent's dummy card, and the approval is spent.
|
|
20
|
-
* Either reports `payment_outcome_unknown` once and holds the checkout until the
|
|
21
|
-
* application reconciles the merchant order. Every card request to the same
|
|
22
|
-
* profile after hand-off is aborted, answered or not: a prepared approval is
|
|
23
|
-
* single use.
|
|
24
|
-
*
|
|
25
|
-
* Which of the two it reports follows the order the page saw them in. A page that
|
|
26
|
-
* retries because the merchant answered 5xx read that answer first, but an
|
|
27
|
-
* adapter can read the retry first (Chrome pauses a request in the browser
|
|
28
|
-
* process, ahead of the renderer's report of the answer), so retried() judges
|
|
29
|
-
* a retry once the adapter has read what the page reported before sending it.
|
|
30
|
-
*/
|
|
31
|
-
export declare class MerchantHandoffWatch {
|
|
32
|
-
private readonly lifecycle;
|
|
33
|
-
private readonly onEvent?;
|
|
34
|
-
private handoff;
|
|
35
|
-
private answered;
|
|
36
|
-
private reported;
|
|
37
|
-
constructor(lifecycle: CheckoutLifecycle, onEvent?: ((event: HandoffEvent) => void) | undefined);
|
|
38
|
-
/** Record a hand-off before its continue is sent, so an answer that races the command is still read. */
|
|
39
|
-
begin(profile: string, authorizationId: string, url: string): void;
|
|
40
|
-
/** The continued request's response arrived with this status. */
|
|
41
|
-
responded(status: number): void;
|
|
42
|
-
/** The continued request failed before any response arrived. */
|
|
43
|
-
failed(): void;
|
|
44
|
-
/**
|
|
45
|
-
* The page sent a card request to a profile. True when it is the profile a
|
|
46
|
-
* hand-off already went to: the caller aborts it at once. A retry sent before
|
|
47
|
-
* any answer reached the page also reports the unknown outcome. When the
|
|
48
|
-
* adapter must first read more of what the page reported before it sent this
|
|
49
|
-
* retry, `inPageOrder` keeps `judge`, calls it once it has, and returns true.
|
|
50
|
-
*/
|
|
51
|
-
retried(profile: string, inPageOrder?: (judge: () => void) => boolean): boolean;
|
|
52
|
-
private unknown;
|
|
53
|
-
}
|
|
54
|
-
export {};
|
package/dist/merchant-handoff.js
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { PaymentOutcomeUnknownError } from './client.js';
|
|
2
|
-
/**
|
|
3
|
-
* A merchant-hosted card request after hand-off, shared by the CDP and
|
|
4
|
-
* Playwright adapters so both read it the same way.
|
|
5
|
-
*
|
|
6
|
-
* The browser continued the merchant's own request with the Vault's ciphertext in
|
|
7
|
-
* it; the merchant's server now charges the card through Adyen and answers its own
|
|
8
|
-
* page. Nothing Agentcard holds says whether it did. Two things after hand-off are
|
|
9
|
-
* therefore an unknown outcome, never a failure to retry:
|
|
10
|
-
* - the continued request answers 5xx or fails in the network: the merchant may
|
|
11
|
-
* have charged the card, and its page may never learn that it did;
|
|
12
|
-
* - the page sends the card request again before an answer arrived (Dick's
|
|
13
|
-
* retries on a network error or a 500, ATG on anything not OK): its retry
|
|
14
|
-
* carries the agent's dummy card, and the approval is spent.
|
|
15
|
-
* Either reports `payment_outcome_unknown` once and holds the checkout until the
|
|
16
|
-
* application reconciles the merchant order. Every card request to the same
|
|
17
|
-
* profile after hand-off is aborted, answered or not: a prepared approval is
|
|
18
|
-
* single use.
|
|
19
|
-
*
|
|
20
|
-
* Which of the two it reports follows the order the page saw them in. A page that
|
|
21
|
-
* retries because the merchant answered 5xx read that answer first, but an
|
|
22
|
-
* adapter can read the retry first (Chrome pauses a request in the browser
|
|
23
|
-
* process, ahead of the renderer's report of the answer), so retried() judges
|
|
24
|
-
* a retry once the adapter has read what the page reported before sending it.
|
|
25
|
-
*/
|
|
26
|
-
export class MerchantHandoffWatch {
|
|
27
|
-
lifecycle;
|
|
28
|
-
onEvent;
|
|
29
|
-
handoff = null;
|
|
30
|
-
answered = false;
|
|
31
|
-
reported = false;
|
|
32
|
-
constructor(lifecycle, onEvent) {
|
|
33
|
-
this.lifecycle = lifecycle;
|
|
34
|
-
this.onEvent = onEvent;
|
|
35
|
-
}
|
|
36
|
-
/** Record a hand-off before its continue is sent, so an answer that races the command is still read. */
|
|
37
|
-
begin(profile, authorizationId, url) {
|
|
38
|
-
this.handoff = { profile, authorizationId, url };
|
|
39
|
-
this.answered = false;
|
|
40
|
-
this.reported = false;
|
|
41
|
-
}
|
|
42
|
-
/** The continued request's response arrived with this status. */
|
|
43
|
-
responded(status) {
|
|
44
|
-
if (!this.handoff || this.answered)
|
|
45
|
-
return;
|
|
46
|
-
this.answered = true;
|
|
47
|
-
if (Number.isInteger(status) && status >= 500)
|
|
48
|
-
this.unknown('merchant_server_error', { status });
|
|
49
|
-
}
|
|
50
|
-
/** The continued request failed before any response arrived. */
|
|
51
|
-
failed() {
|
|
52
|
-
if (!this.handoff || this.answered)
|
|
53
|
-
return;
|
|
54
|
-
this.answered = true;
|
|
55
|
-
this.unknown('merchant_request_failed');
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* The page sent a card request to a profile. True when it is the profile a
|
|
59
|
-
* hand-off already went to: the caller aborts it at once. A retry sent before
|
|
60
|
-
* any answer reached the page also reports the unknown outcome. When the
|
|
61
|
-
* adapter must first read more of what the page reported before it sent this
|
|
62
|
-
* retry, `inPageOrder` keeps `judge`, calls it once it has, and returns true.
|
|
63
|
-
*/
|
|
64
|
-
retried(profile, inPageOrder) {
|
|
65
|
-
const handoff = this.handoff;
|
|
66
|
-
if (!handoff || handoff.profile !== profile)
|
|
67
|
-
return false;
|
|
68
|
-
let judged = false;
|
|
69
|
-
const judge = () => {
|
|
70
|
-
if (judged)
|
|
71
|
-
return;
|
|
72
|
-
judged = true;
|
|
73
|
-
if (this.handoff === handoff && !this.answered)
|
|
74
|
-
this.unknown('merchant_retried_after_handoff');
|
|
75
|
-
this.onEvent?.({ type: 'blocked', detail: 'merchant_retried_after_handoff' });
|
|
76
|
-
};
|
|
77
|
-
let waiting = false;
|
|
78
|
-
// An order the adapter cannot establish is judged on what it has read.
|
|
79
|
-
try {
|
|
80
|
-
waiting = !this.answered && inPageOrder?.(judge) === true;
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
waiting = false;
|
|
84
|
-
}
|
|
85
|
-
if (!waiting)
|
|
86
|
-
judge();
|
|
87
|
-
return true;
|
|
88
|
-
}
|
|
89
|
-
unknown(reason, extra = {}) {
|
|
90
|
-
if (!this.handoff || this.reported)
|
|
91
|
-
return;
|
|
92
|
-
// A result the application already confirmed with the merchant stands.
|
|
93
|
-
if (this.lifecycle.getState().status === 'completed')
|
|
94
|
-
return;
|
|
95
|
-
this.reported = true;
|
|
96
|
-
const { authorizationId, profile, url } = this.handoff;
|
|
97
|
-
this.lifecycle.failed(new PaymentOutcomeUnknownError(authorizationId, reason), true);
|
|
98
|
-
this.onEvent?.({ type: 'payment_outcome_unknown', detail: { authorizationId, reason, profile, url, ...extra } });
|
|
99
|
-
}
|
|
100
|
-
}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
/** 'observe': paused, reported and aborted, never paid. 'enabled': a prepared checkout may pay it. */
|
|
2
|
-
export type MerchantProfileStatus = 'observe' | 'enabled';
|
|
3
|
-
/**
|
|
4
|
-
* A test-mode checkout against your own Adyen TEST account: your own server's
|
|
5
|
-
* card endpoint (an exact HTTPS URL), taking a card request shaped like a reviewed
|
|
6
|
-
* profile's, encrypted under your own Adyen TEST client key (test_...). The API
|
|
7
|
-
* accepts one only from a test-mode client of an org Agentcard turned declarations
|
|
8
|
-
* on for, reads the key's public key from Adyen's TEST platform itself, and the
|
|
9
|
-
* Vault encrypts only Adyen's documented test cards under it.
|
|
10
|
-
*/
|
|
11
|
-
export interface SandboxMerchantDeclaration {
|
|
12
|
-
/** The reviewed profile whose card request your endpoint takes (its body rules, holder and fields). */
|
|
13
|
-
profile: string;
|
|
14
|
-
/** Your endpoint: HTTPS, written exactly as the browser sends it, no port, credentials or fragment. */
|
|
15
|
-
endpoint: string;
|
|
16
|
-
/** Your Adyen TEST client key (test_ followed by 32 letters and digits). */
|
|
17
|
-
clientKey: string;
|
|
18
|
-
}
|
|
19
|
-
/** A reviewed merchant profile this client arms: its id, the merchant it names, and its effective status. */
|
|
20
|
-
export interface MerchantProfile {
|
|
21
|
-
readonly id: string;
|
|
22
|
-
readonly merchant: string;
|
|
23
|
-
readonly status: MerchantProfileStatus;
|
|
24
|
-
/** Present when this client armed the profile's shape at its own declared test endpoint (declareSandboxMerchant). */
|
|
25
|
-
readonly sandboxDeclaration?: Readonly<Pick<SandboxMerchantDeclaration, 'endpoint' | 'clientKey'>>;
|
|
26
|
-
}
|
|
27
|
-
/** A profile's verdict on a paused request; see classifyMerchantRequest. */
|
|
28
|
-
export type MerchantRequestVerdict = {
|
|
29
|
-
verdict: 'pause';
|
|
30
|
-
} | {
|
|
31
|
-
verdict: 'abort';
|
|
32
|
-
reason: string;
|
|
33
|
-
} | {
|
|
34
|
-
verdict: 'pass';
|
|
35
|
-
};
|
|
36
|
-
/** One step of a JSON path: an object key, or an index into an array. */
|
|
37
|
-
export type JsonPathStep = string | number;
|
|
38
|
-
/** A card fact the API asks to write beside the ciphertext (reserved: no profile declares one yet). */
|
|
39
|
-
export interface MerchantHostedFact {
|
|
40
|
-
path: JsonPathStep[];
|
|
41
|
-
value: string;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Where a merchant-hosted approval's ciphertext goes: the profile's holder path
|
|
45
|
-
* (`[]` is the body root), the merchant's names for Adyen's four fields, and the
|
|
46
|
-
* keys at the holder to drop with the swap (adyen-web's `brand`, derived from the
|
|
47
|
-
* agent's dummy digits). payment-core's substituteMerchantHosted refuses anything
|
|
48
|
-
* but exactly the profile's own values.
|
|
49
|
-
*/
|
|
50
|
-
export interface MerchantHostedSubstitutions {
|
|
51
|
-
encoding: 'json';
|
|
52
|
-
kind: 'merchant_hosted';
|
|
53
|
-
profile: string;
|
|
54
|
-
path: JsonPathStep[];
|
|
55
|
-
fields: Record<string, string>;
|
|
56
|
-
remove: string[];
|
|
57
|
-
/** Card facts to write after the swap. No profile declares any yet, and the substitution refuses them. */
|
|
58
|
-
set?: MerchantHostedFact[];
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* The profile's verdict on a paused request: pause (its reviewed card request),
|
|
62
|
-
* abort (encrypted card data it cannot finish, with the reason) or pass (no
|
|
63
|
-
* encrypted card data, or not its endpoint or a sibling of it). Reads only;
|
|
64
|
-
* throws for a profile id this build did not review.
|
|
65
|
-
*/
|
|
66
|
-
export declare const classifyMerchantRequest: (profileId: string, url: string, method: string, body: string | null | undefined) => MerchantRequestVerdict;
|
|
67
|
-
/** The endpoint origin, the path TEMPLATE and the profile's own query: what an event may name. */
|
|
68
|
-
export declare const merchantProfileTemplatedUrl: (profileId: string, url: string) => string;
|
|
69
|
-
/** SHA-256 of a JSON body's sorted key paths, no value in it; null for a body that is not JSON. */
|
|
70
|
-
export declare const merchantBodyKeyPathSha256: (body: string) => string | null;
|
|
71
|
-
/** 'sandbox' for a profile on Adyen's TEST platform, 'production' for every live environment. */
|
|
72
|
-
export declare const merchantProfileEnvironment: (profileId: string) => 'production' | 'sandbox';
|
|
73
|
-
/** classifyMerchantRequest for a sandbox declaration: the profile's body rules at the declared endpoint instead of the profile's. */
|
|
74
|
-
export declare const classifyDeclaredMerchantRequest: (profileId: string, endpoint: string, url: string, method: string, body: string | null | undefined) => MerchantRequestVerdict;
|
|
75
|
-
/**
|
|
76
|
-
* The profiles this client arms: every profile this build reviewed, once each, in
|
|
77
|
-
* this build's order. A served entry is `{ merchant_profile: <the profile's wire
|
|
78
|
-
* projection> }`, and the first one that names a profile with exactly this build's
|
|
79
|
-
* rules (endpoint, body rules, holder, fields, key: everything but `status`) and a
|
|
80
|
-
* status this build knows decides it: 'enabled' only when both that entry and this
|
|
81
|
-
* build say so. Every other profile stays in 'observe': one the API did not serve (no
|
|
82
|
-
* sync yet, a failed sync, an API that predates profiles) and one the API reviewed
|
|
83
|
-
* again after this build was cut, which this build cannot pay. In 'observe' its card
|
|
84
|
-
* request is still paused and aborted, so the agent's dummy card never reaches a
|
|
85
|
-
* reviewed merchant, whatever the API answered.
|
|
86
|
-
*/
|
|
87
|
-
export declare function armServedProfiles(entries?: readonly unknown[]): MerchantProfile[];
|
|
88
|
-
/**
|
|
89
|
-
* Arms a sandbox declaration: the reviewed profile's card request at your own
|
|
90
|
-
* endpoint, under your own Adyen TEST key. Throws a TypeError for a profile this
|
|
91
|
-
* build did not review, an endpoint the API would refuse, or a key that is not a
|
|
92
|
-
* test_ key. The endpoint rule is the API's own (payment-core sandboxDeclarationRefusal):
|
|
93
|
-
* an HTTPS URL in the exact form the browser writes it (no port, credentials or
|
|
94
|
-
* fragment), on a public domain name outside Adyen's domains, Agentcard's and every
|
|
95
|
-
* reviewed merchant's domain (declaredEndpointRefusal), and on no host this build's
|
|
96
|
-
* processor registry names. The armed entry names its host as the merchant, and is
|
|
97
|
-
* 'enabled' whatever the reviewed profile's status: it never pays the reviewed
|
|
98
|
-
* merchant, the API refuses it from a live client and from an org it has not turned
|
|
99
|
-
* declarations on for, and the Vault encrypts only Adyen's documented test cards
|
|
100
|
-
* under a test_ key.
|
|
101
|
-
*/
|
|
102
|
-
export declare function declareSandboxMerchant(input: SandboxMerchantDeclaration): MerchantProfile;
|
|
103
|
-
/** The armed profile whose endpoint, or a sibling of it (same origin and path shape), a URL is; null for any other URL. */
|
|
104
|
-
export declare function merchantProfileFor(profiles: readonly MerchantProfile[], url: string): MerchantProfile | null;
|
|
105
|
-
/** The Fetch.enable globs that pause every armed profile's endpoint and its siblings, a declared endpoint included. */
|
|
106
|
-
export declare function merchantProfileUrlPatterns(profiles: readonly MerchantProfile[]): string[];
|
|
107
|
-
/** classifyMerchantRequest for an armed profile: at its declared endpoint when it has one. */
|
|
108
|
-
export declare function classifyProfileRequest(profile: MerchantProfile, url: string, method: string, body: string | null | undefined): MerchantRequestVerdict;
|
|
109
|
-
/** merchantProfileTemplatedUrl for an armed profile: a declared endpoint's origin and path, never its query. */
|
|
110
|
-
export declare function profileTemplatedUrl(profile: MerchantProfile, url: string): string;
|
|
111
|
-
/**
|
|
112
|
-
* The Fetch.enable globs for every profile this build reviewed. Every one of them is
|
|
113
|
-
* armed from the start (armServedProfiles), so attachToCdp arms all of them at attach
|
|
114
|
-
* and a syncRegistry() before or after it changes only a profile's status: its card
|
|
115
|
-
* request is paused and judged under CDP exactly as attachToPlaywright's per-request
|
|
116
|
-
* route judges it.
|
|
117
|
-
*/
|
|
118
|
-
export declare function reviewedMerchantProfileUrlPatterns(): string[];
|
|
119
|
-
/**
|
|
120
|
-
* The continuation of a merchant-hosted approval: the live paused body with the
|
|
121
|
-
* Vault's ciphertext in place of the dummy fields. The API never sees the body the
|
|
122
|
-
* browser continues, so the live body must first hash to the one the API checked
|
|
123
|
-
* when the authorization was created (`bodySha256`); a page that rewrote its body
|
|
124
|
-
* while the cardholder decided is refused rather than paid. payment-core's
|
|
125
|
-
* substituteMerchantHosted then reads the profile's body rules again on the live
|
|
126
|
-
* body, writes only the profile's four fields, and refuses a profile that is not
|
|
127
|
-
* enabled, unless this client armed the endpoint from its own sandbox declaration
|
|
128
|
-
* (the replay carries `sandboxDeclaration`), where every body rule still applies.
|
|
129
|
-
* Throws SubstitutionError; nothing leaves the browser when it does.
|
|
130
|
-
*/
|
|
131
|
-
export declare function substituteMerchantHostedBody(body: string, replay: {
|
|
132
|
-
substitutions: MerchantHostedSubstitutions;
|
|
133
|
-
bodySha256: string;
|
|
134
|
-
sandboxDeclaration?: MerchantProfile['sandboxDeclaration'];
|
|
135
|
-
}): string;
|
|
136
|
-
/** The URL an event names for a merchant-hosted replay's request: its declared endpoint's origin and path, or the profile's template. */
|
|
137
|
-
export declare function replayTemplatedUrl(replay: {
|
|
138
|
-
profile: string;
|
|
139
|
-
sandboxDeclaration?: MerchantProfile['sandboxDeclaration'];
|
|
140
|
-
}, url: string): string;
|