@agent-cards/sdk 0.24.1 → 0.24.2
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/capabilities.generated.js +1 -1
- package/dist/card-fields.generated.js +354 -263
- package/dist/cdp.js +9 -0
- package/dist/client.d.ts +9 -0
- package/dist/client.js +9 -0
- package/dist/lifecycle.d.ts +10 -0
- package/dist/lifecycle.js +25 -0
- 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 +364 -273
- package/dist/stripe-checkout.generated.js +333 -242
- 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';
|
|
@@ -2084,6 +2085,8 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
2084
2085
|
// The approved TokenEx iframe answers, per frameId (the card-number frame is an out-of-process iframe whose own
|
|
2085
2086
|
// session pauses its post; its frameId names it): the repeat rule (tokenex-iframe.ts).
|
|
2086
2087
|
const tokenexIframeRepeats = new TokenexIframeRepeats();
|
|
2088
|
+
// The last approved plain token answer, for the page's identical re-send (token-repeats.ts).
|
|
2089
|
+
const tokenRepeats = new TokenRepeats();
|
|
2087
2090
|
// The card product each Worldline MyCheckout hosted checkout chose (worldline-mycheckout.ts).
|
|
2088
2091
|
const worldlineProducts = new WorldlineMyCheckoutProducts();
|
|
2089
2092
|
// The Shiji STS getCvvId companion of the getTokenId this attachment last continued (shiji-sts.ts).
|
|
@@ -2905,6 +2908,7 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
2905
2908
|
juspay: juspayCheckout,
|
|
2906
2909
|
datatrans: datatransRepeats,
|
|
2907
2910
|
tokenexIframe: tokenexIframeRepeats,
|
|
2911
|
+
tokenRepeats,
|
|
2908
2912
|
ebanx: ebanxFollowUps,
|
|
2909
2913
|
payrexx: payrexxFollowUps,
|
|
2910
2914
|
nikeOrders,
|
|
@@ -3446,6 +3450,7 @@ export async function attachToCdp(cdp, pageSessionId, opts) {
|
|
|
3446
3450
|
// The frame that received it: the paused request's, or its retry's once rebound.
|
|
3447
3451
|
datatransRepeats.remember(activeRequest?.frameId || undefined, deliverRequest.url, deliverBody, replay);
|
|
3448
3452
|
tokenexIframeRepeats.remember(activeRequest?.frameId || undefined, deliverRequest.url, deliverBody, replay);
|
|
3453
|
+
tokenRepeats.remember(activeRequest?.frameId || undefined, deliverRequest.url, deliverBody, replay);
|
|
3449
3454
|
attempt.assertLive();
|
|
3450
3455
|
// An ACI card-number request answered: its checkout's held CVC and expiry requests get the
|
|
3451
3456
|
// same answer, and its /payment submission may continue (see AciGate).
|
|
@@ -3982,6 +3987,8 @@ export async function attachToPlaywright(page, opts) {
|
|
|
3982
3987
|
const datatransRepeats = new DatatransRepeats();
|
|
3983
3988
|
// The approved TokenEx iframe answers, per Frame: the repeat rule (tokenex-iframe.ts).
|
|
3984
3989
|
const tokenexIframeRepeats = new TokenexIframeRepeats();
|
|
3990
|
+
// The last approved plain token answer, for the page's identical re-send (token-repeats.ts).
|
|
3991
|
+
const tokenRepeats = new TokenRepeats();
|
|
3985
3992
|
// The card product each Worldline MyCheckout hosted checkout chose (worldline-mycheckout.ts).
|
|
3986
3993
|
const worldlineProducts = new WorldlineMyCheckoutProducts();
|
|
3987
3994
|
const frameOf = (request) => { try {
|
|
@@ -4180,6 +4187,7 @@ export async function attachToPlaywright(page, opts) {
|
|
|
4180
4187
|
juspay: juspayCheckout,
|
|
4181
4188
|
datatrans: datatransRepeats,
|
|
4182
4189
|
tokenexIframe: tokenexIframeRepeats,
|
|
4190
|
+
tokenRepeats,
|
|
4183
4191
|
ebanx: ebanxFollowUps,
|
|
4184
4192
|
payrexx: payrexxFollowUps,
|
|
4185
4193
|
nikeOrders,
|
|
@@ -4586,6 +4594,7 @@ export async function attachToPlaywright(page, opts) {
|
|
|
4586
4594
|
await deliverTo.fulfill({ status: replay.status, headers: withCorsHeaders(replay.headers, cors.headers), body: replay.body });
|
|
4587
4595
|
datatransRepeats.remember(frameOf(deliverRequest), deliverRequest.url(), deliverBody, replay);
|
|
4588
4596
|
tokenexIframeRepeats.remember(frameOf(deliverRequest), deliverRequest.url(), deliverBody, replay);
|
|
4597
|
+
tokenRepeats.remember(frameOf(deliverRequest), deliverRequest.url(), deliverBody, replay);
|
|
4589
4598
|
assertRequestLive();
|
|
4590
4599
|
// See the same step in attachToCdp.
|
|
4591
4600
|
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
|
package/dist/lifecycle.d.ts
CHANGED
|
@@ -109,6 +109,7 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
109
109
|
private orderRefusal;
|
|
110
110
|
private readonly handoffs;
|
|
111
111
|
private reconciliation;
|
|
112
|
+
private pendingHold;
|
|
112
113
|
/**
|
|
113
114
|
* EBANX sends this attachment claimed that are still out (pre-claim.ts ebanxFollowUp): the cardholder's device may be
|
|
114
115
|
* sending a confirm that pays, outside `active`, so reconcile() and retryAfterMerchantFailure() wait for them too.
|
|
@@ -150,6 +151,15 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
150
151
|
isCancelled(): boolean;
|
|
151
152
|
/** Whether the application gave a merchant resolver, so reconcile() reads the merchant's own record. */
|
|
152
153
|
hasMerchantResolver(): boolean;
|
|
154
|
+
/**
|
|
155
|
+
* Whether the page's byte-identical re-send of the card request this approval answered may get the same answer
|
|
156
|
+
* (token-repeats.ts, pre-claim.ts tokenRepeatPreClaim): the checkout awaits the merchant on a plain token handoff
|
|
157
|
+
* that held nothing, and the only hold since is the merchant resolver reading the order as pending. A hold from
|
|
158
|
+
* anything else stands: an amount the processor charged that differs from the approval's, an unbound Stripe token,
|
|
159
|
+
* a hosted form or card endpoint, an integrator's requireMerchantResult, a follow-up send still out, an unsupported
|
|
160
|
+
* request, a cancel or an aborted request. The gate still asks the resolver before it answers.
|
|
161
|
+
*/
|
|
162
|
+
repeatAnswerable(): boolean;
|
|
153
163
|
/**
|
|
154
164
|
* For a Datatrans re-submit once the approved answer reached the page (pre-claim.ts): whether the
|
|
155
165
|
* application's merchant resolver still reports this approval's order pending. A read only: no
|
package/dist/lifecycle.js
CHANGED
|
@@ -70,6 +70,8 @@ export class CheckoutLifecycle {
|
|
|
70
70
|
// Every request this attachment handed the card to: see cardHandoffs().
|
|
71
71
|
handoffs = [];
|
|
72
72
|
reconciliation = null;
|
|
73
|
+
// The hold is only the merchant resolver's `pending` on a handoff nothing else held (resolve): see repeatAnswerable.
|
|
74
|
+
pendingHold = false;
|
|
73
75
|
/**
|
|
74
76
|
* EBANX sends this attachment claimed that are still out (pre-claim.ts ebanxFollowUp): the cardholder's device may be
|
|
75
77
|
* sending a confirm that pays, outside `active`, so reconcile() and retryAfterMerchantFailure() wait for them too.
|
|
@@ -140,6 +142,18 @@ export class CheckoutLifecycle {
|
|
|
140
142
|
isCancelled() { return this.cancelled; }
|
|
141
143
|
/** Whether the application gave a merchant resolver, so reconcile() reads the merchant's own record. */
|
|
142
144
|
hasMerchantResolver() { return typeof this.options.resolveMerchantResult === 'function'; }
|
|
145
|
+
/**
|
|
146
|
+
* Whether the page's byte-identical re-send of the card request this approval answered may get the same answer
|
|
147
|
+
* (token-repeats.ts, pre-claim.ts tokenRepeatPreClaim): the checkout awaits the merchant on a plain token handoff
|
|
148
|
+
* that held nothing, and the only hold since is the merchant resolver reading the order as pending. A hold from
|
|
149
|
+
* anything else stands: an amount the processor charged that differs from the approval's, an unbound Stripe token,
|
|
150
|
+
* a hosted form or card endpoint, an integrator's requireMerchantResult, a follow-up send still out, an unsupported
|
|
151
|
+
* request, a cancel or an aborted request. The gate still asks the resolver before it answers.
|
|
152
|
+
*/
|
|
153
|
+
repeatAnswerable() {
|
|
154
|
+
return this.state.status === 'awaiting_merchant' && !!this.state.authorizationId && !this.active && !this.cancelled
|
|
155
|
+
&& !this.merchantAborted && this.followUpsOut === 0 && (!this.held || this.pendingHold);
|
|
156
|
+
}
|
|
143
157
|
/**
|
|
144
158
|
* For a Datatrans re-submit once the approved answer reached the page (pre-claim.ts): whether the
|
|
145
159
|
* application's merchant resolver still reports this approval's order pending. A read only: no
|
|
@@ -169,6 +183,10 @@ export class CheckoutLifecycle {
|
|
|
169
183
|
}
|
|
170
184
|
end() { this.active = false; }
|
|
171
185
|
set(state) {
|
|
186
|
+
// Any state but awaiting the merchant (a challenge, a failure, a completion) ends the pending read's exception for
|
|
187
|
+
// good: a later pending read that brings awaiting_merchant back holds every card request again (repeatAnswerable).
|
|
188
|
+
if (state.status !== 'awaiting_merchant')
|
|
189
|
+
this.pendingHold = false;
|
|
172
190
|
this.state = state;
|
|
173
191
|
// Application telemetry must never interrupt a paused payment after it reaches the processor.
|
|
174
192
|
try {
|
|
@@ -287,6 +305,7 @@ export class CheckoutLifecycle {
|
|
|
287
305
|
*/
|
|
288
306
|
unsupported(reason = 'unrecognized_payment_endpoint') {
|
|
289
307
|
this.held = true;
|
|
308
|
+
this.pendingHold = false;
|
|
290
309
|
if (this.state.authorizationId)
|
|
291
310
|
return; // do not hide an outstanding/completed payment behind a later unsupported request
|
|
292
311
|
this.set({ ...this.state, status: 'unsupported', reason });
|
|
@@ -416,6 +435,7 @@ export class CheckoutLifecycle {
|
|
|
416
435
|
if (this.merchantAborted)
|
|
417
436
|
return;
|
|
418
437
|
this.settled = true;
|
|
438
|
+
this.pendingHold = false;
|
|
419
439
|
if (this.orderRefusal) {
|
|
420
440
|
// Nike's order was refused while this approval was on its way: the answer lands, and the checkout stays failed.
|
|
421
441
|
this.held = true;
|
|
@@ -591,6 +611,10 @@ export class CheckoutLifecycle {
|
|
|
591
611
|
await this.requestUserAction(result.reason);
|
|
592
612
|
}
|
|
593
613
|
else {
|
|
614
|
+
// A pending order on a handoff nothing held still lets the page's identical re-send of the same card request have
|
|
615
|
+
// its answer again (repeatAnswerable); every other card request stays refused.
|
|
616
|
+
if (!this.held && result.status === 'pending' && this.state.status === 'awaiting_merchant')
|
|
617
|
+
this.pendingHold = true;
|
|
594
618
|
this.held = true;
|
|
595
619
|
this.set({ ...this.state, status: result.status === 'pending' ? 'awaiting_merchant' : 'outcome_unknown', reason: 'merchant_not_confirmed' });
|
|
596
620
|
}
|
|
@@ -612,6 +636,7 @@ export class CheckoutLifecycle {
|
|
|
612
636
|
if (this.unboundStripeToken)
|
|
613
637
|
throw new Error('This attachment delivered an unbound Stripe token; reconcile the merchant order and use a separately validated checkout flow.');
|
|
614
638
|
this.held = false;
|
|
639
|
+
this.pendingHold = false;
|
|
615
640
|
this.merchantAborted = false;
|
|
616
641
|
this.orderRefusal = null;
|
|
617
642
|
this.set({ status: 'idle', authorizationId: null });
|
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",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Generated from @agent-cards/payment-core. Do not edit.
|
|
2
|
-
// source-sha256:
|
|
2
|
+
// source-sha256: 84246b0b75dadb1798e0c9bd4ab7a8ab8567df86ea490fb20c9f0f890309e7df
|
|
3
3
|
import { CHECKOUT_PREFLIGHT_CAPABILITIES } from './preflight-capabilities.generated.js';
|
|
4
4
|
/** Advisory page discovery. These rules never admit a payment destination. */
|
|
5
5
|
export const CHECKOUT_PREFLIGHT_VERSION = '1';
|
|
@@ -371,6 +371,15 @@ RULES.push({ id: 'worldline-mycheckout-page', psp: 'worldline_mycheckout', kinds
|
|
|
371
371
|
pathname: /^\/checkout\/(?:payment-product-details\/)?[1-9][0-9]{0,9}-[0-9a-f]{32}:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}:[0-9a-f]{32}$/,
|
|
372
372
|
origin: 'https://payment.pay1.checkout.worldline-solutions.com', path_pattern: '/checkout/{payment-product-details/}:hosted_checkout', sources: worldlineSources }, { id: 'worldline-mycheckout-card-form', psp: 'worldline_mycheckout', kinds: ['form'], hostname: /^payment\.pay1\.checkout\.worldline-solutions\.com$/, pathname: /^\/checkout$/,
|
|
373
373
|
origin: 'https://payment.pay1.checkout.worldline-solutions.com', path_pattern: '/checkout', sources: worldlineSources });
|
|
374
|
+
// BigCommerce's own card form, read 2026-11-06 at drsturm.com: the store's /checkout/payment/hosted-field iframes
|
|
375
|
+
// redirect to one field document per card input on payments.bigcommerce.com, which loads checkout-sdk's hosted-form
|
|
376
|
+
// module and sends the card to BigCommerce's payments API (processors/bigcommerce.js), whichever gateway charges it.
|
|
377
|
+
// BigCommerce ships dark, so the field names bigcommerce and the result stays unknown, as GMO's does.
|
|
378
|
+
RULES.push({ id: 'bigcommerce-hosted-card-field', psp: 'bigcommerce', kinds: ['document', 'frame', 'iframe'], hostname: /^payments\.bigcommerce\.com$/,
|
|
379
|
+
pathname: /^\/pay\/hosted_forms\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/field$/, origin: 'https://payments.bigcommerce.com',
|
|
380
|
+
path_pattern: '/pay/hosted_forms/:form/field',
|
|
381
|
+
sources: [{ kind: 'saved_observation', reference: 'drsturm-2026-11-06:bigcommerce-hosted-form-field-1.997.1', reviewed_on: '2026-11-06' },
|
|
382
|
+
{ kind: 'primary_source', reference: 'https://checkout-sdk.bigcommerce.com/v1/loader-v1.997.1.js', reviewed_on: '2026-11-06' }] });
|
|
374
383
|
// A processor that ships dark (its definition declares a capability) is left out of the bundled
|
|
375
384
|
// catalog. Datatrans's and the TokenEx iframe's discovery rules wait with it: they join RULES only once KNOWN_PSPS, the
|
|
376
385
|
// bundled catalog's processors, lists its psp. Until then its assets are not evidence, so a page
|