@agent-cards/sdk 0.23.22 → 0.23.24
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 +34 -0
- package/PREFLIGHT.md +2 -0
- package/README.md +34 -4
- package/dist/aci.generated.js +3 -3
- package/dist/agent-amount.generated.d.ts +7 -0
- package/dist/agent-amount.generated.js +3 -0
- package/dist/amadeus.d.ts +5 -2
- package/dist/amadeus.js +18 -3
- package/dist/amazon-payment-services.d.ts +25 -0
- package/dist/amazon-payment-services.generated.d.ts +76 -0
- package/dist/amazon-payment-services.generated.js +883 -0
- package/dist/amazon-payment-services.js +53 -0
- package/dist/capabilities.generated.d.ts +2 -0
- package/dist/capabilities.generated.js +3 -0
- package/dist/card-fields.generated.js +1127 -25
- package/dist/cdp.js +116 -15
- package/dist/client.d.ts +107 -8
- package/dist/client.js +277 -128
- package/dist/hosted-entry.js +2 -1
- package/dist/hosted-form.d.ts +5 -0
- package/dist/hosted-form.js +5 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/openpay.generated.d.ts +67 -0
- package/dist/openpay.generated.js +446 -0
- package/dist/paddle-checkout-watch.d.ts +70 -0
- package/dist/paddle-checkout-watch.js +239 -0
- package/dist/paddle-tokenex.generated.d.ts +29 -1
- package/dist/paddle-tokenex.generated.js +175 -26
- package/dist/paytrail.d.ts +58 -0
- package/dist/paytrail.js +98 -0
- package/dist/pre-claim.d.ts +4 -0
- package/dist/pre-claim.js +46 -2
- package/dist/prepared-processor.d.ts +12 -4
- package/dist/prepared-processor.js +31 -5
- package/dist/primer.generated.js +1155 -53
- package/dist/registry.d.ts +4 -3
- package/dist/registry.js +12 -4
- package/dist/sbps.d.ts +57 -0
- package/dist/sbps.generated.d.ts +96 -0
- package/dist/sbps.generated.js +427 -0
- package/dist/sbps.js +90 -0
- package/dist/stripe-checkout.generated.js +458 -8
- package/dist/tap-payments.d.ts +43 -0
- package/dist/tap-payments.generated.d.ts +59 -0
- package/dist/tap-payments.generated.js +990 -0
- package/dist/tap-payments.js +72 -0
- package/dist/transbank.d.ts +33 -0
- package/dist/transbank.js +62 -0
- package/dist/url-mask-parts.d.ts +24 -0
- package/dist/url-mask-parts.js +22 -0
- package/dist/url-masks.generated.d.ts +3 -0
- package/dist/url-masks.generated.js +2 -0
- package/package.json +4 -4
package/dist/cdp.js
CHANGED
|
@@ -8,6 +8,7 @@ import { MERCADO_CHECKOUT_PATTERN } from './mercado-checkout.generated.js';
|
|
|
8
8
|
import { JuspayCheckoutGate } from './juspay-gate.js';
|
|
9
9
|
import { ACI_CHECKOUT_REUSED, AciGate, playwrightReplacesNavigationBody } from './aci.js';
|
|
10
10
|
import { EprotectGate, classifyEprotectRequest, eprotectScriptAnswer } from './eprotect.js';
|
|
11
|
+
import { SbpsGate, classifySbpsRequest, sbpsScriptAnswer } from './sbps.js';
|
|
11
12
|
import { dispatchPreClaim, eventUrl, isArmedCreditguardCall, routesHipayVault } from './pre-claim.js';
|
|
12
13
|
import { GMO_TOKEN_V1_PATTERNS, gmoRequestShop, isGmoTokenV1Request, recognizesGmo } from './gmo.js';
|
|
13
14
|
import { isPaddleVgsCardsUrl } from './paddle-vgs.generated.js';
|
|
@@ -15,11 +16,13 @@ import { isToastPaymentMethodsUrl, readToastBody } from './toast.generated.js';
|
|
|
15
16
|
import { PADDLE_VGS_PAY_PATTERNS, PaddleVgsPayGate, isPaddleCheckoutService, recognizesPaddleVgs } from './paddle-vgs-pay.js';
|
|
16
17
|
import { DatatransRepeats } from './datatrans.js';
|
|
17
18
|
import { TokenexIframeRepeats, isArmedTokenexIframeUrl } from './tokenex-iframe.js';
|
|
19
|
+
import { isArmedPaytrailUrl } from './paytrail.js';
|
|
18
20
|
import { SHIJI_STS_COMPANION_WINDOW_MS, ShijiStsCompanions, ShijiStsError, isShijiStsHost, shijiStsTokenContinuation, } from './shiji-sts.js';
|
|
19
21
|
import { paddleTokenexTokenContinuation } from './paddle-tokenex.js';
|
|
20
22
|
import { twoC2pContinuation, twoC2pRetire } from './twoc2p.js';
|
|
23
|
+
import { tapPaymentsContinuation } from './tap-payments.js';
|
|
21
24
|
import { isArmedEkashuUrl } from './ekashu.js';
|
|
22
|
-
import { isArmedTransbankUrl } from './transbank.js';
|
|
25
|
+
import { isArmedTransbankUrl, transbankMerchantReturn, transbankMerchantReturnAnswer } from './transbank.js';
|
|
23
26
|
import { isArmedRedsysUrl } from './redsys.js';
|
|
24
27
|
import { isArmedPrzelewy24Url } from './przelewy24.js';
|
|
25
28
|
import { isArmedQuickpayUrl } from './quickpay.js';
|
|
@@ -37,6 +40,7 @@ import { replayTemplatedUrl, reviewedMerchantProfileUrlPatterns } from './mercha
|
|
|
37
40
|
import { verifoneTemplatedUrl } from './verifone.js';
|
|
38
41
|
import { MerchantHandoffWatch } from './merchant-handoff.js';
|
|
39
42
|
import { MERCHANT_PAGE_WAIT_MS, MerchantTotalWatch } from './merchant-total-watch.js';
|
|
43
|
+
import { PaddleCheckoutWatch } from './paddle-checkout-watch.js';
|
|
40
44
|
import { hostedFormSubmittedPage } from './hosted-form.js';
|
|
41
45
|
import { armSendWindow, failsAsNetworkError, preparedSendWindowMs, sendWindowProcessor } from './amadeus.js';
|
|
42
46
|
import { HoldAnsweredError, HoldEndedError, HoldGate, HoldRefusedError, matchHoldOnlyRule } from './hold.js';
|
|
@@ -363,7 +367,7 @@ function cseAuthorizedDetail(replay, url, shijiCvv = null) {
|
|
|
363
367
|
* processor takes cseContinuationBody (cse-body.ts cseBody), and `shijiCvv` and
|
|
364
368
|
* `shijiCvvKeySequenceSha256` are null.
|
|
365
369
|
*/
|
|
366
|
-
function cseContinuation(opts, url, body, replay, approved, preparation) {
|
|
370
|
+
function cseContinuation(opts, url, body, replay, approved, preparation, headers) {
|
|
367
371
|
const shiji = shijiStsTokenContinuation(url, body, replay.substitutions, approved, replay.kind === 'merchant_hosted' || replay.kind === 'verifone' ? undefined : replay.shijiStsCompanion);
|
|
368
372
|
if (shiji)
|
|
369
373
|
return { body: shiji.body, shijiCvv: shiji.cvv, shijiCvvKeySequenceSha256: shiji.cvvKeySequenceSha256 };
|
|
@@ -382,6 +386,13 @@ function cseContinuation(opts, url, body, replay, approved, preparation) {
|
|
|
382
386
|
: null;
|
|
383
387
|
if (twoc2p)
|
|
384
388
|
return { body: twoc2p.body, shijiCvv: null, shijiCvvKeySequenceSha256: null };
|
|
389
|
+
// Tap writes one RSA ciphertext at the body root under the merchant's pinned key, which the generic Adyen swap refuses
|
|
390
|
+
// as no JWE, so it is dispatched by the token URL to substituteTapPayments (tap-payments.ts), only into the one request
|
|
391
|
+
// the approval was made for, and only while the request that continues names the merchant's publishable key the
|
|
392
|
+
// approved one named: the browser sends that request's own headers.
|
|
393
|
+
const tap = replay.kind === undefined ? tapPaymentsContinuation(url, body, headers, replay.substitutions, approved) : null;
|
|
394
|
+
if (tap)
|
|
395
|
+
return { body: tap.body, shijiCvv: null, shijiCvvKeySequenceSha256: null };
|
|
385
396
|
return { body: cseContinuationBody(opts, body, replay, url, preparation), shijiCvv: null, shijiCvvKeySequenceSha256: null };
|
|
386
397
|
}
|
|
387
398
|
/**
|
|
@@ -1434,7 +1445,7 @@ function merchantAttempt(lifecycle, survives) {
|
|
|
1434
1445
|
// known non-payment, so the prepared checkout ends failed with that reason, and a fresh attachment can
|
|
1435
1446
|
// prepare again. Every other stop leaves the outcome unknown.
|
|
1436
1447
|
const error = () => reason === 'amadeus_send_window_closed' || reason === 'secure_acceptance_send_window_closed'
|
|
1437
|
-
|| reason === 'wix_payments_send_window_closed' || reason === 'hipay_send_window_closed'
|
|
1448
|
+
|| reason === 'wix_payments_send_window_closed' || reason === 'hipay_send_window_closed' || reason === 'openpay_send_window_closed'
|
|
1438
1449
|
? new CheckoutPreparationError(lifecycle.getState().preparationId ?? null, reason)
|
|
1439
1450
|
: new PaymentOutcomeUnknownError(lifecycle.getState().authorizationId, reason);
|
|
1440
1451
|
const attempt = {
|
|
@@ -1641,6 +1652,22 @@ function eprotectResumedReplay(replay, request) {
|
|
|
1641
1652
|
throw new PaymentOutcomeUnknownError(replay.authorizationId, 'eprotect_registration_unconfirmed');
|
|
1642
1653
|
return { ...replay, status: answer.status, headers: answer.headers, body: answer.body };
|
|
1643
1654
|
}
|
|
1655
|
+
/**
|
|
1656
|
+
* SB Payment Service's token request, resumed by the business, on the same terms as eProtect's above. The read
|
|
1657
|
+
* carries the token as the API stored it, which the paused <script> cannot run, so it gets the answer authorize()
|
|
1658
|
+
* gives on the create path (client.ts): the token inside the callback the paused URL named, under a script type,
|
|
1659
|
+
* and only a token payment-core's judge accepts for that URL. A read in any other mode never answers it either.
|
|
1660
|
+
* The paused URL alone decides, whatever recognizer claimed it. Any other request's replay passes as it came, and
|
|
1661
|
+
* a create's replay never comes here, so no answer is wrapped twice.
|
|
1662
|
+
*/
|
|
1663
|
+
function sbpsResumedReplay(replay, request) {
|
|
1664
|
+
if (classifySbpsRequest(request.url, request.method)?.kind !== 'token_request')
|
|
1665
|
+
return replay;
|
|
1666
|
+
const answer = replay.mode === 'token' ? sbpsScriptAnswer(request.url, replay) : null;
|
|
1667
|
+
if (replay.mode !== 'token' || !answer)
|
|
1668
|
+
throw new PaymentOutcomeUnknownError(replay.authorizationId, 'sbps_token_unconfirmed');
|
|
1669
|
+
return { ...replay, status: answer.status, headers: answer.headers, body: answer.body };
|
|
1670
|
+
}
|
|
1644
1671
|
/** The recogniser that claimed a paused request, by processor name, so a caller never re-matches the URL; null on a duck-typed vault without the read. */
|
|
1645
1672
|
function recognizerNameOf(opts, url, method) {
|
|
1646
1673
|
const read = opts.vault.recognizerOf;
|
|
@@ -1888,6 +1915,7 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
1888
1915
|
const payrexxFollowUps = new PayrexxFollowUps();
|
|
1889
1916
|
const aci = new AciGate(opts.vault);
|
|
1890
1917
|
const eprotect = new EprotectGate(opts.vault);
|
|
1918
|
+
const sbps = new SbpsGate(opts.vault);
|
|
1891
1919
|
// The merchant's follow-up request after a delivered Secure Acceptance reply (cybersource-secure-acceptance.ts).
|
|
1892
1920
|
const secureAcceptanceFollowUpWatch = new SecureAcceptanceFollowUpWatch(opts.onEvent);
|
|
1893
1921
|
lifecycle.abort.signal.addEventListener('abort', () => secureAcceptanceFollowUpWatch.end(), { once: true });
|
|
@@ -1997,6 +2025,8 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
1997
2025
|
// The merchant's own total (merchant-total-watch.ts): its checkout responses, recorded
|
|
1998
2026
|
// read-only from attach on, and the approval a hand-off answers, for the charge report.
|
|
1999
2027
|
const merchantTotal = new MerchantTotalWatch(opts.onEvent, opts.vault);
|
|
2028
|
+
// Paddle's own checkout answers (paddle-checkout-watch.ts), recorded read-only from attach on for a TokenEx /pay.
|
|
2029
|
+
const paddleCheckout = new PaddleCheckoutWatch();
|
|
2000
2030
|
// A reviewed card endpoint merchant's own record of the order (card-endpoint-facts.ts).
|
|
2001
2031
|
const cardEndpointRecord = new CardEndpointFactsWatch();
|
|
2002
2032
|
let handoffReplay = null;
|
|
@@ -2506,6 +2536,7 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
2506
2536
|
merchantTotal.sent(key, { method: params.request.method, url: params.request.url,
|
|
2507
2537
|
...(typeof params.request.postData === 'string' ? { requestBody: params.request.postData } : {}),
|
|
2508
2538
|
...(typeof params.loaderId === 'string' && params.loaderId ? { page: `${owner}:${params.loaderId}` } : {}) });
|
|
2539
|
+
paddleCheckout.sent(key, { method: params.request.method, url: params.request.url });
|
|
2509
2540
|
cardEndpointRecord.sent(key, { method: params.request.method, url: params.request.url, resourceType: params.type ?? null, networkId: params.requestId });
|
|
2510
2541
|
}
|
|
2511
2542
|
if (matchesActive) {
|
|
@@ -2545,6 +2576,14 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
2545
2576
|
cdp.send('Network.getResponseBody', { requestId: params.requestId }, sessionId).then((read) => merchantTotal.log.read(key, typeof read?.body === 'string'
|
|
2546
2577
|
? (read.base64Encoded ? Buffer.from(read.body, 'base64').toString('utf8') : read.body) : null, completedAt), () => merchantTotal.log.read(key, null, completedAt));
|
|
2547
2578
|
}
|
|
2579
|
+
if (paddleCheckout.tracks(key)) {
|
|
2580
|
+
// One of Paddle's checkout answers: stamped finished at once, so a /pay's pause waits for its text, then read
|
|
2581
|
+
// and cut to the terms by the watch.
|
|
2582
|
+
const completedAt = Date.now();
|
|
2583
|
+
paddleCheckout.finished(key, completedAt);
|
|
2584
|
+
cdp.send('Network.getResponseBody', { requestId: params.requestId }, sessionId).then((read) => paddleCheckout.read(key, typeof read?.body === 'string'
|
|
2585
|
+
? (read.base64Encoded ? Buffer.from(read.body, 'base64').toString('utf8') : read.body) : null, completedAt), () => paddleCheckout.read(key, null, completedAt));
|
|
2586
|
+
}
|
|
2548
2587
|
if (payrails && payrailsAnswers.delete(requestKey(sessionId, params.requestId))
|
|
2549
2588
|
&& !(Number(params.encodedDataLength) > PAYRAILS_INIT_BODY_LIMIT)) {
|
|
2550
2589
|
payrails.reading(cdp.send('Network.getResponseBody', { requestId: params.requestId }, sessionId).then((answer) => {
|
|
@@ -2559,6 +2598,7 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
2559
2598
|
}
|
|
2560
2599
|
if (method === 'Network.responseReceived') {
|
|
2561
2600
|
merchantTotal.log.answered(requestKey(sessionId, params.requestId), params.response?.status);
|
|
2601
|
+
paddleCheckout.answered(requestKey(sessionId, params.requestId), params.response?.status);
|
|
2562
2602
|
const recordKey = cardEndpointRecord.keyFor(requestKey(sessionId, params.requestId), params.requestId);
|
|
2563
2603
|
if (recordKey)
|
|
2564
2604
|
cardEndpointRecord.answered(recordKey, params.response?.status);
|
|
@@ -2587,6 +2627,7 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
2587
2627
|
|| (activeRequest && activeRequest.networkId === params.requestId && activeRequest.sourceSessionId === sessionId)))
|
|
2588
2628
|
holdGate.lost();
|
|
2589
2629
|
merchantTotal.log.failed(requestKey(sessionId, params.requestId));
|
|
2630
|
+
paddleCheckout.failed(requestKey(sessionId, params.requestId));
|
|
2590
2631
|
const recordKey = cardEndpointRecord.keyFor(requestKey(sessionId, params.requestId), params.requestId);
|
|
2591
2632
|
if (recordKey)
|
|
2592
2633
|
cardEndpointRecord.failed(recordKey);
|
|
@@ -2805,7 +2846,7 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
2805
2846
|
// headers and body are read lazily, inside the gate that needs them (see PreClaimContext.request).
|
|
2806
2847
|
request: { url: request.url, method: request.method, get headers() { return request.headers; }, get body() { return pausedBody(request); },
|
|
2807
2848
|
navigation: resourceType === 'Document' },
|
|
2808
|
-
vault: opts.vault, guards, mercado: mercadoCheckout, stripe: stripeCheckout, aci, eprotect,
|
|
2849
|
+
vault: opts.vault, guards, mercado: mercadoCheckout, stripe: stripeCheckout, aci, eprotect, sbps,
|
|
2809
2850
|
// This adapter drives Chromium, which sends the body Fetch.continueRequest replaces on a
|
|
2810
2851
|
// navigation (the ACI browser test's classic case, design gate G3).
|
|
2811
2852
|
replacesNavigationBody: async () => true,
|
|
@@ -3105,6 +3146,10 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
3105
3146
|
// The merchant's own record of the order, as of the pause, for a profile that reads one.
|
|
3106
3147
|
const cardRecord = cardEndpoint ? await cardEndpointFacts(cardEndpointRecord, cardEndpoint, request.url, pausedAt, attempt.signal) : null;
|
|
3107
3148
|
attempt.assertLive();
|
|
3149
|
+
// Paddle's own checkout answers as of the pause, once the texts of those that finished before it are read
|
|
3150
|
+
// (a Billing /pay only; sent only with a Paddle TokenEx create, which a pause-only business makes itself).
|
|
3151
|
+
const paddleAnswers = opts.pauseOnly ? undefined : await paddleCheckout.capture(pausedAt, request.url, attempt.signal);
|
|
3152
|
+
attempt.assertLive();
|
|
3108
3153
|
// Hold mode: nothing is created until the person's total releases the request (hold.ts).
|
|
3109
3154
|
if (holdGate) {
|
|
3110
3155
|
if (holdGate.state !== 'watching') {
|
|
@@ -3160,6 +3205,8 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
3160
3205
|
// What the merchant's own checkout said its total was, as this browser recorded it
|
|
3161
3206
|
// (read only for a reviewed profile priced by it): the page is the card request's.
|
|
3162
3207
|
merchantTotal: merchantTotal.capture(pausedAt, cardPage),
|
|
3208
|
+
// Paddle's own checkout answers, as this browser recorded them (sent only with a Paddle TokenEx create).
|
|
3209
|
+
paddleCheckout: paddleAnswers,
|
|
3163
3210
|
onAuthorizationCreated: (id) => {
|
|
3164
3211
|
lifecycle.approvalCreated(id);
|
|
3165
3212
|
if (holdSandbox && !holdRequestFailed) {
|
|
@@ -3191,7 +3238,7 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
3191
3238
|
holdRelease.settle(outcome);
|
|
3192
3239
|
throw new HoldAnsweredError(outcome);
|
|
3193
3240
|
}
|
|
3194
|
-
const replay = pause ? eprotectResumedReplay(await pause.replay, request) : await authorization;
|
|
3241
|
+
const replay = pause ? sbpsResumedReplay(eprotectResumedReplay(await pause.replay, request), request) : await authorization;
|
|
3195
3242
|
attempt.assertLive();
|
|
3196
3243
|
approvedId = replay.authorizationId;
|
|
3197
3244
|
if (lifecycle.isCancelled())
|
|
@@ -3241,8 +3288,14 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
3241
3288
|
// answered the device. The paused NAVIGATION is fulfilled with a page
|
|
3242
3289
|
// that says exactly that (see hosted-form.ts for why not an abort and
|
|
3243
3290
|
// why not a fake result page), and the same form is refused if the
|
|
3244
|
-
// page posts it again.
|
|
3245
|
-
|
|
3291
|
+
// page posts it again. A Webpay entry whose reviewed shop names its
|
|
3292
|
+
// return page goes to that page instead, with the token of the link
|
|
3293
|
+
// the approval was created from, the one the phone paid, since Webpay
|
|
3294
|
+
// tells the shop of a payment only through that return (transbank.ts
|
|
3295
|
+
// transbankMerchantReturn).
|
|
3296
|
+
const merchantReturn = transbankMerchantReturn(request.url, pageOrigin);
|
|
3297
|
+
const page = merchantReturn ? transbankMerchantReturnAnswer(merchantReturn)
|
|
3298
|
+
: hostedFormSubmittedPage({ authorizationId: replay.authorizationId, merchant: opts.merchant, submittedAt: replay.submittedAt });
|
|
3246
3299
|
// A navigation response is never CORS-checked, so the CORS wrap is
|
|
3247
3300
|
// inert here; it is applied so every fulfill goes through one path.
|
|
3248
3301
|
await cdp.send('Fetch.fulfillRequest', {
|
|
@@ -3254,8 +3307,10 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
3254
3307
|
attempt.assertLive();
|
|
3255
3308
|
lastSubmitted = { url: deliverRequest.url, body: deliverBody, at: Date.now(), authorizationId: replay.authorizationId };
|
|
3256
3309
|
// Named for what it is: a device-attested submission with no
|
|
3257
|
-
// processor evidence, never an `authorized` event.
|
|
3258
|
-
|
|
3310
|
+
// processor evidence, never an `authorized` event. A return names the
|
|
3311
|
+
// shop's host, never the URL, which carries Webpay's token.
|
|
3312
|
+
opts.onEvent?.({ type: 'submitted_on_device', detail: { authorizationId: replay.authorizationId, submittedAt: replay.submittedAt, outcome: replay.outcome,
|
|
3313
|
+
...(merchantReturn ? { merchantReturn: { host: new URL(merchantReturn).hostname } } : {}) } });
|
|
3259
3314
|
}
|
|
3260
3315
|
else if (replay.mode === 'cse') {
|
|
3261
3316
|
// The device encrypted the card for the processor; the request itself
|
|
@@ -3272,7 +3327,7 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
3272
3327
|
// companion cannot arrive first, and dropped if the continue fails.
|
|
3273
3328
|
// Both go only to the request the approval was created from, from the
|
|
3274
3329
|
// frame that sent it (cseContinuation refuses any other body).
|
|
3275
|
-
const continuation = cseContinuation(opts, deliverRequest.url, deliverBody, replay, { url: request.url, body }, preparation);
|
|
3330
|
+
const continuation = cseContinuation(opts, deliverRequest.url, deliverBody, replay, { url: request.url, body, headers: request.headers }, preparation, deliverRequest.headers);
|
|
3276
3331
|
const postData = Buffer.from(continuation.body).toString('base64');
|
|
3277
3332
|
if (continuation.shijiCvv !== null) {
|
|
3278
3333
|
shijiCompanions.bind({ url: request.url, method: request.method, body }, cdpShijiPage(sessionId, frameId), continuation.shijiCvv, continuation.shijiCvvKeySequenceSha256 ?? []);
|
|
@@ -3572,6 +3627,7 @@ export async function attachToPlaywright(page, opts) {
|
|
|
3572
3627
|
const aci = new AciGate(opts.vault);
|
|
3573
3628
|
let navigationBodyReplaced;
|
|
3574
3629
|
const eprotect = new EprotectGate(opts.vault);
|
|
3630
|
+
const sbps = new SbpsGate(opts.vault);
|
|
3575
3631
|
// The merchant's follow-up request after a delivered Secure Acceptance reply (cybersource-secure-acceptance.ts).
|
|
3576
3632
|
const secureAcceptanceFollowUpWatch = new SecureAcceptanceFollowUpWatch(opts.onEvent);
|
|
3577
3633
|
lifecycle.abort.signal.addEventListener('abort', () => secureAcceptanceFollowUpWatch.end(), { once: true });
|
|
@@ -3601,6 +3657,8 @@ export async function attachToPlaywright(page, opts) {
|
|
|
3601
3657
|
// but sends no document request, so it keeps the page id, as CDP's loaderId does. Nor does
|
|
3602
3658
|
// a document request that commits nothing: one that failed, or one answered 204 or 205.
|
|
3603
3659
|
const merchantTotal = new MerchantTotalWatch(opts.onEvent, opts.vault);
|
|
3660
|
+
// Paddle's own checkout answers, as attachToCdp records them (paddle-checkout-watch.ts).
|
|
3661
|
+
const paddleCheckout = new PaddleCheckoutWatch();
|
|
3604
3662
|
// A reviewed card endpoint merchant's own record of the order (card-endpoint-facts.ts).
|
|
3605
3663
|
const cardEndpointRecord = new CardEndpointFactsWatch();
|
|
3606
3664
|
let documentSerial = 1;
|
|
@@ -3662,6 +3720,10 @@ export async function attachToPlaywright(page, opts) {
|
|
|
3662
3720
|
...(typeof body === 'string' ? { requestBody: body } : {}), page: `doc:${documentSerial}` });
|
|
3663
3721
|
}
|
|
3664
3722
|
catch { /* a request the page already dropped */ }
|
|
3723
|
+
try {
|
|
3724
|
+
paddleCheckout.sent(keyOf(request), { method: request.method(), url: request.url() });
|
|
3725
|
+
}
|
|
3726
|
+
catch { /* a request the page already dropped */ }
|
|
3665
3727
|
try {
|
|
3666
3728
|
cardEndpointRecord.sent(keyOf(request), { method: request.method(), url: request.url(),
|
|
3667
3729
|
resourceType: typeof request.resourceType === 'function' ? request.resourceType() : null });
|
|
@@ -3703,6 +3765,28 @@ export async function attachToPlaywright(page, opts) {
|
|
|
3703
3765
|
cardEndpointRecord.read(key, text, finishedAt);
|
|
3704
3766
|
}).catch(() => cardEndpointRecord.failed(key));
|
|
3705
3767
|
}
|
|
3768
|
+
if (paddleCheckout.tracks(key)) {
|
|
3769
|
+
// One of Paddle's checkout answers: stamped finished at once, so a /pay's pause waits for its text, then its
|
|
3770
|
+
// status and its text, cut to the terms by the watch.
|
|
3771
|
+
const answeredAt = Date.now();
|
|
3772
|
+
paddleCheckout.finished(key, answeredAt);
|
|
3773
|
+
Promise.resolve().then(async () => {
|
|
3774
|
+
const response = await request.response();
|
|
3775
|
+
if (!response) {
|
|
3776
|
+
paddleCheckout.failed(key);
|
|
3777
|
+
return;
|
|
3778
|
+
}
|
|
3779
|
+
paddleCheckout.answered(key, response.status());
|
|
3780
|
+
let text = null;
|
|
3781
|
+
try {
|
|
3782
|
+
text = await response.text();
|
|
3783
|
+
}
|
|
3784
|
+
catch {
|
|
3785
|
+
text = null;
|
|
3786
|
+
}
|
|
3787
|
+
paddleCheckout.read(key, text, answeredAt);
|
|
3788
|
+
}).catch(() => paddleCheckout.failed(key));
|
|
3789
|
+
}
|
|
3706
3790
|
if (!merchantTotal.log.tracks(key))
|
|
3707
3791
|
return;
|
|
3708
3792
|
const completedAt = Date.now();
|
|
@@ -3772,6 +3856,7 @@ export async function attachToPlaywright(page, opts) {
|
|
|
3772
3856
|
if (request === documentRequest)
|
|
3773
3857
|
documentRequest = null;
|
|
3774
3858
|
merchantTotal.log.failed(keyOf(request));
|
|
3859
|
+
paddleCheckout.failed(keyOf(request));
|
|
3775
3860
|
cardEndpointRecord.failed(keyOf(request));
|
|
3776
3861
|
if (activeRequest && activeRequest.request === request && activeRequest.attempt.lose()) {
|
|
3777
3862
|
// The page's own script gave up on its request; the cardholder's
|
|
@@ -3873,6 +3958,9 @@ export async function attachToPlaywright(page, opts) {
|
|
|
3873
3958
|
|| opts.vault.isCardRequest(url.toString(), 'GET')
|
|
3874
3959
|
|| guards.matches(url.toString()) || stripeCheckout.matches(url.toString()) || mercadoCheckout.matches(url.toString())
|
|
3875
3960
|
|| eprotect.matches(url.toString())
|
|
3961
|
+
// SB Payment Service's token request is a GET too, so its family is routed by the SBPS gate (never
|
|
3962
|
+
// its scripts or the 3-D Secure info request).
|
|
3963
|
+
|| sbps.matches(url.toString())
|
|
3876
3964
|
// An armed merchant profile's endpoint or a sibling of it (merchant-hosted.ts), as attachToCdp arms it.
|
|
3877
3965
|
|| (typeof opts.vault.merchantProfileOf === 'function' && opts.vault.merchantProfileOf(url.toString()) !== null)
|
|
3878
3966
|
// An armed Verifone merchant's origin (verifone.ts), as attachToCdp arms it.
|
|
@@ -3898,6 +3986,10 @@ export async function attachToPlaywright(page, opts) {
|
|
|
3898
3986
|
// Every request to a Webpay host once its entry is served (transbank.ts), as attachToCdp arms the hosts: the
|
|
3899
3987
|
// token's submit and Webpay's card steps reach the Webpay gate and fail, and the entry pauses.
|
|
3900
3988
|
|| isArmedTransbankUrl(opts.vault, url.toString())
|
|
3989
|
+
// Every request to Paytrail's entry host and Payment Highway's card page host once Paytrail's entry is served
|
|
3990
|
+
// (paytrail.ts), as attachToCdp arms the recognizer's host and its abort host: the loading page's post and the
|
|
3991
|
+
// card page's card requests reach the Paytrail gate and fail.
|
|
3992
|
+
|| isArmedPaytrailUrl(opts.vault, url.toString())
|
|
3901
3993
|
// A CreditGuard page's own calls beside its submit (its card lookup and its 3-D Secure calls), for an
|
|
3902
3994
|
// org the API served CreditGuard to, as attachToCdp arms its hosts: the CreditGuard gate answers them
|
|
3903
3995
|
// under a ready preparation and lets them go on with none (pre-claim.ts isArmedCreditguardCall).
|
|
@@ -3965,7 +4057,7 @@ export async function attachToPlaywright(page, opts) {
|
|
|
3965
4057
|
catch {
|
|
3966
4058
|
return false;
|
|
3967
4059
|
} } },
|
|
3968
|
-
vault: opts.vault, guards, mercado: mercadoCheckout, stripe: stripeCheckout, aci, eprotect,
|
|
4060
|
+
vault: opts.vault, guards, mercado: mercadoCheckout, stripe: stripeCheckout, aci, eprotect, sbps,
|
|
3969
4061
|
// Asked once, and only for ACI's classic-mode /payment: whether this page's engine sends
|
|
3970
4062
|
// the body route.continue replaces on a navigation (aci.ts playwrightReplacesNavigationBody).
|
|
3971
4063
|
replacesNavigationBody: () => (navigationBodyReplaced ??= playwrightReplacesNavigationBody(page)),
|
|
@@ -4257,6 +4349,9 @@ export async function attachToPlaywright(page, opts) {
|
|
|
4257
4349
|
// The merchant's own record of the order, as of the pause (see attachToCdp).
|
|
4258
4350
|
const cardRecord = cardEndpoint ? await cardEndpointFacts(cardEndpointRecord, cardEndpoint, request.url(), pausedAt, attempt.signal) : null;
|
|
4259
4351
|
assertRequestLive();
|
|
4352
|
+
// Paddle's own checkout answers as of the pause, once their texts are read (see attachToCdp).
|
|
4353
|
+
const paddleAnswers = await paddleCheckout.capture(pausedAt, request.url(), attempt.signal);
|
|
4354
|
+
assertRequestLive();
|
|
4260
4355
|
const replay = await opts.vault.authorize({
|
|
4261
4356
|
user: opts.user,
|
|
4262
4357
|
merchant: opts.merchant,
|
|
@@ -4276,6 +4371,8 @@ export async function attachToPlaywright(page, opts) {
|
|
|
4276
4371
|
merchantSignal: attempt.signal,
|
|
4277
4372
|
// Same as the CDP path: the merchant's total as this browser recorded it.
|
|
4278
4373
|
merchantTotal: merchantTotal.capture(pausedAt, pausedPage),
|
|
4374
|
+
// And Paddle's own checkout answers, as this browser recorded them.
|
|
4375
|
+
paddleCheckout: paddleAnswers,
|
|
4279
4376
|
onAuthorizationCreated: (id) => lifecycle.approvalCreated(id),
|
|
4280
4377
|
onApprovalUrl: (url) => { if (!preparation && !attempt.signal.aborted) {
|
|
4281
4378
|
lifecycle.approvalUrl(url);
|
|
@@ -4323,13 +4420,17 @@ export async function attachToPlaywright(page, opts) {
|
|
|
4323
4420
|
}
|
|
4324
4421
|
else if (replay.mode === 'hosted_form') {
|
|
4325
4422
|
// Same as the CDP path: the paused navigation resolves to the
|
|
4326
|
-
// synthetic page,
|
|
4327
|
-
|
|
4423
|
+
// synthetic page, or a reviewed Webpay shop's return page, and a
|
|
4424
|
+
// re-post of this form is refused.
|
|
4425
|
+
const merchantReturn = transbankMerchantReturn(request.url(), pageOrigin);
|
|
4426
|
+
const synthetic = merchantReturn ? transbankMerchantReturnAnswer(merchantReturn)
|
|
4427
|
+
: hostedFormSubmittedPage({ authorizationId: replay.authorizationId, merchant: opts.merchant, submittedAt: replay.submittedAt });
|
|
4328
4428
|
// Inert on a navigation (never CORS-checked); one path for every fulfill.
|
|
4329
4429
|
await deliverTo.fulfill({ status: synthetic.status, headers: withCorsHeaders(synthetic.headers, corsHeadersFor(deliverRequest.url(), deliverRequest.headers())), body: synthetic.body });
|
|
4330
4430
|
assertRequestLive();
|
|
4331
4431
|
lastSubmitted = { url: deliverRequest.url(), body: deliverBody, at: Date.now(), authorizationId: replay.authorizationId };
|
|
4332
|
-
opts.onEvent?.({ type: 'submitted_on_device', detail: { authorizationId: replay.authorizationId, submittedAt: replay.submittedAt, outcome: replay.outcome
|
|
4432
|
+
opts.onEvent?.({ type: 'submitted_on_device', detail: { authorizationId: replay.authorizationId, submittedAt: replay.submittedAt, outcome: replay.outcome,
|
|
4433
|
+
...(merchantReturn ? { merchantReturn: { host: new URL(merchantReturn).hostname } } : {}) } });
|
|
4333
4434
|
}
|
|
4334
4435
|
else if (replay.mode === 'cse') {
|
|
4335
4436
|
// Same as the CDP path: the request continues from this browser
|
|
@@ -4342,7 +4443,7 @@ export async function attachToPlaywright(page, opts) {
|
|
|
4342
4443
|
// A Shiji STS getTokenId binds the device's cvv to its companion
|
|
4343
4444
|
// first, exactly as in attachToCdp: only for the request the
|
|
4344
4445
|
// approval was created from, and its frame.
|
|
4345
|
-
const continuation = cseContinuation(opts, deliverRequest.url(), deliverBody, replay, { url: request.url(), body }, preparation);
|
|
4446
|
+
const continuation = cseContinuation(opts, deliverRequest.url(), deliverBody, replay, { url: request.url(), body, headers: request.headers() }, preparation, deliverRequest.headers());
|
|
4346
4447
|
if (continuation.shijiCvv !== null) {
|
|
4347
4448
|
// The document the getTokenId paused in. One that cannot be read leaves the CVV nowhere to
|
|
4348
4449
|
// go, so the card is not tokenized either.
|
package/dist/client.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { type PreparationMode, type PreparationProcessor } from './prepared-proc
|
|
|
6
6
|
import { type VerifoneProfile, type VerifoneSubstitutions } from './verifone.js';
|
|
7
7
|
import { type MerchantSessionCapture } from './merchant-session-probe.js';
|
|
8
8
|
import { type PaddleTokenexServedFacts } from './paddle-tokenex.js';
|
|
9
|
+
import type { PaddleCheckoutCapture } from './paddle-checkout-watch.js';
|
|
9
10
|
import { VoiceModule, type VoiceOptions } from './voice.js';
|
|
10
11
|
import { BuyModule } from './buy.js';
|
|
11
12
|
import { RequestRegistry } from './requests.js';
|
|
@@ -211,6 +212,12 @@ export declare const SUPPORTED_REGISTRY_FEATURES: readonly string[];
|
|
|
211
212
|
* never lets the agent's browser post to (pre-claim.ts, redsys.ts). Served on the same terms as NMI's: only
|
|
212
213
|
* to a build that lists it, for a company Agentcard turned Redsys on for.
|
|
213
214
|
*
|
|
215
|
+
* `paytrail_hosted_payment_page`: Paytrail's card method, whose card-free signed Visa and Mastercard
|
|
216
|
+
* entry this build pauses for the cardholder's device, and whose loading page post, card page posts and
|
|
217
|
+
* card-number lookup on Payment Highway's host this build never lets the agent's browser send
|
|
218
|
+
* (pre-claim.ts, paytrail.ts). Served on the same terms as NMI's and Redsys's: only to a build that lists
|
|
219
|
+
* it, for a company Agentcard turned Paytrail on for.
|
|
220
|
+
*
|
|
214
221
|
* `paddle_vgs_cards`: the card request Paddle's checkout frame sends to its VGS card
|
|
215
222
|
* vault (vault.paddle.com/cards) on a checkout that names VGS, only through a prepared
|
|
216
223
|
* checkout: the frame aborts the request 10 seconds after Pay and sends it once more,
|
|
@@ -327,8 +334,8 @@ export declare const SUPPORTED_REGISTRY_FEATURES: readonly string[];
|
|
|
327
334
|
* This build pauses only the form's own multipart body at that exact URL; the cardholder's
|
|
328
335
|
* device sends the card through the checkout relay, and the frame gets the token answer
|
|
329
336
|
* payment-core's judge rebuilt, with the CORS answer for the frame's own origin, null. The
|
|
330
|
-
* request names no amount, so the agent's pair, above zero, is the one the cardholder approves
|
|
331
|
-
*
|
|
337
|
+
* request names no amount, so the agent's pair, above zero, is the one the cardholder approves.
|
|
338
|
+
* Served on the same terms: only to a build that lists it, for a company
|
|
332
339
|
* Agentcard turned Pay. on for.
|
|
333
340
|
*
|
|
334
341
|
* `paypal_card_fields`: PayPal Card Fields' confirm, the POST its v5 frame sends to
|
|
@@ -396,8 +403,8 @@ export declare const SUPPORTED_REGISTRY_FEATURES: readonly string[];
|
|
|
396
403
|
* encrypted under Clover's key. This build pauses only the frame's own body at that exact URL; the
|
|
397
404
|
* cardholder's device builds the request again with the real card under the key payment-core pins
|
|
398
405
|
* and sends it to Clover itself, and the frame gets the token answer payment-core's judge rebuilt.
|
|
399
|
-
* The request names no amount, so the agent's pair, above zero, is the one the cardholder approves
|
|
400
|
-
*
|
|
406
|
+
* The request names no amount, so the agent's pair, above zero, is the one the cardholder approves.
|
|
407
|
+
* Served on the same terms: only to a build that lists it, for a company
|
|
401
408
|
* Agentcard turned Clover on for.
|
|
402
409
|
*
|
|
403
410
|
* `eximbay_hosted_payment_page`: Eximbay's payment window, whose card-free signed entry
|
|
@@ -415,6 +422,84 @@ export declare const SUPPORTED_REGISTRY_FEATURES: readonly string[];
|
|
|
415
422
|
* this build writes it over the agent's placeholder and nothing else before it
|
|
416
423
|
* continues the request. Served on the same terms: only to a build that lists it, for
|
|
417
424
|
* a company Agentcard turned Toast on for.
|
|
425
|
+
*
|
|
426
|
+
* `xendit_card_token`: the card token request Xendit's hosted invoice checkout
|
|
427
|
+
* (checkout.xendit.co/web/<invoice id>, where Xendit's payment and donation links land) sends
|
|
428
|
+
* when the payer presses Pay Now: Xendit.js posts the card as JSON to
|
|
429
|
+
* https://api.xendit.co/v2/credit_card_tokens from the page itself, under the business's
|
|
430
|
+
* publishable key. This build pauses only the card form's single-use token body at that exact URL
|
|
431
|
+
* (payment-core xendit.js); a token that keeps the card on file, Xendit.js's code-only storeCVN post
|
|
432
|
+
* and any other body there fail in the browser before anything is created. The cardholder's device
|
|
433
|
+
* sends the request itself with the real card, and the page gets the token answer payment-core's
|
|
434
|
+
* judge rebuilt, after which the page runs 3-D Secure and charges the token without the card. The
|
|
435
|
+
* token names the invoice's amount and currency, so no agent pair is needed: the API reads the
|
|
436
|
+
* token's and holds an agent's pair to it. Served on the same terms: only to a build that lists it,
|
|
437
|
+
* for a company Agentcard turned Xendit on for.
|
|
438
|
+
*
|
|
439
|
+
* `omise_card_token`: the card token request every Omise card form sends, Omise.js's pay.html frame
|
|
440
|
+
* or a merchant's own page calling Omise.js or Omise's Node library: a JSON POST to
|
|
441
|
+
* https://vault.omise.co/tokens under the merchant's public key. This build pauses only the card
|
|
442
|
+
* form's token body at that exact URL (payment-core omise.js); a wallet's tokenization and any other
|
|
443
|
+
* body there fail in the browser before anything is created. The cardholder's device sends the
|
|
444
|
+
* request itself with the real card, and the page gets the token answer payment-core's judge
|
|
445
|
+
* rebuilt. The request names no amount, so the agent's pair, above zero, is the one the cardholder
|
|
446
|
+
* approves, and the API pays only a merchant payment-core pins for the checkout
|
|
447
|
+
* page the create names. Served on the same terms: only to a build that lists it, for a company
|
|
448
|
+
* Agentcard turned Omise on for.
|
|
449
|
+
*
|
|
450
|
+
* `sbps_token_jsonp`: SB Payment Service's card token request, the JSONP <script>
|
|
451
|
+
* GET its token script sends to /token/generateToken on token.sps-system.com. This
|
|
452
|
+
* build pauses it only as the browser writes it, aborts any other request on that
|
|
453
|
+
* path, and answers the paused script with the token as the API recorded it, in the
|
|
454
|
+
* request's own callback. The device rebuilds the card's ciphertext and sends it
|
|
455
|
+
* through the checkout relay. Served on the same terms: only to a build that lists
|
|
456
|
+
* it, for a company Agentcard turned SB Payment Service on for.
|
|
457
|
+
*
|
|
458
|
+
* `midtrans_card_token`: the card token Midtrans' Snap popup posts as one JSON request to
|
|
459
|
+
* api.midtrans.com/v2/token (api.sandbox.midtrans.com in test), under the business's
|
|
460
|
+
* publishable client key. The cardholder's device sends it and the page gets back Midtrans'
|
|
461
|
+
* token, which the merchant's own server charges afterwards, card free, running 3-D Secure
|
|
462
|
+
* there. The token names no amount, so authorize() needs the agent's pair.
|
|
463
|
+
* Served on the same terms, and the API holds the lane to Agentcard's own company
|
|
464
|
+
* until a reviewed change binds the client key to the merchant.
|
|
465
|
+
*
|
|
466
|
+
* `tap_card_sdk_token`: the token request Tap Payments' card frame sends to sdk.tap.company, carrying
|
|
467
|
+
* the card only as one ciphertext the frame writes under the merchant's own RSA key. This build pauses
|
|
468
|
+
* it and writes over the placeholder's ciphertext the one the cardholder's device wrote under the key
|
|
469
|
+
* payment-core pins for the request's publishable key (tap-payments.ts), into that request alone; 3-D
|
|
470
|
+
* Secure and the merchant's charge then run in the agent's browser. Served on the same terms: only to
|
|
471
|
+
* a build that lists it, for a company Agentcard turned Tap on for.
|
|
472
|
+
*
|
|
473
|
+
* `fastspring_card_payment`: the card payment FastSpring's checkout posts, on every store's own
|
|
474
|
+
* host, to <store>.onfastspring.com[/popup-<name>]/session/<id>/payment under the session's
|
|
475
|
+
* X-Session-Token. This build pauses only the checkout's own card body at that exact URL (a card
|
|
476
|
+
* FastSpring saved, a renewal, a gift, a tax id's second card send and a CAPTCHA answer are refused
|
|
477
|
+
* at the pause, and another method's payment with no card continues); the cardholder's device writes
|
|
478
|
+
* the real card into the paused body and sends it through the checkout relay, and the checkout gets
|
|
479
|
+
* FastSpring's answer as payment-core's judge rebuilt it. The request names no amount, so the agent's
|
|
480
|
+
* pair, above zero, is the total the checkout shows. Served on the same terms:
|
|
481
|
+
* only to a build that lists it, for a company Agentcard turned FastSpring on for.
|
|
482
|
+
*
|
|
483
|
+
* `openpay_tokenizer`: the token create openpay.js sends from a merchant's own page to
|
|
484
|
+
* api.openpay.mx/v1/<merchant id>/tokens (api.openpay.co, api.openpay.pe; sandbox-api for a test
|
|
485
|
+
* row), only through a prepared checkout: openpay.js abandons the request 40 seconds after Pay, so
|
|
486
|
+
* the cardholder approves before Pay. The token URL names the merchant, so the claim binds the
|
|
487
|
+
* request by its host's environment and its shape, never by the prepared URL. The cardholder's
|
|
488
|
+
* device sends the card to Openpay itself and the page gets back Openpay's token alone, rebuilt by
|
|
489
|
+
* payment-core's judge. The request names no amount, so the agent's pair, above zero
|
|
490
|
+
* (agent-amount-processors.json), is the one the cardholder approves. Served on the same terms: only
|
|
491
|
+
* to a build that lists it, for a company Agentcard turned Openpay on for.
|
|
492
|
+
*
|
|
493
|
+
* `aps_custom_merchant_page`: Amazon Payment Services' custom merchant page, whose own card form
|
|
494
|
+
* posts top-level to /FortAPI/paymentPage on checkout.payfort.com (sbcheckout.payfort.com on APS's
|
|
495
|
+
* sandbox) with service_command=TOKENIZATION. This build pauses that navigation; the cardholder's
|
|
496
|
+
* phone sends the form with the real card through the checkout relay, and the paused navigation
|
|
497
|
+
* gets APS's own answer, its page or its redirect to the form's return page, only as payment-core's
|
|
498
|
+
* judge reads it for that form (amazon-payment-services.ts apsNavigationAnswer). The form names no
|
|
499
|
+
* amount, so the agent's pair, above zero, is the one the cardholder approves.
|
|
500
|
+
* Served on the same terms: only to a build that lists it, for a company Agentcard turned APS on for.
|
|
501
|
+
*
|
|
502
|
+
* The list itself is capabilities.json, sorted, one per line (scripts/generate-capabilities.mjs).
|
|
418
503
|
*/
|
|
419
504
|
export declare const SUPPORTED_CAPABILITIES: readonly string[];
|
|
420
505
|
/**
|
|
@@ -599,7 +684,10 @@ export interface VerifoneReplay extends ExecutionMetadata {
|
|
|
599
684
|
* paused the navigation, so there is no response to replay and no outcome
|
|
600
685
|
* here: resolve the paused navigation with hostedFormSubmittedPage() (the
|
|
601
686
|
* adapters do), never resubmit the form, and confirm the order with the
|
|
602
|
-
* merchant, which learns the outcome from the processor.
|
|
687
|
+
* merchant, which learns the outcome from the processor. Webpay's merchant
|
|
688
|
+
* learns it only from the buyer's browser, so the adapters send a paused
|
|
689
|
+
* Webpay entry whose reviewed shop names its return page to that page instead
|
|
690
|
+
* (transbankMerchantReturn).
|
|
603
691
|
*
|
|
604
692
|
* THIS IS NOT AN APPROVED PAYMENT. `kind` and `outcome` say so in words so
|
|
605
693
|
* no caller mistakes it for one: the API finishes such an authorization as
|
|
@@ -913,6 +1001,13 @@ export interface AuthorizeInput extends ExecutionMetadata {
|
|
|
913
1001
|
* one from its network events, or the payment is refused before any create.
|
|
914
1002
|
*/
|
|
915
1003
|
merchantTotal?: MerchantTotalCapture;
|
|
1004
|
+
/**
|
|
1005
|
+
* For a Paddle TokenEx /pay: when it paused and the answers Paddle's checkout service gave the frame before it,
|
|
1006
|
+
* as this browser recorded them (see paddle-checkout-watch.ts). The adapters pass it, and it rides the create only
|
|
1007
|
+
* for that processor. The API holds `amount` to the total they state for today, and admits a free trial's $0.00
|
|
1008
|
+
* only on them; without them a $0.00 Paddle create is refused as before.
|
|
1009
|
+
*/
|
|
1010
|
+
paddleCheckout?: PaddleCheckoutCapture;
|
|
916
1011
|
}
|
|
917
1012
|
export declare class CardEncryptedError extends Error {
|
|
918
1013
|
psp: string;
|
|
@@ -1363,6 +1458,9 @@ export declare class CheckoutAuthError extends Error {
|
|
|
1363
1458
|
* https://payment.quickpay.net/{session}/3ds_auth.
|
|
1364
1459
|
* On FastSpring's store hosts the session id reads `{session}`:
|
|
1365
1460
|
* https://daisydisk.onfastspring.com/session/{session}/payment.
|
|
1461
|
+
* On PayU Latam's hosts the checkout session's key reads `{key}`:
|
|
1462
|
+
* https://checkout.payulatam.com/ppp-web-gateway-payu/checkout/submit/co/credit_card/{key}.
|
|
1463
|
+
* Each mask in src/url-masks/ says what it reads in its own file.
|
|
1366
1464
|
* A string that is not a URL keeps the part before any `?` or `#`, with the
|
|
1367
1465
|
* same segments masked for every processor whose host it names.
|
|
1368
1466
|
* A URL is read by its host only when the parser finds one. Text before a URL
|
|
@@ -1571,9 +1669,10 @@ export declare class VaultClient {
|
|
|
1571
1669
|
* capability (syncRegistry does), so before a sync, or against an API that
|
|
1572
1670
|
* withheld it, the adapters leave that processor's traffic exactly as they
|
|
1573
1671
|
* found it. prepare() asks this for ACI, whose card-number request names a
|
|
1574
|
-
* checkout id the merchant mints only at Pay time,
|
|
1575
|
-
*
|
|
1576
|
-
*
|
|
1672
|
+
* checkout id the merchant mints only at Pay time, for Openpay, whose token
|
|
1673
|
+
* URL names the merchant's own id, and for a processor whose card request is
|
|
1674
|
+
* a GET (Worldpay eProtect), since that request is recognized by a query the
|
|
1675
|
+
* page has not written yet.
|
|
1577
1676
|
*/
|
|
1578
1677
|
recognizesProcessor(psp: string): boolean;
|
|
1579
1678
|
/**
|