@agent-cards/checkout 0.18.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 -669
- 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 -124
- package/PREFLIGHT.md +0 -308
- 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 -189
- package/dist/cdp.js +0 -2194
- package/dist/checkout-com.generated.d.ts +0 -4
- package/dist/checkout-com.generated.js +0 -183
- package/dist/client.d.ts +0 -618
- package/dist/client.js +0 -1251
- package/dist/hosted-form.d.ts +0 -44
- package/dist/hosted-form.js +0 -78
- package/dist/index.d.ts +0 -13
- package/dist/index.js +0 -6
- package/dist/lifecycle.d.ts +0 -165
- package/dist/lifecycle.js +0 -370
- 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/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/preflight-capabilities.generated.d.ts +0 -1253
- package/dist/preflight-capabilities.generated.js +0 -1929
- package/dist/preflight-catalog.json +0 -4595
- package/dist/preflight-playwright.d.ts +0 -34
- package/dist/preflight-playwright.js +0 -355
- package/dist/preflight-schemas.json +0 -1110
- package/dist/preflight.d.ts +0 -1
- package/dist/preflight.generated.d.ts +0 -1965
- package/dist/preflight.generated.js +0 -556
- package/dist/preflight.js +0 -2
- package/dist/preparation.d.ts +0 -31
- package/dist/preparation.js +0 -164
- package/dist/prepared-processor.d.ts +0 -10
- package/dist/prepared-processor.js +0 -122
- package/dist/recurly.generated.d.ts +0 -1
- package/dist/recurly.generated.js +0 -87
- package/dist/registry.d.ts +0 -76
- package/dist/registry.js +0 -296
- 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 -1004
- 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 -10
- package/dist/substitutions.generated.js +0 -66
- 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
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,24 +0,0 @@
|
|
|
1
|
-
declare var OWNED_SHOP_OPERATION: string;
|
|
2
|
-
declare var OWNED_SHOP_SKU: string;
|
|
3
|
-
declare var OWNED_SHOP_AMOUNT_CENTS: number;
|
|
4
|
-
declare var OWNED_SHOP_CURRENCY: string;
|
|
5
|
-
declare var OWNED_SHOP_ORDER_FIELD: string;
|
|
6
|
-
declare function isOwnedShopPaymentIntentId(value: any): boolean;
|
|
7
|
-
declare function serializeOwnedShopOrder(value: any): string;
|
|
8
|
-
declare function hasOwnedShopMarker(request: any): any;
|
|
9
|
-
declare function parseOwnedShopOrder(request: any): {
|
|
10
|
-
order_id: any;
|
|
11
|
-
sku: string;
|
|
12
|
-
amount: number;
|
|
13
|
-
currency: string;
|
|
14
|
-
} | null;
|
|
15
|
-
declare function parseOwnedShopReceipt(value: any, expectedOrder: any): {
|
|
16
|
-
object: string;
|
|
17
|
-
order_id: any;
|
|
18
|
-
payment_intent_id: any;
|
|
19
|
-
status: string;
|
|
20
|
-
amount: number;
|
|
21
|
-
currency: string;
|
|
22
|
-
livemode: boolean;
|
|
23
|
-
} | null;
|
|
24
|
-
export { OWNED_SHOP_AMOUNT_CENTS, OWNED_SHOP_CURRENCY, OWNED_SHOP_OPERATION, OWNED_SHOP_ORDER_FIELD, OWNED_SHOP_SKU, hasOwnedShopMarker, isOwnedShopPaymentIntentId, parseOwnedShopOrder, parseOwnedShopReceipt, serializeOwnedShopOrder };
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
// Generated from @agent-cards/payment-core. Do not edit.
|
|
3
|
-
// artifact-sha256: c8cfb844f3de3f156ee741a0167256d2e764ddfb7d243ce813e011761d3b711a
|
|
4
|
-
// src/owned-shop.js
|
|
5
|
-
var OWNED_SHOP_OPERATION = "stripe.owned_shop_token_to_payment_intent.v1";
|
|
6
|
-
var OWNED_SHOP_SKU = "autopilot-pilot-100";
|
|
7
|
-
var OWNED_SHOP_AMOUNT_CENTS = 100;
|
|
8
|
-
var OWNED_SHOP_CURRENCY = "usd";
|
|
9
|
-
var OWNED_SHOP_ORDER_FIELD = "agentcard_shop_order";
|
|
10
|
-
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}(?![\s\S])/;
|
|
11
|
-
var INTENT = /^pi_[A-Za-z0-9]{1,200}(?![\s\S])/;
|
|
12
|
-
var refuse = () => {
|
|
13
|
-
throw new Error("stripe_owned_shop_refused");
|
|
14
|
-
};
|
|
15
|
-
var record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
16
|
-
var keys = (value, allowed) => record(value) && Object.keys(value).length === allowed.length && Object.keys(value).every((key) => allowed.includes(key));
|
|
17
|
-
function isOwnedShopPaymentIntentId(value) {
|
|
18
|
-
return typeof value === "string" && INTENT.test(value);
|
|
19
|
-
}
|
|
20
|
-
function order(value) {
|
|
21
|
-
if (!keys(value, ["order_id", "sku", "amount", "currency"]) || typeof value.order_id !== "string" || !UUID.test(value.order_id) || value.sku !== OWNED_SHOP_SKU || value.amount !== OWNED_SHOP_AMOUNT_CENTS || value.currency !== OWNED_SHOP_CURRENCY)
|
|
22
|
-
refuse();
|
|
23
|
-
return {
|
|
24
|
-
order_id: value.order_id,
|
|
25
|
-
sku: OWNED_SHOP_SKU,
|
|
26
|
-
amount: OWNED_SHOP_AMOUNT_CENTS,
|
|
27
|
-
currency: OWNED_SHOP_CURRENCY
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
function serializeOwnedShopOrder(value) {
|
|
31
|
-
return JSON.stringify(order(value));
|
|
32
|
-
}
|
|
33
|
-
function hasOwnedShopMarker(request) {
|
|
34
|
-
if (typeof request?.body !== "string")
|
|
35
|
-
return false;
|
|
36
|
-
return request.body.split("&").some((part) => {
|
|
37
|
-
const raw = part.split("=", 1)[0];
|
|
38
|
-
const loose = raw.replace(/\+/g, " ").replace(/%([0-9a-f]{2})/gi, (_, hex) => String.fromCharCode(parseInt(hex, 16)));
|
|
39
|
-
return loose.toLowerCase().includes(OWNED_SHOP_ORDER_FIELD);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
function form(body) {
|
|
43
|
-
if (typeof body !== "string" || !body || body.length > 16384 || /[^\x21-\x7e]/.test(body))
|
|
44
|
-
refuse();
|
|
45
|
-
const chunks = body.split("&");
|
|
46
|
-
if (chunks.length > 16)
|
|
47
|
-
refuse();
|
|
48
|
-
const entries = /* @__PURE__ */ new Map();
|
|
49
|
-
const seen = /* @__PURE__ */ new Set();
|
|
50
|
-
for (const chunk of chunks) {
|
|
51
|
-
const eq = chunk.indexOf("=");
|
|
52
|
-
if (eq < 1)
|
|
53
|
-
refuse();
|
|
54
|
-
let key, value;
|
|
55
|
-
try {
|
|
56
|
-
key = decodeURIComponent(chunk.slice(0, eq).replace(/\+/g, " "));
|
|
57
|
-
value = decodeURIComponent(chunk.slice(eq + 1).replace(/\+/g, " "));
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
refuse();
|
|
61
|
-
}
|
|
62
|
-
if (seen.has(key.toLowerCase()) || value.length > 2048 || /[\x00-\x1f\x7f]/.test(key + value))
|
|
63
|
-
refuse();
|
|
64
|
-
seen.add(key.toLowerCase());
|
|
65
|
-
entries.set(key, value);
|
|
66
|
-
}
|
|
67
|
-
return entries;
|
|
68
|
-
}
|
|
69
|
-
function parseOwnedShopOrder(request) {
|
|
70
|
-
if (!hasOwnedShopMarker(request))
|
|
71
|
-
return null;
|
|
72
|
-
const entries = form(request.body);
|
|
73
|
-
if (!entries.has(OWNED_SHOP_ORDER_FIELD) || [...entries.keys()].some((key) => key !== OWNED_SHOP_ORDER_FIELD && key.toLowerCase().includes(OWNED_SHOP_ORDER_FIELD)))
|
|
74
|
-
refuse();
|
|
75
|
-
const encoded = entries.get(OWNED_SHOP_ORDER_FIELD);
|
|
76
|
-
let parsed;
|
|
77
|
-
try {
|
|
78
|
-
parsed = JSON.parse(encoded);
|
|
79
|
-
}
|
|
80
|
-
catch {
|
|
81
|
-
refuse();
|
|
82
|
-
}
|
|
83
|
-
const result = order(parsed);
|
|
84
|
-
if (serializeOwnedShopOrder(result) !== encoded)
|
|
85
|
-
refuse();
|
|
86
|
-
return result;
|
|
87
|
-
}
|
|
88
|
-
function parseOwnedShopReceipt(value, expectedOrder) {
|
|
89
|
-
let boundOrder;
|
|
90
|
-
try {
|
|
91
|
-
boundOrder = order(expectedOrder);
|
|
92
|
-
}
|
|
93
|
-
catch {
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
if (!keys(value, ["object", "order_id", "payment_intent_id", "status", "amount", "currency", "livemode"]) || value.object !== "agentcard_shop_receipt" || value.order_id !== boundOrder.order_id || !isOwnedShopPaymentIntentId(value.payment_intent_id) || value.status !== "succeeded" || value.amount !== OWNED_SHOP_AMOUNT_CENTS || value.currency !== OWNED_SHOP_CURRENCY || value.livemode !== false)
|
|
97
|
-
return null;
|
|
98
|
-
return {
|
|
99
|
-
object: "agentcard_shop_receipt",
|
|
100
|
-
order_id: boundOrder.order_id,
|
|
101
|
-
payment_intent_id: value.payment_intent_id,
|
|
102
|
-
status: "succeeded",
|
|
103
|
-
amount: OWNED_SHOP_AMOUNT_CENTS,
|
|
104
|
-
currency: OWNED_SHOP_CURRENCY,
|
|
105
|
-
livemode: false
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
export { OWNED_SHOP_AMOUNT_CENTS, OWNED_SHOP_CURRENCY, OWNED_SHOP_OPERATION, OWNED_SHOP_ORDER_FIELD, OWNED_SHOP_SKU, hasOwnedShopMarker, isOwnedShopPaymentIntentId, parseOwnedShopOrder, parseOwnedShopReceipt, serializeOwnedShopOrder };
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export type PaysafePreparationEnvironment = 'production' | 'sandbox';
|
|
2
|
-
export declare function paysafePreparationUrl(environment: string): string;
|
|
3
|
-
/** Exact strings refuse credentials, queries, fragments and URL normalization. */
|
|
4
|
-
export declare function paysafeEnvironment(url: string): PaysafePreparationEnvironment | undefined;
|
|
5
|
-
/** Checkout 1.8.0 starts a 40-second XHR when Pay is pressed. Prior approval may
|
|
6
|
-
* consume only its new-card request, including native clientInfo and headers.
|
|
7
|
-
* Saved cards, alternate APIs and 3DS-only requests require separate review.
|
|
8
|
-
* Source: hosted.paysafe.com/checkout/1.8.0/main.bundle.js, SHA-256
|
|
9
|
-
* e9e111ff03073cc936a47674e8e7c5db4a6d1050e1b65bf5e20723116fd5080c.
|
|
10
|
-
* The guard checks original bytes and never changes the request.
|
|
11
|
-
*/
|
|
12
|
-
export declare function isPreparedPaysafeRequest(url: string, method: string, body: string | null, environment: string, headers?: Record<string, string>): boolean;
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
// Generated from @agent-cards/payment-core. Do not edit.
|
|
2
|
-
// source-sha256: 24c7940ae8974c0d24e5a365144c1b07ccc46863ae3094eb92b3c54c8307e837
|
|
3
|
-
import { readTokenizationJson } from './braintree.js';
|
|
4
|
-
const ENDPOINTS = {
|
|
5
|
-
production: 'https://hosted.paysafe.com/checkout/api/v1/tokenize',
|
|
6
|
-
sandbox: 'https://hosted.test.paysafe.com/checkout/api/v1/tokenize',
|
|
7
|
-
};
|
|
8
|
-
const record = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
9
|
-
const keys = (value, allowed) => record(value) && Object.keys(value).every(key => allowed.includes(key));
|
|
10
|
-
const exact = (pattern, value) => typeof value === 'string' && pattern.exec(value)?.[0] === value;
|
|
11
|
-
const text = (value, max = 1024) => typeof value === 'string' && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
|
|
12
|
-
const own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
13
|
-
const uuid = (value) => exact(/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/i, value);
|
|
14
|
-
export function paysafePreparationUrl(environment) {
|
|
15
|
-
if (environment !== 'production' && environment !== 'sandbox')
|
|
16
|
-
throw new Error('unsupported_preparation_environment');
|
|
17
|
-
return ENDPOINTS[environment];
|
|
18
|
-
}
|
|
19
|
-
/** Exact strings refuse credentials, queries, fragments and URL normalization. */
|
|
20
|
-
export function paysafeEnvironment(url) {
|
|
21
|
-
return url === ENDPOINTS.production ? 'production' : url === ENDPOINTS.sandbox ? 'sandbox' : undefined;
|
|
22
|
-
}
|
|
23
|
-
const ADDRESS_FIELDS = ['city', 'country', 'zip', 'street', 'street2', 'state'];
|
|
24
|
-
function billing(value) {
|
|
25
|
-
return keys(value, ADDRESS_FIELDS) && Object.values(value).every(value => text(value))
|
|
26
|
-
&& (!own(value, 'country') || exact(/^[A-Z]{2}$/, value.country));
|
|
27
|
-
}
|
|
28
|
-
function freshCard(value) {
|
|
29
|
-
if (!keys(value, ['card', 'clientInfo', 'billingAddress']) || !keys(value.card, ['cardNum', 'cardExpiry', 'cvv', 'holderName']))
|
|
30
|
-
return false;
|
|
31
|
-
const card = value.card;
|
|
32
|
-
if (!exact(/^[0-9]{12,19}$/, card.cardNum) || !exact(/^[0-9]{3,4}$/, card.cvv)
|
|
33
|
-
|| !keys(card.cardExpiry, ['month', 'year']) || !exact(/^(?:0[1-9]|1[0-2])$/, card.cardExpiry.month)
|
|
34
|
-
|| !exact(/^20[0-9]{2}$/, card.cardExpiry.year) || own(card, 'holderName') && !text(card.holderName)
|
|
35
|
-
|| own(value, 'billingAddress') && !billing(value.billingAddress))
|
|
36
|
-
return false;
|
|
37
|
-
const info = value.clientInfo;
|
|
38
|
-
return keys(info, ['correlationId', 'invocationId', 'version', 'appName'])
|
|
39
|
-
&& uuid(info.correlationId) && uuid(info.invocationId) && info.version === '1.8.0' && info.appName === 'paysafe.checkout';
|
|
40
|
-
}
|
|
41
|
-
const BROWSER_HEADERS = new Set(['accept', 'accept-language', 'accept-encoding', 'content-length', 'origin', 'referer',
|
|
42
|
-
'user-agent', 'host', 'connection', 'cache-control', 'pragma', 'priority', 'dnt',
|
|
43
|
-
'sec-fetch-dest', 'sec-fetch-mode', 'sec-fetch-site', 'sec-fetch-user']);
|
|
44
|
-
function singleUseCredential(value) {
|
|
45
|
-
if (!exact(/^Basic [A-Za-z0-9+/]+={0,2}$/, value) || value.length > 1024)
|
|
46
|
-
return false;
|
|
47
|
-
try {
|
|
48
|
-
const encoded = value.slice(6), decoded = atob(encoded);
|
|
49
|
-
// Checkout receives public OT credentials, never merchant API credentials.
|
|
50
|
-
return btoa(decoded) === encoded && exact(/^OT-[0-9]{1,20}:[!-~]{1,512}$/, decoded);
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
function nativeHeaders(headers, correlationId) {
|
|
57
|
-
if (!record(headers))
|
|
58
|
-
return false;
|
|
59
|
-
const parsed = new Map();
|
|
60
|
-
let bytes = 0;
|
|
61
|
-
for (const [name, value] of Object.entries(headers)) {
|
|
62
|
-
const lower = name.toLowerCase();
|
|
63
|
-
if (parsed.size >= 64 || parsed.has(lower) || !exact(/^[A-Za-z0-9-]+$/, name) || !text(value, 8192)
|
|
64
|
-
|| (bytes += name.length + value.length) > 32768)
|
|
65
|
-
return false;
|
|
66
|
-
if (!['content-type', 'correlationid', 'x-paysafe-credentials'].includes(lower) && !BROWSER_HEADERS.has(lower)
|
|
67
|
-
&& !exact(/^sec-ch-ua(?:-[a-z0-9-]+)?$/, lower))
|
|
68
|
-
return false;
|
|
69
|
-
parsed.set(lower, value);
|
|
70
|
-
}
|
|
71
|
-
return exact(/^application\/json(?:;\s*charset=utf-8)?$/i, parsed.get('content-type'))
|
|
72
|
-
&& parsed.get('correlationid') === correlationId && singleUseCredential(parsed.get('x-paysafe-credentials'));
|
|
73
|
-
}
|
|
74
|
-
/** Checkout 1.8.0 starts a 40-second XHR when Pay is pressed. Prior approval may
|
|
75
|
-
* consume only its new-card request, including native clientInfo and headers.
|
|
76
|
-
* Saved cards, alternate APIs and 3DS-only requests require separate review.
|
|
77
|
-
* Source: hosted.paysafe.com/checkout/1.8.0/main.bundle.js, SHA-256
|
|
78
|
-
* e9e111ff03073cc936a47674e8e7c5db4a6d1050e1b65bf5e20723116fd5080c.
|
|
79
|
-
* The guard checks original bytes and never changes the request.
|
|
80
|
-
*/
|
|
81
|
-
export function isPreparedPaysafeRequest(url, method, body, environment, headers) {
|
|
82
|
-
if (method !== 'POST' || (environment !== 'production' && environment !== 'sandbox')
|
|
83
|
-
|| paysafeEnvironment(url) !== environment)
|
|
84
|
-
return false;
|
|
85
|
-
const value = readTokenizationJson(body);
|
|
86
|
-
return freshCard(value) && record(value.clientInfo) && nativeHeaders(headers, value.clientInfo.correlationId);
|
|
87
|
-
}
|
package/dist/playwright.d.ts
DELETED
package/dist/playwright.js
DELETED