@agent-cards/sdk 0.24.1 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/approvals.d.ts +44 -0
- package/dist/approvals.js +10 -0
- package/dist/capabilities.generated.js +1 -1
- package/dist/card-fields.generated.js +357 -263
- package/dist/cdp.js +34 -13
- package/dist/client.d.ts +9 -0
- package/dist/client.js +9 -0
- package/dist/datatrans.generated.js +3 -1
- package/dist/index.d.ts +1 -1
- package/dist/lifecycle.d.ts +23 -5
- package/dist/lifecycle.js +45 -22
- package/dist/merchant-card-endpoints.generated.js +30 -3
- package/dist/payrails.generated.js +3 -1
- package/dist/pre-claim.d.ts +3 -0
- package/dist/pre-claim.js +45 -1
- package/dist/preflight-catalog.json +25 -0
- package/dist/preflight-schemas.json +2 -0
- package/dist/preflight.generated.js +10 -1
- package/dist/primer.generated.js +366 -273
- package/dist/stripe-checkout.generated.js +336 -242
- package/dist/stripe-continuation.d.ts +45 -0
- package/dist/stripe-continuation.js +106 -0
- package/dist/stripe-setup.d.ts +5 -10
- package/dist/stripe-setup.js +11 -39
- package/dist/token-repeats.d.ts +32 -0
- package/dist/token-repeats.js +64 -0
- package/examples/preflight/kernel-native/inventory.json +1 -1
- package/package.json +2 -2
package/dist/cdp.js
CHANGED
|
@@ -15,6 +15,7 @@ import { isPaddleVgsCardsUrl } from './paddle-vgs.generated.js';
|
|
|
15
15
|
import { isToastPaymentMethodsUrl, readToastBody } from './toast.generated.js';
|
|
16
16
|
import { PADDLE_VGS_PAY_PATTERNS, PaddleVgsPayGate, isPaddleCheckoutService, recognizesPaddleVgs } from './paddle-vgs-pay.js';
|
|
17
17
|
import { DatatransRepeats } from './datatrans.js';
|
|
18
|
+
import { TokenRepeats } from './token-repeats.js';
|
|
18
19
|
import { TokenexIframeRepeats, isArmedTokenexIframeUrl } from './tokenex-iframe.js';
|
|
19
20
|
import { isArmedPaytrailUrl } from './paytrail.js';
|
|
20
21
|
import { SHIJI_STS_COMPANION_WINDOW_MS, ShijiStsCompanions, ShijiStsError, isShijiStsHost, shijiStsTokenContinuation, } from './shiji-sts.js';
|
|
@@ -43,6 +44,7 @@ import { CYBERSOURCE_SECURE_ACCEPTANCE_PATTERNS, CYBERSOURCE_SECURE_ACCEPTANCE_R
|
|
|
43
44
|
import { CheckoutAttachmentError, attachmentDeadline, attachmentFailure, withinAttachmentDeadline } from './attachment.js';
|
|
44
45
|
import { cseBody } from './cse-body.js';
|
|
45
46
|
import { STRIPE_SETUP_INTENT_CONFIRM, setupConfirmPayingWith } from './stripe-setup.js';
|
|
47
|
+
import { confirmPayingWith } from './stripe-continuation.js';
|
|
46
48
|
import { replayTemplatedUrl, reviewedMerchantProfileUrlPatterns } from './merchant-hosted.js';
|
|
47
49
|
import { verifoneTemplatedUrl } from './verifone.js';
|
|
48
50
|
import { MerchantHandoffWatch } from './merchant-handoff.js';
|
|
@@ -1112,30 +1114,41 @@ function claimStripeContinuation(opts, lifecycle, url, method, body) {
|
|
|
1112
1114
|
}
|
|
1113
1115
|
if (parsed.origin !== 'https://api.stripe.com')
|
|
1114
1116
|
return null;
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1117
|
+
const payment = STRIPE_PAYMENT_INTENT_CONFIRM.test(parsed.pathname);
|
|
1118
|
+
const setup = !payment && STRIPE_SETUP_INTENT_CONFIRM.test(parsed.pathname);
|
|
1119
|
+
if (!payment && !setup)
|
|
1120
|
+
return null;
|
|
1121
|
+
// Each kind needs the client method that judges it; an older client keeps the ordinary hold.
|
|
1122
|
+
if (payment && typeof opts.vault.checkStripeContinuation !== 'function')
|
|
1123
|
+
return null;
|
|
1124
|
+
if (setup && typeof opts.vault.checkStripeSetupContinuation !== 'function')
|
|
1122
1125
|
return null;
|
|
1123
1126
|
const withoutCard = opts.vault.withoutCard?.(url, body);
|
|
1124
1127
|
let send = null;
|
|
1125
1128
|
if (withoutCard === 'refuse')
|
|
1126
1129
|
send = body;
|
|
1127
1130
|
else if (withoutCard === null) {
|
|
1128
|
-
// The card again, inline: only the
|
|
1129
|
-
// and only when what is left carries no card at
|
|
1130
|
-
|
|
1131
|
-
|
|
1131
|
+
// The card again, inline: only the object the cardholder's approval
|
|
1132
|
+
// returned may replace it, and only when what is left carries no card at
|
|
1133
|
+
// all. A payment pays with whichever object its approval produced (a
|
|
1134
|
+
// confirmation token, for a store that creates one for a fraud check and
|
|
1135
|
+
// then confirms with the Payment Element); a card save pays with a payment
|
|
1136
|
+
// method alone, which is all a SetupIntent confirm takes.
|
|
1137
|
+
if (payment) {
|
|
1138
|
+
const way = lifecycle.approvedStripeWay();
|
|
1139
|
+
send = way ? confirmPayingWith(body, way) : null;
|
|
1140
|
+
}
|
|
1141
|
+
else {
|
|
1142
|
+
const paymentMethod = lifecycle.approvedStripePaymentMethod();
|
|
1143
|
+
send = paymentMethod ? setupConfirmPayingWith(body, paymentMethod) : null;
|
|
1144
|
+
}
|
|
1132
1145
|
if (send !== null && opts.vault.withoutCard?.(url, send) !== 'refuse')
|
|
1133
1146
|
send = null;
|
|
1134
1147
|
}
|
|
1135
1148
|
if (send === null)
|
|
1136
1149
|
return null;
|
|
1137
1150
|
const authorizationId = lifecycle.claimStripeContinuation();
|
|
1138
|
-
return authorizationId ? { authorizationId, kind: 'setup', body: send, rewritten: send !== body } : null;
|
|
1151
|
+
return authorizationId ? { authorizationId, kind: payment ? 'payment' : 'setup', body: send, rewritten: send !== body } : null;
|
|
1139
1152
|
}
|
|
1140
1153
|
/**
|
|
1141
1154
|
* Ask the API about a claimed continuation, with the body it would continue
|
|
@@ -1158,7 +1171,7 @@ async function checkStripeContinuation(opts, lifecycle, claim, request) {
|
|
|
1158
1171
|
if (proceed) {
|
|
1159
1172
|
opts.onEvent?.(kind === 'setup'
|
|
1160
1173
|
? { type: 'stripe_setup_continued', detail: { authorizationId, setupIntentId: intentId, rewritten: claim.rewritten } }
|
|
1161
|
-
: { type: 'stripe_payment_continued', detail: { authorizationId, paymentIntentId: intentId } });
|
|
1174
|
+
: { type: 'stripe_payment_continued', detail: { authorizationId, paymentIntentId: intentId, rewritten: claim.rewritten } });
|
|
1162
1175
|
}
|
|
1163
1176
|
else if (intentId !== null)
|
|
1164
1177
|
opts.onEvent?.({ type: 'blocked', detail: 'stripe_continuation_superseded' });
|
|
@@ -2084,6 +2097,8 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
2084
2097
|
// The approved TokenEx iframe answers, per frameId (the card-number frame is an out-of-process iframe whose own
|
|
2085
2098
|
// session pauses its post; its frameId names it): the repeat rule (tokenex-iframe.ts).
|
|
2086
2099
|
const tokenexIframeRepeats = new TokenexIframeRepeats();
|
|
2100
|
+
// The last approved plain token answer, for the page's identical re-send (token-repeats.ts).
|
|
2101
|
+
const tokenRepeats = new TokenRepeats();
|
|
2087
2102
|
// The card product each Worldline MyCheckout hosted checkout chose (worldline-mycheckout.ts).
|
|
2088
2103
|
const worldlineProducts = new WorldlineMyCheckoutProducts();
|
|
2089
2104
|
// The Shiji STS getCvvId companion of the getTokenId this attachment last continued (shiji-sts.ts).
|
|
@@ -2905,6 +2920,7 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
2905
2920
|
juspay: juspayCheckout,
|
|
2906
2921
|
datatrans: datatransRepeats,
|
|
2907
2922
|
tokenexIframe: tokenexIframeRepeats,
|
|
2923
|
+
tokenRepeats,
|
|
2908
2924
|
ebanx: ebanxFollowUps,
|
|
2909
2925
|
payrexx: payrexxFollowUps,
|
|
2910
2926
|
nikeOrders,
|
|
@@ -3446,6 +3462,7 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
3446
3462
|
// The frame that received it: the paused request's, or its retry's once rebound.
|
|
3447
3463
|
datatransRepeats.remember(activeRequest?.frameId || undefined, deliverRequest.url, deliverBody, replay);
|
|
3448
3464
|
tokenexIframeRepeats.remember(activeRequest?.frameId || undefined, deliverRequest.url, deliverBody, replay);
|
|
3465
|
+
tokenRepeats.remember(activeRequest?.frameId || undefined, deliverRequest.url, deliverBody, replay);
|
|
3449
3466
|
attempt.assertLive();
|
|
3450
3467
|
// An ACI card-number request answered: its checkout's held CVC and expiry requests get the
|
|
3451
3468
|
// same answer, and its /payment submission may continue (see AciGate).
|
|
@@ -3982,6 +3999,8 @@ export async function attachToPlaywright(page, opts) {
|
|
|
3982
3999
|
const datatransRepeats = new DatatransRepeats();
|
|
3983
4000
|
// The approved TokenEx iframe answers, per Frame: the repeat rule (tokenex-iframe.ts).
|
|
3984
4001
|
const tokenexIframeRepeats = new TokenexIframeRepeats();
|
|
4002
|
+
// The last approved plain token answer, for the page's identical re-send (token-repeats.ts).
|
|
4003
|
+
const tokenRepeats = new TokenRepeats();
|
|
3985
4004
|
// The card product each Worldline MyCheckout hosted checkout chose (worldline-mycheckout.ts).
|
|
3986
4005
|
const worldlineProducts = new WorldlineMyCheckoutProducts();
|
|
3987
4006
|
const frameOf = (request) => { try {
|
|
@@ -4180,6 +4199,7 @@ export async function attachToPlaywright(page, opts) {
|
|
|
4180
4199
|
juspay: juspayCheckout,
|
|
4181
4200
|
datatrans: datatransRepeats,
|
|
4182
4201
|
tokenexIframe: tokenexIframeRepeats,
|
|
4202
|
+
tokenRepeats,
|
|
4183
4203
|
ebanx: ebanxFollowUps,
|
|
4184
4204
|
payrexx: payrexxFollowUps,
|
|
4185
4205
|
nikeOrders,
|
|
@@ -4586,6 +4606,7 @@ export async function attachToPlaywright(page, opts) {
|
|
|
4586
4606
|
await deliverTo.fulfill({ status: replay.status, headers: withCorsHeaders(replay.headers, cors.headers), body: replay.body });
|
|
4587
4607
|
datatransRepeats.remember(frameOf(deliverRequest), deliverRequest.url(), deliverBody, replay);
|
|
4588
4608
|
tokenexIframeRepeats.remember(frameOf(deliverRequest), deliverRequest.url(), deliverBody, replay);
|
|
4609
|
+
tokenRepeats.remember(frameOf(deliverRequest), deliverRequest.url(), deliverBody, replay);
|
|
4589
4610
|
assertRequestLive();
|
|
4590
4611
|
// See the same step in attachToCdp.
|
|
4591
4612
|
aci.answered(deliverRequest.url(), { status: replay.status, headers: replay.headers, body: replay.body }, replay.authorizationId);
|
package/dist/client.d.ts
CHANGED
|
@@ -608,6 +608,15 @@ export declare const SUPPORTED_REGISTRY_FEATURES: readonly string[];
|
|
|
608
608
|
* judge. Served on the same terms: only to a build that lists it, for a company Agentcard turned Frisbii
|
|
609
609
|
* on for.
|
|
610
610
|
*
|
|
611
|
+
* `bigcommerce_card_form`: the payment BigCommerce's own card form (the card fields on
|
|
612
|
+
* payments.bigcommerce.com/pay/hosted_forms/<id>/field, or the store page's own inputs) sends as JSON to
|
|
613
|
+
* https://payments.bigcommerce.com/api/public/v1/orders/payments under the order's payment token, the card
|
|
614
|
+
* in payment.credit_card. This build pauses only a body that carries a new card there (payment-core
|
|
615
|
+
* processors/bigcommerce.js); a card saved at the store, another processor's token and a wallet continue
|
|
616
|
+
* untouched, and a card the store would keep fails in the browser before anything is created. The body
|
|
617
|
+
* names the store's total, which the cardholder approves. Served on the same terms: only to a build that
|
|
618
|
+
* lists it, for a company Agentcard turned BigCommerce on for.
|
|
619
|
+
*
|
|
611
620
|
* `aps_custom_merchant_page`: Amazon Payment Services' custom merchant page, whose own card form
|
|
612
621
|
* posts top-level to /FortAPI/paymentPage on checkout.payfort.com (sbcheckout.payfort.com on APS's
|
|
613
622
|
* sandbox) with service_command=TOKENIZATION. This build pauses that navigation; the cardholder's
|
package/dist/client.js
CHANGED
|
@@ -602,6 +602,15 @@ export const SUPPORTED_REGISTRY_FEATURES = ['card_fields', 'checkout_sessions'];
|
|
|
602
602
|
* judge. Served on the same terms: only to a build that lists it, for a company Agentcard turned Frisbii
|
|
603
603
|
* on for.
|
|
604
604
|
*
|
|
605
|
+
* `bigcommerce_card_form`: the payment BigCommerce's own card form (the card fields on
|
|
606
|
+
* payments.bigcommerce.com/pay/hosted_forms/<id>/field, or the store page's own inputs) sends as JSON to
|
|
607
|
+
* https://payments.bigcommerce.com/api/public/v1/orders/payments under the order's payment token, the card
|
|
608
|
+
* in payment.credit_card. This build pauses only a body that carries a new card there (payment-core
|
|
609
|
+
* processors/bigcommerce.js); a card saved at the store, another processor's token and a wallet continue
|
|
610
|
+
* untouched, and a card the store would keep fails in the browser before anything is created. The body
|
|
611
|
+
* names the store's total, which the cardholder approves. Served on the same terms: only to a build that
|
|
612
|
+
* lists it, for a company Agentcard turned BigCommerce on for.
|
|
613
|
+
*
|
|
605
614
|
* `aps_custom_merchant_page`: Amazon Payment Services' custom merchant page, whose own card form
|
|
606
615
|
* posts top-level to /FortAPI/paymentPage on checkout.payfort.com (sbcheckout.payfort.com on APS's
|
|
607
616
|
* sandbox) with service_command=TOKENIZATION. This build pauses that navigation; the cardholder's
|
|
@@ -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: c4280e1c95d016a93163f49d9d66178a9c4fdfae08e4570952c9c7f533a1c643
|
|
4
4
|
// src/answer-card-leak.js
|
|
5
5
|
var DECIMAL = /\p{Nd}/u;
|
|
6
6
|
function digitValue(char) {
|
|
@@ -20,6 +20,8 @@ function enclosedValue(char) {
|
|
|
20
20
|
var asciiDigits = (text2) => (typeof text2.normalize === "function" ? text2.normalize("NFKC") : text2).replace(ENCLOSED_CHAR, enclosedValue).replace(/\p{Nd}/gu, (char) => char >= "0" && char <= "9" ? char : digitValue(char));
|
|
21
21
|
var digitCount = (text2) => (asciiDigits(String(text2)).match(/\p{N}/gu) ?? []).length;
|
|
22
22
|
var NAME_DIGITS = 3;
|
|
23
|
+
var UTF8_SEQUENCE = "[\\x00-\\x7f]|[\\xc2-\\xdf][\\x80-\\xbf]|\\xe0[\\xa0-\\xbf][\\x80-\\xbf]|[\\xe1-\\xec\\xee\\xef][\\x80-\\xbf]{2}|\\xed[\\x80-\\x9f][\\x80-\\xbf]|\\xf0[\\x90-\\xbf][\\x80-\\xbf]{2}|[\\xf1-\\xf3][\\x80-\\xbf]{3}|\\xf4[\\x80-\\x8f][\\x80-\\xbf]{2}";
|
|
24
|
+
var UTF8_WHOLE = /* @__PURE__ */ new RegExp(`^(?:${UTF8_SEQUENCE})*$`);
|
|
23
25
|
// src/datatrans.js
|
|
24
26
|
var DATATRANS_HOSTS = Object.freeze(["pay.datatrans.com", "pay.sandbox.datatrans.com"]);
|
|
25
27
|
var DATATRANS_TOKENIZE_PATH = "/upp/payment/SecureFields/paymentField";
|
package/dist/index.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ export type { ApiTransport } from './api-module.js';
|
|
|
46
46
|
export { BuyModule, BuyError, isBuyDeclined, BUY_TURN_TIMEOUT_MS } from './buy.js';
|
|
47
47
|
export type { BuyStatus, BuyCart, BuyCartLine, BuyDeliveryAddress, BuyPaymentSource, BuyOutcome, BuyPlacement, BuyCatalog, BuyUnmatched, BuyTurn, BuyDeclined, BuyOrder, BuyLastCheckout, BuyConversation, BuyAskInput, BuyConfirmInput, BuyConversationInput, BuyCheckoutHandoff, BuyOpenOffer, BuyBrowserCheckout, BuyApiAmount, } from './buy.js';
|
|
48
48
|
export { ApprovalsModule, CANCEL_REASONS, SANDBOX_REQUEST } from './approvals.js';
|
|
49
|
-
export type { CreateAuthorizationInput, Authorization, AuthorizationResult, AuthorizationFields, Cancelled, PayingCard, ChoosableCard } from './approvals.js';
|
|
49
|
+
export type { CreateAuthorizationInput, OrderLineItem, OrderShipTo, Authorization, AuthorizationResult, AuthorizationFields, Cancelled, PayingCard, ChoosableCard } from './approvals.js';
|
|
50
50
|
export { verifyWebhook, signWebhook, parseWebhookEvent, parseSignatureHeader, isCheckoutAuthorizationEvent, isVaultEvent, CHECKOUT_AUTHORIZATION_EVENT_TYPES, VAULT_EVENT_TYPES } from './webhooks.js';
|
|
51
51
|
export type { WebhookEvent, AgentcardEvent, CheckoutAuthorizationEvent, CheckoutAuthorizationEventType, CheckoutAuthorizationEventData, VaultEvent, VaultEventType, VaultEventData, OtherEvent, VerifyWebhookOptions } from './webhooks.js';
|
|
52
52
|
export { AgentcardError } from './api-types.js';
|
package/dist/lifecycle.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type { ShijiStsUnsupportedReason } from './shiji-sts.js';
|
|
|
6
6
|
import type { PaddleVgsPayRefusal } from './paddle-vgs-pay.js';
|
|
7
7
|
import type { PaypalCardFormReason } from './paypal-card-forms.js';
|
|
8
8
|
import { type CardRequestHold, type HoldReleaseInput, type HoldReleaseOutcome } from './hold.js';
|
|
9
|
+
import { type StripeApprovedWay } from './stripe-continuation.js';
|
|
9
10
|
/** The application's resolver confirmed the payment for this checkout authorization. */
|
|
10
11
|
export interface MerchantPaymentConfirmation {
|
|
11
12
|
kind: 'merchant_payment';
|
|
@@ -104,11 +105,12 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
104
105
|
private wspayChallenge;
|
|
105
106
|
private heldBeforeHandoff;
|
|
106
107
|
private stripeContinuedReason;
|
|
107
|
-
private
|
|
108
|
+
private approvedWay;
|
|
108
109
|
private ownedShopOrderId;
|
|
109
110
|
private orderRefusal;
|
|
110
111
|
private readonly handoffs;
|
|
111
112
|
private reconciliation;
|
|
113
|
+
private pendingHold;
|
|
112
114
|
/**
|
|
113
115
|
* EBANX sends this attachment claimed that are still out (pre-claim.ts ebanxFollowUp): the cardholder's device may be
|
|
114
116
|
* sending a confirm that pays, outside `active`, so reconcile() and retryAfterMerchantFailure() wait for them too.
|
|
@@ -150,6 +152,15 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
150
152
|
isCancelled(): boolean;
|
|
151
153
|
/** Whether the application gave a merchant resolver, so reconcile() reads the merchant's own record. */
|
|
152
154
|
hasMerchantResolver(): boolean;
|
|
155
|
+
/**
|
|
156
|
+
* Whether the page's byte-identical re-send of the card request this approval answered may get the same answer
|
|
157
|
+
* (token-repeats.ts, pre-claim.ts tokenRepeatPreClaim): the checkout awaits the merchant on a plain token handoff
|
|
158
|
+
* that held nothing, and the only hold since is the merchant resolver reading the order as pending. A hold from
|
|
159
|
+
* anything else stands: an amount the processor charged that differs from the approval's, an unbound Stripe token,
|
|
160
|
+
* a hosted form or card endpoint, an integrator's requireMerchantResult, a follow-up send still out, an unsupported
|
|
161
|
+
* request, a cancel or an aborted request. The gate still asks the resolver before it answers.
|
|
162
|
+
*/
|
|
163
|
+
repeatAnswerable(): boolean;
|
|
153
164
|
/**
|
|
154
165
|
* For a Datatrans re-submit once the approved answer reached the page (pre-claim.ts): whether the
|
|
155
166
|
* application's merchant resolver still reports this approval's order pending. A read only: no
|
|
@@ -258,12 +269,19 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
258
269
|
* VaultClient.withoutCard, which then refuses a Nuvei payment without a card.
|
|
259
270
|
*/
|
|
260
271
|
cardHandoffs(): readonly string[];
|
|
272
|
+
/**
|
|
273
|
+
* The object a Stripe confirmation may pay with in place of the card it sends
|
|
274
|
+
* again (cdp.ts claimStripeContinuation): the one this attachment's approved
|
|
275
|
+
* tokenization returned, with the field that names it, while its continuation
|
|
276
|
+
* is still open. Null for a tokenization no confirmation names by id
|
|
277
|
+
* (`/v1/tokens`), and once the checkout was cancelled, aborted or reconciled.
|
|
278
|
+
*/
|
|
279
|
+
approvedStripeWay(): StripeApprovedWay | null;
|
|
261
280
|
/**
|
|
262
281
|
* The payment method a Stripe card save may pay with in place of the card
|
|
263
|
-
* it sends again
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
* checkout was cancelled, aborted or reconciled.
|
|
282
|
+
* it sends again: the `pm_` an approved `/v1/payment_methods` request
|
|
283
|
+
* returned. Null for every other approved object, since a SetupIntent
|
|
284
|
+
* confirm pays with a payment method alone.
|
|
267
285
|
*/
|
|
268
286
|
approvedStripePaymentMethod(): string | null;
|
|
269
287
|
/**
|
package/dist/lifecycle.js
CHANGED
|
@@ -3,6 +3,7 @@ import { CardEndpointRefusedError } from './card-endpoint.js';
|
|
|
3
3
|
import { parseOwnedShopReceipt, OWNED_SHOP_SKU, OWNED_SHOP_AMOUNT_CENTS, OWNED_SHOP_CURRENCY } from './owned-shop.generated.js';
|
|
4
4
|
import { isWspayChallenge } from './wspay.js';
|
|
5
5
|
import { HoldAnsweredError, HoldEndedError } from './hold.js';
|
|
6
|
+
import { stripeApprovedWay } from './stripe-continuation.js';
|
|
6
7
|
/**
|
|
7
8
|
* The statuses that end an attempt: its outcome is known (`completed`, `declined`, `failed`,
|
|
8
9
|
* `timed_out`, `unsupported`, `cancelled`), or the SDK already reported it unknown with its own
|
|
@@ -25,19 +26,6 @@ export const MAX_STRIPE_CONTINUATION_CHECKS = 3;
|
|
|
25
26
|
* the post becomes a new approval instead of hanging the checkout.
|
|
26
27
|
*/
|
|
27
28
|
export const MERCHANT_ORDER_READ_MS = 5_000;
|
|
28
|
-
const STRIPE_PAYMENT_METHOD_ID = /^pm_[A-Za-z0-9]{1,250}$/;
|
|
29
|
-
/** The `pm_` id in a Stripe `/v1/payment_methods` answer, or null for any other body. */
|
|
30
|
-
function stripePaymentMethodId(body) {
|
|
31
|
-
if (typeof body !== 'string')
|
|
32
|
-
return null;
|
|
33
|
-
try {
|
|
34
|
-
const id = JSON.parse(body)?.id;
|
|
35
|
-
return typeof id === 'string' && STRIPE_PAYMENT_METHOD_ID.test(id) ? id : null;
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
29
|
/** Shared by the raw CDP and Playwright transports. No browser ownership or payment execution lives here. */
|
|
42
30
|
export class CheckoutLifecycle {
|
|
43
31
|
options;
|
|
@@ -62,14 +50,17 @@ export class CheckoutLifecycle {
|
|
|
62
50
|
heldBeforeHandoff = false;
|
|
63
51
|
// What the continuation that went through confirmed: a payment, or a card save.
|
|
64
52
|
stripeContinuedReason = 'stripe_payment_continued';
|
|
65
|
-
// The
|
|
66
|
-
|
|
53
|
+
// The object a Stripe tokenization approval returned, and the field a confirmation
|
|
54
|
+
// names it by: see approvedStripeWay.
|
|
55
|
+
approvedWay = null;
|
|
67
56
|
ownedShopOrderId = null;
|
|
68
57
|
// The reason Nike's order was refused while this attempt was under way (merchantOrderRefused): its handoff keeps it failed.
|
|
69
58
|
orderRefusal = null;
|
|
70
59
|
// Every request this attachment handed the card to: see cardHandoffs().
|
|
71
60
|
handoffs = [];
|
|
72
61
|
reconciliation = null;
|
|
62
|
+
// The hold is only the merchant resolver's `pending` on a handoff nothing else held (resolve): see repeatAnswerable.
|
|
63
|
+
pendingHold = false;
|
|
73
64
|
/**
|
|
74
65
|
* EBANX sends this attachment claimed that are still out (pre-claim.ts ebanxFollowUp): the cardholder's device may be
|
|
75
66
|
* sending a confirm that pays, outside `active`, so reconcile() and retryAfterMerchantFailure() wait for them too.
|
|
@@ -140,6 +131,18 @@ export class CheckoutLifecycle {
|
|
|
140
131
|
isCancelled() { return this.cancelled; }
|
|
141
132
|
/** Whether the application gave a merchant resolver, so reconcile() reads the merchant's own record. */
|
|
142
133
|
hasMerchantResolver() { return typeof this.options.resolveMerchantResult === 'function'; }
|
|
134
|
+
/**
|
|
135
|
+
* Whether the page's byte-identical re-send of the card request this approval answered may get the same answer
|
|
136
|
+
* (token-repeats.ts, pre-claim.ts tokenRepeatPreClaim): the checkout awaits the merchant on a plain token handoff
|
|
137
|
+
* that held nothing, and the only hold since is the merchant resolver reading the order as pending. A hold from
|
|
138
|
+
* anything else stands: an amount the processor charged that differs from the approval's, an unbound Stripe token,
|
|
139
|
+
* a hosted form or card endpoint, an integrator's requireMerchantResult, a follow-up send still out, an unsupported
|
|
140
|
+
* request, a cancel or an aborted request. The gate still asks the resolver before it answers.
|
|
141
|
+
*/
|
|
142
|
+
repeatAnswerable() {
|
|
143
|
+
return this.state.status === 'awaiting_merchant' && !!this.state.authorizationId && !this.active && !this.cancelled
|
|
144
|
+
&& !this.merchantAborted && this.followUpsOut === 0 && (!this.held || this.pendingHold);
|
|
145
|
+
}
|
|
143
146
|
/**
|
|
144
147
|
* For a Datatrans re-submit once the approved answer reached the page (pre-claim.ts): whether the
|
|
145
148
|
* application's merchant resolver still reports this approval's order pending. A read only: no
|
|
@@ -169,6 +172,10 @@ export class CheckoutLifecycle {
|
|
|
169
172
|
}
|
|
170
173
|
end() { this.active = false; }
|
|
171
174
|
set(state) {
|
|
175
|
+
// Any state but awaiting the merchant (a challenge, a failure, a completion) ends the pending read's exception for
|
|
176
|
+
// good: a later pending read that brings awaiting_merchant back holds every card request again (repeatAnswerable).
|
|
177
|
+
if (state.status !== 'awaiting_merchant')
|
|
178
|
+
this.pendingHold = false;
|
|
172
179
|
this.state = state;
|
|
173
180
|
// Application telemetry must never interrupt a paused payment after it reaches the processor.
|
|
174
181
|
try {
|
|
@@ -287,6 +294,7 @@ export class CheckoutLifecycle {
|
|
|
287
294
|
*/
|
|
288
295
|
unsupported(reason = 'unrecognized_payment_endpoint') {
|
|
289
296
|
this.held = true;
|
|
297
|
+
this.pendingHold = false;
|
|
290
298
|
if (this.state.authorizationId)
|
|
291
299
|
return; // do not hide an outstanding/completed payment behind a later unsupported request
|
|
292
300
|
this.set({ ...this.state, status: 'unsupported', reason });
|
|
@@ -348,8 +356,7 @@ export class CheckoutLifecycle {
|
|
|
348
356
|
this.unboundStripeToken = true;
|
|
349
357
|
this.stripeTokenPrepared = true;
|
|
350
358
|
this.held = true;
|
|
351
|
-
|
|
352
|
-
this.approvedPaymentMethod = stripePaymentMethodId(replay.body);
|
|
359
|
+
this.approvedWay = stripeApprovedWay(url.pathname, replay.body);
|
|
353
360
|
}
|
|
354
361
|
}
|
|
355
362
|
catch { /* unknown URL cannot establish a token binding */ }
|
|
@@ -363,15 +370,25 @@ export class CheckoutLifecycle {
|
|
|
363
370
|
* VaultClient.withoutCard, which then refuses a Nuvei payment without a card.
|
|
364
371
|
*/
|
|
365
372
|
cardHandoffs() { return [...this.handoffs]; }
|
|
373
|
+
/**
|
|
374
|
+
* The object a Stripe confirmation may pay with in place of the card it sends
|
|
375
|
+
* again (cdp.ts claimStripeContinuation): the one this attachment's approved
|
|
376
|
+
* tokenization returned, with the field that names it, while its continuation
|
|
377
|
+
* is still open. Null for a tokenization no confirmation names by id
|
|
378
|
+
* (`/v1/tokens`), and once the checkout was cancelled, aborted or reconciled.
|
|
379
|
+
*/
|
|
380
|
+
approvedStripeWay() {
|
|
381
|
+
return this.stripeContinuationOpen() ? this.approvedWay : null;
|
|
382
|
+
}
|
|
366
383
|
/**
|
|
367
384
|
* The payment method a Stripe card save may pay with in place of the card
|
|
368
|
-
* it sends again
|
|
369
|
-
*
|
|
370
|
-
*
|
|
371
|
-
* checkout was cancelled, aborted or reconciled.
|
|
385
|
+
* it sends again: the `pm_` an approved `/v1/payment_methods` request
|
|
386
|
+
* returned. Null for every other approved object, since a SetupIntent
|
|
387
|
+
* confirm pays with a payment method alone.
|
|
372
388
|
*/
|
|
373
389
|
approvedStripePaymentMethod() {
|
|
374
|
-
|
|
390
|
+
const way = this.approvedStripeWay();
|
|
391
|
+
return way?.field === 'payment_method' ? way.id : null;
|
|
375
392
|
}
|
|
376
393
|
/**
|
|
377
394
|
* The approval a page's card-free Stripe confirmation may continue, or null.
|
|
@@ -416,6 +433,7 @@ export class CheckoutLifecycle {
|
|
|
416
433
|
if (this.merchantAborted)
|
|
417
434
|
return;
|
|
418
435
|
this.settled = true;
|
|
436
|
+
this.pendingHold = false;
|
|
419
437
|
if (this.orderRefusal) {
|
|
420
438
|
// Nike's order was refused while this approval was on its way: the answer lands, and the checkout stays failed.
|
|
421
439
|
this.held = true;
|
|
@@ -591,6 +609,10 @@ export class CheckoutLifecycle {
|
|
|
591
609
|
await this.requestUserAction(result.reason);
|
|
592
610
|
}
|
|
593
611
|
else {
|
|
612
|
+
// A pending order on a handoff nothing held still lets the page's identical re-send of the same card request have
|
|
613
|
+
// its answer again (repeatAnswerable); every other card request stays refused.
|
|
614
|
+
if (!this.held && result.status === 'pending' && this.state.status === 'awaiting_merchant')
|
|
615
|
+
this.pendingHold = true;
|
|
594
616
|
this.held = true;
|
|
595
617
|
this.set({ ...this.state, status: result.status === 'pending' ? 'awaiting_merchant' : 'outcome_unknown', reason: 'merchant_not_confirmed' });
|
|
596
618
|
}
|
|
@@ -612,6 +634,7 @@ export class CheckoutLifecycle {
|
|
|
612
634
|
if (this.unboundStripeToken)
|
|
613
635
|
throw new Error('This attachment delivered an unbound Stripe token; reconcile the merchant order and use a separately validated checkout flow.');
|
|
614
636
|
this.held = false;
|
|
637
|
+
this.pendingHold = false;
|
|
615
638
|
this.merchantAborted = false;
|
|
616
639
|
this.orderRefusal = null;
|
|
617
640
|
this.set({ status: 'idle', authorizationId: null });
|
|
@@ -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: e2228c7919341a7b3615b285c3aa77948c247c13145a1e394a1bb1c64acbca06
|
|
4
4
|
// src/json-path.js
|
|
5
5
|
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
6
6
|
function isPlainObject(v) {
|
|
@@ -318,17 +318,39 @@ function enclosedValue(char) {
|
|
|
318
318
|
}
|
|
319
319
|
var asciiDigits = (text) => (typeof text.normalize === "function" ? text.normalize("NFKC") : text).replace(ENCLOSED_CHAR, enclosedValue).replace(/\p{Nd}/gu, (char) => char >= "0" && char <= "9" ? char : digitValue(char));
|
|
320
320
|
var unescaped = (text) => text.replace(/\\u([0-9a-fA-F]{4})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)));
|
|
321
|
+
var UTF8_SEQUENCE = "[\\x00-\\x7f]|[\\xc2-\\xdf][\\x80-\\xbf]|\\xe0[\\xa0-\\xbf][\\x80-\\xbf]|[\\xe1-\\xec\\xee\\xef][\\x80-\\xbf]{2}|\\xed[\\x80-\\x9f][\\x80-\\xbf]|\\xf0[\\x90-\\xbf][\\x80-\\xbf]{2}|[\\xf1-\\xf3][\\x80-\\xbf]{3}|\\xf4[\\x80-\\x8f][\\x80-\\xbf]{2}";
|
|
322
|
+
var UTF8_WHOLE = /* @__PURE__ */ new RegExp(`^(?:${UTF8_SEQUENCE})*$`);
|
|
323
|
+
var UTF8_ONE = /* @__PURE__ */ new RegExp(UTF8_SEQUENCE, "g");
|
|
324
|
+
function utf8Of(bytes) {
|
|
325
|
+
if (!/[\x80-\xff]/.test(bytes) || !UTF8_WHOLE.test(bytes))
|
|
326
|
+
return null;
|
|
327
|
+
return bytes.replace(UTF8_ONE, (sequence) => {
|
|
328
|
+
if (sequence.length === 1)
|
|
329
|
+
return sequence;
|
|
330
|
+
const lead = sequence.charCodeAt(0);
|
|
331
|
+
let point = lead & (sequence.length === 2 ? 31 : sequence.length === 3 ? 15 : 7);
|
|
332
|
+
for (let i = 1; i < sequence.length; i += 1)
|
|
333
|
+
point = point << 6 | sequence.charCodeAt(i) & 63;
|
|
334
|
+
return String.fromCodePoint(point);
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
var utf8Runs = (text) => text.replace(/[\x80-\xff]+/g, (run) => utf8Of(run) ?? run);
|
|
321
338
|
var decodedInPlace = (text) => text.replace(BASE64_PIECE, (piece) => {
|
|
322
339
|
const bare = piece.replace(/=+$/, "");
|
|
323
340
|
for (let skip = 0; skip < 4 && skip < bare.length - 1; skip += 1) {
|
|
324
341
|
const bytes = base64Text(bare.slice(skip));
|
|
325
342
|
if (/^[\x20-\x7e]+$/.test(bytes))
|
|
326
343
|
return bare.slice(0, skip) + bytes;
|
|
344
|
+
const utf82 = utf8Of(bytes);
|
|
345
|
+
if (utf82 !== null && !/\p{C}/u.test(utf82))
|
|
346
|
+
return bare.slice(0, skip) + utf82;
|
|
327
347
|
}
|
|
328
348
|
return piece;
|
|
329
349
|
});
|
|
330
350
|
function collect(text, layers, streams, runs) {
|
|
331
351
|
const base = /* @__PURE__ */ new Set([...readings(text), ...readings(unescaped(text))]);
|
|
352
|
+
for (const reading of [...base])
|
|
353
|
+
base.add(utf8Runs(reading));
|
|
332
354
|
for (const reading of /* @__PURE__ */ new Set([...base, ...[...base].map(decodedInPlace)])) {
|
|
333
355
|
const digits = asciiDigits(reading);
|
|
334
356
|
const sequence = digits.match(/[0-9]+/g) ?? [];
|
|
@@ -341,8 +363,13 @@ function collect(text, layers, streams, runs) {
|
|
|
341
363
|
if (layers === 0)
|
|
342
364
|
continue;
|
|
343
365
|
for (const run of new Set(reading.match(BASE64_RUN))) {
|
|
344
|
-
for (let skip = 0; skip < 4; skip += 1)
|
|
345
|
-
|
|
366
|
+
for (let skip = 0; skip < 4; skip += 1) {
|
|
367
|
+
const bytes = base64Text(run.slice(skip));
|
|
368
|
+
collect(bytes, layers - 1, streams, runs);
|
|
369
|
+
const utf82 = utf8Of(bytes);
|
|
370
|
+
if (utf82 !== null)
|
|
371
|
+
collect(utf82, layers - 1, streams, runs);
|
|
372
|
+
}
|
|
346
373
|
}
|
|
347
374
|
}
|
|
348
375
|
}
|
|
@@ -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: d5e732dd0bce3debee02e3f31107e65059e0d3888b54a605357a5817bb8909ce
|
|
4
4
|
// src/json-path.js
|
|
5
5
|
function roundTrips(parsed, body) {
|
|
6
6
|
try {
|
|
@@ -29,6 +29,8 @@ function enclosedValue(char) {
|
|
|
29
29
|
var asciiDigits = (text) => (typeof text.normalize === "function" ? text.normalize("NFKC") : text).replace(ENCLOSED_CHAR, enclosedValue).replace(/\p{Nd}/gu, (char) => char >= "0" && char <= "9" ? char : digitValue(char));
|
|
30
30
|
var digitCount = (text) => (asciiDigits(String(text)).match(/\p{N}/gu) ?? []).length;
|
|
31
31
|
var NAME_DIGITS = 3;
|
|
32
|
+
var UTF8_SEQUENCE = "[\\x00-\\x7f]|[\\xc2-\\xdf][\\x80-\\xbf]|\\xe0[\\xa0-\\xbf][\\x80-\\xbf]|[\\xe1-\\xec\\xee\\xef][\\x80-\\xbf]{2}|\\xed[\\x80-\\x9f][\\x80-\\xbf]|\\xf0[\\x90-\\xbf][\\x80-\\xbf]{2}|[\\xf1-\\xf3][\\x80-\\xbf]{3}|\\xf4[\\x80-\\x8f][\\x80-\\xbf]{2}";
|
|
33
|
+
var UTF8_WHOLE = /* @__PURE__ */ new RegExp(`^(?:${UTF8_SEQUENCE})*$`);
|
|
32
34
|
// src/sha256.js
|
|
33
35
|
var K = /* @__PURE__ */ new Uint32Array([
|
|
34
36
|
1116352408,
|
package/dist/pre-claim.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { type CardEndpointProfile } from './card-endpoint.js';
|
|
|
15
15
|
import { type NikeOrders } from './nike-order.js';
|
|
16
16
|
import { type PayrailsSessionCapture, type PayrailsSidecar } from './payrails.js';
|
|
17
17
|
import { type VerifoneProfile } from './verifone.js';
|
|
18
|
+
import type { TokenRepeats } from './token-repeats.js';
|
|
18
19
|
import { type WorldlineMyCheckoutProducts } from './worldline-mycheckout.js';
|
|
19
20
|
import { type PaddleVgsPayGate } from './paddle-vgs-pay.js';
|
|
20
21
|
import { type EbanxFollowUps } from './ebanx.js';
|
|
@@ -210,6 +211,8 @@ export interface PreClaimContext {
|
|
|
210
211
|
datatrans?: DatatransRepeats;
|
|
211
212
|
/** The attachment's approved TokenEx iframe answers (the repeat rule, tokenex-iframe.ts). Absent: none are kept. */
|
|
212
213
|
tokenexIframe?: TokenexIframeRepeats;
|
|
214
|
+
/** The attachment's last approved plain token answer, for the page's identical re-send (token-repeats.ts). Absent: none is kept. */
|
|
215
|
+
tokenRepeats?: TokenRepeats;
|
|
213
216
|
/** The adapter's identity for the request's frame (CDP frameId, Playwright Frame); undefined when unknown. */
|
|
214
217
|
frame?: unknown;
|
|
215
218
|
/**
|
package/dist/pre-claim.js
CHANGED
|
@@ -1002,6 +1002,50 @@ const tokenexIframePreClaim = (ctx) => {
|
|
|
1002
1002
|
return ctx.lifecycle.getState().status === 'awaiting_merchant'
|
|
1003
1003
|
? repeatAfterHandoff(ctx, repeat, TOKENEX_IFRAME_PSP) : answerRepeat(ctx, repeat, TOKENEX_IFRAME_PSP);
|
|
1004
1004
|
};
|
|
1005
|
+
// Any processor's plain token request, sent again by the page byte for byte after its approved answer reached it
|
|
1006
|
+
// (token-repeats.ts). Last among the gates, so a processor with its own repeat rule (Datatrans, the TokenEx iframe) or
|
|
1007
|
+
// its own hold (Stripe, a card endpoint) decides first. While the lifecycle reads the re-send as answerable
|
|
1008
|
+
// (repeatAnswerable: the same approval awaits the merchant, and nothing but a pending read holds it), the gate asks the
|
|
1009
|
+
// merchant resolver and answers with the stored token only while the order still reads pending, as repeatAfterHandoff
|
|
1010
|
+
// does. Every other card request, another amount or approval among them, defers to the terminal arbiter and the
|
|
1011
|
+
// adapters' hold, as before.
|
|
1012
|
+
const tokenRepeatPreClaim = (ctx) => {
|
|
1013
|
+
const { url, method } = ctx.request;
|
|
1014
|
+
if (!ctx.tokenRepeats || method.toUpperCase() !== 'POST' || !ctx.lifecycle.repeatAnswerable?.() || !ctx.lifecycle.hasMerchantResolver?.())
|
|
1015
|
+
return undefined;
|
|
1016
|
+
// A processor with its own repeat rule keeps its own limits: a re-send its rule declined is a new question.
|
|
1017
|
+
if (isDatatransHost(url) || isTokenexIframePath(url))
|
|
1018
|
+
return undefined;
|
|
1019
|
+
if (ctx.terminal() || ctx.interceptionAborted() || ctx.lifecycleAborted())
|
|
1020
|
+
return undefined;
|
|
1021
|
+
// Read only here, past every cheaper check: a body the adapter cannot read is no re-send of an answered one.
|
|
1022
|
+
let body;
|
|
1023
|
+
try {
|
|
1024
|
+
body = ctx.request.body;
|
|
1025
|
+
}
|
|
1026
|
+
catch {
|
|
1027
|
+
return undefined;
|
|
1028
|
+
}
|
|
1029
|
+
const repeats = ctx.tokenRepeats;
|
|
1030
|
+
const repeat = repeats.answerFor(ctx.frame, url, body, ctx.lifecycle.getState().authorizationId);
|
|
1031
|
+
if (!repeat)
|
|
1032
|
+
return undefined;
|
|
1033
|
+
// A re-send the page never got an answer for gives its place in the count back.
|
|
1034
|
+
return tokenRepeatWhilePending(ctx, repeat).then((decision) => {
|
|
1035
|
+
if (decision?.kind !== 'answer')
|
|
1036
|
+
repeats.released(repeat.authorizationId);
|
|
1037
|
+
return decision;
|
|
1038
|
+
}, (error) => { repeats.released(repeat.authorizationId); throw error; });
|
|
1039
|
+
};
|
|
1040
|
+
async function tokenRepeatWhilePending(ctx, repeat) {
|
|
1041
|
+
if (!await ctx.lifecycle.merchantOrderPending())
|
|
1042
|
+
return undefined;
|
|
1043
|
+
// The resolver answered asynchronously: the same approval must still be the one awaiting the merchant.
|
|
1044
|
+
if (!ctx.lifecycle.repeatAnswerable() || ctx.lifecycle.getState().authorizationId !== repeat.authorizationId
|
|
1045
|
+
|| ctx.terminal() || ctx.interceptionAborted() || ctx.lifecycleAborted())
|
|
1046
|
+
return undefined;
|
|
1047
|
+
return answerRepeat(ctx, repeat, 'token');
|
|
1048
|
+
}
|
|
1005
1049
|
async function tokenexIframeBlock(ctx, reason) {
|
|
1006
1050
|
ctx.onEvent?.({ type: 'blocked', detail: reason });
|
|
1007
1051
|
await ctx.effects.abort();
|
|
@@ -2623,7 +2667,7 @@ async function unsupportedContinue(ctx) {
|
|
|
2623
2667
|
* pauses each one itself. */
|
|
2624
2668
|
export const PSP_PRE_CLAIM_GATES = [cardEndpointResendPreClaim, cardEndpointPreClaim, nikeOrderPreClaim, mercadoPreClaim, juspayPreClaim, braintreePreClaim, stripePreClaim, merchantHostedPreClaim, verifonePreClaim, fiservPreClaim, gmoPreClaim, cybersourceFlexPreClaim, datatransPreClaim, tokenexIframePreClaim, pelecardPreClaim, aciPreClaim, creditguardPreClaim, primerPreClaim, payrailsPreClaim, convergePreClaim, eprotectPreClaim, sbpsPreClaim, wspayPreClaim, shijiStsPreClaim, ekashuPreClaim, redsysPreClaim, quickpayPreClaim, comgatePreClaim, przelewy24PreClaim, transbankPreClaim, eximbayPreClaim, barionPreClaim, payplugPreClaim, cardlinkVposPreClaim, eghlPreClaim, paypalHostedFieldsPreClaim,
|
|
2625
2669
|
paypalCardFormsPreClaim, cybersourceSecureAcceptancePreClaim, worldlineMyCheckoutPreClaim, paddleVgsPayPreClaim, ebanxPreClaim, payrexxPreClaim, hipayPreClaim, paytrailPreClaim,
|
|
2626
|
-
oceanpaymentPreClaim, aurusPreClaim];
|
|
2670
|
+
oceanpaymentPreClaim, aurusPreClaim, tokenRepeatPreClaim];
|
|
2627
2671
|
/** Run each gate in order; the first to return a decision wins. If none does,
|
|
2628
2672
|
* the terminal arbiter decides between continue, abort (unsupported) and pause.
|
|
2629
2673
|
* Returns synchronously while every gate defers synchronously (an ordinary card
|
|
@@ -3522,6 +3522,31 @@
|
|
|
3522
3522
|
"hostname_pattern": "^payment\\.pay1\\.checkout\\.worldline-solutions\\.com$",
|
|
3523
3523
|
"pathname_pattern": "^\\/checkout$"
|
|
3524
3524
|
},
|
|
3525
|
+
{
|
|
3526
|
+
"id": "bigcommerce-hosted-card-field",
|
|
3527
|
+
"psp": "bigcommerce",
|
|
3528
|
+
"kinds": [
|
|
3529
|
+
"document",
|
|
3530
|
+
"frame",
|
|
3531
|
+
"iframe"
|
|
3532
|
+
],
|
|
3533
|
+
"origin": "https://payments.bigcommerce.com",
|
|
3534
|
+
"path_pattern": "/pay/hosted_forms/:form/field",
|
|
3535
|
+
"sources": [
|
|
3536
|
+
{
|
|
3537
|
+
"kind": "saved_observation",
|
|
3538
|
+
"reference": "drsturm-2026-11-06:bigcommerce-hosted-form-field-1.997.1",
|
|
3539
|
+
"reviewed_on": "2026-11-06"
|
|
3540
|
+
},
|
|
3541
|
+
{
|
|
3542
|
+
"kind": "primary_source",
|
|
3543
|
+
"reference": "https://checkout-sdk.bigcommerce.com/v1/loader-v1.997.1.js",
|
|
3544
|
+
"reviewed_on": "2026-11-06"
|
|
3545
|
+
}
|
|
3546
|
+
],
|
|
3547
|
+
"hostname_pattern": "^payments\\.bigcommerce\\.com$",
|
|
3548
|
+
"pathname_pattern": "^\\/pay\\/hosted_forms\\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\/field$"
|
|
3549
|
+
},
|
|
3525
3550
|
{
|
|
3526
3551
|
"id": "gmo-mp-token-script-test",
|
|
3527
3552
|
"psp": "gmo_pg",
|
|
@@ -525,6 +525,7 @@
|
|
|
525
525
|
"amadeus-data-collection-page",
|
|
526
526
|
"worldline-mycheckout-page",
|
|
527
527
|
"worldline-mycheckout-card-form",
|
|
528
|
+
"bigcommerce-hosted-card-field",
|
|
528
529
|
"gmo-mp-token-script-test",
|
|
529
530
|
"gmo-token-v1-script-test",
|
|
530
531
|
"gmo-elements-card-frame-test",
|
|
@@ -1170,6 +1171,7 @@
|
|
|
1170
1171
|
"amadeus-data-collection-page",
|
|
1171
1172
|
"worldline-mycheckout-page",
|
|
1172
1173
|
"worldline-mycheckout-card-form",
|
|
1174
|
+
"bigcommerce-hosted-card-field",
|
|
1173
1175
|
"gmo-mp-token-script-test",
|
|
1174
1176
|
"gmo-token-v1-script-test",
|
|
1175
1177
|
"gmo-elements-card-frame-test",
|