@agent-cards/sdk 0.20.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 +51 -0
- package/PREFLIGHT.md +34 -0
- package/README.md +1217 -15
- 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 +6 -1
- package/dist/cdp.js +983 -147
- package/dist/client.d.ts +493 -13
- package/dist/client.js +1100 -82
- package/dist/creditguard.generated.d.ts +79 -0
- package/dist/creditguard.generated.js +662 -0
- package/dist/cse-body.js +11 -1
- package/dist/cybersource-flex.d.ts +183 -0
- package/dist/cybersource-flex.generated.d.ts +92 -0
- package/dist/cybersource-flex.generated.js +689 -0
- package/dist/cybersource-flex.js +275 -0
- 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/gmo.d.ts +63 -0
- package/dist/gmo.generated.d.ts +60 -0
- package/dist/gmo.generated.js +586 -0
- package/dist/gmo.js +119 -0
- package/dist/hosted-form.d.ts +3 -2
- package/dist/hosted-form.js +3 -2
- package/dist/index.d.ts +19 -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 +62 -6
- package/dist/lifecycle.js +123 -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 +84 -3
- package/dist/pre-claim.js +987 -9
- package/dist/preflight-catalog.json +2310 -263
- package/dist/preflight-schemas.json +187 -6
- package/dist/preflight.generated.d.ts +1 -1
- package/dist/preflight.generated.js +247 -4
- package/dist/preparation.d.ts +5 -2
- package/dist/preparation.js +36 -10
- package/dist/prepared-processor.d.ts +86 -5
- package/dist/prepared-processor.js +157 -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 +114 -12
- 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 +735 -10
- 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,6 +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';
|
|
5
|
+
import type { GmoUnsupportedReason } from './gmo.js';
|
|
6
|
+
import type { ShijiStsUnsupportedReason } from './shiji-sts.js';
|
|
4
7
|
/** The application's resolver confirmed the payment for this checkout authorization. */
|
|
5
8
|
export interface MerchantPaymentConfirmation {
|
|
6
9
|
kind: 'merchant_payment';
|
|
@@ -27,7 +30,8 @@ export interface CheckoutState {
|
|
|
27
30
|
status: 'idle' | 'awaiting_approval' | 'ready_to_submit' | 'awaiting_merchant' | 'requires_user_action' | 'completed' | 'declined' | 'timed_out' | 'cancelled' | 'unsupported' | 'outcome_unknown' | 'failed';
|
|
28
31
|
authorizationId: string | null;
|
|
29
32
|
preparationId?: string;
|
|
30
|
-
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';
|
|
31
35
|
orderId?: string;
|
|
32
36
|
confirmation?: MerchantPaymentConfirmation;
|
|
33
37
|
/** Stable SDK category; never includes a request body, processor response, or approval link. */
|
|
@@ -115,6 +119,12 @@ export interface CheckoutController {
|
|
|
115
119
|
}
|
|
116
120
|
/** How many times one approval's card-free Stripe confirmation may be checked before it is simply held. */
|
|
117
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;
|
|
118
128
|
/** Shared by the raw CDP and Playwright transports. No browser ownership or payment execution lives here. */
|
|
119
129
|
export declare class CheckoutLifecycle implements CheckoutController {
|
|
120
130
|
private readonly options;
|
|
@@ -127,7 +137,12 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
127
137
|
private stripeTokenPrepared;
|
|
128
138
|
private stripeContinuation;
|
|
129
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;
|
|
130
144
|
private ownedShopOrderId;
|
|
145
|
+
private readonly handoffs;
|
|
131
146
|
private reconciliation;
|
|
132
147
|
private preparationHandler?;
|
|
133
148
|
private preparationUsed;
|
|
@@ -146,6 +161,17 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
146
161
|
preparationFailed(error: CheckoutPreparationError): void;
|
|
147
162
|
isBlocked(): boolean;
|
|
148
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>;
|
|
149
175
|
begin(): void;
|
|
150
176
|
end(): void;
|
|
151
177
|
private set;
|
|
@@ -183,10 +209,23 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
183
209
|
/**
|
|
184
210
|
* A card request this SDK cannot pay was aborted. `reason`: an unrecognized
|
|
185
211
|
* declared payment endpoint (the default), a merchant profile Agentcard has not
|
|
186
|
-
* turned on (merchant_profile_observe),
|
|
187
|
-
* finish (merchant_request_unsupported)
|
|
212
|
+
* turned on (merchant_profile_observe), a card request the profile cannot
|
|
213
|
+
* finish (merchant_request_unsupported), a recognized processor's request in
|
|
214
|
+
* a form its gate refuses (GMO's unsupported_gmo_request and
|
|
215
|
+
* unsupported_gmo_token_v1), a CyberSource Flex request that is not a
|
|
216
|
+
* reviewed Microform v2 card field's (microform_unsupported,
|
|
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).
|
|
188
227
|
*/
|
|
189
|
-
unsupported(reason?: 'unrecognized_payment_endpoint' | 'merchant_profile_observe' | 'merchant_request_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;
|
|
190
229
|
/**
|
|
191
230
|
* A card request that only a prepared checkout pays (an Adyen merchant
|
|
192
231
|
* profile's, or a Fiserv card capture) arrived with no preparation on this
|
|
@@ -196,6 +235,22 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
196
235
|
*/
|
|
197
236
|
preparationRequired(): void;
|
|
198
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;
|
|
199
254
|
/**
|
|
200
255
|
* The approval a page's card-free Stripe confirmation may continue, or null.
|
|
201
256
|
* Only once a Stripe tokenization is being handed to the page, and while
|
|
@@ -210,9 +265,10 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
210
265
|
* Settle a claimed check. True only when the API allowed it and the checkout
|
|
211
266
|
* still awaits the merchant (nothing cancelled, aborted or reconciled it
|
|
212
267
|
* while the API answered): the page's confirmation continues, and no later
|
|
213
|
-
* 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.
|
|
214
270
|
*/
|
|
215
|
-
stripeContinuationChecked(allowed: boolean): boolean;
|
|
271
|
+
stripeContinuationChecked(allowed: boolean, kind?: 'payment' | 'setup'): boolean;
|
|
216
272
|
private stripeContinuationOpen;
|
|
217
273
|
handedOff(replay: ReplayResponse): void;
|
|
218
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 } : {}) });
|
|
@@ -132,8 +185,21 @@ export class CheckoutLifecycle {
|
|
|
132
185
|
/**
|
|
133
186
|
* A card request this SDK cannot pay was aborted. `reason`: an unrecognized
|
|
134
187
|
* declared payment endpoint (the default), a merchant profile Agentcard has not
|
|
135
|
-
* turned on (merchant_profile_observe),
|
|
136
|
-
* finish (merchant_request_unsupported)
|
|
188
|
+
* turned on (merchant_profile_observe), a card request the profile cannot
|
|
189
|
+
* finish (merchant_request_unsupported), a recognized processor's request in
|
|
190
|
+
* a form its gate refuses (GMO's unsupported_gmo_request and
|
|
191
|
+
* unsupported_gmo_token_v1), a CyberSource Flex request that is not a
|
|
192
|
+
* reviewed Microform v2 card field's (microform_unsupported,
|
|
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).
|
|
137
203
|
*/
|
|
138
204
|
unsupported(reason = 'unrecognized_payment_endpoint') {
|
|
139
205
|
this.held = true;
|
|
@@ -154,6 +220,8 @@ export class CheckoutLifecycle {
|
|
|
154
220
|
this.set({ ...this.state, status: 'failed', reason: 'preparation_required' });
|
|
155
221
|
}
|
|
156
222
|
prepareHandoff(replay, requestUrl) {
|
|
223
|
+
this.wspayChallenge = isWspayChallenge(requestUrl, replay);
|
|
224
|
+
this.handoffs.push(requestUrl);
|
|
157
225
|
if (replay.mode === 'token' && replay.executionMode === 'autopilot' && replay.shopOrderId) {
|
|
158
226
|
let receipt;
|
|
159
227
|
try {
|
|
@@ -181,11 +249,31 @@ export class CheckoutLifecycle {
|
|
|
181
249
|
this.unboundStripeToken = true;
|
|
182
250
|
this.stripeTokenPrepared = true;
|
|
183
251
|
this.held = true;
|
|
252
|
+
if (url.pathname === '/v1/payment_methods')
|
|
253
|
+
this.approvedPaymentMethod = stripePaymentMethodId(replay.body);
|
|
184
254
|
}
|
|
185
255
|
}
|
|
186
256
|
catch { /* unknown URL cannot establish a token binding */ }
|
|
187
257
|
}
|
|
188
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
|
+
}
|
|
189
277
|
/**
|
|
190
278
|
* The approval a page's card-free Stripe confirmation may continue, or null.
|
|
191
279
|
* Only once a Stripe tokenization is being handed to the page, and while
|
|
@@ -207,15 +295,18 @@ export class CheckoutLifecycle {
|
|
|
207
295
|
* Settle a claimed check. True only when the API allowed it and the checkout
|
|
208
296
|
* still awaits the merchant (nothing cancelled, aborted or reconciled it
|
|
209
297
|
* while the API answered): the page's confirmation continues, and no later
|
|
210
|
-
* 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.
|
|
211
300
|
*/
|
|
212
|
-
stripeContinuationChecked(allowed) {
|
|
301
|
+
stripeContinuationChecked(allowed, kind = 'payment') {
|
|
213
302
|
if (this.stripeContinuation !== 'checking')
|
|
214
303
|
return false;
|
|
215
304
|
const proceed = allowed && this.stripeContinuationOpen();
|
|
216
305
|
this.stripeContinuation = proceed ? 'continued' : 'none';
|
|
217
|
-
if (proceed)
|
|
218
|
-
this.
|
|
306
|
+
if (proceed) {
|
|
307
|
+
this.stripeContinuedReason = kind === 'setup' ? 'stripe_setup_continued' : 'stripe_payment_continued';
|
|
308
|
+
this.set({ ...this.state, reason: this.stripeContinuedReason });
|
|
309
|
+
}
|
|
219
310
|
return proceed;
|
|
220
311
|
}
|
|
221
312
|
stripeContinuationOpen() {
|
|
@@ -230,14 +321,31 @@ export class CheckoutLifecycle {
|
|
|
230
321
|
this.set({ status: 'completed', authorizationId: replay.authorizationId, mode: 'token', orderId: this.ownedShopOrderId });
|
|
231
322
|
return;
|
|
232
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
|
+
}
|
|
233
338
|
const mismatch = (!replay.mode || replay.mode === 'token') && replay.amountVerified === false;
|
|
234
|
-
|
|
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;
|
|
235
343
|
if (mismatch)
|
|
236
344
|
this.stripeTokenPrepared = false;
|
|
237
345
|
this.set({ status: 'awaiting_merchant', authorizationId: replay.authorizationId, mode: replay.mode ?? 'token',
|
|
238
346
|
...(this.state.preparationId ? { preparationId: this.state.preparationId } : {}),
|
|
239
347
|
...(mismatch ? { reason: 'charged_amount_mismatch' }
|
|
240
|
-
: this.stripeContinuation === 'continued' ? { reason:
|
|
348
|
+
: this.stripeContinuation === 'continued' ? { reason: this.stripeContinuedReason }
|
|
241
349
|
: this.unboundStripeToken ? { reason: 'stripe_tokenization_unbound' } : {}) });
|
|
242
350
|
}
|
|
243
351
|
failed(error, handoffStarted = false) {
|
|
@@ -257,6 +365,13 @@ export class CheckoutLifecycle {
|
|
|
257
365
|
this.held = true;
|
|
258
366
|
this.set({ ...this.state, authorizationId, status: 'outcome_unknown', reason: error instanceof PaymentOutcomeUnknownError ? error.reason : error instanceof IntentNotConfirmableError ? 'intent_not_confirmable' : 'browser_handoff_failed' });
|
|
259
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
|
+
}
|
|
260
375
|
else if (error instanceof CheckoutCancelledError) {
|
|
261
376
|
this.cancel();
|
|
262
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 };
|