@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/client.js
CHANGED
|
@@ -14,6 +14,7 @@ import { creditguardPageProcessUrl, creditguardPpDomainHost, creditguardPreparat
|
|
|
14
14
|
import { CONVERGE_CAPABILITY } from './elavon-converge.js';
|
|
15
15
|
import { SHIJI_STS_CAPABILITY, SHIJI_STS_PSP, isShijiStsServedCompanion, isShijiStsServedSubstitution } from './shiji-sts.js';
|
|
16
16
|
import { AMADEUS_CHECKOUT_CAPABILITY, AMADEUS_CHECKOUT_PSP } from './amadeus-checkout.generated.js';
|
|
17
|
+
import { PADDLE_VGS_CAPABILITY, PADDLE_VGS_PSP, paddleVgsCardFactsOf } from './paddle-vgs.generated.js';
|
|
17
18
|
import { classifyStripeCheckoutRequest, encodeStripeCheckoutContext, hasStripeCheckoutMarker, parseStripeCheckoutContext, parseStripeCheckoutResponse, STRIPE_CHECKOUT_CONTEXT_HEADER, } from './stripe-checkout.generated.js';
|
|
18
19
|
import { VoiceModule } from './voice.js';
|
|
19
20
|
import { BuyModule } from './buy.js';
|
|
@@ -185,8 +186,16 @@ export const SUPPORTED_REGISTRY_FEATURES = ['card_fields', 'checkout_sessions'];
|
|
|
185
186
|
* the same terms: only to a build that lists it, for a company Agentcard turned
|
|
186
187
|
* Moneris on for. A gated recognizer never sits in BUILTIN_REGISTRY, so it is paused
|
|
187
188
|
* only after a sync.
|
|
189
|
+
*
|
|
190
|
+
* `paddle_vgs_cards`: the card request Paddle's checkout frame sends to its VGS card
|
|
191
|
+
* vault (vault.paddle.com/cards) on a checkout that names VGS, only through a prepared
|
|
192
|
+
* checkout: the frame aborts the request 10 seconds after Pay and sends it once more,
|
|
193
|
+
* and this build answers that second request from the same approval. The cardholder's
|
|
194
|
+
* device sends the card itself and the frame gets back the stored card's id alone.
|
|
195
|
+
* Served on the same terms: only to a build that lists it, for a company Agentcard
|
|
196
|
+
* turned Paddle on for.
|
|
188
197
|
*/
|
|
189
|
-
export const SUPPORTED_CAPABILITIES = ['fiserv_card_capture', GMO_CAPABILITY, CYBERSOURCE_FLEX_CAPABILITY, JUSPAY_CAPABILITY, DATATRANS_CAPABILITY, 'authorize_net_dpm_form', PELECARD_CAPABILITY, ACI_CAPABILITY, 'creditguard_pps_process', PRIMER_CAPABILITY, PAYRAILS_CAPABILITY, CONVERGE_CAPABILITY, EPROTECT_CAPABILITY, WSPAY_CAPABILITY, SHIJI_STS_CAPABILITY, AMADEUS_CHECKOUT_CAPABILITY, 'worldline_mycheckout_form', 'verifone_card_capture', 'ekashu_hosted_payment_page', SECURE_ACCEPTANCE_CAPABILITY, 'gravy_session_fields_put', 'moneris_hosted_tokenization'];
|
|
198
|
+
export const SUPPORTED_CAPABILITIES = ['fiserv_card_capture', GMO_CAPABILITY, CYBERSOURCE_FLEX_CAPABILITY, JUSPAY_CAPABILITY, DATATRANS_CAPABILITY, 'authorize_net_dpm_form', PELECARD_CAPABILITY, ACI_CAPABILITY, 'creditguard_pps_process', PRIMER_CAPABILITY, PAYRAILS_CAPABILITY, CONVERGE_CAPABILITY, EPROTECT_CAPABILITY, WSPAY_CAPABILITY, SHIJI_STS_CAPABILITY, AMADEUS_CHECKOUT_CAPABILITY, 'worldline_mycheckout_form', 'verifone_card_capture', 'ekashu_hosted_payment_page', SECURE_ACCEPTANCE_CAPABILITY, 'gravy_session_fields_put', 'moneris_hosted_tokenization', PADDLE_VGS_CAPABILITY];
|
|
190
199
|
/**
|
|
191
200
|
* Processors whose paused request names no amount at all, so the pair the
|
|
192
201
|
* agent passes is the amount the cardholder approves: authorize() refuses one
|
|
@@ -207,13 +216,15 @@ export const SUPPORTED_CAPABILITIES = ['fiserv_card_capture', GMO_CAPABILITY, CY
|
|
|
207
216
|
* no more than that (the API's card rule). Moneris Hosted Tokenization's
|
|
208
217
|
* request.php carries the card and no price: the merchant's server charges the
|
|
209
218
|
* token later, so the agent's pair, above zero (MONERIS_PSP below), is the one
|
|
210
|
-
* figure the approval shows.
|
|
219
|
+
* figure the approval shows. Paddle VGS's card request carries none either: Paddle
|
|
220
|
+
* charges the stored card at /pay for what the checkout says, so the agent's pair,
|
|
221
|
+
* which the prepared checkout carries, is the total the cardholder approves.
|
|
211
222
|
*/
|
|
212
223
|
const MONERIS_PSP = 'moneris';
|
|
213
|
-
const AGENT_AMOUNT_PROCESSORS = [GMO_PSP, PELECARD_PSP, WSPAY_PSP, SECURE_ACCEPTANCE_PSP, MONERIS_PSP];
|
|
224
|
+
const AGENT_AMOUNT_PROCESSORS = [GMO_PSP, PELECARD_PSP, WSPAY_PSP, SECURE_ACCEPTANCE_PSP, MONERIS_PSP, PADDLE_VGS_PSP];
|
|
214
225
|
/** How AmountRequiredError names a processor. */
|
|
215
226
|
const PROCESSOR_NAMES = { [GMO_PSP]: 'GMO', [PELECARD_PSP]: 'Pelecard', [WSPAY_PSP]: 'WSPay',
|
|
216
|
-
[SECURE_ACCEPTANCE_PSP]: 'CyberSource Secure Acceptance', [MONERIS_PSP]: 'Moneris' };
|
|
227
|
+
[SECURE_ACCEPTANCE_PSP]: 'CyberSource Secure Acceptance', [MONERIS_PSP]: 'Moneris', [PADDLE_VGS_PSP]: 'Paddle' };
|
|
217
228
|
/**
|
|
218
229
|
* Processors whose request and answer name no amount at all, so the total the
|
|
219
230
|
* payment page shows (`pageAmount`) is the one figure that ties the agent's pair
|
|
@@ -949,6 +960,71 @@ function maskCreditguardTxId(path) {
|
|
|
949
960
|
const PATH_SECRET_HOSTS = ['proxy.wspay.biz', 'proxy-test.wspay.biz', 'ipg.monri.com', 'ipgtest.monri.com'];
|
|
950
961
|
/** The segment after a `payment` segment, in any case (the WSPay proxy is IIS) or after an escaped slash. */
|
|
951
962
|
const PATH_SECRET = /(\/payment(?:\/|%2f))[^/]*/gi;
|
|
963
|
+
/**
|
|
964
|
+
* Gravy (Gr4vy) gives every merchant hosts of its own under gr4vy.app, and Secure Fields sends the
|
|
965
|
+
* card to /checkout/sessions/<session id>/fields with no auth header, so the session id is that
|
|
966
|
+
* request's only credential (payment-core definitions.js): with it anyone can write card fields
|
|
967
|
+
* into the session until it expires. On those hosts the segment after /checkout/sessions/, in any
|
|
968
|
+
* case or after an escaped slash, reads {session}, as does any other id shaped like Gravy's UUID
|
|
969
|
+
* session ids.
|
|
970
|
+
*/
|
|
971
|
+
const GRAVY_HOST = /(?:^|\.)gr4vy\.app\.?$/i;
|
|
972
|
+
const GRAVY_SESSION = /(\/checkout\/sessions(?:\/|%2f))[^/]*/gi;
|
|
973
|
+
const GRAVY_SESSION_ID = /[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}/gi;
|
|
974
|
+
function maskGravySession(path) {
|
|
975
|
+
return path.replace(GRAVY_SESSION, '$1{session}').replace(GRAVY_SESSION_ID, '{session}');
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* Rapyd's hosted pages send the card to api.rapyd.net (sandboxapi.rapyd.net in test) with no auth
|
|
979
|
+
* header: the page's own id in the path, checkout_<id> for a checkout page and hp_card_<id> for a
|
|
980
|
+
* card page, is the request's only credential (payment-core definitions.js), and with it anyone can
|
|
981
|
+
* read that page and post a card to it until it expires. On Rapyd's hosts every id of those shapes
|
|
982
|
+
* (hp_reuse_<id>, a payment link's, too) and the segment after /hosted/collect/card/, in any case or
|
|
983
|
+
* after an escaped slash, read {token}.
|
|
984
|
+
*/
|
|
985
|
+
const RAPYD_HOST = /(?:^|\.)rapyd\.net\.?$/i;
|
|
986
|
+
const RAPYD_CARD_PAGE = /(\/hosted\/collect\/card(?:\/|%2f))[^/]*/gi;
|
|
987
|
+
const RAPYD_PAGE_ID = /(?:checkout|hp_[a-z]+)_[a-z0-9]+/gi;
|
|
988
|
+
function maskRapydToken(path) {
|
|
989
|
+
return path.replace(RAPYD_CARD_PAGE, '$1{token}').replace(RAPYD_PAGE_ID, '{token}');
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* Stripe Checkout's pages confirm a Checkout Session at /v1/payment_pages/<session id>/confirm on
|
|
993
|
+
* api.stripe.com with the merchant's publishable key, which is public, so the session id is what
|
|
994
|
+
* lets anyone confirm a payment on that checkout until it expires. There the segment after
|
|
995
|
+
* /payment_pages/, in any case or after an escaped slash, reads {session}. A PaymentIntent or
|
|
996
|
+
* SetupIntent id stays: confirming one also needs its client_secret, which rides in the body.
|
|
997
|
+
*/
|
|
998
|
+
const STRIPE_API_HOST = /^api\.stripe\.com\.?$/i;
|
|
999
|
+
const STRIPE_PAYMENT_PAGE = /(\/payment_pages(?:\/|%2f))[^/]*/gi;
|
|
1000
|
+
function maskStripeSession(path) {
|
|
1001
|
+
return path.replace(STRIPE_PAYMENT_PAGE, '$1{session}');
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* redactAciCheckoutId (aci.ts) takes the checkout id out of the paths ACI's widget sends. This rule
|
|
1005
|
+
* takes any other copy of it out on ACI's hosts: a trailing dot on the host, an escaped or doubled
|
|
1006
|
+
* slash, another case, a string that is not a URL. The segment after /v1/checkouts/ and any id of
|
|
1007
|
+
* ACI's shape (<32 hex>.<cluster>-vm-tx<nn>) read {checkoutId}.
|
|
1008
|
+
*/
|
|
1009
|
+
const ACI_HOST = /^(?:eu-prod\.|eu-test\.|test\.)?oppwa\.com\.?$/i;
|
|
1010
|
+
const ACI_CHECKOUT = /(\/v1\/checkouts(?:\/|%2f))[^/]*/gi;
|
|
1011
|
+
const ACI_CHECKOUT_ID = /[0-9a-f]{32}\.[a-z0-9]{1,16}-vm-tx[0-9]{1,3}/gi;
|
|
1012
|
+
function maskAciCheckout(path) {
|
|
1013
|
+
return path.replace(ACI_CHECKOUT, '$1{checkoutId}').replace(ACI_CHECKOUT_ID, '{checkoutId}');
|
|
1014
|
+
}
|
|
1015
|
+
/**
|
|
1016
|
+
* The processors whose card request carries its own credential in the URL path, with the hosts
|
|
1017
|
+
* that send it, the text that names those hosts in a string that is not a URL, and the mask. The
|
|
1018
|
+
* guard in redact-url.test.mjs fails for a payment-core recognizer that no one has sorted into
|
|
1019
|
+
* this list or out of it.
|
|
1020
|
+
*/
|
|
1021
|
+
const PATH_CREDENTIALS = [
|
|
1022
|
+
{ host: CREDITGUARD_HOST, named: /creditguard\.co\.il/i, mask: maskCreditguardTxId },
|
|
1023
|
+
{ host: GRAVY_HOST, named: /gr4vy\.app/i, mask: maskGravySession },
|
|
1024
|
+
{ host: RAPYD_HOST, named: /rapyd\.net/i, mask: maskRapydToken },
|
|
1025
|
+
{ host: STRIPE_API_HOST, named: /api\.stripe\.com/i, mask: maskStripeSession },
|
|
1026
|
+
{ host: ACI_HOST, named: /oppwa\.com/i, mask: maskAciCheckout },
|
|
1027
|
+
];
|
|
952
1028
|
/**
|
|
953
1029
|
* A URL as it may appear in an error message: origin + path only. A paused
|
|
954
1030
|
* request's URL can carry a client secret in its query string, and error
|
|
@@ -958,8 +1034,13 @@ const PATH_SECRET = /(\/payment(?:\/|%2f))[^/]*/gi;
|
|
|
958
1034
|
* so it reads {txId}, as does any other id-shaped segment there.
|
|
959
1035
|
* On the Monri and WSPay hosts the secret is a path segment, so it is replaced
|
|
960
1036
|
* with `{client_secret}`: https://proxy.wspay.biz/v2/payment/{client_secret}/confirm.
|
|
1037
|
+
* On Gravy's hosts the checkout session id is the credential, so it reads
|
|
1038
|
+
* `{session}`: https://api.<merchant>.gr4vy.app/checkout/sessions/{session}/fields.
|
|
1039
|
+
* On Rapyd's hosts the hosted page's id reads `{token}`: https://api.rapyd.net/v1/checkout/{token}.
|
|
1040
|
+
* On api.stripe.com a Checkout Session id reads `{session}`:
|
|
1041
|
+
* https://api.stripe.com/v1/payment_pages/{session}/confirm.
|
|
961
1042
|
* A string that is not a URL keeps the part before any `?` or `#`, with the
|
|
962
|
-
* same
|
|
1043
|
+
* same segments masked.
|
|
963
1044
|
*/
|
|
964
1045
|
export function redactUrl(raw) {
|
|
965
1046
|
// An ACI checkout id is that checkout's only capability; it never rides on an event.
|
|
@@ -969,12 +1050,18 @@ export function redactUrl(raw) {
|
|
|
969
1050
|
try {
|
|
970
1051
|
const u = new URL(raw);
|
|
971
1052
|
// A trailing dot names the same host, so it cannot let the secret through.
|
|
972
|
-
|
|
973
|
-
|
|
1053
|
+
let path = PATH_SECRET_HOSTS.includes(u.hostname.replace(/\.$/, '')) ? u.pathname.replace(PATH_SECRET, '$1{client_secret}') : u.pathname;
|
|
1054
|
+
for (const rule of PATH_CREDENTIALS)
|
|
1055
|
+
if (rule.host.test(u.hostname))
|
|
1056
|
+
path = rule.mask(path);
|
|
1057
|
+
return `${u.origin}${path}`;
|
|
974
1058
|
}
|
|
975
1059
|
catch {
|
|
976
|
-
|
|
977
|
-
|
|
1060
|
+
let bare = raw.split(/[?#]/)[0].replace(PATH_SECRET, '$1{client_secret}');
|
|
1061
|
+
for (const rule of PATH_CREDENTIALS)
|
|
1062
|
+
if (rule.named.test(bare))
|
|
1063
|
+
bare = rule.mask(bare);
|
|
1064
|
+
return bare;
|
|
978
1065
|
}
|
|
979
1066
|
}
|
|
980
1067
|
/**
|
|
@@ -1029,6 +1116,17 @@ const EPROTECT_PREPARATION_REFUSALS = ['merchant_profile_mismatch'];
|
|
|
1029
1116
|
const SECURE_ACCEPTANCE_PREPARATION_REFUSALS = [
|
|
1030
1117
|
'processor_unavailable', 'sandbox_host_on_live_row', 'live_host_on_sandbox_row', 'unsupported_checkout', 'merchant_profile_mismatch',
|
|
1031
1118
|
];
|
|
1119
|
+
/**
|
|
1120
|
+
* The API's refusals of a Paddle VGS preparation, before any preparation exists, that prepareCheckout
|
|
1121
|
+
* surfaces by name: the lane is held to Agentcard's own account (`processor_unavailable`), the environment
|
|
1122
|
+
* is not the client's test or live mode, a live checkout's merchant is not the name the reviewed seller pin
|
|
1123
|
+
* carries (`merchant_profile_mismatch`), and the locked card is on a network Paddle's card request is not
|
|
1124
|
+
* paid on (`paddle_vgs_card_unsupported`). An unreviewed seller's page answers `unsupported_checkout`, which
|
|
1125
|
+
* PREPARATION_REFUSALS names for every checkout. Only for a Paddle checkout.
|
|
1126
|
+
*/
|
|
1127
|
+
const PADDLE_VGS_PREPARATION_REFUSALS = [
|
|
1128
|
+
'processor_unavailable', 'sandbox_host_on_live_row', 'live_host_on_sandbox_row', 'merchant_profile_mismatch', 'paddle_vgs_card_unsupported',
|
|
1129
|
+
];
|
|
1032
1130
|
/**
|
|
1033
1131
|
* The reason the cardholder's device declines a bound prepared row with, per processor, when its own
|
|
1034
1132
|
* send boundary passed before the card left it (the Vault's sendWindow, 12 seconds after it last saw
|
|
@@ -1541,6 +1639,12 @@ export class VaultClient {
|
|
|
1541
1639
|
const amadeus = input.psp === AMADEUS_CHECKOUT_PSP;
|
|
1542
1640
|
if (amadeus && !input.cardId)
|
|
1543
1641
|
throw fail('card_required');
|
|
1642
|
+
// Paddle VGS: Paddle's /pay sends the expiry and the card network the agent typed into Paddle's form
|
|
1643
|
+
// (placeholderCard) beside the card the device stores, so the preparation names that card, and the API
|
|
1644
|
+
// approves no other; refusing here asks nobody to approve a preparation that could never bind.
|
|
1645
|
+
const paddle = input.psp === PADDLE_VGS_PSP;
|
|
1646
|
+
if (paddle && !input.cardId)
|
|
1647
|
+
throw fail('card_required');
|
|
1544
1648
|
// CyberSource Flex, tokenized before Pay: the loaded card field's capture context and fields,
|
|
1545
1649
|
// verified here against the keys payment-core pins before anything is created (the API and the
|
|
1546
1650
|
// cardholder's device verify them again).
|
|
@@ -1665,6 +1769,8 @@ export class VaultClient {
|
|
|
1665
1769
|
|| (secureAcceptance && (state.secure_acceptance_profile_id !== secureAcceptanceProfileId || state.card_id !== input.cardId))
|
|
1666
1770
|
// Amadeus: the card the cardholder approved is the one whose expiry the agent typed.
|
|
1667
1771
|
|| (amadeus && state.card_id !== input.cardId)
|
|
1772
|
+
// Paddle VGS: the card the cardholder approved is the one whose facts the agent typed.
|
|
1773
|
+
|| (paddle && state.card_id !== input.cardId)
|
|
1668
1774
|
// The API says a preparation tokenizes before Pay exactly when this one carried a capture context.
|
|
1669
1775
|
|| (state.tokenize_before_pay === true) !== !!flexContext)
|
|
1670
1776
|
throw fail('ready_unconfirmed', id);
|
|
@@ -1709,6 +1815,7 @@ export class VaultClient {
|
|
|
1709
1815
|
&& ((error.status >= 400 && error.status < 500 && (PREPARATION_REFUSALS.includes(error.code)
|
|
1710
1816
|
|| (input.psp === 'fiserv' && FISERV_PREPARATION_REFUSALS.includes(error.code))
|
|
1711
1817
|
|| (input.psp === EPROTECT_PSP && EPROTECT_PREPARATION_REFUSALS.includes(error.code))
|
|
1818
|
+
|| (input.psp === PADDLE_VGS_PSP && PADDLE_VGS_PREPARATION_REFUSALS.includes(error.code))
|
|
1712
1819
|
|| (!!flexContext && CYBERSOURCE_FLEX_PREPARATION_REFUSALS.includes(error.code))))
|
|
1713
1820
|
|| (input.psp === 'fiserv' && error.status === 502 && error.code === 'cse_key_unavailable')))
|
|
1714
1821
|
throw fail(error.code);
|
|
@@ -2138,9 +2245,12 @@ export class VaultClient {
|
|
|
2138
2245
|
// A prepared CyberSource Secure Acceptance token create too, for 30 seconds:
|
|
2139
2246
|
// the merchant's page asks its frame for the reply for 30 seconds from Save,
|
|
2140
2247
|
// and the API names 500 ms as such a row's poll interval.
|
|
2248
|
+
// A prepared Paddle VGS card request too, for 20 seconds: Paddle's frame aborts it 10 seconds after
|
|
2249
|
+
// Pay and sends it once more, and the API names 500 ms as such a row's poll interval.
|
|
2141
2250
|
const preparedFastPollUntil = preparation?.psp === 'mercado_pago' ? Date.now() + 10_000
|
|
2142
|
-
: preparation?.psp ===
|
|
2143
|
-
: preparation?.psp ===
|
|
2251
|
+
: preparation?.psp === PADDLE_VGS_PSP ? Date.now() + 20_000
|
|
2252
|
+
: preparation?.psp === EPROTECT_PSP ? Date.now() + 15_000
|
|
2253
|
+
: preparation?.psp === SECURE_ACCEPTANCE_PSP ? Date.now() + SECURE_ACCEPTANCE_FAST_POLL_MS : 0;
|
|
2144
2254
|
// A preparation that tokenized before Pay: the cardholder's device already holds CyberSource's
|
|
2145
2255
|
// token and approves as soon as this bind reaches it, while the page may give createToken only
|
|
2146
2256
|
// seconds (Alaska Airlines' flight checkout gives it three). Poll every 100 ms for 10 seconds,
|
|
@@ -2510,6 +2620,14 @@ export class VaultClient {
|
|
|
2510
2620
|
throw new PaymentOutcomeUnknownError(authorizationId, 'mercado_checkout_metadata_invalid');
|
|
2511
2621
|
}
|
|
2512
2622
|
}
|
|
2623
|
+
else if (rec?.psp === PADDLE_VGS_PSP) {
|
|
2624
|
+
// Paddle VGS: the approved card's details the phone read from the card it stored at VGS, which the
|
|
2625
|
+
// frame's /pay names in place of the placeholder's (paddle-vgs-pay.ts). Exactly those five, or the
|
|
2626
|
+
// stored card's id never reaches the frame.
|
|
2627
|
+
processorContext = paddleVgsCardFactsOf(s.processor_context) ?? undefined;
|
|
2628
|
+
if (!processorContext)
|
|
2629
|
+
throw new PaymentOutcomeUnknownError(authorizationId, 'paddle_vgs_card_facts_unavailable');
|
|
2630
|
+
}
|
|
2513
2631
|
else if (s.processor_context !== undefined)
|
|
2514
2632
|
throw new PaymentOutcomeUnknownError(authorizationId, 'unexpected_processor_context');
|
|
2515
2633
|
return {
|
|
@@ -2686,11 +2804,12 @@ export class VaultClient {
|
|
|
2686
2804
|
* approval produced: a SetupIntent confirm that carries no card and pays with
|
|
2687
2805
|
* exactly the approved payment method (the page's own, or written by the
|
|
2688
2806
|
* adapters in place of a card the confirm carries again).
|
|
2689
|
-
* The API allows a card save
|
|
2690
|
-
*
|
|
2691
|
-
*
|
|
2692
|
-
*
|
|
2693
|
-
*
|
|
2807
|
+
* The API allows a card save for any company, for an approval given on the
|
|
2808
|
+
* Vault page, not by voice, with no amount, and a SetupIntent Stripe reports
|
|
2809
|
+
* still confirmable on the same Stripe account; any other answer rejects with
|
|
2810
|
+
* a CheckoutApiError whose code says why (for example `amount_mismatch`, or
|
|
2811
|
+
* `continuation_invalid` for a confirm that is not a card-free SetupIntent
|
|
2812
|
+
* confirm). Nothing
|
|
2694
2813
|
* is charged: the adapters continue the page's request once this resolves.
|
|
2695
2814
|
*/
|
|
2696
2815
|
async checkStripeSetupContinuation(authorizationId, request) {
|
package/dist/lifecycle.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { PayrailsUnsupportedReason } from './payrails.js';
|
|
|
4
4
|
import type { Substitutions } from './substitute.js';
|
|
5
5
|
import type { GmoUnsupportedReason } from './gmo.js';
|
|
6
6
|
import type { ShijiStsUnsupportedReason } from './shiji-sts.js';
|
|
7
|
+
import type { PaddleVgsPayRefusal } from './paddle-vgs-pay.js';
|
|
7
8
|
/** The application's resolver confirmed the payment for this checkout authorization. */
|
|
8
9
|
export interface MerchantPaymentConfirmation {
|
|
9
10
|
kind: 'merchant_payment';
|
|
@@ -91,6 +92,11 @@ export interface ResumeResult {
|
|
|
91
92
|
headers: Record<string, string>;
|
|
92
93
|
body: string;
|
|
93
94
|
};
|
|
95
|
+
/**
|
|
96
|
+
* The read's `processor_context`, as the API serves it. A Paddle VGS read carries the approved card's
|
|
97
|
+
* details here, which the frame's /pay names; without them the stored card's id is never handed to the page.
|
|
98
|
+
*/
|
|
99
|
+
processor_context?: unknown;
|
|
94
100
|
substitutions?: Substitutions;
|
|
95
101
|
submitted_at?: string;
|
|
96
102
|
execution_mode?: string;
|
|
@@ -239,9 +245,12 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
239
245
|
* over (unsupported_paypal_hosted_fields, paypal-hosted-fields.ts), or a card
|
|
240
246
|
* a merchant's page posts to CyberSource Secure Acceptance's Silent Order
|
|
241
247
|
* POST, which no Vault mode takes over either
|
|
242
|
-
* (unsupported_cybersource_secure_acceptance, cybersource-secure-acceptance.ts)
|
|
248
|
+
* (unsupported_cybersource_secure_acceptance, cybersource-secure-acceptance.ts), or a
|
|
249
|
+
* Paddle /pay naming a stored card that its binding does not continue (the
|
|
250
|
+
* paddle-vgs-pay.ts reasons): once an approval exists the state keeps it, and only the
|
|
251
|
+
* hold changes.
|
|
243
252
|
*/
|
|
244
|
-
unsupported(reason?: 'unrecognized_payment_endpoint' | 'merchant_profile_observe' | 'merchant_request_unsupported' | GmoUnsupportedReason | 'microform_unsupported' | 'juspay_request_unsupported' | 'merchant_card_endpoint_not_enabled' | 'merchant_card_endpoint_resend_refused' | 'creditguard_three_d_secure' | 'unsupported_primer_sdk' | 'unsupported_primer_request' | PayrailsUnsupportedReason | ShijiStsUnsupportedReason | 'processor_card_page' | 'unsupported_paypal_hosted_fields' | 'unsupported_cybersource_secure_acceptance'): void;
|
|
253
|
+
unsupported(reason?: 'unrecognized_payment_endpoint' | 'merchant_profile_observe' | 'merchant_request_unsupported' | GmoUnsupportedReason | 'microform_unsupported' | 'juspay_request_unsupported' | 'merchant_card_endpoint_not_enabled' | 'merchant_card_endpoint_resend_refused' | 'creditguard_three_d_secure' | 'unsupported_primer_sdk' | 'unsupported_primer_request' | PayrailsUnsupportedReason | ShijiStsUnsupportedReason | 'processor_card_page' | 'unsupported_paypal_hosted_fields' | 'unsupported_cybersource_secure_acceptance' | PaddleVgsPayRefusal): void;
|
|
245
254
|
/**
|
|
246
255
|
* A card request that only a prepared checkout pays (an Adyen merchant
|
|
247
256
|
* profile's, or a Fiserv card capture) arrived with no preparation on this
|
package/dist/lifecycle.js
CHANGED
|
@@ -238,7 +238,10 @@ export class CheckoutLifecycle {
|
|
|
238
238
|
* over (unsupported_paypal_hosted_fields, paypal-hosted-fields.ts), or a card
|
|
239
239
|
* a merchant's page posts to CyberSource Secure Acceptance's Silent Order
|
|
240
240
|
* POST, which no Vault mode takes over either
|
|
241
|
-
* (unsupported_cybersource_secure_acceptance, cybersource-secure-acceptance.ts)
|
|
241
|
+
* (unsupported_cybersource_secure_acceptance, cybersource-secure-acceptance.ts), or a
|
|
242
|
+
* Paddle /pay naming a stored card that its binding does not continue (the
|
|
243
|
+
* paddle-vgs-pay.ts reasons): once an approval exists the state keeps it, and only the
|
|
244
|
+
* hold changes.
|
|
242
245
|
*/
|
|
243
246
|
unsupported(reason = 'unrecognized_payment_endpoint') {
|
|
244
247
|
this.held = true;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { ReplayResponse } from './client.js';
|
|
2
|
+
/**
|
|
3
|
+
* Why a /pay naming a stored card was aborted, reported as the `reason` of the `unsupported_checkout` event:
|
|
4
|
+
* paddle_vgs_pay_unbound this attachment handed no stored card's id to the frame that sent it
|
|
5
|
+
* paddle_vgs_pay_expired it came more than a minute after the id reached the frame
|
|
6
|
+
* paddle_vgs_pay_used the one /pay for that id already went
|
|
7
|
+
* paddle_vgs_pay_card_mismatch it names another stored card, or the other environment's checkout service
|
|
8
|
+
* paddle_vgs_pay_unsupported anything else payment-core's rule refuses: another shape, a card saved at
|
|
9
|
+
* Paddle for later, a network the frame chose from the typed card
|
|
10
|
+
*/
|
|
11
|
+
export type PaddleVgsPayRefusal = 'paddle_vgs_pay_unbound' | 'paddle_vgs_pay_expired' | 'paddle_vgs_pay_used' | 'paddle_vgs_pay_card_mismatch' | 'paddle_vgs_pay_unsupported';
|
|
12
|
+
/** The patterns attachToCdp holds Paddle's two checkout services under, only for an attachment the API served Paddle VGS to. */
|
|
13
|
+
export declare const PADDLE_VGS_PAY_PATTERNS: readonly string[];
|
|
14
|
+
/** Whether `url` is on one of Paddle's two checkout services: what attachToPlaywright routes, once served. */
|
|
15
|
+
export declare function isPaddleCheckoutService(url: string): boolean;
|
|
16
|
+
/** Whether the synced registry serves Paddle VGS's card request: an org Agentcard turned Paddle on for. */
|
|
17
|
+
export declare function recognizesPaddleVgs(vault: {
|
|
18
|
+
isCardRequest?: (url: string, method?: string) => boolean;
|
|
19
|
+
} | null | undefined): boolean;
|
|
20
|
+
/** The URL an event names for a /pay: its origin and path, with the checkout's id as {checkout}. */
|
|
21
|
+
export declare function paddleVgsPayEventUrl(url: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* One attachment's /pay binding: at most one, to the stored card's id it last handed a Paddle frame. `arm` runs
|
|
24
|
+
* right before the id is handed over, `release` when the attachment is cancelled, and `judge` for every request
|
|
25
|
+
* to Paddle's checkout services. `served` says whether the synced registry serves Paddle VGS; it is asked only
|
|
26
|
+
* about a POST to /pay, so no other request reads the registry here.
|
|
27
|
+
*/
|
|
28
|
+
export declare class PaddleVgsPayGate {
|
|
29
|
+
private readonly served;
|
|
30
|
+
private readonly now;
|
|
31
|
+
private bound;
|
|
32
|
+
constructor(served: () => boolean, now?: () => number);
|
|
33
|
+
/** Whether the gate judges this request: a POST to /pay, on an attachment the API served Paddle VGS to. */
|
|
34
|
+
holds(url: string, method: string): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Bind the next /pay of `frame`, the frame about to receive `replay` for its card request to `cardsUrl`, to the
|
|
37
|
+
* stored card's id in the replay and the approved card's facts the API served beside it. Does nothing for a
|
|
38
|
+
* request to anything but Paddle's card vault. Throws when the frame is unknown, or the replay carries no id or
|
|
39
|
+
* no facts payment-core reads: the id must then not reach the frame, since its /pay could only carry the
|
|
40
|
+
* placeholder's facts.
|
|
41
|
+
*/
|
|
42
|
+
arm(frame: unknown, cardsUrl: string, replay: ReplayResponse): void;
|
|
43
|
+
/** Drop the binding: no /pay continues with these facts after this. */
|
|
44
|
+
release(): void;
|
|
45
|
+
/**
|
|
46
|
+
* What becomes of a request to Paddle's checkout services: null when it is not a /pay naming a stored card (it
|
|
47
|
+
* continues untouched), the body to continue it with (payment-core paddleVgsPayVerdict), or why it is aborted.
|
|
48
|
+
* The binding answers one /pay: the first one from its frame continues or is refused, and either way ends it.
|
|
49
|
+
*/
|
|
50
|
+
judge(frame: unknown, url: string, method: string, body: string | null): {
|
|
51
|
+
body: string;
|
|
52
|
+
} | {
|
|
53
|
+
reason: PaddleVgsPayRefusal;
|
|
54
|
+
} | null;
|
|
55
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// Paddle's /pay, the request that charges the card the cardholder's phone stored at VGS, as the SDK sees it
|
|
2
|
+
// (payment-core paddle-vgs.js has the request's shape and the rule).
|
|
3
|
+
//
|
|
4
|
+
// Once the SDK hands the stored card's id to Paddle's checkout frame, the frame posts /pay to its checkout
|
|
5
|
+
// service with that id beside card facts it read from the number typed into its own form: on this lane the
|
|
6
|
+
// agent's placeholder, so the placeholder's first six, last four and brand. This build holds that /pay and
|
|
7
|
+
// writes over those five values the approved card's own, which the phone read from the card it sent to VGS and
|
|
8
|
+
// the API served with the id (payment-core paddleVgsPayVerdict). Every other byte goes as the frame wrote it.
|
|
9
|
+
//
|
|
10
|
+
// The binding: the frame that received the stored card's id, the id, the vault's environment and the approved
|
|
11
|
+
// card's facts, for PADDLE_VGS_CARD_ID_WINDOW_MS after the hand-over, for one /pay. A /pay naming a stored card
|
|
12
|
+
// is aborted, so Paddle charges nothing, when this attachment handed no id to that frame
|
|
13
|
+
// (paddle_vgs_pay_unbound), after the window (paddle_vgs_pay_expired), after the one /pay already went
|
|
14
|
+
// (paddle_vgs_pay_used), or when payment-core's rule refuses it: another stored card or environment
|
|
15
|
+
// (paddle_vgs_pay_card_mismatch), or any other shape (paddle_vgs_pay_unsupported). A /pay naming no stored card
|
|
16
|
+
// (PayPal, a wallet) carries none of the cardholder's cards and continues untouched.
|
|
17
|
+
//
|
|
18
|
+
// Nothing is decided without the registry: an attachment the API did not serve Paddle VGS to never holds
|
|
19
|
+
// Paddle's checkout service, so its /pay continues untouched, exactly as before.
|
|
20
|
+
import { PADDLE_VGS_CARD_ID_WINDOW_MS, PADDLE_VGS_CARDS_URLS, paddleVgsCardFactsOf, paddleVgsEnvironment, paddleVgsPayCarriesStoredCard, paddleVgsPayTarget, paddleVgsPayVerdict, } from './paddle-vgs.generated.js';
|
|
21
|
+
const CHECKOUT_SERVICES = ['https://checkout-service.paddle.com', 'https://sandbox-checkout-service.paddle.com'];
|
|
22
|
+
/** The patterns attachToCdp holds Paddle's two checkout services under, only for an attachment the API served Paddle VGS to. */
|
|
23
|
+
export const PADDLE_VGS_PAY_PATTERNS = CHECKOUT_SERVICES.map((origin) => `${origin}/*`);
|
|
24
|
+
/** Whether `url` is on one of Paddle's two checkout services: what attachToPlaywright routes, once served. */
|
|
25
|
+
export function isPaddleCheckoutService(url) {
|
|
26
|
+
try {
|
|
27
|
+
return CHECKOUT_SERVICES.includes(new URL(url).origin);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Whether the synced registry serves Paddle VGS's card request: an org Agentcard turned Paddle on for. */
|
|
34
|
+
export function recognizesPaddleVgs(vault) {
|
|
35
|
+
if (!vault || typeof vault.isCardRequest !== 'function')
|
|
36
|
+
return false;
|
|
37
|
+
try {
|
|
38
|
+
return vault.isCardRequest(PADDLE_VGS_CARDS_URLS.production, 'POST') || vault.isCardRequest(PADDLE_VGS_CARDS_URLS.sandbox, 'POST');
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** The URL an event names for a /pay: its origin and path, with the checkout's id as {checkout}. */
|
|
45
|
+
export function paddleVgsPayEventUrl(url) {
|
|
46
|
+
return url.replace(/^(https:\/\/[^/]+\/(?:checkout|transaction-checkout)\/)[^/]+(\/pay)$/, '$1{checkout}$2');
|
|
47
|
+
}
|
|
48
|
+
const known = (frame) => frame !== undefined && frame !== null && frame !== '';
|
|
49
|
+
/**
|
|
50
|
+
* One attachment's /pay binding: at most one, to the stored card's id it last handed a Paddle frame. `arm` runs
|
|
51
|
+
* right before the id is handed over, `release` when the attachment is cancelled, and `judge` for every request
|
|
52
|
+
* to Paddle's checkout services. `served` says whether the synced registry serves Paddle VGS; it is asked only
|
|
53
|
+
* about a POST to /pay, so no other request reads the registry here.
|
|
54
|
+
*/
|
|
55
|
+
export class PaddleVgsPayGate {
|
|
56
|
+
served;
|
|
57
|
+
now;
|
|
58
|
+
bound = null;
|
|
59
|
+
constructor(served, now = Date.now) {
|
|
60
|
+
this.served = served;
|
|
61
|
+
this.now = now;
|
|
62
|
+
}
|
|
63
|
+
/** Whether the gate judges this request: a POST to /pay, on an attachment the API served Paddle VGS to. */
|
|
64
|
+
holds(url, method) {
|
|
65
|
+
return String(method).toUpperCase() === 'POST' && paddleVgsPayTarget(url) !== null && this.served();
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Bind the next /pay of `frame`, the frame about to receive `replay` for its card request to `cardsUrl`, to the
|
|
69
|
+
* stored card's id in the replay and the approved card's facts the API served beside it. Does nothing for a
|
|
70
|
+
* request to anything but Paddle's card vault. Throws when the frame is unknown, or the replay carries no id or
|
|
71
|
+
* no facts payment-core reads: the id must then not reach the frame, since its /pay could only carry the
|
|
72
|
+
* placeholder's facts.
|
|
73
|
+
*/
|
|
74
|
+
arm(frame, cardsUrl, replay) {
|
|
75
|
+
const environment = paddleVgsEnvironment(cardsUrl);
|
|
76
|
+
if (environment === null)
|
|
77
|
+
return;
|
|
78
|
+
this.release();
|
|
79
|
+
const token = replay.mode === undefined || replay.mode === 'token' ? replay : null;
|
|
80
|
+
const facts = token ? paddleVgsCardFactsOf(token.processorContext) : null;
|
|
81
|
+
let cardId = null;
|
|
82
|
+
try {
|
|
83
|
+
cardId = token ? JSON.parse(token.body)?.data?.id : null;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
cardId = null;
|
|
87
|
+
}
|
|
88
|
+
if (!known(frame) || !facts || typeof cardId !== 'string')
|
|
89
|
+
throw new Error('paddle_vgs_card_facts_unavailable');
|
|
90
|
+
this.bound = { frame, environment, cardId, facts, until: this.now() + PADDLE_VGS_CARD_ID_WINDOW_MS, used: false };
|
|
91
|
+
}
|
|
92
|
+
/** Drop the binding: no /pay continues with these facts after this. */
|
|
93
|
+
release() {
|
|
94
|
+
this.bound = null;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* What becomes of a request to Paddle's checkout services: null when it is not a /pay naming a stored card (it
|
|
98
|
+
* continues untouched), the body to continue it with (payment-core paddleVgsPayVerdict), or why it is aborted.
|
|
99
|
+
* The binding answers one /pay: the first one from its frame continues or is refused, and either way ends it.
|
|
100
|
+
*/
|
|
101
|
+
judge(frame, url, method, body) {
|
|
102
|
+
if (!this.holds(url, method) || !paddleVgsPayCarriesStoredCard(body))
|
|
103
|
+
return null;
|
|
104
|
+
const bound = this.bound;
|
|
105
|
+
if (!bound || !known(frame) || frame !== bound.frame)
|
|
106
|
+
return { reason: 'paddle_vgs_pay_unbound' };
|
|
107
|
+
if (bound.used)
|
|
108
|
+
return { reason: 'paddle_vgs_pay_used' };
|
|
109
|
+
bound.used = true;
|
|
110
|
+
if (this.now() > bound.until)
|
|
111
|
+
return { reason: 'paddle_vgs_pay_expired' };
|
|
112
|
+
const verdict = paddleVgsPayVerdict({ url, method, body }, { environment: bound.environment, cardId: bound.cardId, facts: bound.facts });
|
|
113
|
+
return verdict.verdict === 'continue' ? { body: verdict.body } : { reason: verdict.code };
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
declare var PADDLE_VGS_PSP: string;
|
|
2
|
+
declare var PADDLE_VGS_CAPABILITY: string;
|
|
3
|
+
declare var PADDLE_VGS_OPERATION: string;
|
|
4
|
+
declare var PADDLE_VGS_CONTENT_TYPE: string;
|
|
5
|
+
declare var PADDLE_VGS_CARDS_URLS: Readonly<{
|
|
6
|
+
production: "https://vault.paddle.com/cards";
|
|
7
|
+
sandbox: "https://sandbox-vault.paddle.com/cards";
|
|
8
|
+
}>;
|
|
9
|
+
declare var PADDLE_VGS_REFUSAL_CODES: readonly string[];
|
|
10
|
+
declare function paddleVgsEnvironment(url: any): "production" | "sandbox" | null;
|
|
11
|
+
declare function isPaddleVgsCardsUrl(url: any): boolean;
|
|
12
|
+
declare function paddleVgsBodyVerdict(body: any): Readonly<{
|
|
13
|
+
verdict: "refuse";
|
|
14
|
+
code: any;
|
|
15
|
+
}> | Readonly<{
|
|
16
|
+
verdict: "card";
|
|
17
|
+
}>;
|
|
18
|
+
declare function paddleVgsRequestRefusal(request: any): any;
|
|
19
|
+
declare function isPreparedPaddleVgsRequest(url: any, method: any, body: any, environment: any, headers: any): boolean;
|
|
20
|
+
declare var PADDLE_VGS_MERCHANT_PINS: readonly any[];
|
|
21
|
+
declare function paddleVgsMerchantPin(merchantOrigin: any, pins?: readonly any[]): any;
|
|
22
|
+
declare function paddleVgsMerchantRefusal(environment: any, merchantOrigin: any, authorization: any, pins?: readonly any[]): "unsupported_environment" | "paddle_vgs_merchant_unreviewed" | "paddle_vgs_seller_unreviewed" | null;
|
|
23
|
+
declare function paddleVgsSellerClaimsPinned(pins?: readonly any[]): boolean;
|
|
24
|
+
declare function paddleVgsRefusalMessage(code: any): any;
|
|
25
|
+
declare var PADDLE_VGS_CARD_NETWORKS: readonly string[];
|
|
26
|
+
declare function paddleVgsCardRefusal(body: any, card: any): any;
|
|
27
|
+
declare function paddleVgsStoredCardRefusal(brand: any): "paddle_vgs_card_unsupported" | null;
|
|
28
|
+
declare function paddleVgsTypedCardRefusal(body: any, stored: any): any;
|
|
29
|
+
declare function injectPaddleVgsCard(body: any, card: any): {
|
|
30
|
+
body: string;
|
|
31
|
+
where: string[];
|
|
32
|
+
};
|
|
33
|
+
declare function paddleVgsRefusalCode(text: any): string | null;
|
|
34
|
+
declare function paddleVgsAnswerOutcome(status: any, text: any, card: any): {
|
|
35
|
+
outcome: string;
|
|
36
|
+
reason: string;
|
|
37
|
+
code?: undefined;
|
|
38
|
+
body?: undefined;
|
|
39
|
+
} | {
|
|
40
|
+
outcome: string;
|
|
41
|
+
code: string;
|
|
42
|
+
reason?: undefined;
|
|
43
|
+
body?: undefined;
|
|
44
|
+
} | {
|
|
45
|
+
outcome: string;
|
|
46
|
+
body: string;
|
|
47
|
+
reason?: undefined;
|
|
48
|
+
code?: undefined;
|
|
49
|
+
};
|
|
50
|
+
declare var PADDLE_VGS_CARD_ID_WINDOW_MS: number;
|
|
51
|
+
declare function paddleVgsPayTarget(url: any): Readonly<{
|
|
52
|
+
environment: "production" | "sandbox";
|
|
53
|
+
line: "classic" | "billing";
|
|
54
|
+
}> | null;
|
|
55
|
+
declare function paddleVgsPayCarriesStoredCard(body: any): boolean;
|
|
56
|
+
declare function paddleVgsCardFacts(card: any): Readonly<{
|
|
57
|
+
card_first_six: string;
|
|
58
|
+
card_last_four: string;
|
|
59
|
+
expiry_month: number;
|
|
60
|
+
expiry_year: number;
|
|
61
|
+
card_brand: "visa" | "master" | "american_express";
|
|
62
|
+
}>;
|
|
63
|
+
declare function paddleVgsCardFactsOf(value: any): Readonly<{
|
|
64
|
+
card_first_six: any;
|
|
65
|
+
card_last_four: string;
|
|
66
|
+
expiry_month: any;
|
|
67
|
+
expiry_year: any;
|
|
68
|
+
card_brand: any;
|
|
69
|
+
}> | null;
|
|
70
|
+
declare function paddleVgsCardFactsAgree(facts: any, stored: any): boolean;
|
|
71
|
+
declare function paddleVgsPayVerdict(request: any, approved: any): Readonly<{
|
|
72
|
+
verdict: "refuse";
|
|
73
|
+
code: any;
|
|
74
|
+
}> | Readonly<{
|
|
75
|
+
verdict: "continue";
|
|
76
|
+
body: string;
|
|
77
|
+
}>;
|
|
78
|
+
export { PADDLE_VGS_CAPABILITY, PADDLE_VGS_CARDS_URLS, PADDLE_VGS_CARD_ID_WINDOW_MS, PADDLE_VGS_CARD_NETWORKS, PADDLE_VGS_CONTENT_TYPE, PADDLE_VGS_MERCHANT_PINS, PADDLE_VGS_OPERATION, PADDLE_VGS_PSP, PADDLE_VGS_REFUSAL_CODES, injectPaddleVgsCard, isPaddleVgsCardsUrl, isPreparedPaddleVgsRequest, paddleVgsAnswerOutcome, paddleVgsBodyVerdict, paddleVgsCardFacts, paddleVgsCardFactsAgree, paddleVgsCardFactsOf, paddleVgsCardRefusal, paddleVgsEnvironment, paddleVgsMerchantPin, paddleVgsMerchantRefusal, paddleVgsPayCarriesStoredCard, paddleVgsPayTarget, paddleVgsPayVerdict, paddleVgsRefusalCode, paddleVgsRefusalMessage, paddleVgsRequestRefusal, paddleVgsSellerClaimsPinned, paddleVgsStoredCardRefusal, paddleVgsTypedCardRefusal };
|