@agent-cards/sdk 0.21.0 → 0.22.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 +47 -0
- package/PREFLIGHT.md +30 -0
- package/README.md +1070 -21
- package/dist/aci.d.ts +173 -0
- package/dist/aci.generated.d.ts +87 -0
- package/dist/aci.generated.js +306 -0
- package/dist/aci.js +371 -0
- package/dist/adyen-merchant-hosted.generated.d.ts +3 -3
- package/dist/adyen-merchant-hosted.generated.js +283 -49
- package/dist/agentcard.d.ts +9 -2
- package/dist/agentcard.js +4 -2
- package/dist/amadeus-checkout.generated.d.ts +57 -0
- package/dist/amadeus-checkout.generated.js +549 -0
- package/dist/amadeus.d.ts +41 -0
- package/dist/amadeus.js +81 -0
- package/dist/builtin-registry.generated.js +1 -1
- package/dist/card-endpoint.d.ts +177 -0
- package/dist/card-endpoint.js +286 -0
- package/dist/card-fields.generated.d.ts +5 -3
- package/dist/card-fields.generated.js +284 -7
- package/dist/cdp.d.ts +5 -1
- package/dist/cdp.js +841 -135
- package/dist/client.d.ts +403 -19
- package/dist/client.js +949 -98
- package/dist/creditguard.generated.d.ts +79 -0
- package/dist/creditguard.generated.js +662 -0
- package/dist/cse-body.js +11 -1
- package/dist/datatrans.d.ts +96 -0
- package/dist/datatrans.generated.d.ts +64 -0
- package/dist/datatrans.generated.js +426 -0
- package/dist/datatrans.js +178 -0
- package/dist/elavon-converge.d.ts +37 -0
- package/dist/elavon-converge.generated.d.ts +49 -0
- package/dist/elavon-converge.generated.js +439 -0
- package/dist/elavon-converge.js +84 -0
- package/dist/eprotect.d.ts +152 -0
- package/dist/eprotect.generated.d.ts +77 -0
- package/dist/eprotect.generated.js +498 -0
- package/dist/eprotect.js +222 -0
- package/dist/hosted-form.d.ts +3 -2
- package/dist/hosted-form.js +3 -2
- package/dist/index.d.ts +17 -3
- package/dist/index.js +6 -1
- package/dist/juspay-gate.d.ts +82 -0
- package/dist/juspay-gate.js +126 -0
- package/dist/juspay.generated.d.ts +89 -0
- package/dist/juspay.generated.js +705 -0
- package/dist/lifecycle.d.ts +57 -6
- package/dist/lifecycle.js +119 -8
- package/dist/merchant-card-endpoints.generated.d.ts +63 -0
- package/dist/merchant-card-endpoints.generated.js +1103 -0
- package/dist/merchant-hosted.d.ts +4 -1
- package/dist/merchant-hosted.js +5 -2
- package/dist/merchant-session-probe.d.ts +48 -0
- package/dist/merchant-session-probe.js +53 -0
- package/dist/merchant-session.generated.d.ts +69 -0
- package/dist/merchant-session.generated.js +919 -0
- package/dist/payrails.d.ts +133 -0
- package/dist/payrails.generated.d.ts +73 -0
- package/dist/payrails.generated.js +596 -0
- package/dist/payrails.js +305 -0
- package/dist/pelecard.d.ts +32 -0
- package/dist/pelecard.generated.d.ts +32 -0
- package/dist/pelecard.generated.js +283 -0
- package/dist/pelecard.js +42 -0
- package/dist/pre-claim.d.ts +72 -2
- package/dist/pre-claim.js +857 -5
- package/dist/preflight-catalog.json +2218 -287
- package/dist/preflight-schemas.json +179 -6
- package/dist/preflight.generated.d.ts +1 -1
- package/dist/preflight.generated.js +233 -4
- package/dist/preparation.d.ts +5 -2
- package/dist/preparation.js +36 -10
- package/dist/prepared-processor.d.ts +84 -5
- package/dist/prepared-processor.js +147 -6
- package/dist/primer.d.ts +53 -0
- package/dist/primer.generated.d.ts +38 -0
- package/dist/primer.generated.js +624 -0
- package/dist/primer.js +82 -0
- package/dist/registry.d.ts +100 -8
- package/dist/registry.js +85 -11
- package/dist/shiji-sts.d.ts +144 -0
- package/dist/shiji-sts.generated.d.ts +72 -0
- package/dist/shiji-sts.generated.js +913 -0
- package/dist/shiji-sts.js +222 -0
- package/dist/stripe-checkout.generated.d.ts +1 -1
- package/dist/stripe-checkout.generated.js +699 -9
- package/dist/stripe-setup.d.ts +16 -0
- package/dist/stripe-setup.js +61 -0
- package/dist/substitutions.generated.js +187 -29
- package/dist/verifone.d.ts +68 -0
- package/dist/verifone.generated.d.ts +51 -0
- package/dist/verifone.generated.js +1401 -0
- package/dist/verifone.js +119 -0
- package/dist/voice-types.d.ts +27 -0
- package/dist/voice.d.ts +6 -1
- package/dist/voice.js +6 -1
- package/dist/wspay.d.ts +41 -0
- package/dist/wspay.generated.d.ts +41 -0
- package/dist/wspay.generated.js +370 -0
- package/dist/wspay.js +65 -0
- package/examples/preflight/kernel-native/inventory.json +1 -1
- package/package.json +3 -3
package/dist/lifecycle.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { CheckoutPreparationError, type PrepareCheckoutOptions, type PreparedCheckout, type ReplayResponse } from './client.js';
|
|
2
2
|
import type { CheckoutMode } from './registry.js';
|
|
3
|
+
import type { PayrailsUnsupportedReason } from './payrails.js';
|
|
3
4
|
import type { Substitutions } from './substitute.js';
|
|
4
5
|
import type { GmoUnsupportedReason } from './gmo.js';
|
|
6
|
+
import type { ShijiStsUnsupportedReason } from './shiji-sts.js';
|
|
5
7
|
/** The application's resolver confirmed the payment for this checkout authorization. */
|
|
6
8
|
export interface MerchantPaymentConfirmation {
|
|
7
9
|
kind: 'merchant_payment';
|
|
@@ -28,7 +30,8 @@ export interface CheckoutState {
|
|
|
28
30
|
status: 'idle' | 'awaiting_approval' | 'ready_to_submit' | 'awaiting_merchant' | 'requires_user_action' | 'completed' | 'declined' | 'timed_out' | 'cancelled' | 'unsupported' | 'outcome_unknown' | 'failed';
|
|
29
31
|
authorizationId: string | null;
|
|
30
32
|
preparationId?: string;
|
|
31
|
-
mode
|
|
33
|
+
/** How the card reached the merchant: a processor mode, or `card_endpoint` for a reviewed merchant's own card endpoint. */
|
|
34
|
+
mode?: CheckoutMode | 'card_endpoint';
|
|
32
35
|
orderId?: string;
|
|
33
36
|
confirmation?: MerchantPaymentConfirmation;
|
|
34
37
|
/** Stable SDK category; never includes a request body, processor response, or approval link. */
|
|
@@ -116,6 +119,12 @@ export interface CheckoutController {
|
|
|
116
119
|
}
|
|
117
120
|
/** How many times one approval's card-free Stripe confirmation may be checked before it is simply held. */
|
|
118
121
|
export declare const MAX_STRIPE_CONTINUATION_CHECKS = 3;
|
|
122
|
+
/**
|
|
123
|
+
* How long a Datatrans re-submit waits for the merchant resolver (merchantOrderPending) while the
|
|
124
|
+
* page's card post stays paused. A resolver that has not answered by then reads as not pending, so
|
|
125
|
+
* the post becomes a new approval instead of hanging the checkout.
|
|
126
|
+
*/
|
|
127
|
+
export declare const MERCHANT_ORDER_READ_MS = 5000;
|
|
119
128
|
/** Shared by the raw CDP and Playwright transports. No browser ownership or payment execution lives here. */
|
|
120
129
|
export declare class CheckoutLifecycle implements CheckoutController {
|
|
121
130
|
private readonly options;
|
|
@@ -128,7 +137,12 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
128
137
|
private stripeTokenPrepared;
|
|
129
138
|
private stripeContinuation;
|
|
130
139
|
private stripeContinuationChecks;
|
|
140
|
+
/** The handoff in progress is WSPay's 3-D Secure step; see handedOff. */
|
|
141
|
+
private wspayChallenge;
|
|
142
|
+
private stripeContinuedReason;
|
|
143
|
+
private approvedPaymentMethod;
|
|
131
144
|
private ownedShopOrderId;
|
|
145
|
+
private readonly handoffs;
|
|
132
146
|
private reconciliation;
|
|
133
147
|
private preparationHandler?;
|
|
134
148
|
private preparationUsed;
|
|
@@ -147,6 +161,17 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
147
161
|
preparationFailed(error: CheckoutPreparationError): void;
|
|
148
162
|
isBlocked(): boolean;
|
|
149
163
|
isCancelled(): boolean;
|
|
164
|
+
/** Whether the application gave a merchant resolver, so reconcile() reads the merchant's own record. */
|
|
165
|
+
hasMerchantResolver(): boolean;
|
|
166
|
+
/**
|
|
167
|
+
* For a Datatrans re-submit once the approved answer reached the page (pre-claim.ts): whether the
|
|
168
|
+
* application's merchant resolver still reports this approval's order pending. A read only: no
|
|
169
|
+
* answer changes the state or the hold, so a pending order leaves the checkout exactly as it was.
|
|
170
|
+
* False with no resolver, while a request is in flight, once the checkout no longer awaits the
|
|
171
|
+
* merchant, when the resolver throws or answers anything but pending, and when it has not answered
|
|
172
|
+
* within `deadlineMs` (MERCHANT_ORDER_READ_MS): the paused card post never waits on it longer.
|
|
173
|
+
*/
|
|
174
|
+
merchantOrderPending(deadlineMs?: number): Promise<boolean>;
|
|
150
175
|
begin(): void;
|
|
151
176
|
end(): void;
|
|
152
177
|
private set;
|
|
@@ -187,11 +212,20 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
187
212
|
* turned on (merchant_profile_observe), a card request the profile cannot
|
|
188
213
|
* finish (merchant_request_unsupported), a recognized processor's request in
|
|
189
214
|
* a form its gate refuses (GMO's unsupported_gmo_request and
|
|
190
|
-
* unsupported_gmo_token_v1),
|
|
215
|
+
* unsupported_gmo_token_v1), a CyberSource Flex request that is not a
|
|
191
216
|
* reviewed Microform v2 card field's (microform_unsupported,
|
|
192
|
-
* cybersource-flex.ts)
|
|
217
|
+
* cybersource-flex.ts), a Juspay card request that is not the reviewed
|
|
218
|
+
* payment (juspay_request_unsupported, juspay-gate.ts), such as save card,
|
|
219
|
+
* EMI, a direct card or a sibling host, a reviewed merchant card endpoint
|
|
220
|
+
* this build does not pay (merchant_card_endpoint_not_enabled), a CreditGuard
|
|
221
|
+
* page that runs its own 3-D Secure (creditguard_three_d_secure), a
|
|
222
|
+
* recognized Primer request in a form its gate refuses (unsupported_primer_sdk,
|
|
223
|
+
* unsupported_primer_request), a Payrails request its gate refuses
|
|
224
|
+
* (`unsupported_payrails_card_payment` and the card-save refusal codes), or a
|
|
225
|
+
* Shiji STS request its gate refuses (shiji_sts_keep_on_file and the other
|
|
226
|
+
* shiji-sts.ts reasons).
|
|
193
227
|
*/
|
|
194
|
-
unsupported(reason?: 'unrecognized_payment_endpoint' | 'merchant_profile_observe' | 'merchant_request_unsupported' | GmoUnsupportedReason | 'microform_unsupported'): void;
|
|
228
|
+
unsupported(reason?: 'unrecognized_payment_endpoint' | 'merchant_profile_observe' | 'merchant_request_unsupported' | GmoUnsupportedReason | 'microform_unsupported' | 'juspay_request_unsupported' | 'merchant_card_endpoint_not_enabled' | 'creditguard_three_d_secure' | 'unsupported_primer_sdk' | 'unsupported_primer_request' | PayrailsUnsupportedReason | ShijiStsUnsupportedReason): void;
|
|
195
229
|
/**
|
|
196
230
|
* A card request that only a prepared checkout pays (an Adyen merchant
|
|
197
231
|
* profile's, or a Fiserv card capture) arrived with no preparation on this
|
|
@@ -201,6 +235,22 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
201
235
|
*/
|
|
202
236
|
preparationRequired(): void;
|
|
203
237
|
prepareHandoff(replay: ReplayResponse, requestUrl: string): void;
|
|
238
|
+
/**
|
|
239
|
+
* The URLs of the requests this attachment has handed the card to, oldest
|
|
240
|
+
* first. Each is recorded before delivery, since the processor may already
|
|
241
|
+
* have minted a token from the card even if the browser never acknowledges
|
|
242
|
+
* it, and none is forgotten on a retry. The adapters pass them to
|
|
243
|
+
* VaultClient.withoutCard, which then refuses a Nuvei payment without a card.
|
|
244
|
+
*/
|
|
245
|
+
cardHandoffs(): readonly string[];
|
|
246
|
+
/**
|
|
247
|
+
* The payment method a Stripe card save may pay with in place of the card
|
|
248
|
+
* it sends again (cdp.ts claimStripeContinuation): the one this
|
|
249
|
+
* attachment's approved `/v1/payment_methods` request returned, while its
|
|
250
|
+
* continuation is still open. Null for any other tokenization, and once the
|
|
251
|
+
* checkout was cancelled, aborted or reconciled.
|
|
252
|
+
*/
|
|
253
|
+
approvedStripePaymentMethod(): string | null;
|
|
204
254
|
/**
|
|
205
255
|
* The approval a page's card-free Stripe confirmation may continue, or null.
|
|
206
256
|
* Only once a Stripe tokenization is being handed to the page, and while
|
|
@@ -215,9 +265,10 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
215
265
|
* Settle a claimed check. True only when the API allowed it and the checkout
|
|
216
266
|
* still awaits the merchant (nothing cancelled, aborted or reconciled it
|
|
217
267
|
* while the API answered): the page's confirmation continues, and no later
|
|
218
|
-
* one will.
|
|
268
|
+
* one will. `kind` names what it confirms: a payment (a PaymentIntent) or a
|
|
269
|
+
* card save (a SetupIntent), which the reason then says.
|
|
219
270
|
*/
|
|
220
|
-
stripeContinuationChecked(allowed: boolean): boolean;
|
|
271
|
+
stripeContinuationChecked(allowed: boolean, kind?: 'payment' | 'setup'): boolean;
|
|
221
272
|
private stripeContinuationOpen;
|
|
222
273
|
handedOff(replay: ReplayResponse): void;
|
|
223
274
|
failed(error: unknown, handoffStarted?: boolean): void;
|
package/dist/lifecycle.js
CHANGED
|
@@ -1,7 +1,28 @@
|
|
|
1
1
|
import { AdyenTestPlatformRefusedError, ApprovalDeclinedError, ApprovalTimeoutError, CheckoutCancelledError, CheckoutPreparationError, IntentNotConfirmableError, PaymentOutcomeUnknownError, ProcessorRefusedError } from './client.js';
|
|
2
|
+
import { CardEndpointRefusedError } from './card-endpoint.js';
|
|
2
3
|
import { parseOwnedShopReceipt, OWNED_SHOP_SKU, OWNED_SHOP_AMOUNT_CENTS, OWNED_SHOP_CURRENCY } from './owned-shop.generated.js';
|
|
4
|
+
import { isWspayChallenge } from './wspay.js';
|
|
3
5
|
/** How many times one approval's card-free Stripe confirmation may be checked before it is simply held. */
|
|
4
6
|
export const MAX_STRIPE_CONTINUATION_CHECKS = 3;
|
|
7
|
+
/**
|
|
8
|
+
* How long a Datatrans re-submit waits for the merchant resolver (merchantOrderPending) while the
|
|
9
|
+
* page's card post stays paused. A resolver that has not answered by then reads as not pending, so
|
|
10
|
+
* the post becomes a new approval instead of hanging the checkout.
|
|
11
|
+
*/
|
|
12
|
+
export const MERCHANT_ORDER_READ_MS = 5_000;
|
|
13
|
+
const STRIPE_PAYMENT_METHOD_ID = /^pm_[A-Za-z0-9]{1,250}$/;
|
|
14
|
+
/** The `pm_` id in a Stripe `/v1/payment_methods` answer, or null for any other body. */
|
|
15
|
+
function stripePaymentMethodId(body) {
|
|
16
|
+
if (typeof body !== 'string')
|
|
17
|
+
return null;
|
|
18
|
+
try {
|
|
19
|
+
const id = JSON.parse(body)?.id;
|
|
20
|
+
return typeof id === 'string' && STRIPE_PAYMENT_METHOD_ID.test(id) ? id : null;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
5
26
|
/** Shared by the raw CDP and Playwright transports. No browser ownership or payment execution lives here. */
|
|
6
27
|
export class CheckoutLifecycle {
|
|
7
28
|
options;
|
|
@@ -15,7 +36,15 @@ export class CheckoutLifecycle {
|
|
|
15
36
|
stripeTokenPrepared = false;
|
|
16
37
|
stripeContinuation = 'none';
|
|
17
38
|
stripeContinuationChecks = 0;
|
|
39
|
+
/** The handoff in progress is WSPay's 3-D Secure step; see handedOff. */
|
|
40
|
+
wspayChallenge = false;
|
|
41
|
+
// What the continuation that went through confirmed: a payment, or a card save.
|
|
42
|
+
stripeContinuedReason = 'stripe_payment_continued';
|
|
43
|
+
// The payment method a Stripe /v1/payment_methods approval returned: see approvedStripePaymentMethod.
|
|
44
|
+
approvedPaymentMethod = null;
|
|
18
45
|
ownedShopOrderId = null;
|
|
46
|
+
// Every request this attachment handed the card to: see cardHandoffs().
|
|
47
|
+
handoffs = [];
|
|
19
48
|
reconciliation = null;
|
|
20
49
|
preparationHandler;
|
|
21
50
|
preparationUsed = false;
|
|
@@ -58,6 +87,30 @@ export class CheckoutLifecycle {
|
|
|
58
87
|
}
|
|
59
88
|
isBlocked() { return this.held || this.cancelled; }
|
|
60
89
|
isCancelled() { return this.cancelled; }
|
|
90
|
+
/** Whether the application gave a merchant resolver, so reconcile() reads the merchant's own record. */
|
|
91
|
+
hasMerchantResolver() { return typeof this.options.resolveMerchantResult === 'function'; }
|
|
92
|
+
/**
|
|
93
|
+
* For a Datatrans re-submit once the approved answer reached the page (pre-claim.ts): whether the
|
|
94
|
+
* application's merchant resolver still reports this approval's order pending. A read only: no
|
|
95
|
+
* answer changes the state or the hold, so a pending order leaves the checkout exactly as it was.
|
|
96
|
+
* False with no resolver, while a request is in flight, once the checkout no longer awaits the
|
|
97
|
+
* merchant, when the resolver throws or answers anything but pending, and when it has not answered
|
|
98
|
+
* within `deadlineMs` (MERCHANT_ORDER_READ_MS): the paused card post never waits on it longer.
|
|
99
|
+
*/
|
|
100
|
+
async merchantOrderPending(deadlineMs = MERCHANT_ORDER_READ_MS) {
|
|
101
|
+
const resolver = this.options.resolveMerchantResult;
|
|
102
|
+
if (!resolver || this.active || this.state.status !== 'awaiting_merchant')
|
|
103
|
+
return false;
|
|
104
|
+
let timer;
|
|
105
|
+
const expired = new Promise((resolve) => { timer = setTimeout(() => resolve(false), deadlineMs); });
|
|
106
|
+
const read = Promise.resolve().then(() => resolver(this.getState())).then((result) => !!result && typeof result === 'object' && !Array.isArray(result) && result.status === 'pending', () => false);
|
|
107
|
+
try {
|
|
108
|
+
return await Promise.race([read, expired]);
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
clearTimeout(timer);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
61
114
|
begin() {
|
|
62
115
|
this.active = true;
|
|
63
116
|
this.set({ status: 'awaiting_approval', authorizationId: null, ...(this.state.preparationId ? { preparationId: this.state.preparationId } : {}) });
|
|
@@ -135,9 +188,18 @@ export class CheckoutLifecycle {
|
|
|
135
188
|
* turned on (merchant_profile_observe), a card request the profile cannot
|
|
136
189
|
* finish (merchant_request_unsupported), a recognized processor's request in
|
|
137
190
|
* a form its gate refuses (GMO's unsupported_gmo_request and
|
|
138
|
-
* unsupported_gmo_token_v1),
|
|
191
|
+
* unsupported_gmo_token_v1), a CyberSource Flex request that is not a
|
|
139
192
|
* reviewed Microform v2 card field's (microform_unsupported,
|
|
140
|
-
* cybersource-flex.ts)
|
|
193
|
+
* cybersource-flex.ts), a Juspay card request that is not the reviewed
|
|
194
|
+
* payment (juspay_request_unsupported, juspay-gate.ts), such as save card,
|
|
195
|
+
* EMI, a direct card or a sibling host, a reviewed merchant card endpoint
|
|
196
|
+
* this build does not pay (merchant_card_endpoint_not_enabled), a CreditGuard
|
|
197
|
+
* page that runs its own 3-D Secure (creditguard_three_d_secure), a
|
|
198
|
+
* recognized Primer request in a form its gate refuses (unsupported_primer_sdk,
|
|
199
|
+
* unsupported_primer_request), a Payrails request its gate refuses
|
|
200
|
+
* (`unsupported_payrails_card_payment` and the card-save refusal codes), or a
|
|
201
|
+
* Shiji STS request its gate refuses (shiji_sts_keep_on_file and the other
|
|
202
|
+
* shiji-sts.ts reasons).
|
|
141
203
|
*/
|
|
142
204
|
unsupported(reason = 'unrecognized_payment_endpoint') {
|
|
143
205
|
this.held = true;
|
|
@@ -158,6 +220,8 @@ export class CheckoutLifecycle {
|
|
|
158
220
|
this.set({ ...this.state, status: 'failed', reason: 'preparation_required' });
|
|
159
221
|
}
|
|
160
222
|
prepareHandoff(replay, requestUrl) {
|
|
223
|
+
this.wspayChallenge = isWspayChallenge(requestUrl, replay);
|
|
224
|
+
this.handoffs.push(requestUrl);
|
|
161
225
|
if (replay.mode === 'token' && replay.executionMode === 'autopilot' && replay.shopOrderId) {
|
|
162
226
|
let receipt;
|
|
163
227
|
try {
|
|
@@ -185,11 +249,31 @@ export class CheckoutLifecycle {
|
|
|
185
249
|
this.unboundStripeToken = true;
|
|
186
250
|
this.stripeTokenPrepared = true;
|
|
187
251
|
this.held = true;
|
|
252
|
+
if (url.pathname === '/v1/payment_methods')
|
|
253
|
+
this.approvedPaymentMethod = stripePaymentMethodId(replay.body);
|
|
188
254
|
}
|
|
189
255
|
}
|
|
190
256
|
catch { /* unknown URL cannot establish a token binding */ }
|
|
191
257
|
}
|
|
192
258
|
}
|
|
259
|
+
/**
|
|
260
|
+
* The URLs of the requests this attachment has handed the card to, oldest
|
|
261
|
+
* first. Each is recorded before delivery, since the processor may already
|
|
262
|
+
* have minted a token from the card even if the browser never acknowledges
|
|
263
|
+
* it, and none is forgotten on a retry. The adapters pass them to
|
|
264
|
+
* VaultClient.withoutCard, which then refuses a Nuvei payment without a card.
|
|
265
|
+
*/
|
|
266
|
+
cardHandoffs() { return [...this.handoffs]; }
|
|
267
|
+
/**
|
|
268
|
+
* The payment method a Stripe card save may pay with in place of the card
|
|
269
|
+
* it sends again (cdp.ts claimStripeContinuation): the one this
|
|
270
|
+
* attachment's approved `/v1/payment_methods` request returned, while its
|
|
271
|
+
* continuation is still open. Null for any other tokenization, and once the
|
|
272
|
+
* checkout was cancelled, aborted or reconciled.
|
|
273
|
+
*/
|
|
274
|
+
approvedStripePaymentMethod() {
|
|
275
|
+
return this.stripeContinuationOpen() ? this.approvedPaymentMethod : null;
|
|
276
|
+
}
|
|
193
277
|
/**
|
|
194
278
|
* The approval a page's card-free Stripe confirmation may continue, or null.
|
|
195
279
|
* Only once a Stripe tokenization is being handed to the page, and while
|
|
@@ -211,15 +295,18 @@ export class CheckoutLifecycle {
|
|
|
211
295
|
* Settle a claimed check. True only when the API allowed it and the checkout
|
|
212
296
|
* still awaits the merchant (nothing cancelled, aborted or reconciled it
|
|
213
297
|
* while the API answered): the page's confirmation continues, and no later
|
|
214
|
-
* one will.
|
|
298
|
+
* one will. `kind` names what it confirms: a payment (a PaymentIntent) or a
|
|
299
|
+
* card save (a SetupIntent), which the reason then says.
|
|
215
300
|
*/
|
|
216
|
-
stripeContinuationChecked(allowed) {
|
|
301
|
+
stripeContinuationChecked(allowed, kind = 'payment') {
|
|
217
302
|
if (this.stripeContinuation !== 'checking')
|
|
218
303
|
return false;
|
|
219
304
|
const proceed = allowed && this.stripeContinuationOpen();
|
|
220
305
|
this.stripeContinuation = proceed ? 'continued' : 'none';
|
|
221
|
-
if (proceed)
|
|
222
|
-
this.
|
|
306
|
+
if (proceed) {
|
|
307
|
+
this.stripeContinuedReason = kind === 'setup' ? 'stripe_setup_continued' : 'stripe_payment_continued';
|
|
308
|
+
this.set({ ...this.state, reason: this.stripeContinuedReason });
|
|
309
|
+
}
|
|
223
310
|
return proceed;
|
|
224
311
|
}
|
|
225
312
|
stripeContinuationOpen() {
|
|
@@ -234,14 +321,31 @@ export class CheckoutLifecycle {
|
|
|
234
321
|
this.set({ status: 'completed', authorizationId: replay.authorizationId, mode: 'token', orderId: this.ownedShopOrderId });
|
|
235
322
|
return;
|
|
236
323
|
}
|
|
324
|
+
if (this.wspayChallenge) {
|
|
325
|
+
// WSPay answered with its 3-D Secure step, and the card frame now runs the
|
|
326
|
+
// bank's challenge in this browser. Nothing is charged until the cardholder
|
|
327
|
+
// completes it there, which the SDK cannot see, so this reads as
|
|
328
|
+
// requestUserAction('3ds') would, and holds until the merchant is reconciled.
|
|
329
|
+
// The step names no amount (amountVerified is null): WSPay then charges the
|
|
330
|
+
// amount the merchant's server set, and no answer Agentcard receives
|
|
331
|
+
// confirms it, so only the merchant's order can.
|
|
332
|
+
this.held = true;
|
|
333
|
+
this.set({ status: 'requires_user_action', authorizationId: replay.authorizationId, mode: 'token', reason: '3ds',
|
|
334
|
+
...(this.state.preparationId ? { preparationId: this.state.preparationId } : {}) });
|
|
335
|
+
this.notify({ reason: '3ds', authorizationId: replay.authorizationId });
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
237
338
|
const mismatch = (!replay.mode || replay.mode === 'token') && replay.amountVerified === false;
|
|
238
|
-
|
|
339
|
+
// A card endpoint answer means the merchant already holds the card: its page's own
|
|
340
|
+
// retry, or a step-up that sends the card again, is refused until the application
|
|
341
|
+
// reconciles the order, exactly as for a hosted form the device submitted.
|
|
342
|
+
this.held = !!this.options.requireMerchantResult || replay.mode === 'hosted_form' || replay.mode === 'card_endpoint' || mismatch || this.unboundStripeToken;
|
|
239
343
|
if (mismatch)
|
|
240
344
|
this.stripeTokenPrepared = false;
|
|
241
345
|
this.set({ status: 'awaiting_merchant', authorizationId: replay.authorizationId, mode: replay.mode ?? 'token',
|
|
242
346
|
...(this.state.preparationId ? { preparationId: this.state.preparationId } : {}),
|
|
243
347
|
...(mismatch ? { reason: 'charged_amount_mismatch' }
|
|
244
|
-
: this.stripeContinuation === 'continued' ? { reason:
|
|
348
|
+
: this.stripeContinuation === 'continued' ? { reason: this.stripeContinuedReason }
|
|
245
349
|
: this.unboundStripeToken ? { reason: 'stripe_tokenization_unbound' } : {}) });
|
|
246
350
|
}
|
|
247
351
|
failed(error, handoffStarted = false) {
|
|
@@ -261,6 +365,13 @@ export class CheckoutLifecycle {
|
|
|
261
365
|
this.held = true;
|
|
262
366
|
this.set({ ...this.state, authorizationId, status: 'outcome_unknown', reason: error instanceof PaymentOutcomeUnknownError ? error.reason : error instanceof IntentNotConfirmableError ? 'intent_not_confirmable' : 'browser_handoff_failed' });
|
|
263
367
|
}
|
|
368
|
+
else if (error instanceof CardEndpointRefusedError) {
|
|
369
|
+
// Refused before anything was created or sent. A refusal that every later request
|
|
370
|
+
// would meet holds the attachment; one about this request alone does not.
|
|
371
|
+
if (error.permanent)
|
|
372
|
+
this.held = true;
|
|
373
|
+
this.set({ ...this.state, status: error.reason === 'not_enabled' ? 'unsupported' : 'failed', reason: `merchant_card_endpoint_${error.reason}` });
|
|
374
|
+
}
|
|
264
375
|
else if (error instanceof CheckoutCancelledError) {
|
|
265
376
|
this.cancel();
|
|
266
377
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
declare var SubstitutionError: {
|
|
2
|
+
new (message: any): {
|
|
3
|
+
name: string;
|
|
4
|
+
message: string;
|
|
5
|
+
stack?: string;
|
|
6
|
+
cause?: unknown;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
declare var MERCHANT_CARD_ENDPOINT_PSP: string;
|
|
10
|
+
declare var MERCHANT_CARD_ENDPOINT_MODE: string;
|
|
11
|
+
declare var MERCHANT_CARD_ENDPOINT_PROFILES: any;
|
|
12
|
+
declare var MERCHANT_CARD_ENDPOINT_RECOGNIZERS: any;
|
|
13
|
+
declare var MERCHANT_CARD_ENDPOINT_CLIENT_TABLE: any;
|
|
14
|
+
declare function merchantCardEndpointById(id: any): any;
|
|
15
|
+
declare function trustedMerchantCardEndpoint(idOrEntry: any): any;
|
|
16
|
+
declare function merchantCardEndpointRecognizerById(id: any): any;
|
|
17
|
+
declare function merchantCardEndpointLive(idOrEntry: any): boolean;
|
|
18
|
+
declare var MERCHANT_CARD_ENDPOINT_LIMITS: Readonly<{
|
|
19
|
+
bodyBytes: number;
|
|
20
|
+
answerBytes: number;
|
|
21
|
+
urlLength: 8192;
|
|
22
|
+
headerValueBytes: number;
|
|
23
|
+
headerBytes: number;
|
|
24
|
+
cookies: 64;
|
|
25
|
+
}>;
|
|
26
|
+
declare function merchantCardEndpointBodyRefusal(profile: any, body: any, contentType: any): string | null;
|
|
27
|
+
declare function merchantCardEndpointAmount(profile: any, body: any, contentType: any): {
|
|
28
|
+
amountCents: null;
|
|
29
|
+
currency: any;
|
|
30
|
+
} | {
|
|
31
|
+
amountCents: number;
|
|
32
|
+
currency: any;
|
|
33
|
+
};
|
|
34
|
+
declare function merchantCardEndpointMatches(profile: any, rawUrl: any, method: any, opts: any): boolean;
|
|
35
|
+
declare function matchMerchantCardEndpoint(rawUrl: any, method: any, opts: any): any;
|
|
36
|
+
declare function assertMerchantCardEndpoint(authorization: any): URL & {
|
|
37
|
+
profile: any;
|
|
38
|
+
};
|
|
39
|
+
declare function merchantCardEndpointSessionRefusal(profile: any, bundle: any): string | null;
|
|
40
|
+
declare function substituteMerchantCardEndpoint(body: any, contentType: any, profile: any, card: any): any;
|
|
41
|
+
declare function merchantEndpointRequest(profile: any, bundle: any, card: any): {
|
|
42
|
+
url: any;
|
|
43
|
+
method: any;
|
|
44
|
+
headers: {
|
|
45
|
+
"content-type": any;
|
|
46
|
+
};
|
|
47
|
+
body: any;
|
|
48
|
+
};
|
|
49
|
+
declare function responseCardLeak(card: any, response: any): "card_in_response" | "unreadable_in_response" | null;
|
|
50
|
+
declare function merchantCardEndpointAnswer(profile: any, response: any, card: any): {
|
|
51
|
+
status: any;
|
|
52
|
+
withheld: string;
|
|
53
|
+
headers: {};
|
|
54
|
+
set_cookies: never[];
|
|
55
|
+
bodyText: null;
|
|
56
|
+
} | {
|
|
57
|
+
status: any;
|
|
58
|
+
headers: {};
|
|
59
|
+
set_cookies: any[];
|
|
60
|
+
bodyText: any;
|
|
61
|
+
withheld?: undefined;
|
|
62
|
+
};
|
|
63
|
+
export { MERCHANT_CARD_ENDPOINT_CLIENT_TABLE, MERCHANT_CARD_ENDPOINT_LIMITS, MERCHANT_CARD_ENDPOINT_MODE, MERCHANT_CARD_ENDPOINT_PROFILES, MERCHANT_CARD_ENDPOINT_PSP, MERCHANT_CARD_ENDPOINT_RECOGNIZERS, SubstitutionError, assertMerchantCardEndpoint, matchMerchantCardEndpoint, merchantCardEndpointAmount, merchantCardEndpointAnswer, merchantCardEndpointBodyRefusal, merchantCardEndpointById, merchantCardEndpointLive, merchantCardEndpointMatches, merchantCardEndpointRecognizerById, merchantCardEndpointSessionRefusal, merchantEndpointRequest, responseCardLeak, substituteMerchantCardEndpoint, trustedMerchantCardEndpoint };
|