@agent-cards/sdk 0.23.14 → 0.23.15
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 +4 -0
- package/PREFLIGHT.md +2 -0
- package/README.md +2 -0
- package/dist/amadeus.d.ts +5 -2
- package/dist/amadeus.js +17 -3
- package/dist/card-fields.generated.js +87 -4
- package/dist/cdp.js +16 -8
- package/dist/client.d.ts +10 -0
- package/dist/client.js +43 -8
- package/dist/lifecycle.d.ts +5 -1
- package/dist/lifecycle.js +3 -0
- package/dist/paypal-card-forms.d.ts +73 -0
- package/dist/paypal-card-forms.js +126 -0
- package/dist/pre-claim.d.ts +1 -0
- package/dist/pre-claim.js +59 -3
- package/dist/prepared-processor.d.ts +5 -1
- package/dist/prepared-processor.js +11 -0
- package/dist/primer.generated.js +103 -20
- package/dist/stripe-checkout.generated.js +33 -1
- package/dist/wix-payments.generated.d.ts +42 -0
- package/dist/wix-payments.generated.js +241 -0
- package/package.json +3 -3
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PayPal's Card Fields and PayPal's guest card form, which this SDK refuses for every company until a
|
|
3
|
+
* synced recognizer takes the request.
|
|
4
|
+
*
|
|
5
|
+
* Read 2026-10-15 from PayPal's public bundles and card-free page reads (WooCommerce PayPal Payments
|
|
6
|
+
* 4.1.3 checkouts on PayPal JS SDK 5.0.582, card-field client 1.270.0; web-sdk v6 6.68.0):
|
|
7
|
+
*
|
|
8
|
+
* Card Fields v5 (components=card-fields): each field is a frame on www.paypal.com/smart/card-field,
|
|
9
|
+
* and at submit the number frame sends the typed card as plaintext JSON, a same-origin XHR:
|
|
10
|
+
* POST https://www.paypal.com/v2/checkout/orders/<order id>/confirm-payment-source
|
|
11
|
+
* {"payment_source":{"card":{"number","expiry":"YYYY-MM","security_code","name"?,"billing_address"?}}}
|
|
12
|
+
* Card Fields v6 (web-sdk v6): the same request, sent to api-m.paypal.com.
|
|
13
|
+
* Card Fields saving a card with no purchase: POST https://www.paypal.com/graphql?UpdateVaultSetupToken,
|
|
14
|
+
* the card at variables.paymentSource.card.
|
|
15
|
+
* PayPal's guest card form, behind the black "Debit or Credit Card" button: PayPal's checkout page
|
|
16
|
+
* sends the card as POST https://www.paypal.com/graphql?OnboardGuestMutation, the number at
|
|
17
|
+
* variables.card.cardNumber.
|
|
18
|
+
* PayPal's sandbox serves each on www.sandbox.paypal.com and api-m.sandbox.paypal.com.
|
|
19
|
+
*
|
|
20
|
+
* An SDK without this guard let the agent's placeholder card reach PayPal there, and PayPal declined it.
|
|
21
|
+
* Both adapters arm these paths whatever the synced registry serves, and the pre-claim gate
|
|
22
|
+
* (paypalCardFormsPreClaim, pre-claim.ts) judges each POST:
|
|
23
|
+
* - a Card Fields confirm whose body carries a number at payment_source.card.number aborts, reason
|
|
24
|
+
* `unsupported_paypal_card_fields`, unless the synced registry recognizes it as a card request: an
|
|
25
|
+
* org Agentcard turned PayPal Card Fields on for pauses and pays that confirm through the recognizer,
|
|
26
|
+
* which judges the body itself;
|
|
27
|
+
* - a GraphQL operation carrying a card aborts whatever the registry serves, since no recognizer pays
|
|
28
|
+
* one: the guest form's card as `unsupported_paypal_guest_checkout`, a card saved with no purchase as
|
|
29
|
+
* `unsupported_paypal_card_fields`;
|
|
30
|
+
* - a body with no card (a PayPal wallet confirm, a saved card, every other GraphQL operation the
|
|
31
|
+
* buttons send) continues untouched;
|
|
32
|
+
* - a confirm the adapter could not read aborts that request alone, since nothing proves it carries no
|
|
33
|
+
* card. A GraphQL post it could not read aborts only when its query names one of the two card
|
|
34
|
+
* operations: PayPal's buttons send many others, and failing them would break PayPal's own wallet.
|
|
35
|
+
* Each abort holds the attachment as every unsupported refusal does: the page's next submit would carry
|
|
36
|
+
* the card again, so another way to pay needs a new attachment.
|
|
37
|
+
*
|
|
38
|
+
* A guest form PayPal opens in a popup window runs in another page, which an attachment covers only when
|
|
39
|
+
* the agent attaches the SDK to that page as well. PayPal's BIN lookup (/v2/payments/find-bin-details)
|
|
40
|
+
* reads the first digits the agent types and pays nothing; neither adapter intercepts it.
|
|
41
|
+
*/
|
|
42
|
+
import { paypalHostedFieldsBody } from './paypal-hosted-fields.js';
|
|
43
|
+
export const PAYPAL_CARD_FIELDS_REASON = 'unsupported_paypal_card_fields';
|
|
44
|
+
export const PAYPAL_GUEST_CHECKOUT_REASON = 'unsupported_paypal_guest_checkout';
|
|
45
|
+
/** The hosts Card Fields sends its confirm to: v5 on www, v6 on api-m, live and sandbox. */
|
|
46
|
+
export const PAYPAL_CARD_FIELDS_HOSTS = Object.freeze(['www.paypal.com', 'www.sandbox.paypal.com',
|
|
47
|
+
'api-m.paypal.com', 'api-m.sandbox.paypal.com']);
|
|
48
|
+
/** The hosts of PayPal's own pages, whose GraphQL endpoint takes the guest form's card and a card saved with no purchase. */
|
|
49
|
+
export const PAYPAL_GRAPHQL_HOSTS = Object.freeze(['www.paypal.com', 'www.sandbox.paypal.com']);
|
|
50
|
+
const CONFIRM_PATH = /^\/v2\/checkout\/orders\/[^/]+\/confirm-payment-source\/?$/;
|
|
51
|
+
const GRAPHQL_PATH = /^\/graphql\/?$/;
|
|
52
|
+
/** The two GraphQL operations that carry a card, as PayPal's clients name them in the query string. */
|
|
53
|
+
const CARD_OPERATIONS = ['OnboardGuestMutation', 'UpdateVaultSetupToken'];
|
|
54
|
+
/**
|
|
55
|
+
* CDP Fetch patterns, armed on every attachment: the confirm on its four hosts and GraphQL on PayPal's
|
|
56
|
+
* two page hosts. Chrome sends the canonical URL, whose host is lower case, and the trailing `*` keeps a
|
|
57
|
+
* query or a trailing slash paused. Nothing else on www.paypal.com is armed.
|
|
58
|
+
*/
|
|
59
|
+
export const PAYPAL_CARD_FORM_PATTERNS = Object.freeze([
|
|
60
|
+
...PAYPAL_CARD_FIELDS_HOSTS.map((host) => `https://${host}/v2/checkout/orders/*/confirm-payment-source*`),
|
|
61
|
+
...PAYPAL_GRAPHQL_HOSTS.map((host) => `https://${host}/graphql*`),
|
|
62
|
+
]);
|
|
63
|
+
function paypalUrl(url, hosts, path) {
|
|
64
|
+
let parsed;
|
|
65
|
+
try {
|
|
66
|
+
parsed = new URL(url);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
return parsed.protocol === 'https:' && !parsed.port && !parsed.username && !parsed.password
|
|
72
|
+
&& hosts.includes(parsed.hostname.toLowerCase()) && path.test(parsed.pathname) ? parsed : null;
|
|
73
|
+
}
|
|
74
|
+
/** Whether this URL is the Card Fields confirm on one of its four hosts (https, standard port, no credentials). */
|
|
75
|
+
export function isPaypalCardFieldsConfirm(url) {
|
|
76
|
+
return paypalUrl(url, PAYPAL_CARD_FIELDS_HOSTS, CONFIRM_PATH) !== null;
|
|
77
|
+
}
|
|
78
|
+
/** Whether this URL is GraphQL on one of PayPal's two page hosts. */
|
|
79
|
+
export function isPaypalGraphql(url) {
|
|
80
|
+
return paypalUrl(url, PAYPAL_GRAPHQL_HOSTS, GRAPHQL_PATH) !== null;
|
|
81
|
+
}
|
|
82
|
+
/** Whether this URL is any request the guard judges, for the Playwright route's predicate. */
|
|
83
|
+
export function isPaypalCardFormUrl(url) {
|
|
84
|
+
return isPaypalCardFieldsConfirm(url) || isPaypalGraphql(url);
|
|
85
|
+
}
|
|
86
|
+
/** Whether a GraphQL URL's query names one of the two card operations (`/graphql?OnboardGuestMutation`). */
|
|
87
|
+
export function paypalGraphqlNamesCardOperation(url) {
|
|
88
|
+
const parsed = paypalUrl(url, PAYPAL_GRAPHQL_HOSTS, GRAPHQL_PATH);
|
|
89
|
+
return parsed !== null && CARD_OPERATIONS.some((name) => parsed.searchParams.has(name));
|
|
90
|
+
}
|
|
91
|
+
const record = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
|
|
92
|
+
const present = (value) => value !== undefined && value !== null && value !== '';
|
|
93
|
+
/**
|
|
94
|
+
* What a GraphQL post carries, read as PayPal reads it (the last of a repeated key wins in both), for one
|
|
95
|
+
* operation or a batch of them: 'guest_card' when an operation's variables.card.cardNumber holds anything
|
|
96
|
+
* but null or an empty string, 'saved_card' when an operation's variables.paymentSource.card is an object,
|
|
97
|
+
* 'no_card' for any other JSON object or array of them, and 'unreadable' for a body the adapter could not
|
|
98
|
+
* read (null), an empty one, or one that is neither.
|
|
99
|
+
*/
|
|
100
|
+
export function paypalGraphqlCard(body) {
|
|
101
|
+
if (typeof body !== 'string' || body === '')
|
|
102
|
+
return 'unreadable';
|
|
103
|
+
let parsed;
|
|
104
|
+
try {
|
|
105
|
+
parsed = JSON.parse(body);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return 'unreadable';
|
|
109
|
+
}
|
|
110
|
+
const operations = Array.isArray(parsed) ? parsed : [parsed];
|
|
111
|
+
if (operations.length === 0 || !operations.every(record))
|
|
112
|
+
return 'unreadable';
|
|
113
|
+
let carried = 'no_card';
|
|
114
|
+
for (const operation of operations) {
|
|
115
|
+
const variables = operation.variables;
|
|
116
|
+
if (!record(variables))
|
|
117
|
+
continue;
|
|
118
|
+
if (record(variables.card) && present(variables.card.cardNumber))
|
|
119
|
+
return 'guest_card';
|
|
120
|
+
if (record(variables.paymentSource) && record(variables.paymentSource.card))
|
|
121
|
+
carried = 'saved_card';
|
|
122
|
+
}
|
|
123
|
+
return carried;
|
|
124
|
+
}
|
|
125
|
+
/** What a Card Fields confirm carries: its body is the Orders v2 shape Hosted Fields also sends. */
|
|
126
|
+
export const paypalCardFieldsBody = paypalHostedFieldsBody;
|
package/dist/pre-claim.d.ts
CHANGED
|
@@ -252,6 +252,7 @@ export declare function isArmedCreditguardCall(vault: {
|
|
|
252
252
|
export declare const ekashuPreClaim: PreClaimGate;
|
|
253
253
|
export declare const redsysPreClaim: PreClaimGate;
|
|
254
254
|
export declare const paypalHostedFieldsPreClaim: PreClaimGate;
|
|
255
|
+
export declare const paypalCardFormsPreClaim: PreClaimGate;
|
|
255
256
|
export declare const cybersourceSecureAcceptancePreClaim: PreClaimGate;
|
|
256
257
|
export declare const worldlineMyCheckoutPreClaim: PreClaimGate;
|
|
257
258
|
export declare const paddleVgsPayPreClaim: PreClaimGate;
|
package/dist/pre-claim.js
CHANGED
|
@@ -16,8 +16,9 @@
|
|
|
16
16
|
// card-saving bodies, WSPay's confirm URL, which also carries bodies with
|
|
17
17
|
// no new card, Shiji STS's getTokenId and getCvvId, which also carry
|
|
18
18
|
// requests the vault must never pay, PayPal's legacy Hosted Fields
|
|
19
|
-
// confirm
|
|
20
|
-
// no Vault mode takes over
|
|
19
|
+
// confirm, PayPal's Card Fields and guest card form, and CyberSource Secure
|
|
20
|
+
// Acceptance's Silent Order POST, whose card no Vault mode takes over until a
|
|
21
|
+
// recognizer does, Worldline MyCheckout's card form, held to the
|
|
21
22
|
// card product its page chose, and EBANX's 3-D Secure calls and hosted confirm,
|
|
22
23
|
// which send the card again after its token and leave only from the
|
|
23
24
|
// cardholder's device, under the token request's approval.
|
|
@@ -80,6 +81,7 @@ import { classifyVerifoneProfileRequest, verifoneTemplatedUrl } from './verifone
|
|
|
80
81
|
import { ekashuEntryUrl, isEkashuEntry, isEkashuHost } from './ekashu.js';
|
|
81
82
|
import { isRedsysEntry, isRedsysHost, redsysEntryUrl } from './redsys.js';
|
|
82
83
|
import { PAYPAL_HOSTED_FIELDS_REASON, isPaypalHostedFieldsConfirm, paypalHostedFieldsBody } from './paypal-hosted-fields.js';
|
|
84
|
+
import { PAYPAL_CARD_FIELDS_REASON, PAYPAL_GUEST_CHECKOUT_REASON, isPaypalCardFieldsConfirm, isPaypalGraphql, paypalCardFieldsBody, paypalGraphqlCard, paypalGraphqlNamesCardOperation, } from './paypal-card-forms.js';
|
|
83
85
|
import { CYBERSOURCE_SECURE_ACCEPTANCE_REASON, CYBERSOURCE_SECURE_ACCEPTANCE_RECIPIENT, cybersourceSecureAcceptanceRequest, isCybersourceSecureAcceptanceUrl, isSecureAcceptanceFramePost, } from './cybersource-secure-acceptance.js';
|
|
84
86
|
import { isWorldlineMyCheckoutEndpoint } from './worldline-mycheckout.js';
|
|
85
87
|
import { paddleVgsPayEventUrl } from './paddle-vgs-pay.js';
|
|
@@ -1671,6 +1673,60 @@ async function paypalHostedFieldsUnreadable(ctx) {
|
|
|
1671
1673
|
await ctx.effects.abort();
|
|
1672
1674
|
return { kind: 'abort' };
|
|
1673
1675
|
}
|
|
1676
|
+
// PayPal's Card Fields and guest card form (paypal-card-forms.ts). Every company's adapters hand each
|
|
1677
|
+
// POST to the Card Fields confirm (www and api-m, live and sandbox) and to GraphQL on www (live and
|
|
1678
|
+
// sandbox) to this gate:
|
|
1679
|
+
// - a confirm with a card number at payment_source.card.number aborts as an unsupported checkout,
|
|
1680
|
+
// reason `unsupported_paypal_card_fields`, with no claim, create or prompt, unless the synced
|
|
1681
|
+
// registry recognizes it as a card request: then it defers, and the PayPal Card Fields lane pauses
|
|
1682
|
+
// it for the cardholder's approval, judging the body itself;
|
|
1683
|
+
// - a GraphQL operation with a card aborts the same way whatever the registry serves:
|
|
1684
|
+
// `unsupported_paypal_guest_checkout` for the guest form's variables.card.cardNumber,
|
|
1685
|
+
// `unsupported_paypal_card_fields` for a card saved with no purchase (variables.paymentSource.card);
|
|
1686
|
+
// - a confirm the adapter could not read, and a GraphQL post it could not read whose query names one
|
|
1687
|
+
// of the two card operations, abort that request alone with a `blocked` event,
|
|
1688
|
+
// `unreadable_paypal_request`, and do not hold the attachment;
|
|
1689
|
+
// - anything else (a PayPal wallet confirm, a saved card, the buttons' other GraphQL operations, a GET
|
|
1690
|
+
// or a preflight) defers, and the arbiter continues it untouched.
|
|
1691
|
+
// Synchronous until it must abort, like every gate. Exported for the gate registry's tests.
|
|
1692
|
+
export const paypalCardFormsPreClaim = (ctx) => {
|
|
1693
|
+
const { url, method } = ctx.request;
|
|
1694
|
+
if (String(method).toUpperCase() !== 'POST')
|
|
1695
|
+
return undefined;
|
|
1696
|
+
const confirm = isPaypalCardFieldsConfirm(url);
|
|
1697
|
+
if (!confirm && !isPaypalGraphql(url))
|
|
1698
|
+
return undefined;
|
|
1699
|
+
if (confirm && ctx.vault.isCardRequest(url, method))
|
|
1700
|
+
return undefined;
|
|
1701
|
+
let body;
|
|
1702
|
+
// A reader that throws (Playwright's postData() can) proves nothing either way.
|
|
1703
|
+
try {
|
|
1704
|
+
body = ctx.request.body;
|
|
1705
|
+
}
|
|
1706
|
+
catch {
|
|
1707
|
+
body = null;
|
|
1708
|
+
}
|
|
1709
|
+
if (confirm) {
|
|
1710
|
+
const carried = paypalCardFieldsBody(body);
|
|
1711
|
+
if (carried === 'no_card')
|
|
1712
|
+
return undefined;
|
|
1713
|
+
return carried === 'card' ? paypalCardFormAbort(ctx, PAYPAL_CARD_FIELDS_REASON) : paypalHostedFieldsUnreadable(ctx);
|
|
1714
|
+
}
|
|
1715
|
+
const carried = paypalGraphqlCard(body);
|
|
1716
|
+
if (carried === 'guest_card')
|
|
1717
|
+
return paypalCardFormAbort(ctx, PAYPAL_GUEST_CHECKOUT_REASON);
|
|
1718
|
+
if (carried === 'saved_card')
|
|
1719
|
+
return paypalCardFormAbort(ctx, PAYPAL_CARD_FIELDS_REASON);
|
|
1720
|
+
return carried === 'unreadable' && paypalGraphqlNamesCardOperation(url) ? paypalHostedFieldsUnreadable(ctx) : undefined;
|
|
1721
|
+
};
|
|
1722
|
+
async function paypalCardFormAbort(ctx, reason) {
|
|
1723
|
+
const { url, method } = ctx.request;
|
|
1724
|
+
ctx.preparationGate.invalidate('unsupported_checkout');
|
|
1725
|
+
ctx.lifecycle.unsupported(reason);
|
|
1726
|
+
ctx.onEvent?.({ type: 'unsupported_checkout', detail: { url: eventUrl(ctx.vault, url), method, reason } });
|
|
1727
|
+
await ctx.effects.abort();
|
|
1728
|
+
return { kind: 'abort' };
|
|
1729
|
+
}
|
|
1674
1730
|
// CyberSource Secure Acceptance's Silent Order POST (cybersource-secure-acceptance.ts). The merchant's
|
|
1675
1731
|
// page posts the card the agent typed, beside the fields its server signed, to a /silent/ path on
|
|
1676
1732
|
// CyberSource's Secure Acceptance hosts, which no Vault mode takes over, so every company's adapters
|
|
@@ -2092,7 +2148,7 @@ async function unsupportedContinue(ctx) {
|
|
|
2092
2148
|
* after Stripe is never offered a step Stripe claimed: Stripe answers, aborts or
|
|
2093
2149
|
* pauses each one itself. */
|
|
2094
2150
|
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, redsysPreClaim, paypalHostedFieldsPreClaim,
|
|
2095
|
-
cybersourceSecureAcceptancePreClaim, worldlineMyCheckoutPreClaim, paddleVgsPayPreClaim, ebanxPreClaim];
|
|
2151
|
+
paypalCardFormsPreClaim, cybersourceSecureAcceptancePreClaim, worldlineMyCheckoutPreClaim, paddleVgsPayPreClaim, ebanxPreClaim];
|
|
2096
2152
|
/** Run each gate in order; the first to return a decision wins. If none does,
|
|
2097
2153
|
* the terminal arbiter decides between continue, abort (unsupported) and pause.
|
|
2098
2154
|
* Returns synchronously while every gate defers synchronously (an ordinary card
|
|
@@ -20,8 +20,12 @@
|
|
|
20
20
|
* paddle_vgs: prepared only. Paddle's checkout frame aborts its card request to its VGS card vault 10
|
|
21
21
|
* seconds after Pay and sends it once more, too soon for an approval after Pay. Its environments are its
|
|
22
22
|
* two card URLs: vault.paddle.com (production) and sandbox-vault.paddle.com (sandbox).
|
|
23
|
+
*
|
|
24
|
+
* wix_payments: prepared only. Wix's payment widget fails the payment 30 seconds after it asks Wix
|
|
25
|
+
* Cashier's card frame for a token, too soon for an approval after Pay. Its one environment is
|
|
26
|
+
* production: Wix's tokenizer has no test host.
|
|
23
27
|
*/
|
|
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';
|
|
28
|
+
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' | 'wix_payments';
|
|
25
29
|
export type PreparationEnvironment = 'production' | 'sandbox' | 'shared';
|
|
26
30
|
/**
|
|
27
31
|
* How the approved card reaches the processor: the device's own request (token), or
|
|
@@ -14,6 +14,7 @@ import { amadeusEnvironment, amadeusPreparationUrls, amadeusRequestRefusal, isPr
|
|
|
14
14
|
import { isPreparedVerifoneRequest } from './verifone.js';
|
|
15
15
|
import { isPreparedSecureAcceptanceRequest, secureAcceptanceEnvironment, secureAcceptancePreparationUrl, secureAcceptanceRequestRefusal, } from './cybersource-secure-acceptance.generated.js';
|
|
16
16
|
import { PADDLE_VGS_CARDS_URLS, isPreparedPaddleVgsRequest } from './paddle-vgs.generated.js';
|
|
17
|
+
import { WIX_PAYMENTS_TOKENIZE_URL, isPreparedWixPaymentsRequest } from './wix-payments.generated.js';
|
|
17
18
|
export function preparationMode(psp) {
|
|
18
19
|
return psp === 'adyen' || psp === 'fiserv' || psp === 'verifone' ? 'cse' : 'token';
|
|
19
20
|
}
|
|
@@ -53,6 +54,9 @@ export function preparedApprovalAnswersRetry(psp) {
|
|
|
53
54
|
export function validPreparationEnvironment(psp, environment) {
|
|
54
55
|
if (psp === 'bambora' || psp === 'mercado_pago' || psp === 'recurly' || psp === 'spreedly')
|
|
55
56
|
return environment === 'shared';
|
|
57
|
+
// Wix Payments has production alone: its tokenizer has no test host.
|
|
58
|
+
if (psp === 'wix_payments')
|
|
59
|
+
return environment === 'production';
|
|
56
60
|
return ['square', 'braintree', 'worldpay', 'adyen', 'checkout_com', 'paysafe', 'fiserv', 'cybersource_flex', 'aci', 'creditguard', 'worldpay_eprotect', 'amadeus_checkout', 'verifone',
|
|
57
61
|
'cybersource_secure_acceptance', 'paddle_vgs'].includes(psp) && ['production', 'sandbox'].includes(environment);
|
|
58
62
|
}
|
|
@@ -99,6 +103,9 @@ export function preparationEndpoint(psp, environment) {
|
|
|
99
103
|
// Paddle VGS: the environment's one card URL, the only URL the claim takes for it.
|
|
100
104
|
if (psp === 'paddle_vgs')
|
|
101
105
|
return PADDLE_VGS_CARDS_URLS[environment];
|
|
106
|
+
// Wix Payments: the tokenize URL, the only URL the claim takes for it.
|
|
107
|
+
if (psp === 'wix_payments')
|
|
108
|
+
return WIX_PAYMENTS_TOKENIZE_URL;
|
|
102
109
|
// A Verifone endpoint is its reviewed profile's leg, never one per environment (verifone.ts).
|
|
103
110
|
if (psp === 'verifone')
|
|
104
111
|
throw new Error('unsupported_preparation_processor');
|
|
@@ -252,6 +259,10 @@ export function matchesPreparedRequest(psp, environment, requestUrl, method, bod
|
|
|
252
259
|
// the JSON:API content type and the frame's body), the rule the API and the Vault bind with too.
|
|
253
260
|
if (psp === 'paddle_vgs')
|
|
254
261
|
return isPreparedPaddleVgsRequest(requestUrl, method.toUpperCase(), body ?? null, environment, headers ?? {});
|
|
262
|
+
// Wix Payments: production, the tokenize URL and payment-core's whole request rule (a JSON content type, the
|
|
263
|
+
// site's app instance and the card frame's body), the rule the API and the Vault bind with too.
|
|
264
|
+
if (psp === 'wix_payments')
|
|
265
|
+
return isPreparedWixPaymentsRequest(requestUrl, method.toUpperCase(), body ?? null, environment, headers ?? {});
|
|
255
266
|
if (psp === 'creditguard')
|
|
256
267
|
return matchesPreparedCreditguard(environment, requestUrl, body, headers, binding);
|
|
257
268
|
// 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: 1d05273d23008e96c38c3be306ab215212b654fc275b96cf11e6452dee60c0d7
|
|
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
|
|
@@ -666,10 +666,10 @@ var TYPED_ARRAY = Object.getPrototypeOf(Uint8Array.prototype);
|
|
|
666
666
|
var typedArrayName = Object.getOwnPropertyDescriptor(TYPED_ARRAY, Symbol.toStringTag).get;
|
|
667
667
|
function parseRsaPublicKey(key) {
|
|
668
668
|
const spki = key && typeof key === "object" ? key.spki : void 0;
|
|
669
|
-
const
|
|
669
|
+
const pin4 = key && typeof key === "object" ? key.sha256 : void 0;
|
|
670
670
|
if (typeof spki !== "string" || spki.length > 1024 || spki.length % 4 !== 0 || !BASE64.test(spki))
|
|
671
671
|
throw refuse6("key");
|
|
672
|
-
if (typeof
|
|
672
|
+
if (typeof pin4 !== "string" || !SHA256_HEX.test(pin4))
|
|
673
673
|
throw refuse6("key");
|
|
674
674
|
let binary;
|
|
675
675
|
try {
|
|
@@ -681,7 +681,7 @@ function parseRsaPublicKey(key) {
|
|
|
681
681
|
if (btoa(binary) !== spki)
|
|
682
682
|
throw refuse6("key");
|
|
683
683
|
const der = Uint8Array.from(binary, (c) => c.charCodeAt(0));
|
|
684
|
-
if (sha256Hex(der) !==
|
|
684
|
+
if (sha256Hex(der) !== pin4)
|
|
685
685
|
throw refuse6("key");
|
|
686
686
|
const outer = readElement(der, 0, 48);
|
|
687
687
|
if (outer.end !== der.length || outer.start + RSA_ALGORITHM.length > der.length)
|
|
@@ -1241,10 +1241,93 @@ var LYRA_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
|
1241
1241
|
hosts: Object.freeze(["api.systempay.fr"])
|
|
1242
1242
|
})
|
|
1243
1243
|
]);
|
|
1244
|
+
// src/wix-payments.js
|
|
1245
|
+
var WIX_PAYMENTS_PSP = "wix_payments";
|
|
1246
|
+
var WIX_PAYMENTS_TOKENIZE_URL = "https://cashier-pci.wixapps.net/_api/payment-gateway-web/tokenize/v2/tokens";
|
|
1247
|
+
var BODY_LIMIT5 = 8192;
|
|
1248
|
+
var ROOT_KEYS3 = /* @__PURE__ */ Object.freeze(["cvv", "creditCard"]);
|
|
1249
|
+
var CARD_KEYS5 = /* @__PURE__ */ Object.freeze(["number", "expiration", "additionalInformation", "billingAddress"]);
|
|
1250
|
+
var EXPIRATION_KEYS = /* @__PURE__ */ Object.freeze(["month", "year"]);
|
|
1251
|
+
var HOLDER_KEYS = /* @__PURE__ */ Object.freeze(["holderName"]);
|
|
1252
|
+
var CARD_NUMBER6 = /^[0-9]{12,19}$/;
|
|
1253
|
+
var SECURITY_CODE5 = /^[0-9]{3,4}$/;
|
|
1254
|
+
var FIRST_YEAR = 2e3;
|
|
1255
|
+
var LAST_YEAR = 2099;
|
|
1256
|
+
var FIELD_NAME = /^[A-Za-z][A-Za-z0-9]{0,63}$/;
|
|
1257
|
+
var MAX_FIELDS = 32;
|
|
1258
|
+
var MAX_NESTED_FIELDS = 8;
|
|
1259
|
+
var TEXT_LIMIT = 256;
|
|
1260
|
+
var CONTROL4 = /[\u0000-\u001f\u007f]/;
|
|
1261
|
+
var record6 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1262
|
+
var sameKeys3 = (value, keys) => {
|
|
1263
|
+
const own = Object.keys(value);
|
|
1264
|
+
return own.length === keys.length && own.every((key, at) => key === keys[at]);
|
|
1265
|
+
};
|
|
1266
|
+
var plainText = (value) => typeof value === "string" && value.length <= TEXT_LIMIT && !CONTROL4.test(value) && (value.match(/[0-9]/g) ?? []).length < 12;
|
|
1267
|
+
var refuse9 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
1268
|
+
var CARD8 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
1269
|
+
function isWixPaymentsTokenizeUrl(url) {
|
|
1270
|
+
return url === WIX_PAYMENTS_TOKENIZE_URL;
|
|
1271
|
+
}
|
|
1272
|
+
function readBody3(body) {
|
|
1273
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT5)
|
|
1274
|
+
return null;
|
|
1275
|
+
let value;
|
|
1276
|
+
try {
|
|
1277
|
+
value = JSON.parse(body);
|
|
1278
|
+
if (!record6(value) || JSON.stringify(value) !== body)
|
|
1279
|
+
return null;
|
|
1280
|
+
}
|
|
1281
|
+
catch {
|
|
1282
|
+
return null;
|
|
1283
|
+
}
|
|
1284
|
+
return value;
|
|
1285
|
+
}
|
|
1286
|
+
var billingText = (value) => value === null || plainText(value);
|
|
1287
|
+
function billingFields(value) {
|
|
1288
|
+
if (!record6(value))
|
|
1289
|
+
return false;
|
|
1290
|
+
const names = Object.keys(value);
|
|
1291
|
+
if (names.length > MAX_FIELDS)
|
|
1292
|
+
return false;
|
|
1293
|
+
return names.every((name) => {
|
|
1294
|
+
const field = value[name];
|
|
1295
|
+
if (!FIELD_NAME.test(name))
|
|
1296
|
+
return false;
|
|
1297
|
+
if (!record6(field))
|
|
1298
|
+
return billingText(field);
|
|
1299
|
+
const nested = Object.keys(field);
|
|
1300
|
+
return nested.length <= MAX_NESTED_FIELDS && nested.every((key) => FIELD_NAME.test(key) && billingText(field[key]));
|
|
1301
|
+
});
|
|
1302
|
+
}
|
|
1303
|
+
function wixPaymentsBodyVerdict(body) {
|
|
1304
|
+
const value = readBody3(body);
|
|
1305
|
+
if (value === null || !sameKeys3(value, ROOT_KEYS3) || !record6(value.creditCard) || !sameKeys3(value.creditCard, CARD_KEYS5)) {
|
|
1306
|
+
return refuse9("wix_payments_body_unsupported");
|
|
1307
|
+
}
|
|
1308
|
+
const card = value.creditCard;
|
|
1309
|
+
const expiration = card.expiration;
|
|
1310
|
+
const holder = card.additionalInformation;
|
|
1311
|
+
if (typeof value.cvv !== "string" || !SECURITY_CODE5.test(value.cvv) || typeof card.number !== "string" || !CARD_NUMBER6.test(card.number) || !record6(expiration) || !sameKeys3(expiration, EXPIRATION_KEYS) || !Number.isInteger(expiration.month) || expiration.month < 1 || expiration.month > 12 || !Number.isInteger(expiration.year) || expiration.year < FIRST_YEAR || expiration.year > LAST_YEAR || !record6(holder) || !sameKeys3(holder, HOLDER_KEYS) || !plainText(holder.holderName) || !billingFields(card.billingAddress)) {
|
|
1312
|
+
return refuse9("wix_payments_body_unsupported");
|
|
1313
|
+
}
|
|
1314
|
+
return CARD8;
|
|
1315
|
+
}
|
|
1316
|
+
var pin3 = (fields) => Object.freeze({ ...fields, origins: Object.freeze([...fields.origins]) });
|
|
1317
|
+
var WIX_PAYMENTS_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
1318
|
+
pin3({ id: "parahouse_magazine", merchant: "ParaHouse Magazine", origins: ["https://www.parahousemagazine.com"] }),
|
|
1319
|
+
pin3({ id: "psalms_and_potions", merchant: "Psalms & Potions", origins: ["https://www.psalmsandpotions.com"] }),
|
|
1320
|
+
pin3({ id: "alexandra_hagel", merchant: "Alexandra Hagel, LLC", origins: ["https://www.alexandrahagel.com"] })
|
|
1321
|
+
]);
|
|
1244
1322
|
// src/card-fields.js
|
|
1245
1323
|
function processorGate(recognizer, url, body) {
|
|
1246
1324
|
if (recognizer && recognizer.psp === LYRA_PSP)
|
|
1247
1325
|
return lyraBodyVerdict(body, url);
|
|
1326
|
+
if (recognizer && recognizer.psp === WIX_PAYMENTS_PSP) {
|
|
1327
|
+
if (url !== void 0 && !isWixPaymentsTokenizeUrl(url))
|
|
1328
|
+
return { verdict: "refuse", code: "wix_payments_url_refused" };
|
|
1329
|
+
return wixPaymentsBodyVerdict(body);
|
|
1330
|
+
}
|
|
1248
1331
|
if (recognizer && recognizer.psp === PADDLE_VGS_PSP) {
|
|
1249
1332
|
if (url !== void 0 && !isPaddleVgsCardsUrl(url))
|
|
1250
1333
|
return { verdict: "refuse", code: "paddle_vgs_url_refused" };
|
|
@@ -1381,12 +1464,12 @@ var KEEP_ON_FILE_REFUSAL = "Refusing to pay: this Primer payment would keep the
|
|
|
1381
1464
|
var UNSUPPORTED_SDK_REFUSAL = "Refusing to pay: this checkout uses a Primer SDK Agentcard does not support yet. Nothing was sent.";
|
|
1382
1465
|
var NETWORK_MISMATCH_REFUSAL = "Refusing to pay: this Primer payment names a card network that is not your card's. Nothing was sent.";
|
|
1383
1466
|
var FILL_REFUSAL = "Could not fill the card fields for Primer. Nothing was sent.";
|
|
1384
|
-
var
|
|
1467
|
+
var BODY_LIMIT6 = 16384;
|
|
1385
1468
|
var RESPONSE_LIMIT = 32768;
|
|
1386
|
-
var
|
|
1469
|
+
var ROOT_KEYS4 = ["paymentInstrument", "userDescription", "tokenType", "paymentFlow"];
|
|
1387
1470
|
var INSTRUMENT_KEYS = ["number", "cvv", "expirationMonth", "expirationYear", "cardholderName", "preferredNetwork"];
|
|
1388
1471
|
var REQUIRED_INSTRUMENT_KEYS = ["number", "cvv", "expirationMonth", "expirationYear"];
|
|
1389
|
-
var
|
|
1472
|
+
var record7 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1390
1473
|
var owns5 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
1391
1474
|
var exact = (pattern, value) => typeof value === "string" && pattern.exec(value)?.[0] === value;
|
|
1392
1475
|
var text2 = (value, max) => typeof value === "string" && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
|
|
@@ -1409,7 +1492,7 @@ function isPrimerTokenizeUrl(url, method = "POST") {
|
|
|
1409
1492
|
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;
|
|
1410
1493
|
}
|
|
1411
1494
|
function judgeBody2(body) {
|
|
1412
|
-
if (typeof body !== "string" || body === "" || body.length >
|
|
1495
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT6)
|
|
1413
1496
|
return null;
|
|
1414
1497
|
let value;
|
|
1415
1498
|
try {
|
|
@@ -1418,12 +1501,12 @@ function judgeBody2(body) {
|
|
|
1418
1501
|
catch {
|
|
1419
1502
|
return null;
|
|
1420
1503
|
}
|
|
1421
|
-
if (!
|
|
1504
|
+
if (!record7(value) || !roundTrips(value, body))
|
|
1422
1505
|
return null;
|
|
1423
|
-
if (!Object.keys(value).every((key) =>
|
|
1506
|
+
if (!Object.keys(value).every((key) => ROOT_KEYS4.includes(key)) || !owns5(value, "paymentInstrument"))
|
|
1424
1507
|
return null;
|
|
1425
1508
|
const instrument = value.paymentInstrument;
|
|
1426
|
-
if (!
|
|
1509
|
+
if (!record7(instrument) || !Object.keys(instrument).every((key) => INSTRUMENT_KEYS.includes(key)) || !REQUIRED_INSTRUMENT_KEYS.every((key) => owns5(instrument, key)))
|
|
1427
1510
|
return null;
|
|
1428
1511
|
if (!digits(instrument.number, 12, 19) || !digits(instrument.cvv, 3, 4) || !exact(MONTH3, instrument.expirationMonth) || !exact(YEAR3, instrument.expirationYear))
|
|
1429
1512
|
return null;
|
|
@@ -1451,7 +1534,7 @@ var CLIENT_TOKEN = /^[A-Za-z0-9._~+/=-]{16,4096}$/;
|
|
|
1451
1534
|
var REQUEST_ID = /^[A-Za-z0-9-]{1,64}$/;
|
|
1452
1535
|
var API_VERSION = /^2\.[0-9]{1,2}$/;
|
|
1453
1536
|
function readHeaders(headers) {
|
|
1454
|
-
if (!
|
|
1537
|
+
if (!record7(headers))
|
|
1455
1538
|
return null;
|
|
1456
1539
|
const folded = /* @__PURE__ */ new Map();
|
|
1457
1540
|
for (const [name, value] of Object.entries(headers)) {
|
|
@@ -1498,7 +1581,7 @@ function onTokenizePath(url) {
|
|
|
1498
1581
|
}
|
|
1499
1582
|
}
|
|
1500
1583
|
function primerTokenizeRefusal(request) {
|
|
1501
|
-
if (!
|
|
1584
|
+
if (!record7(request) || request.method !== "POST" || !isPrimerTokenizeUrl(request.url))
|
|
1502
1585
|
return "unsupported";
|
|
1503
1586
|
return headersRefusal(request.headers) ?? primerBodyRefusal(request.body);
|
|
1504
1587
|
}
|
|
@@ -1513,7 +1596,7 @@ function primerCardOnFileRefusal(url, options, policy = PRIMER_SESSION_CARD_ON_F
|
|
|
1513
1596
|
return "unsupported";
|
|
1514
1597
|
if (new URL(url).hostname !== LIVE_PCI_HOST)
|
|
1515
1598
|
return null;
|
|
1516
|
-
return primerCardOnFileDisclosure(url, policy) &&
|
|
1599
|
+
return primerCardOnFileDisclosure(url, policy) && record7(options) && options.keepOnFile === true ? null : "keep_on_file";
|
|
1517
1600
|
}
|
|
1518
1601
|
function primerRefusalMessage(reason) {
|
|
1519
1602
|
if (reason === "keep_on_file")
|
|
@@ -1597,7 +1680,7 @@ function readAnswer(body) {
|
|
|
1597
1680
|
return null;
|
|
1598
1681
|
try {
|
|
1599
1682
|
const value = JSON.parse(body);
|
|
1600
|
-
return
|
|
1683
|
+
return record7(value) ? value : null;
|
|
1601
1684
|
}
|
|
1602
1685
|
catch {
|
|
1603
1686
|
return null;
|
|
@@ -1606,16 +1689,16 @@ function readAnswer(body) {
|
|
|
1606
1689
|
var tokenValue = (value) => exact(TOKEN2, value) && !panLike(value);
|
|
1607
1690
|
var optional = (value, key, check) => !owns5(value, key) || value[key] === null || check(value[key]);
|
|
1608
1691
|
function cardDetails(data) {
|
|
1609
|
-
if (!
|
|
1692
|
+
if (!record7(data) || !exact(/^[0-9]{4}$/, data.last4Digits))
|
|
1610
1693
|
return null;
|
|
1611
|
-
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",
|
|
1694
|
+
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", record7))
|
|
1612
1695
|
return null;
|
|
1613
1696
|
const safe = { last4Digits: data.last4Digits };
|
|
1614
1697
|
for (const key of ["first6Digits", "expirationMonth", "expirationYear", "cardholderName", "network", "isNetworkTokenized"]) {
|
|
1615
1698
|
if (owns5(data, key) && data[key] !== null)
|
|
1616
1699
|
safe[key] = data[key];
|
|
1617
1700
|
}
|
|
1618
|
-
if (
|
|
1701
|
+
if (record7(data.binData)) {
|
|
1619
1702
|
const bin = {};
|
|
1620
1703
|
for (const key of BIN_KEYS) {
|
|
1621
1704
|
if (!owns5(data.binData, key) || data.binData[key] === null)
|
|
@@ -1631,7 +1714,7 @@ function cardDetails(data) {
|
|
|
1631
1714
|
function threeDsSummary(value) {
|
|
1632
1715
|
if (value === void 0 || value === null)
|
|
1633
1716
|
return null;
|
|
1634
|
-
if (!
|
|
1717
|
+
if (!record7(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"))
|
|
1635
1718
|
return void 0;
|
|
1636
1719
|
const safe = { responseCode: value.responseCode };
|
|
1637
1720
|
for (const key of ["reasonCode", "reasonText", "protocolVersion", "challengeIssued"]) {
|
|
@@ -1659,7 +1742,7 @@ function rebuildToken(value) {
|
|
|
1659
1742
|
}
|
|
1660
1743
|
function primerErrorId(body) {
|
|
1661
1744
|
const value = readAnswer(body);
|
|
1662
|
-
const id = value &&
|
|
1745
|
+
const id = value && record7(value.error) ? value.error.errorId : null;
|
|
1663
1746
|
return exact(ERROR_ID, id) && !panLike(id) ? id : null;
|
|
1664
1747
|
}
|
|
1665
1748
|
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: ce4887768a0ee59bbca5f329bce47a2831a24b06d7bea1d5517335f7afad75e0
|
|
4
4
|
// src/deep-freeze.js
|
|
5
5
|
function deepFreeze(value) {
|
|
6
6
|
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
@@ -1660,6 +1660,31 @@ var PROCESSOR_DEFINITIONS = deepFreeze([
|
|
|
1660
1660
|
passthroughHeaders: [],
|
|
1661
1661
|
jsonCardFields: [["paymentForm", "pan"]],
|
|
1662
1662
|
passWithoutCard: "api(?:\\.payzen\\.eu|\\.systempay\\.fr|-sogecommerce\\.societegenerale\\.eu|\\.lyra\\.com)/api-payment/V4/Charge/Public/ProcessPayment/2(?:;jsessionid=[A-Za-z0-9._-]{1,128})?"
|
|
1663
|
+
},
|
|
1664
|
+
{
|
|
1665
|
+
psp: "wix_payments",
|
|
1666
|
+
// Wix Cashier's card frame (cashier-pci.wixapps.net/card-form), which every Wix checkout mounts: for
|
|
1667
|
+
// Wix Payments and classic Stripe on Wix it posts the card as one JSON body to Wix's own tokenizer,
|
|
1668
|
+
// under the site's signed app instance. PAN@ creditCard.number, CVV@ cvv at the root, the expiry as
|
|
1669
|
+
// creditCard.expiration.month and .year (numbers, the year in four digits). wix-payments.js holds the
|
|
1670
|
+
// request rule the pause decision, the API's create, the prepared bind and the device all read: exactly
|
|
1671
|
+
// this URL (never /v2/credit-cards, which saves a card, or a saved card's token URL), a JSON
|
|
1672
|
+
// Content-Type, the instance, and the frame's body byte for byte. Wix's payment widget fails the
|
|
1673
|
+
// payment 30 seconds after it asks the frame for a token, so the lane is prepared only
|
|
1674
|
+
// (preparationRequired): the cardholder approves before the agent clicks Pay. The tokenizer answers no
|
|
1675
|
+
// browser origin, so the card leaves the cardholder's device only through the checkout relay. Wix's
|
|
1676
|
+
// other headers ride beside the instance, as the frame sends them. No sandbox host: a Wix site in test
|
|
1677
|
+
// mode answers inside the frame with a fake token and sends nothing, so the lane takes production only,
|
|
1678
|
+
// and the API refuses a test-mode client before any row (wix-payments.js wixPaymentsMerchantRefusal).
|
|
1679
|
+
// Ships dark: served only to a client that declares `wix_payments_tokenize`, gated off for every org
|
|
1680
|
+
// until an operator lists one (`wix_payments:<org>`), and autopilot never sends this request
|
|
1681
|
+
// (autopilot.js DEVICE_REPLAY_REFUSED_OPERATIONS).
|
|
1682
|
+
capability: "wix_payments_tokenize",
|
|
1683
|
+
match: "cashier-pci\\.wixapps\\.net/_api/payment-gateway-web/tokenize/v2/tokens",
|
|
1684
|
+
hosts: ["^cashier-pci\\.wixapps\\.net$"],
|
|
1685
|
+
preparationRequired: true,
|
|
1686
|
+
encoding: "json",
|
|
1687
|
+
passthroughHeaders: ["^authorization$", "^x-wix-client-artifact-id$", "^commonconfig$", "^x-wix-brand$", "^consent-policy$", "^x-wix-linguist$"]
|
|
1663
1688
|
}
|
|
1664
1689
|
]);
|
|
1665
1690
|
var PSP_RECOGNIZERS = deepFreeze(PROCESSOR_DEFINITIONS.map(({ compose, encryptedCardFields, deviceSteps, deviceEncrypt, ...definition }) => definition));
|
|
@@ -1817,6 +1842,13 @@ var LYRA_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
|
1817
1842
|
hosts: Object.freeze(["api.systempay.fr"])
|
|
1818
1843
|
})
|
|
1819
1844
|
]);
|
|
1845
|
+
// src/wix-payments.js
|
|
1846
|
+
var pin3 = (fields) => Object.freeze({ ...fields, origins: Object.freeze([...fields.origins]) });
|
|
1847
|
+
var WIX_PAYMENTS_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
1848
|
+
pin3({ id: "parahouse_magazine", merchant: "ParaHouse Magazine", origins: ["https://www.parahousemagazine.com"] }),
|
|
1849
|
+
pin3({ id: "psalms_and_potions", merchant: "Psalms & Potions", origins: ["https://www.psalmsandpotions.com"] }),
|
|
1850
|
+
pin3({ id: "alexandra_hagel", merchant: "Alexandra Hagel, LLC", origins: ["https://www.alexandrahagel.com"] })
|
|
1851
|
+
]);
|
|
1820
1852
|
// src/cybersource-secure-acceptance.js
|
|
1821
1853
|
var SA_BODY_LIMIT = 32 * 1024;
|
|
1822
1854
|
var SA_REPLY_LIMIT = 64 * 1024;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
declare var WIX_PAYMENTS_PSP: string;
|
|
2
|
+
declare var WIX_PAYMENTS_CAPABILITY: string;
|
|
3
|
+
declare var WIX_PAYMENTS_OPERATION: string;
|
|
4
|
+
declare var WIX_PAYMENTS_HOST: string;
|
|
5
|
+
declare var WIX_PAYMENTS_TOKENIZE_URL: string;
|
|
6
|
+
declare var WIX_PAYMENTS_REFUSAL_CODES: readonly string[];
|
|
7
|
+
declare function isWixPaymentsTokenizeUrl(url: any): boolean;
|
|
8
|
+
declare function wixPaymentsBodyVerdict(body: any): Readonly<{
|
|
9
|
+
verdict: "refuse";
|
|
10
|
+
code: any;
|
|
11
|
+
}> | Readonly<{
|
|
12
|
+
verdict: "card";
|
|
13
|
+
}>;
|
|
14
|
+
declare function wixPaymentsRequestRefusal(request: any): any;
|
|
15
|
+
declare function isPreparedWixPaymentsRequest(url: any, method: any, body: any, environment: any, headers: any): boolean;
|
|
16
|
+
declare var WIX_PAYMENTS_MERCHANT_PINS: readonly any[];
|
|
17
|
+
declare function wixPaymentsMerchantPin(merchantOrigin: any, pins?: readonly any[]): any;
|
|
18
|
+
declare function wixPaymentsMerchantRefusal(environment: any, merchantOrigin: any, pins?: readonly any[]): "unsupported_environment" | "wix_payments_merchant_unreviewed" | null;
|
|
19
|
+
declare function wixPaymentsRefusalMessage(code: any): any;
|
|
20
|
+
declare function injectWixPaymentsCard(body: any, card: any): {
|
|
21
|
+
body: string;
|
|
22
|
+
where: string[];
|
|
23
|
+
};
|
|
24
|
+
declare function isWixPaymentsDeviceRequest(templateBody: any, deviceBody: any): boolean;
|
|
25
|
+
declare function wixPaymentsRefusalCode(text: any): string | null;
|
|
26
|
+
declare function wixPaymentsAnswerOutcome(status: any, text: any, card: any): {
|
|
27
|
+
outcome: string;
|
|
28
|
+
reason: string;
|
|
29
|
+
code?: undefined;
|
|
30
|
+
body?: undefined;
|
|
31
|
+
} | {
|
|
32
|
+
outcome: string;
|
|
33
|
+
code: string;
|
|
34
|
+
reason?: undefined;
|
|
35
|
+
body?: undefined;
|
|
36
|
+
} | {
|
|
37
|
+
outcome: string;
|
|
38
|
+
body: string;
|
|
39
|
+
reason?: undefined;
|
|
40
|
+
code?: undefined;
|
|
41
|
+
};
|
|
42
|
+
export { WIX_PAYMENTS_CAPABILITY, WIX_PAYMENTS_HOST, WIX_PAYMENTS_MERCHANT_PINS, WIX_PAYMENTS_OPERATION, WIX_PAYMENTS_PSP, WIX_PAYMENTS_REFUSAL_CODES, WIX_PAYMENTS_TOKENIZE_URL, injectWixPaymentsCard, isPreparedWixPaymentsRequest, isWixPaymentsDeviceRequest, isWixPaymentsTokenizeUrl, wixPaymentsAnswerOutcome, wixPaymentsBodyVerdict, wixPaymentsMerchantPin, wixPaymentsMerchantRefusal, wixPaymentsRefusalCode, wixPaymentsRefusalMessage, wixPaymentsRequestRefusal };
|