@agent-cards/sdk 0.23.11 → 0.23.13
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/CHANGELOG.md +12 -0
- package/LICENSE +38 -0
- package/PREFLIGHT.md +2 -0
- package/README.md +9 -7
- package/dist/builtin-registry.generated.js +1 -1
- package/dist/card-fields.generated.js +74 -1
- package/dist/cdp.js +63 -10
- package/dist/client.d.ts +24 -7
- package/dist/client.js +135 -16
- package/dist/lifecycle.d.ts +11 -2
- package/dist/lifecycle.js +4 -1
- package/dist/paddle-vgs-pay.d.ts +55 -0
- package/dist/paddle-vgs-pay.js +115 -0
- package/dist/paddle-vgs.generated.d.ts +78 -0
- package/dist/paddle-vgs.generated.js +408 -0
- package/dist/payrails.generated.js +8 -12
- package/dist/paysafe.generated.d.ts +5 -7
- package/dist/paysafe.generated.js +50 -18
- package/dist/pre-claim.d.ts +8 -0
- package/dist/pre-claim.js +48 -1
- package/dist/prepared-processor.d.ts +12 -4
- package/dist/prepared-processor.js +17 -5
- package/dist/primer.generated.js +90 -17
- package/dist/stripe-checkout.generated.js +64 -3
- package/package.json +3 -3
package/dist/pre-claim.js
CHANGED
|
@@ -79,6 +79,7 @@ import { ekashuEntryUrl, isEkashuEntry, isEkashuHost } from './ekashu.js';
|
|
|
79
79
|
import { PAYPAL_HOSTED_FIELDS_REASON, isPaypalHostedFieldsConfirm, paypalHostedFieldsBody } from './paypal-hosted-fields.js';
|
|
80
80
|
import { CYBERSOURCE_SECURE_ACCEPTANCE_REASON, CYBERSOURCE_SECURE_ACCEPTANCE_RECIPIENT, cybersourceSecureAcceptanceRequest, isCybersourceSecureAcceptanceUrl, isSecureAcceptanceFramePost, } from './cybersource-secure-acceptance.js';
|
|
81
81
|
import { isWorldlineMyCheckoutEndpoint } from './worldline-mycheckout.js';
|
|
82
|
+
import { paddleVgsPayEventUrl } from './paddle-vgs-pay.js';
|
|
82
83
|
/**
|
|
83
84
|
* The URL an event may name for a request. For an armed merchant profile's
|
|
84
85
|
* endpoint or a sibling of it: the endpoint origin, the path TEMPLATE and the
|
|
@@ -1737,6 +1738,52 @@ async function worldlineMyCheckoutBlock(ctx, reason) {
|
|
|
1737
1738
|
await ctx.effects.abort();
|
|
1738
1739
|
return { kind: 'abort' };
|
|
1739
1740
|
}
|
|
1741
|
+
// Paddle's /pay (paddle-vgs-pay.ts), held only on an attachment the API served Paddle VGS to: a POST to /pay
|
|
1742
|
+
// that names a stored card continues with the approved card's first six, last four, expiry and brand written
|
|
1743
|
+
// over the ones the frame read from the agent's placeholder, when this attachment handed that frame the stored
|
|
1744
|
+
// card's id within the minute and this is its first /pay; otherwise it aborts as an unsupported checkout, with
|
|
1745
|
+
// the gate's reason, so Paddle never receives the real card's id beside the placeholder's facts. Anything else
|
|
1746
|
+
// on Paddle's checkout services (its create, the buyer's first step, 3-D Secure's follow-up, a PayPal or wallet
|
|
1747
|
+
// /pay naming no stored card) defers, and the terminal arbiter continues it untouched. Synchronous until the
|
|
1748
|
+
// continue or the abort.
|
|
1749
|
+
export const paddleVgsPayPreClaim = (ctx) => {
|
|
1750
|
+
const { url, method } = ctx.request;
|
|
1751
|
+
if (!ctx.paddleVgsPay?.holds(url, method))
|
|
1752
|
+
return undefined;
|
|
1753
|
+
let body;
|
|
1754
|
+
// A reader that throws (Playwright's postData() can) proves nothing: judged as a body that is not the frame's.
|
|
1755
|
+
try {
|
|
1756
|
+
body = ctx.request.body;
|
|
1757
|
+
}
|
|
1758
|
+
catch {
|
|
1759
|
+
body = null;
|
|
1760
|
+
}
|
|
1761
|
+
const judged = ctx.paddleVgsPay.judge(ctx.frame, url, method, body);
|
|
1762
|
+
if (judged === null)
|
|
1763
|
+
return undefined;
|
|
1764
|
+
return 'reason' in judged ? paddleVgsPayRefused(ctx, judged.reason) : paddleVgsPayContinued(ctx, judged.body);
|
|
1765
|
+
};
|
|
1766
|
+
async function paddleVgsPayRefused(ctx, reason) {
|
|
1767
|
+
const { url, method } = ctx.request;
|
|
1768
|
+
ctx.preparationGate.invalidate('unsupported_checkout');
|
|
1769
|
+
ctx.lifecycle.unsupported(reason);
|
|
1770
|
+
ctx.onEvent?.({ type: 'unsupported_checkout', detail: { url: paddleVgsPayEventUrl(url), method, reason } });
|
|
1771
|
+
await ctx.effects.abort();
|
|
1772
|
+
return { kind: 'abort' };
|
|
1773
|
+
}
|
|
1774
|
+
async function paddleVgsPayContinued(ctx, body) {
|
|
1775
|
+
try {
|
|
1776
|
+
await ctx.effects.continueRequest(body);
|
|
1777
|
+
}
|
|
1778
|
+
catch (error) {
|
|
1779
|
+
ctx.onEvent?.({ type: 'failed', detail: ctx.failureSummary(error) });
|
|
1780
|
+
await ctx.effects.abort().catch(() => { });
|
|
1781
|
+
return { kind: 'abort' };
|
|
1782
|
+
}
|
|
1783
|
+
ctx.onEvent?.({ type: 'companion_continued', detail: { url: paddleVgsPayEventUrl(ctx.request.url), psp: 'paddle_vgs',
|
|
1784
|
+
fields: ['card_first_six', 'card_last_four', 'expiry_month', 'expiry_year', 'card_brand'] } });
|
|
1785
|
+
return { kind: 'continue' };
|
|
1786
|
+
}
|
|
1740
1787
|
// The terminal arbiter, always last. A request that no gate claimed and that is
|
|
1741
1788
|
// neither a native Stripe step nor a recognized card request continues, unless
|
|
1742
1789
|
// it matches a declared payment endpoint we do not support (then it aborts as an
|
|
@@ -1771,7 +1818,7 @@ async function unsupportedContinue(ctx) {
|
|
|
1771
1818
|
* after Stripe is never offered a step Stripe claimed: Stripe answers, aborts or
|
|
1772
1819
|
* pauses each one itself. */
|
|
1773
1820
|
export const PSP_PRE_CLAIM_GATES = [cardEndpointResendPreClaim, cardEndpointPreClaim, mercadoPreClaim, juspayPreClaim, braintreePreClaim, stripePreClaim, merchantHostedPreClaim, verifonePreClaim, fiservPreClaim, gmoPreClaim, cybersourceFlexPreClaim, datatransPreClaim, pelecardPreClaim, aciPreClaim, creditguardPreClaim, primerPreClaim, payrailsPreClaim, convergePreClaim, eprotectPreClaim, wspayPreClaim, shijiStsPreClaim, ekashuPreClaim, paypalHostedFieldsPreClaim,
|
|
1774
|
-
cybersourceSecureAcceptancePreClaim, worldlineMyCheckoutPreClaim];
|
|
1821
|
+
cybersourceSecureAcceptancePreClaim, worldlineMyCheckoutPreClaim, paddleVgsPayPreClaim];
|
|
1775
1822
|
/** Run each gate in order; the first to return a decision wins. If none does,
|
|
1776
1823
|
* the terminal arbiter decides between continue, abort (unsupported) and pause.
|
|
1777
1824
|
* Returns synchronously while every gate defers synchronously (an ordinary card
|
|
@@ -16,8 +16,12 @@
|
|
|
16
16
|
* CyberSource's reply 30 times, a second apart, from Save (Arrow Electronics), too soon for an
|
|
17
17
|
* approval after Save. Its environments are its two hosts: secureacceptance (production) and
|
|
18
18
|
* testsecureacceptance (sandbox).
|
|
19
|
+
*
|
|
20
|
+
* paddle_vgs: prepared only. Paddle's checkout frame aborts its card request to its VGS card vault 10
|
|
21
|
+
* seconds after Pay and sends it once more, too soon for an approval after Pay. Its environments are its
|
|
22
|
+
* two card URLs: vault.paddle.com (production) and sandbox-vault.paddle.com (sandbox).
|
|
19
23
|
*/
|
|
20
|
-
export type PreparationProcessor = 'square' | 'braintree' | 'worldpay' | 'bambora' | 'mercado_pago' | 'recurly' | 'spreedly' | 'adyen' | 'checkout_com' | 'paysafe' | 'fiserv' | 'cybersource_flex' | 'aci' | 'creditguard' | 'worldpay_eprotect' | 'amadeus_checkout' | 'verifone' | 'cybersource_secure_acceptance';
|
|
24
|
+
export type PreparationProcessor = 'square' | 'braintree' | 'worldpay' | 'bambora' | 'mercado_pago' | 'recurly' | 'spreedly' | 'adyen' | 'checkout_com' | 'paysafe' | 'fiserv' | 'cybersource_flex' | 'aci' | 'creditguard' | 'worldpay_eprotect' | 'amadeus_checkout' | 'verifone' | 'cybersource_secure_acceptance' | 'paddle_vgs';
|
|
21
25
|
export type PreparationEnvironment = 'production' | 'sandbox' | 'shared';
|
|
22
26
|
/**
|
|
23
27
|
* How the approved card reaches the processor: the device's own request (token), or
|
|
@@ -39,8 +43,11 @@ export declare function preparationRequestMethod(psp: string): 'GET' | 'POST';
|
|
|
39
43
|
* sending it, and a Pay button that runs the tokenization again sends the same placeholder and
|
|
40
44
|
* fields (WooCommerce's Bambora plugin shows the timeout, clears its token fields and lets Pay be
|
|
41
45
|
* clicked again). The cardholder's device answers with a token that pays nothing until the
|
|
42
|
-
* merchant's server charges it.
|
|
43
|
-
*
|
|
46
|
+
* merchant's server charges it. Paddle VGS too: Paddle's frame aborts its card request to its VGS
|
|
47
|
+
* card vault 10 seconds after sending it and sends the same body under the same bearer once more, and
|
|
48
|
+
* the device's answer is the stored card's id, which pays nothing until Paddle's /pay names it. Only
|
|
49
|
+
* that repeat, byte for byte under the same bearer, is answered (cdp.ts paddleVgsRetryKey).
|
|
50
|
+
* Every other prepared checkout still answers only the request it was bound to.
|
|
44
51
|
*/
|
|
45
52
|
export declare function preparedApprovalAnswersRetry(psp: string): boolean;
|
|
46
53
|
/**
|
|
@@ -50,7 +57,8 @@ export declare function preparedApprovalAnswersRetry(psp: string): boolean;
|
|
|
50
57
|
* Flex's: flex.cybersource.com is live, testflex.cybersource.com is test, and each has
|
|
51
58
|
* its own signing keys. A Verifone preparation pays in the environment of the key its reviewed
|
|
52
59
|
* profile pins. CyberSource Secure Acceptance's are separate hosts too: secureacceptance is
|
|
53
|
-
* live, testsecureacceptance is test.
|
|
60
|
+
* live, testsecureacceptance is test. So are Paddle VGS's two card URLs: vault is live,
|
|
61
|
+
* sandbox-vault is test.
|
|
54
62
|
*/
|
|
55
63
|
export declare function validPreparationEnvironment(psp: string, environment: string): boolean;
|
|
56
64
|
/**
|
|
@@ -13,6 +13,7 @@ import { eprotectPreparationUrl, isPreparedEprotectRequest } from './eprotect.ge
|
|
|
13
13
|
import { amadeusEnvironment, amadeusPreparationUrls, amadeusRequestRefusal, isPreparedAmadeusRequest } from './amadeus-checkout.generated.js';
|
|
14
14
|
import { isPreparedVerifoneRequest } from './verifone.js';
|
|
15
15
|
import { isPreparedSecureAcceptanceRequest, secureAcceptanceEnvironment, secureAcceptancePreparationUrl, secureAcceptanceRequestRefusal, } from './cybersource-secure-acceptance.generated.js';
|
|
16
|
+
import { PADDLE_VGS_CARDS_URLS, isPreparedPaddleVgsRequest } from './paddle-vgs.generated.js';
|
|
16
17
|
export function preparationMode(psp) {
|
|
17
18
|
return psp === 'adyen' || psp === 'fiserv' || psp === 'verifone' ? 'cse' : 'token';
|
|
18
19
|
}
|
|
@@ -30,11 +31,14 @@ export function preparationRequestMethod(psp) {
|
|
|
30
31
|
* sending it, and a Pay button that runs the tokenization again sends the same placeholder and
|
|
31
32
|
* fields (WooCommerce's Bambora plugin shows the timeout, clears its token fields and lets Pay be
|
|
32
33
|
* clicked again). The cardholder's device answers with a token that pays nothing until the
|
|
33
|
-
* merchant's server charges it.
|
|
34
|
-
*
|
|
34
|
+
* merchant's server charges it. Paddle VGS too: Paddle's frame aborts its card request to its VGS
|
|
35
|
+
* card vault 10 seconds after sending it and sends the same body under the same bearer once more, and
|
|
36
|
+
* the device's answer is the stored card's id, which pays nothing until Paddle's /pay names it. Only
|
|
37
|
+
* that repeat, byte for byte under the same bearer, is answered (cdp.ts paddleVgsRetryKey).
|
|
38
|
+
* Every other prepared checkout still answers only the request it was bound to.
|
|
35
39
|
*/
|
|
36
40
|
export function preparedApprovalAnswersRetry(psp) {
|
|
37
|
-
return psp === 'bambora';
|
|
41
|
+
return psp === 'bambora' || psp === 'paddle_vgs';
|
|
38
42
|
}
|
|
39
43
|
/**
|
|
40
44
|
* Shared endpoint processors cannot attest test/live mode from their URL or key prefix.
|
|
@@ -43,13 +47,14 @@ export function preparedApprovalAnswersRetry(psp) {
|
|
|
43
47
|
* Flex's: flex.cybersource.com is live, testflex.cybersource.com is test, and each has
|
|
44
48
|
* its own signing keys. A Verifone preparation pays in the environment of the key its reviewed
|
|
45
49
|
* profile pins. CyberSource Secure Acceptance's are separate hosts too: secureacceptance is
|
|
46
|
-
* live, testsecureacceptance is test.
|
|
50
|
+
* live, testsecureacceptance is test. So are Paddle VGS's two card URLs: vault is live,
|
|
51
|
+
* sandbox-vault is test.
|
|
47
52
|
*/
|
|
48
53
|
export function validPreparationEnvironment(psp, environment) {
|
|
49
54
|
if (psp === 'bambora' || psp === 'mercado_pago' || psp === 'recurly' || psp === 'spreedly')
|
|
50
55
|
return environment === 'shared';
|
|
51
56
|
return ['square', 'braintree', 'worldpay', 'adyen', 'checkout_com', 'paysafe', 'fiserv', 'cybersource_flex', 'aci', 'creditguard', 'worldpay_eprotect', 'amadeus_checkout', 'verifone',
|
|
52
|
-
'cybersource_secure_acceptance'].includes(psp) && ['production', 'sandbox'].includes(environment);
|
|
57
|
+
'cybersource_secure_acceptance', 'paddle_vgs'].includes(psp) && ['production', 'sandbox'].includes(environment);
|
|
53
58
|
}
|
|
54
59
|
/**
|
|
55
60
|
* ACI's prepared endpoint, the literal the API names (backend checkout-prepared-processor.ts): its
|
|
@@ -91,6 +96,9 @@ export function preparationEndpoint(psp, environment) {
|
|
|
91
96
|
// The token-create URL on the environment's host, as the API names it: the one request the claim binds.
|
|
92
97
|
if (psp === 'cybersource_secure_acceptance')
|
|
93
98
|
return secureAcceptancePreparationUrl(environment);
|
|
99
|
+
// Paddle VGS: the environment's one card URL, the only URL the claim takes for it.
|
|
100
|
+
if (psp === 'paddle_vgs')
|
|
101
|
+
return PADDLE_VGS_CARDS_URLS[environment];
|
|
94
102
|
// A Verifone endpoint is its reviewed profile's leg, never one per environment (verifone.ts).
|
|
95
103
|
if (psp === 'verifone')
|
|
96
104
|
throw new Error('unsupported_preparation_processor');
|
|
@@ -236,6 +244,10 @@ export function matchesPreparedRequest(psp, environment, requestUrl, method, bod
|
|
|
236
244
|
// Flex gate verified the issuing field iframe's capture context against that JWE's key.
|
|
237
245
|
if (psp === 'cybersource_flex')
|
|
238
246
|
return isPreparedCybersourceFlexRequest(requestUrl, method.toUpperCase(), body ?? null, environment, headers);
|
|
247
|
+
// Paddle VGS: the environment's own card URL and payment-core's whole request rule (the checkout's bearer,
|
|
248
|
+
// the JSON:API content type and the frame's body), the rule the API and the Vault bind with too.
|
|
249
|
+
if (psp === 'paddle_vgs')
|
|
250
|
+
return isPreparedPaddleVgsRequest(requestUrl, method.toUpperCase(), body ?? null, environment, headers ?? {});
|
|
239
251
|
if (psp === 'creditguard')
|
|
240
252
|
return matchesPreparedCreditguard(environment, requestUrl, body, headers, binding);
|
|
241
253
|
// A Verifone request is judged only through the profile its preparation names (matchesPreparation).
|
package/dist/primer.generated.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
// Generated from @agent-cards/payment-core. Do not edit.
|
|
3
|
-
// artifact-sha256:
|
|
3
|
+
// artifact-sha256: 80af165492668e00d651e9a039d3f24fe336bc3601dd5d2ab937a4b79bbb7ad8
|
|
4
4
|
// src/card-number-key.js
|
|
5
5
|
var CARD_NUMBER_KEY = /^(number|card_number|cardnumber|cardNum|card_num|pan)$/i;
|
|
6
6
|
// src/json-path.js
|
|
@@ -348,8 +348,81 @@ function amadeusBodyKind(body) {
|
|
|
348
348
|
return record2(value.data) && holdsPan(value.data.mopdata) ? "card" : "other";
|
|
349
349
|
return "other";
|
|
350
350
|
}
|
|
351
|
+
// src/paddle-vgs.js
|
|
352
|
+
var PADDLE_VGS_PSP = "paddle_vgs";
|
|
353
|
+
var PADDLE_VGS_CARDS_URLS = /* @__PURE__ */ Object.freeze({
|
|
354
|
+
production: "https://vault.paddle.com/cards",
|
|
355
|
+
sandbox: "https://sandbox-vault.paddle.com/cards"
|
|
356
|
+
});
|
|
357
|
+
var BODY_LIMIT2 = 4096;
|
|
358
|
+
var ROOT_KEYS2 = /* @__PURE__ */ Object.freeze(["data"]);
|
|
359
|
+
var DATA_KEYS = /* @__PURE__ */ Object.freeze(["type", "attributes"]);
|
|
360
|
+
var ATTRIBUTE_KEYS = /* @__PURE__ */ Object.freeze(["pan", "cvc", "exp_month", "exp_year", "cardholder"]);
|
|
361
|
+
var CARD_NUMBER4 = /^[0-9]{12,19}$/;
|
|
362
|
+
var SECURITY_CODE2 = /^[0-9]{3,4}$/;
|
|
363
|
+
var NAME_LIMIT = 256;
|
|
364
|
+
var CONTROL = /[\u0000-\u001f\u007f]/;
|
|
365
|
+
var cardLikeName = (name) => (name.match(/[0-9]/g) ?? []).length >= 12;
|
|
366
|
+
var record3 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
367
|
+
var sameKeys = (value, keys) => {
|
|
368
|
+
const own = Object.keys(value);
|
|
369
|
+
return own.length === keys.length && own.every((key, at) => key === keys[at]);
|
|
370
|
+
};
|
|
371
|
+
var refuse4 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
372
|
+
var CARD4 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
373
|
+
function paddleVgsEnvironment(url) {
|
|
374
|
+
if (url === PADDLE_VGS_CARDS_URLS.production)
|
|
375
|
+
return "production";
|
|
376
|
+
if (url === PADDLE_VGS_CARDS_URLS.sandbox)
|
|
377
|
+
return "sandbox";
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
function isPaddleVgsCardsUrl(url) {
|
|
381
|
+
return paddleVgsEnvironment(url) !== null;
|
|
382
|
+
}
|
|
383
|
+
function readBody2(body) {
|
|
384
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT2)
|
|
385
|
+
return null;
|
|
386
|
+
let value;
|
|
387
|
+
try {
|
|
388
|
+
value = JSON.parse(body);
|
|
389
|
+
if (!record3(value) || JSON.stringify(value) !== body)
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
catch {
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
395
|
+
return value;
|
|
396
|
+
}
|
|
397
|
+
function paddleVgsBodyVerdict(body) {
|
|
398
|
+
const value = readBody2(body);
|
|
399
|
+
if (value === null || !sameKeys(value, ROOT_KEYS2) || !record3(value.data) || !sameKeys(value.data, DATA_KEYS) || value.data.type !== "cards" || !record3(value.data.attributes) || !sameKeys(value.data.attributes, ATTRIBUTE_KEYS)) {
|
|
400
|
+
return refuse4("paddle_vgs_body_unsupported");
|
|
401
|
+
}
|
|
402
|
+
const card = value.data.attributes;
|
|
403
|
+
const holder = card.cardholder;
|
|
404
|
+
if (typeof card.pan !== "string" || !CARD_NUMBER4.test(card.pan) || typeof card.cvc !== "string" || !SECURITY_CODE2.test(card.cvc) || !Number.isInteger(card.exp_month) || card.exp_month < 1 || card.exp_month > 12 || !Number.isInteger(card.exp_year) || card.exp_year < 0 || card.exp_year > 99 || !record3(holder) || !sameKeys(holder, ["name"]) || typeof holder.name !== "string" || holder.name.length > NAME_LIMIT || CONTROL.test(holder.name) || cardLikeName(holder.name)) {
|
|
405
|
+
return refuse4("paddle_vgs_body_unsupported");
|
|
406
|
+
}
|
|
407
|
+
return CARD4;
|
|
408
|
+
}
|
|
409
|
+
var pin2 = (fields) => Object.freeze({
|
|
410
|
+
...fields,
|
|
411
|
+
origins: Object.freeze([...fields.origins]),
|
|
412
|
+
sellerClaim: fields.sellerClaim ? Object.freeze({ ...fields.sellerClaim }) : null
|
|
413
|
+
});
|
|
414
|
+
var PADDLE_VGS_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
415
|
+
pin2({ id: "rectangle_pro", merchant: "Rectangle Pro", origins: ["https://rectangleapp.com"], sellerClaim: null })
|
|
416
|
+
]);
|
|
417
|
+
var FACT_KEYS = /* @__PURE__ */ Object.freeze(["card_first_six", "card_last_four", "expiry_month", "expiry_year", "card_brand"]);
|
|
418
|
+
var METADATA_KEYS = /* @__PURE__ */ Object.freeze(["cardholder_name", ...FACT_KEYS]);
|
|
351
419
|
// src/card-fields.js
|
|
352
420
|
function processorGate(recognizer, url, body) {
|
|
421
|
+
if (recognizer && recognizer.psp === PADDLE_VGS_PSP) {
|
|
422
|
+
if (url !== void 0 && !isPaddleVgsCardsUrl(url))
|
|
423
|
+
return { verdict: "refuse", code: "paddle_vgs_url_refused" };
|
|
424
|
+
return paddleVgsBodyVerdict(body);
|
|
425
|
+
}
|
|
353
426
|
if (recognizer && recognizer.psp === GRAVY_PSP)
|
|
354
427
|
return gravyBodyVerdict(body);
|
|
355
428
|
if (recognizer && recognizer.psp === MONERIS_PSP) {
|
|
@@ -470,12 +543,12 @@ var KEEP_ON_FILE_REFUSAL = "Refusing to pay: this Primer payment would keep the
|
|
|
470
543
|
var UNSUPPORTED_SDK_REFUSAL = "Refusing to pay: this checkout uses a Primer SDK Agentcard does not support yet. Nothing was sent.";
|
|
471
544
|
var NETWORK_MISMATCH_REFUSAL = "Refusing to pay: this Primer payment names a card network that is not your card's. Nothing was sent.";
|
|
472
545
|
var FILL_REFUSAL = "Could not fill the card fields for Primer. Nothing was sent.";
|
|
473
|
-
var
|
|
546
|
+
var BODY_LIMIT3 = 16384;
|
|
474
547
|
var RESPONSE_LIMIT = 32768;
|
|
475
|
-
var
|
|
548
|
+
var ROOT_KEYS3 = ["paymentInstrument", "userDescription", "tokenType", "paymentFlow"];
|
|
476
549
|
var INSTRUMENT_KEYS = ["number", "cvv", "expirationMonth", "expirationYear", "cardholderName", "preferredNetwork"];
|
|
477
550
|
var REQUIRED_INSTRUMENT_KEYS = ["number", "cvv", "expirationMonth", "expirationYear"];
|
|
478
|
-
var
|
|
551
|
+
var record4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
479
552
|
var owns4 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
480
553
|
var exact = (pattern, value) => typeof value === "string" && pattern.exec(value)?.[0] === value;
|
|
481
554
|
var text = (value, max) => typeof value === "string" && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
|
|
@@ -498,7 +571,7 @@ function isPrimerTokenizeUrl(url, method = "POST") {
|
|
|
498
571
|
return parsed.href === url && parsed.protocol === "https:" && !parsed.port && !parsed.username && !parsed.password && !parsed.search && !parsed.hash && PRIMER_PCI_HOSTS.includes(parsed.hostname) && parsed.pathname === PRIMER_TOKENIZE_PATH;
|
|
499
572
|
}
|
|
500
573
|
function judgeBody(body) {
|
|
501
|
-
if (typeof body !== "string" || body === "" || body.length >
|
|
574
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT3)
|
|
502
575
|
return null;
|
|
503
576
|
let value;
|
|
504
577
|
try {
|
|
@@ -507,12 +580,12 @@ function judgeBody(body) {
|
|
|
507
580
|
catch {
|
|
508
581
|
return null;
|
|
509
582
|
}
|
|
510
|
-
if (!
|
|
583
|
+
if (!record4(value) || !roundTrips(value, body))
|
|
511
584
|
return null;
|
|
512
|
-
if (!Object.keys(value).every((key) =>
|
|
585
|
+
if (!Object.keys(value).every((key) => ROOT_KEYS3.includes(key)) || !owns4(value, "paymentInstrument"))
|
|
513
586
|
return null;
|
|
514
587
|
const instrument = value.paymentInstrument;
|
|
515
|
-
if (!
|
|
588
|
+
if (!record4(instrument) || !Object.keys(instrument).every((key) => INSTRUMENT_KEYS.includes(key)) || !REQUIRED_INSTRUMENT_KEYS.every((key) => owns4(instrument, key)))
|
|
516
589
|
return null;
|
|
517
590
|
if (!digits(instrument.number, 12, 19) || !digits(instrument.cvv, 3, 4) || !exact(MONTH, instrument.expirationMonth) || !exact(YEAR, instrument.expirationYear))
|
|
518
591
|
return null;
|
|
@@ -540,7 +613,7 @@ var CLIENT_TOKEN = /^[A-Za-z0-9._~+/=-]{16,4096}$/;
|
|
|
540
613
|
var REQUEST_ID = /^[A-Za-z0-9-]{1,64}$/;
|
|
541
614
|
var API_VERSION = /^2\.[0-9]{1,2}$/;
|
|
542
615
|
function readHeaders(headers) {
|
|
543
|
-
if (!
|
|
616
|
+
if (!record4(headers))
|
|
544
617
|
return null;
|
|
545
618
|
const folded = /* @__PURE__ */ new Map();
|
|
546
619
|
for (const [name, value] of Object.entries(headers)) {
|
|
@@ -587,7 +660,7 @@ function onTokenizePath(url) {
|
|
|
587
660
|
}
|
|
588
661
|
}
|
|
589
662
|
function primerTokenizeRefusal(request) {
|
|
590
|
-
if (!
|
|
663
|
+
if (!record4(request) || request.method !== "POST" || !isPrimerTokenizeUrl(request.url))
|
|
591
664
|
return "unsupported";
|
|
592
665
|
return headersRefusal(request.headers) ?? primerBodyRefusal(request.body);
|
|
593
666
|
}
|
|
@@ -602,7 +675,7 @@ function primerCardOnFileRefusal(url, options, policy = PRIMER_SESSION_CARD_ON_F
|
|
|
602
675
|
return "unsupported";
|
|
603
676
|
if (new URL(url).hostname !== LIVE_PCI_HOST)
|
|
604
677
|
return null;
|
|
605
|
-
return primerCardOnFileDisclosure(url, policy) &&
|
|
678
|
+
return primerCardOnFileDisclosure(url, policy) && record4(options) && options.keepOnFile === true ? null : "keep_on_file";
|
|
606
679
|
}
|
|
607
680
|
function primerRefusalMessage(reason) {
|
|
608
681
|
if (reason === "keep_on_file")
|
|
@@ -686,7 +759,7 @@ function readAnswer(body) {
|
|
|
686
759
|
return null;
|
|
687
760
|
try {
|
|
688
761
|
const value = JSON.parse(body);
|
|
689
|
-
return
|
|
762
|
+
return record4(value) ? value : null;
|
|
690
763
|
}
|
|
691
764
|
catch {
|
|
692
765
|
return null;
|
|
@@ -695,16 +768,16 @@ function readAnswer(body) {
|
|
|
695
768
|
var tokenValue = (value) => exact(TOKEN, value) && !panLike(value);
|
|
696
769
|
var optional = (value, key, check) => !owns4(value, key) || value[key] === null || check(value[key]);
|
|
697
770
|
function cardDetails(data) {
|
|
698
|
-
if (!
|
|
771
|
+
if (!record4(data) || !exact(/^[0-9]{4}$/, data.last4Digits))
|
|
699
772
|
return null;
|
|
700
|
-
if (!optional(data, "first6Digits", (v) => exact(/^[0-9]{6}$/, v)) || !optional(data, "expirationMonth", (v) => exact(RESPONSE_MONTH, v)) || !optional(data, "expirationYear", (v) => exact(RESPONSE_YEAR, v)) || !optional(data, "cardholderName", (v) => plain(v, 256)) || !optional(data, "network", (v) => exact(NETWORK_NAME, v)) || !optional(data, "isNetworkTokenized", (v) => typeof v === "boolean") || !optional(data, "binData",
|
|
773
|
+
if (!optional(data, "first6Digits", (v) => exact(/^[0-9]{6}$/, v)) || !optional(data, "expirationMonth", (v) => exact(RESPONSE_MONTH, v)) || !optional(data, "expirationYear", (v) => exact(RESPONSE_YEAR, v)) || !optional(data, "cardholderName", (v) => plain(v, 256)) || !optional(data, "network", (v) => exact(NETWORK_NAME, v)) || !optional(data, "isNetworkTokenized", (v) => typeof v === "boolean") || !optional(data, "binData", record4))
|
|
701
774
|
return null;
|
|
702
775
|
const safe = { last4Digits: data.last4Digits };
|
|
703
776
|
for (const key of ["first6Digits", "expirationMonth", "expirationYear", "cardholderName", "network", "isNetworkTokenized"]) {
|
|
704
777
|
if (owns4(data, key) && data[key] !== null)
|
|
705
778
|
safe[key] = data[key];
|
|
706
779
|
}
|
|
707
|
-
if (
|
|
780
|
+
if (record4(data.binData)) {
|
|
708
781
|
const bin = {};
|
|
709
782
|
for (const key of BIN_KEYS) {
|
|
710
783
|
if (!owns4(data.binData, key) || data.binData[key] === null)
|
|
@@ -720,7 +793,7 @@ function cardDetails(data) {
|
|
|
720
793
|
function threeDsSummary(value) {
|
|
721
794
|
if (value === void 0 || value === null)
|
|
722
795
|
return null;
|
|
723
|
-
if (!
|
|
796
|
+
if (!record4(value) || !exact(CODE, value.responseCode) || !optional(value, "reasonCode", (v) => exact(CODE, v)) || !optional(value, "reasonText", (v) => plain(v, 256)) || !optional(value, "protocolVersion", (v) => v === "" || exact(PROTOCOL, v)) || !optional(value, "challengeIssued", (v) => typeof v === "boolean"))
|
|
724
797
|
return void 0;
|
|
725
798
|
const safe = { responseCode: value.responseCode };
|
|
726
799
|
for (const key of ["reasonCode", "reasonText", "protocolVersion", "challengeIssued"]) {
|
|
@@ -748,7 +821,7 @@ function rebuildToken(value) {
|
|
|
748
821
|
}
|
|
749
822
|
function primerErrorId(body) {
|
|
750
823
|
const value = readAnswer(body);
|
|
751
|
-
const id = value &&
|
|
824
|
+
const id = value && record4(value.error) ? value.error.errorId : null;
|
|
752
825
|
return exact(ERROR_ID, id) && !panLike(id) ? id : null;
|
|
753
826
|
}
|
|
754
827
|
function matchesCard(details, card) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
// Generated from @agent-cards/payment-core. Do not edit.
|
|
3
|
-
// artifact-sha256:
|
|
3
|
+
// artifact-sha256: 7e7a9b515128df56d149df50e0c275c7f6e8e522945ed818ca714ccac7eb1cd7
|
|
4
4
|
// src/deep-freeze.js
|
|
5
5
|
function deepFreeze(value) {
|
|
6
6
|
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
@@ -583,13 +583,26 @@ var PROCESSOR_DEFINITIONS = deepFreeze([
|
|
|
583
583
|
// Verified from https://hosted.test.paysafe.com/checkout/1.8.0/main.bundle.js
|
|
584
584
|
// and its byte-identical production sibling (SHA-256 e9e111ff03073cc936a47674e8e7c5db4a6d1050e1b65bf5e20723116fd5080c).
|
|
585
585
|
// Its native LIVE/TEST environment map selects exactly hosted[.test].paysafe.com.
|
|
586
|
+
// Checkout v1 latest (loader version 1.16.1; checkout/v1/latest/main.js SHA-256
|
|
587
|
+
// 328c6443da930f3648826248afa3c342cdd07d04e49a78b0878dda187772bf80) posts the same body to
|
|
588
|
+
// checkout/api/v1/tokenize on api[.test].paysafe.com, the hosts its vendor.js maps LIVE/TEST to.
|
|
589
|
+
// It and Paysafe.js latest set X-Internal-Correlation-Id, X-App-Version and X-TransactionSource
|
|
590
|
+
// on every card request, and Paysafe's CORS answer on all three API card paths allows them for
|
|
591
|
+
// any origin (2026-10-15), so a replay keeps them as the native request sends them.
|
|
586
592
|
// Keep host/path pairs separate: details/log are not card requests;
|
|
587
593
|
// card/tokenize uses a saved paymentToken, and 3DS-specific paths are unverified.
|
|
588
|
-
match: "(?:api(\\.test)?\\.paysafe\\.com/(?:paymenthub/v1/singleusepaymenthandles|js/api/v1/tokenize)|hosted(\\.test)?\\.paysafe\\.com/checkout/api/v1/tokenize)(?![\\w/-])",
|
|
594
|
+
match: "(?:api(\\.test)?\\.paysafe\\.com/(?:paymenthub/v1/singleusepaymenthandles|js/api/v1/tokenize|checkout/api/v1/tokenize)|hosted(\\.test)?\\.paysafe\\.com/checkout/api/v1/tokenize)(?![\\w/-])",
|
|
589
595
|
hosts: ["^api\\.paysafe\\.com$", "^api\\.test\\.paysafe\\.com$", "^hosted\\.paysafe\\.com$", "^hosted\\.test\\.paysafe\\.com$"],
|
|
590
596
|
sandboxHosts: ["^api\\.test\\.paysafe\\.com$", "^hosted\\.test\\.paysafe\\.com$"],
|
|
591
597
|
encoding: "json",
|
|
592
|
-
passthroughHeaders: [
|
|
598
|
+
passthroughHeaders: [
|
|
599
|
+
"^authorization$",
|
|
600
|
+
"^x-paysafe-credentials$",
|
|
601
|
+
"^correlationid$",
|
|
602
|
+
"^x-internal-correlation-id$",
|
|
603
|
+
"^x-app-version$",
|
|
604
|
+
"^x-transactionsource$"
|
|
605
|
+
]
|
|
593
606
|
},
|
|
594
607
|
{
|
|
595
608
|
psp: "recurly",
|
|
@@ -1418,6 +1431,33 @@ var PROCESSOR_DEFINITIONS = deepFreeze([
|
|
|
1418
1431
|
// A checked "remember" asks Worldline to keep the card for later purchases.
|
|
1419
1432
|
token: "remember"
|
|
1420
1433
|
}
|
|
1434
|
+
},
|
|
1435
|
+
{
|
|
1436
|
+
psp: "paddle_vgs",
|
|
1437
|
+
// Paddle's checkout frame (buy.paddle.com) on a checkout whose card method names VGS as its
|
|
1438
|
+
// tokenizer: one JSON:API POST to /cards on vault.paddle.com, a VGS inbound proxy Paddle runs
|
|
1439
|
+
// (sandbox-vault.paddle.com in test), with the checkout's own bearer JWT. PAN@
|
|
1440
|
+
// data.attributes.pan, with cvc, exp_month (1 to 12) and exp_year (two digits) beside it, all
|
|
1441
|
+
// numbers but the pan and the cvc. paddle-vgs.js holds the request rule the pause decision, the
|
|
1442
|
+
// API's create, the prepared bind and the device all read: exactly one of the two URLs, the
|
|
1443
|
+
// frame's Content-Type and bearer, and the frame's body byte for byte. VGS answers with the
|
|
1444
|
+
// stored card's id, which the frame sends on to Paddle's /pay. The frame aborts this request
|
|
1445
|
+
// after 10 seconds and sends it once more, so the lane is prepared only (preparationRequired):
|
|
1446
|
+
// the cardholder approves before the agent clicks Pay. The card leaves the cardholder's device
|
|
1447
|
+
// by a direct fetch, since the proxy answers any origin. The checkouts that name TokenEx or
|
|
1448
|
+
// Spreedly send the card elsewhere and are not this entry.
|
|
1449
|
+
// Ships dark: served only to a client that declares `paddle_vgs_cards`, gated off for every org
|
|
1450
|
+
// until an operator lists one (`paddle_vgs:<org>`), and autopilot never sends this request
|
|
1451
|
+
// (autopilot.js DEVICE_REPLAY_REFUSED_OPERATIONS). The environment is pinned (S7):
|
|
1452
|
+
// sandbox-vault only on test rows and only with documented test cards, vault only on live rows.
|
|
1453
|
+
capability: "paddle_vgs_cards",
|
|
1454
|
+
match: "(?:sandbox-)?vault\\.paddle\\.com/cards",
|
|
1455
|
+
hosts: ["^vault\\.paddle\\.com$", "^sandbox-vault\\.paddle\\.com$"],
|
|
1456
|
+
sandboxHosts: ["^sandbox-vault\\.paddle\\.com$"],
|
|
1457
|
+
hostEnvironmentPinned: true,
|
|
1458
|
+
preparationRequired: true,
|
|
1459
|
+
encoding: "json",
|
|
1460
|
+
passthroughHeaders: ["^authorization$"]
|
|
1421
1461
|
}
|
|
1422
1462
|
]);
|
|
1423
1463
|
var PSP_RECOGNIZERS = deepFreeze(PROCESSOR_DEFINITIONS.map(({ compose, encryptedCardFields, deviceSteps, deviceEncrypt, ...definition }) => definition));
|
|
@@ -1520,6 +1560,17 @@ var pin = (fields) => Object.freeze({ ...fields, origins: Object.freeze([...fiel
|
|
|
1520
1560
|
var MONERIS_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
1521
1561
|
pin({ id: "jack_org_raisin", merchant: "Jack.org", origins: ["https://jack.akaraisin.com"], profileIds: ["htL7TR9H7ICYN2B"] })
|
|
1522
1562
|
]);
|
|
1563
|
+
// src/paddle-vgs.js
|
|
1564
|
+
var pin2 = (fields) => Object.freeze({
|
|
1565
|
+
...fields,
|
|
1566
|
+
origins: Object.freeze([...fields.origins]),
|
|
1567
|
+
sellerClaim: fields.sellerClaim ? Object.freeze({ ...fields.sellerClaim }) : null
|
|
1568
|
+
});
|
|
1569
|
+
var PADDLE_VGS_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
1570
|
+
pin2({ id: "rectangle_pro", merchant: "Rectangle Pro", origins: ["https://rectangleapp.com"], sellerClaim: null })
|
|
1571
|
+
]);
|
|
1572
|
+
var FACT_KEYS = /* @__PURE__ */ Object.freeze(["card_first_six", "card_last_four", "expiry_month", "expiry_year", "card_brand"]);
|
|
1573
|
+
var METADATA_KEYS = /* @__PURE__ */ Object.freeze(["cardholder_name", ...FACT_KEYS]);
|
|
1523
1574
|
// src/cybersource-secure-acceptance.js
|
|
1524
1575
|
var SA_BODY_LIMIT = 32 * 1024;
|
|
1525
1576
|
var SA_REPLY_LIMIT = 64 * 1024;
|
|
@@ -1607,6 +1658,7 @@ var ALLOWED_MEDIA_TYPES = {
|
|
|
1607
1658
|
jwe: ["application/jwt"]
|
|
1608
1659
|
};
|
|
1609
1660
|
var JWE_CONTENT_TYPE = "application/jwt; charset=utf-8";
|
|
1661
|
+
var PADDLE_VGS_MEDIA_TYPE = "application/vnd.api+json";
|
|
1610
1662
|
function contentTypeFor(pspOrEntry, headers) {
|
|
1611
1663
|
const rec = trustedClientRecognizer(pspOrEntry);
|
|
1612
1664
|
if (rec.encoding === "jwe") {
|
|
@@ -1616,6 +1668,13 @@ function contentTypeFor(pspOrEntry, headers) {
|
|
|
1616
1668
|
throw new Error("Refusing to pay: this processor takes its sealed card only as application/jwt.");
|
|
1617
1669
|
return JWE_CONTENT_TYPE;
|
|
1618
1670
|
}
|
|
1671
|
+
if (rec.psp === "paddle_vgs") {
|
|
1672
|
+
const captured = Object.entries(headers || {}).find(([k]) => /^content-type$/i.test(k));
|
|
1673
|
+
if (!captured || typeof captured[1] !== "string" || captured[1].trim().toLowerCase() !== PADDLE_VGS_MEDIA_TYPE) {
|
|
1674
|
+
throw new Error("Refusing to pay: this processor takes its card only as application/vnd.api+json.");
|
|
1675
|
+
}
|
|
1676
|
+
return PADDLE_VGS_MEDIA_TYPE;
|
|
1677
|
+
}
|
|
1619
1678
|
const encoding = rec && rec.encoding === "form" ? "form" : "json";
|
|
1620
1679
|
const allowed = ALLOWED_MEDIA_TYPES[encoding];
|
|
1621
1680
|
const fallback = allowed[0];
|
|
@@ -1635,6 +1694,8 @@ function replayHeaders(pspOrEntry, captured = {}) {
|
|
|
1635
1694
|
const headers = { "content-type": contentTypeFor(rec, captured) };
|
|
1636
1695
|
if (rec.psp === "creditguard")
|
|
1637
1696
|
headers.accept = "application/json";
|
|
1697
|
+
if (rec.psp === "paddle_vgs")
|
|
1698
|
+
headers.accept = PADDLE_VGS_MEDIA_TYPE;
|
|
1638
1699
|
for (const [name, value] of Object.entries(captured)) {
|
|
1639
1700
|
if (rec.headers.some((pattern) => pattern.test(name)) && !HEADER_NEVER_FORWARD.test(name))
|
|
1640
1701
|
headers[name] = value;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-cards/sdk",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.13",
|
|
4
4
|
"description": "Agentcard's SDK: one client, Agentcard, with two modules. checkout pauses a browser purchase and pays it with the person's own card; voice connects a person to your product once and approves a purchase by voice inside it. Card data never enters your process.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"_comment_build": "The public SDK keeps zero runtime dependencies. Its build vendors deterministic metadata and substitution artifacts from the internal payment core, and the voice streaming door from packages/voice/src/core (the phone package, @agent-cards/voice, ships it to phones); TypeScript remains pinned.",
|
|
28
28
|
"build": "node ../payment-core/scripts/build.mjs && node scripts/generate-payment-core.mjs && node scripts/generate-voice-stream.mjs && npx -y -p typescript@5.9.3 tsc && node scripts/generate-preflight-contract.mjs",
|
|
29
29
|
"prepublishOnly": "pnpm build",
|
|
30
|
-
"test": "node test.mjs && node --test lifecycle.test.mjs merchant-abort.test.mjs preparation.test.mjs braintree.test.mjs pre-claim.test.mjs ekashu.test.mjs paypal-hosted-fields.test.mjs cybersource-secure-acceptance.test.mjs autopilot.test.mjs stripe-checkout.test.mjs stripe-setup.test.mjs stripe-legacy-checkout.test.mjs payment-core.test.mjs prepared-processor.test.mjs merchant-hosted.test.mjs merchant-total.test.mjs sandbox-declaration.test.mjs minimum-delay.test.mjs paysafe.test.mjs payu.test.mjs attachment.test.mjs worker-targets.test.mjs mercado-checkout.test.mjs mercado-polling.test.mjs amadeus.test.mjs pelecard.test.mjs aci.test.mjs primer.test.mjs payrails.test.mjs elavon-converge.test.mjs voice.test.mjs agentcard.test.mjs buy.test.mjs readme.test.mjs gmo.test.mjs cybersource-flex.test.mjs juspay-gate.test.mjs card-endpoint.test.mjs card-endpoint-fastspring.test.mjs card-endpoint-navigation.test.mjs merchant-session-probe.test.mjs datatrans.test.mjs authorize-net-dpm.test.mjs creditguard.test.mjs eprotect.test.mjs wspay.test.mjs shiji-sts.test.mjs worldline-mycheckout.test.mjs verifone.test.mjs gravy.test.mjs && node --test preflight-package.test.mjs preflight-collector.test.mjs && node --test kernel-native-qualification.test.mjs && node --test ../vault/scripts/recurly-validation/watch-duty-sdk-result.test.mjs",
|
|
30
|
+
"test": "node test.mjs && node --test lifecycle.test.mjs merchant-abort.test.mjs preparation.test.mjs braintree.test.mjs pre-claim.test.mjs ekashu.test.mjs paypal-hosted-fields.test.mjs cybersource-secure-acceptance.test.mjs autopilot.test.mjs stripe-checkout.test.mjs stripe-setup.test.mjs stripe-legacy-checkout.test.mjs payment-core.test.mjs prepared-processor.test.mjs merchant-hosted.test.mjs merchant-total.test.mjs sandbox-declaration.test.mjs minimum-delay.test.mjs paysafe.test.mjs payu.test.mjs attachment.test.mjs worker-targets.test.mjs mercado-checkout.test.mjs mercado-polling.test.mjs amadeus.test.mjs pelecard.test.mjs aci.test.mjs primer.test.mjs payrails.test.mjs elavon-converge.test.mjs voice.test.mjs agentcard.test.mjs buy.test.mjs readme.test.mjs gmo.test.mjs cybersource-flex.test.mjs juspay-gate.test.mjs card-endpoint.test.mjs card-endpoint-fastspring.test.mjs card-endpoint-navigation.test.mjs merchant-session-probe.test.mjs datatrans.test.mjs authorize-net-dpm.test.mjs creditguard.test.mjs eprotect.test.mjs wspay.test.mjs shiji-sts.test.mjs worldline-mycheckout.test.mjs verifone.test.mjs gravy.test.mjs paddle-vgs.test.mjs redact-url.test.mjs && node --test preflight-package.test.mjs preflight-collector.test.mjs && node --test kernel-native-qualification.test.mjs && node --test ../vault/scripts/recurly-validation/watch-duty-sdk-result.test.mjs",
|
|
31
31
|
"test:browser": "node browser.test.mjs && node stripe-browser.test.mjs && node preparation-browser.test.mjs && node checkout-com-browser.test.mjs && node paysafe-preparation-browser.test.mjs && node owned-shop-browser.test.mjs && node spreedly-browser.test.mjs && node worker-browser.test.mjs && node amadeus-browser.test.mjs && node adyen-merchant-hosted-browser.test.mjs && node adyen-merchant-frames-browser.test.mjs && node fiserv-browser.test.mjs && node gmo-browser.test.mjs && node cybersource-flex-browser.test.mjs && node juspay-browser.test.mjs && node card-endpoint-browser.test.mjs && node datatrans-browser.test.mjs && node authorize-net-dpm-browser.test.mjs && node pelecard-browser.test.mjs && node aci-browser.test.mjs && node creditguard-browser.test.mjs && node primer-browser.test.mjs && node payrails-browser.test.mjs && node elavon-converge-browser.test.mjs && node eprotect-browser.test.mjs && node wspay-browser.test.mjs && node shiji-sts-browser.test.mjs && node worldline-mycheckout-browser.test.mjs && node paypal-hosted-fields-browser.test.mjs && node cybersource-secure-acceptance-browser.test.mjs && node gravy-browser.test.mjs",
|
|
32
32
|
"check:payment-core": "node scripts/generate-payment-core.mjs --check",
|
|
33
33
|
"check:voice-stream": "node scripts/generate-voice-stream.mjs --check",
|
|
@@ -49,5 +49,5 @@
|
|
|
49
49
|
"engines": {
|
|
50
50
|
"node": ">=22"
|
|
51
51
|
},
|
|
52
|
-
"license": "
|
|
52
|
+
"license": "SEE LICENSE IN LICENSE"
|
|
53
53
|
}
|