@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/gmo.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// GMO Payment Gateway, PG Multipayment token v2 (mp-token.js), as the SDK sees it.
|
|
2
|
+
//
|
|
3
|
+
// A GMO merchant page that calls Multipayment.init(shopId) with one argument (teamLab's ticket
|
|
4
|
+
// sites do) sends the card as mp-token.js's getToken: one fetch POST to
|
|
5
|
+
// https://token.mul-pay.jp/payment/CreateToken.json (test host stg.token.mul-pay.jp), as
|
|
6
|
+
// application/json with X-MP-Client-Type: js-legacy, whose body is AES ciphertext of the card with
|
|
7
|
+
// its key wrapped under GMO's shared public key. The agent's page encrypts the placeholder card, so
|
|
8
|
+
// nothing in the paused body can be filled in. The cardholder's device rebuilds the whole envelope
|
|
9
|
+
// with the real card and sends it to GMO itself, and the page receives only GMO's answer: one
|
|
10
|
+
// single-use token, valid 30 minutes and spendable only by the shop's own site (token mode).
|
|
11
|
+
//
|
|
12
|
+
// The registry entry ships dark (capability gmo_shared_pk). This build declares the capability on
|
|
13
|
+
// syncRegistry, and the API serves the entry only to an org Agentcard enabled for GMO, so for every
|
|
14
|
+
// other org nothing here fires: isCardRequest never recognizes a GMO URL and GMO's requests go
|
|
15
|
+
// through untouched, exactly as before.
|
|
16
|
+
//
|
|
17
|
+
// For an org in the dark launch, a POST the registry recognizes on a GMO token host is judged by
|
|
18
|
+
// payment-core's one guard (gmo.generated.ts isGmoSharedPkRequest), the check the API runs at
|
|
19
|
+
// create and the device runs before it rebuilds anything:
|
|
20
|
+
// - mp-token.js's SHARED_PK getToken for one token pauses for approval;
|
|
21
|
+
// - anything else on that URL can never be paid by the vault: UNIQUE_PK (a merchant-registered
|
|
22
|
+
// key nobody can check), GMO Elements (js-iframe), several tokens, a shop id of the other
|
|
23
|
+
// environment's shape, or any serialization mp-token.js does not write. It is aborted as an
|
|
24
|
+
// unsupported checkout before any create or prompt.
|
|
25
|
+
// Token v1 (ext/js/token.js) sends the card as a JSONP GET that no vault mode covers. It is aborted
|
|
26
|
+
// the same way, so the placeholder is never tokenized silently.
|
|
27
|
+
import { GMO_PSP, GMO_TOKEN_URLS, isGmoSharedPkRequest, isGmoTokenHost, sanitizeGmoTokenResponse, } from './gmo.generated.js';
|
|
28
|
+
export { GMO_PSP, isGmoTokenHost };
|
|
29
|
+
/** The dark-launch capability a build declares when it pauses only what isGmoSharedPkRequest accepts. */
|
|
30
|
+
export const GMO_CAPABILITY = 'gmo_shared_pk';
|
|
31
|
+
/** The hosts GMO token v1 (ext/js/token.js) sends its JSONP GET to: production, then test. */
|
|
32
|
+
const GMO_TOKEN_V1_HOSTS = ['p01.mul-pay.jp', 'stg.token.mul-pay.jp'];
|
|
33
|
+
const GMO_TOKEN_V1_PATH = '/ext/api/gettoken';
|
|
34
|
+
/**
|
|
35
|
+
* Fetch interception patterns for GMO token v1's JSONP GET, armed only for an org the API served GMO
|
|
36
|
+
* to. A CDP pattern matches the URL as written, path case included, while isGmoTokenV1Request
|
|
37
|
+
* accepts any path case, a trailing dot on the host and any port. So each v1 host is armed whole,
|
|
38
|
+
* in those four spellings, and the pre-claim gate classifies every paused request with
|
|
39
|
+
* isGmoTokenV1Request: the v1 GET is aborted, and anything else on the host continues untouched.
|
|
40
|
+
* Chrome writes the host in lower case, and it blocks a subresource URL that carries credentials.
|
|
41
|
+
*/
|
|
42
|
+
export const GMO_TOKEN_V1_PATTERNS = GMO_TOKEN_V1_HOSTS.flatMap((host) => [`https://${host}/*`, `https://${host}:*`, `https://${host}./*`, `https://${host}.:*`]);
|
|
43
|
+
/**
|
|
44
|
+
* Whether the vault's current registry recognizes GMO's card request: true only after
|
|
45
|
+
* syncRegistry() for an org the API serves the dark entry to.
|
|
46
|
+
*/
|
|
47
|
+
export function recognizesGmo(vault) {
|
|
48
|
+
if (!vault || typeof vault.isCardRequest !== 'function')
|
|
49
|
+
return false;
|
|
50
|
+
try {
|
|
51
|
+
return vault.isCardRequest(GMO_TOKEN_URLS.production, 'POST') || vault.isCardRequest(GMO_TOKEN_URLS.sandbox, 'POST');
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* GMO token v1's card request: a GET (or, with no method, a URL a route matcher is asked about)
|
|
59
|
+
* to /ext/api/getToken on either v1 host, in any case or with a trailing dot, since the servers
|
|
60
|
+
* behind it need not care.
|
|
61
|
+
*/
|
|
62
|
+
export function isGmoTokenV1Request(rawUrl, method) {
|
|
63
|
+
if (method !== undefined && method.toUpperCase() !== 'GET')
|
|
64
|
+
return false;
|
|
65
|
+
let url;
|
|
66
|
+
try {
|
|
67
|
+
url = new URL(rawUrl);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
if (url.protocol !== 'https:')
|
|
73
|
+
return false;
|
|
74
|
+
const host = url.hostname.toLowerCase().replace(/\.$/, '');
|
|
75
|
+
return GMO_TOKEN_V1_HOSTS.includes(host) && url.pathname.toLowerCase() === GMO_TOKEN_V1_PATH;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Whether a POST the registry recognized on a GMO token host is anything but mp-token.js's
|
|
79
|
+
* SHARED_PK getToken for one token: null when the guard accepts it (it pauses for approval), else
|
|
80
|
+
* the reason it is aborted. A guard that throws refuses.
|
|
81
|
+
*/
|
|
82
|
+
export function gmoRequestRefusal(request) {
|
|
83
|
+
try {
|
|
84
|
+
return isGmoSharedPkRequest({ url: request.url, method: request.method.toUpperCase(), headers: request.headers ?? {}, body: request.body })
|
|
85
|
+
? null : 'unsupported_gmo_request';
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return 'unsupported_gmo_request';
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* The shop a GMO token request names (encryptionParameters.apiKey), as part of that request's
|
|
93
|
+
* identity. GMO mints a token for that one shop, so a retry that names another shop is a new
|
|
94
|
+
* question and never takes the first request's approval. Undefined when the URL is not a GMO token
|
|
95
|
+
* host; null when the body names no shop that can be read.
|
|
96
|
+
*/
|
|
97
|
+
export function gmoRequestShop(url, body) {
|
|
98
|
+
if (!isGmoTokenHost(url))
|
|
99
|
+
return undefined;
|
|
100
|
+
try {
|
|
101
|
+
const shop = JSON.parse(body)?.encryptionParameters?.apiKey;
|
|
102
|
+
return typeof shop === 'string' ? shop : null;
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The only answer the page may receive for an approved GMO request: status 200, and GMO's body
|
|
110
|
+
* reduced to the five fields mp-token.js reads with exactly one 64-hex token
|
|
111
|
+
* (sanitizeGmoTokenResponse), under a JSON content type. Null for anything else, including
|
|
112
|
+
* several tokens, which one approval never pays for.
|
|
113
|
+
*/
|
|
114
|
+
export function gmoTokenAnswer(status, body) {
|
|
115
|
+
if (status !== 200)
|
|
116
|
+
return null;
|
|
117
|
+
const sanitized = sanitizeGmoTokenResponse(body);
|
|
118
|
+
return sanitized ? { status: 200, headers: { 'content-type': 'application/json' }, body: sanitized } : null;
|
|
119
|
+
}
|
package/dist/hosted-form.d.ts
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* The hosted_form half of a replay: what the paused navigation is resolved
|
|
3
3
|
* with once the cardholder's device has submitted the processor's own form.
|
|
4
4
|
*
|
|
5
|
-
* On a hosted-form processor (Tranzila
|
|
6
|
-
* form navigation inside
|
|
5
|
+
* On a hosted-form processor (Tranzila, Authorize.Net DPM and SIM) the paused
|
|
6
|
+
* request is a form navigation inside a frame, not an XHR: the processor's own
|
|
7
|
+
* form, or the merchant's form that posts to the processor. The cardholder's
|
|
7
8
|
* device rebuilds that form with the real card and submits it itself, so the
|
|
8
9
|
* processor's answer (approved, declined) is shown on the device and reaches
|
|
9
10
|
* the merchant from the processor. The agent's browser never gets it.
|
package/dist/hosted-form.js
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* The hosted_form half of a replay: what the paused navigation is resolved
|
|
3
3
|
* with once the cardholder's device has submitted the processor's own form.
|
|
4
4
|
*
|
|
5
|
-
* On a hosted-form processor (Tranzila
|
|
6
|
-
* form navigation inside
|
|
5
|
+
* On a hosted-form processor (Tranzila, Authorize.Net DPM and SIM) the paused
|
|
6
|
+
* request is a form navigation inside a frame, not an XHR: the processor's own
|
|
7
|
+
* form, or the merchant's form that posts to the processor. The cardholder's
|
|
7
8
|
* device rebuilds that form with the real card and submits it itself, so the
|
|
8
9
|
* processor's answer (approved, declined) is shown on the device and reaches
|
|
9
10
|
* the merchant from the processor. The agent's browser never gets it.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
export { Agentcard, Agentcard as VaultClient, CheckoutModule } from './agentcard.js';
|
|
2
2
|
export type { CheckoutAttachOptions } from './agentcard.js';
|
|
3
|
-
export { CardEncryptedError, UnsupportedModeError, PreparationRequiredError, ApprovalTimeoutError, ApprovalDeclinedError, AmountMismatchError, PresetRefusedError, PRESET_REFUSAL_REASONS, IntentNotConfirmableError, ProcessorRefusedError, CheckoutApiError, CheckoutAuthError, redactUrl, SUPPORTED_MODES, PaymentOutcomeUnknownError, CheckoutCancelledError, CheckoutPreparationError, AdyenTestPlatformRefusedError, MerchantTotalError, } from './client.js';
|
|
4
|
-
export type {
|
|
3
|
+
export { CardEncryptedError, UnsupportedModeError, UnsupportedCapabilityError, PreparationRequiredError, AmountRequiredError, PageAmountRequiredError, ApprovalTimeoutError, ApprovalDeclinedError, AmountMismatchError, PresetRefusedError, PRESET_REFUSAL_REASONS, IntentNotConfirmableError, ProcessorRefusedError, CheckoutApiError, CheckoutAuthError, redactUrl, SUPPORTED_MODES, SUPPORTED_CAPABILITIES, PaymentOutcomeUnknownError, CheckoutCancelledError, CheckoutPreparationError, AdyenTestPlatformRefusedError, MerchantTotalError, PlaceholderCardError, } from './client.js';
|
|
4
|
+
export type { GmoUnsupportedReason } from './gmo.js';
|
|
5
|
+
export type { DatatransRefusalReason } from './datatrans.js';
|
|
6
|
+
export type { PelecardRefusalReason } from './pelecard.js';
|
|
7
|
+
export type { PrimerUnsupportedReason, PrimerBlockedReason } from './primer.js';
|
|
8
|
+
export { CONVERGE_REFUSAL_REASONS } from './elavon-converge.js';
|
|
9
|
+
export type { ConvergeRefusalReason } from './elavon-converge.js';
|
|
10
|
+
export type { WspayRefusalReason } from './wspay.js';
|
|
11
|
+
export type { ShijiStsUnsupportedReason } from './shiji-sts.js';
|
|
12
|
+
export type { PausedRequest, ReplayResponse, TokenReplay, CseReplay, MerchantHostedReplay, VerifoneReplay, HostedFormReplay, CardEndpointReplay, DeviceEncryptReplay, AmountAuthority, AuthorizeInput, VaultClientOptions, AgentcardOptions, AdyenTestPlatformRefusal, MerchantTotalRefusal, PrepareCheckoutOptions, PrepareCheckoutInput, PreparedCheckout, RazorpayProcessorError, RuntimeCancelReason, ExecutionMetadata, PlaceholderCard, } from './client.js';
|
|
13
|
+
export type { MicroformField, MicroformSidecar } from './cybersource-flex.js';
|
|
5
14
|
export { attachToCdp, attachToPlaywright, corsHeadersFor, corsDecision, withCorsHeaders } from './cdp.js';
|
|
6
15
|
export { CheckoutAttachmentError } from './attachment.js';
|
|
16
|
+
export { CardEndpointRefusedError, cardEndpointPatterns } from './card-endpoint.js';
|
|
17
|
+
export { MerchantSessionRefusedError, captureMerchantSession, merchantSessionCapture, merchantSessionReadUrl } from './merchant-session-probe.js';
|
|
18
|
+
export type { MerchantSessionCapture, MerchantSessionCookie, MerchantSessionCdp, MerchantSessionRefusal } from './merchant-session-probe.js';
|
|
19
|
+
export type { CardEndpointRefusal, CardEndpointSession, CardEndpointCookie } from './card-endpoint.js';
|
|
7
20
|
export type { CdpLike, AttachOptions, CorsOutcome } from './cdp.js';
|
|
8
21
|
export type { StripeCheckoutOptions, StripeCheckoutBlockedDetail, StripeCheckoutBlockStage, StripeCheckoutBlockReason } from './stripe-checkout.js';
|
|
9
22
|
export { substituteEncryptedFields, SubstitutionError } from './substitute.js';
|
|
@@ -13,10 +26,13 @@ export type { MerchantProfile, MerchantProfileStatus, MerchantRequestVerdict, Me
|
|
|
13
26
|
export { MerchantExchangeLog, merchantAmountExchanges, merchantAmountFromResponses, merchantChargeReport, merchantProfilePricedBySource, merchantTotalAtRelease, MERCHANT_EXCHANGES_MAX, } from './merchant-total.js';
|
|
14
27
|
export type { MerchantAmountCard, MerchantExchange, MerchantRequestSeen, MerchantTotalApproved, MerchantTotalCapture, MerchantTotalScope } from './merchant-total.js';
|
|
15
28
|
export { substituteFiservEnvelope } from './fiserv.js';
|
|
29
|
+
export { classifyVerifoneProfileRequest, substituteVerifoneBody } from './verifone.js';
|
|
30
|
+
export type { VerifoneProfile, VerifoneProfileStatus, VerifoneRequestVerdict, VerifoneSubstitutions } from './verifone.js';
|
|
16
31
|
export { hostedFormSubmittedPage, HOSTED_FORM_SUBMITTED_OUTCOME } from './hosted-form.js';
|
|
17
32
|
export type { HostedFormSubmittedPageInput, SyntheticPage } from './hosted-form.js';
|
|
18
33
|
export { BUILTIN_REGISTRY, cardUrlPatterns, findRecognizer, isLoopbackUrl, LOOPBACK_URL_PATTERNS } from './registry.js';
|
|
19
34
|
export type { Recognizer, CheckoutMode, RecognizerOptions } from './registry.js';
|
|
35
|
+
export type { PayrailsSidecar, PayrailsUnsupportedReason } from './payrails.js';
|
|
20
36
|
export type { CheckoutController, CheckoutState, MerchantResult, MerchantPaymentConfirmation, UserAction, LifecycleOptions, PaymentEndpointGuard, PausedCheckout, ResumeResult } from './lifecycle.js';
|
|
21
37
|
export { RequestRegistry, BUILTIN_REQUEST_BUILDERS, stripePaymentIntentConfirm, stripePaymentIntentConfirmRequest, stripeCardTokenRequest, stripePaymentMethodRequest } from './requests.js';
|
|
22
38
|
export type { RequestBuilder, BuildInput, MintedIntent } from './requests.js';
|
|
@@ -32,6 +48,6 @@ export type { WebhookEvent, AgentcardEvent, CheckoutAuthorizationEvent, Checkout
|
|
|
32
48
|
export { readReturnLink } from './voice-pkce.js';
|
|
33
49
|
export type { PkceCrypto } from './voice-pkce.js';
|
|
34
50
|
export { AgentcardError } from './voice-types.js';
|
|
35
|
-
export type { Lang, VoiceAsk, ApprovalPosture, Action, ConnectInput, ConnectResult, Connected, Person, Proposed, Done, ActionState, CreateAuthorizationInput, AuthorizationStatus, Authorization, VoiceResetInput, VoiceChallenge, AuthorizationResult, Verdict, AuthorizationDetail, Exchanged, ExchangeInput, Revoked, TerminalReason, DeliveryChannel, InteractionEvidence, Intent, ApprovalRequestFields, CancelReason, Cancelled, Settlement, SessionState, ReturnLink, VoiceResetOutcome, VaultSessionStep, HostApprovalBundle, AppVoiceKeyDescription, RegisteredAppVoiceKey, RevokedAppVoiceKey, PayingCard, ChoosableCard, } from './voice-types.js';
|
|
51
|
+
export type { Lang, VoiceAsk, ApprovalPosture, Action, ConnectInput, ConnectResult, Connected, Person, Proposed, Done, ActionState, CreateAuthorizationInput, AuthorizationStatus, Authorization, VoiceResetInput, VoiceChallenge, AuthorizationResult, Verdict, AuthorizationDetail, Exchanged, ExchangeInput, Revoked, TerminalReason, DeliveryChannel, InteractionEvidence, Intent, ApprovalRequestFields, CancelReason, Cancelled, Settlement, SessionState, ReturnLink, VoiceResetOutcome, VaultSessionStep, HostApprovalBundle, AppVoiceKeyDescription, HardwareAttestation, RegisteredAppVoiceKey, RevokedAppVoiceKey, PayingCard, ChoosableCard, } from './voice-types.js';
|
|
36
52
|
export { openStream, streamBuffer } from './voice-stream.generated.js';
|
|
37
53
|
export type { Hearing, StreamFormat, StreamHandle, StreamInput, StreamVerdict, ChannelKind } from './voice-stream.generated.js';
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
// The one client and its modules. `VaultClient` is the client's older name and
|
|
2
2
|
// stays importable for one release; it constructs the same object.
|
|
3
3
|
export { Agentcard, Agentcard as VaultClient, CheckoutModule } from './agentcard.js';
|
|
4
|
-
export { CardEncryptedError, UnsupportedModeError, PreparationRequiredError, ApprovalTimeoutError, ApprovalDeclinedError, AmountMismatchError, PresetRefusedError, PRESET_REFUSAL_REASONS, IntentNotConfirmableError, ProcessorRefusedError, CheckoutApiError, CheckoutAuthError, redactUrl, SUPPORTED_MODES, PaymentOutcomeUnknownError, CheckoutCancelledError, CheckoutPreparationError, AdyenTestPlatformRefusedError, MerchantTotalError, } from './client.js';
|
|
4
|
+
export { CardEncryptedError, UnsupportedModeError, UnsupportedCapabilityError, PreparationRequiredError, AmountRequiredError, PageAmountRequiredError, ApprovalTimeoutError, ApprovalDeclinedError, AmountMismatchError, PresetRefusedError, PRESET_REFUSAL_REASONS, IntentNotConfirmableError, ProcessorRefusedError, CheckoutApiError, CheckoutAuthError, redactUrl, SUPPORTED_MODES, SUPPORTED_CAPABILITIES, PaymentOutcomeUnknownError, CheckoutCancelledError, CheckoutPreparationError, AdyenTestPlatformRefusedError, MerchantTotalError, PlaceholderCardError, } from './client.js';
|
|
5
|
+
export { CONVERGE_REFUSAL_REASONS } from './elavon-converge.js';
|
|
5
6
|
export { attachToCdp, attachToPlaywright, corsHeadersFor, corsDecision, withCorsHeaders } from './cdp.js';
|
|
6
7
|
export { CheckoutAttachmentError } from './attachment.js';
|
|
8
|
+
export { CardEndpointRefusedError, cardEndpointPatterns } from './card-endpoint.js';
|
|
9
|
+
// The merchant-session probe's capture (the deterministic merchant total, phase 0): no card, no Pay.
|
|
10
|
+
export { MerchantSessionRefusedError, captureMerchantSession, merchantSessionCapture, merchantSessionReadUrl } from './merchant-session-probe.js';
|
|
7
11
|
export { substituteEncryptedFields, SubstitutionError } from './substitute.js';
|
|
8
12
|
export { classifyDeclaredMerchantRequest, classifyMerchantRequest, substituteMerchantHostedBody } from './merchant-hosted.js';
|
|
9
13
|
// The merchant's own total for a raw CDP runtime that intercepts on its own (merchant-total.ts).
|
|
10
14
|
export { MerchantExchangeLog, merchantAmountExchanges, merchantAmountFromResponses, merchantChargeReport, merchantProfilePricedBySource, merchantTotalAtRelease, MERCHANT_EXCHANGES_MAX, } from './merchant-total.js';
|
|
11
15
|
export { substituteFiservEnvelope } from './fiserv.js';
|
|
16
|
+
export { classifyVerifoneProfileRequest, substituteVerifoneBody } from './verifone.js';
|
|
12
17
|
export { hostedFormSubmittedPage, HOSTED_FORM_SUBMITTED_OUTCOME } from './hosted-form.js';
|
|
13
18
|
export { BUILTIN_REGISTRY, cardUrlPatterns, findRecognizer, isLoopbackUrl, LOOPBACK_URL_PATTERNS } from './registry.js';
|
|
14
19
|
// The request builders: `agentcard.checkout.requests`, and the shipped builders as functions.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export declare const JUSPAY_PSP = "juspay";
|
|
2
|
+
/** The capability the API serves the Juspay recognizer behind (payment-core definitions.js). */
|
|
3
|
+
export declare const JUSPAY_CAPABILITY = "juspay_txns.v1";
|
|
4
|
+
/**
|
|
5
|
+
* Fetch.enable globs for every host the gate judges. The registry arms api.juspay.in and
|
|
6
|
+
* sandbox.juspay.in already; api.juspay.io and api-ns1.juspay.in are Juspay's too and in no
|
|
7
|
+
* recognizer, so without these a card request there would never pause to be refused.
|
|
8
|
+
*/
|
|
9
|
+
export declare const JUSPAY_URL_PATTERNS: readonly string[];
|
|
10
|
+
/** The request a gate judges: the pre-claim context's own shape (body null when the adapter could not read it). */
|
|
11
|
+
export interface JuspayRequest {
|
|
12
|
+
url: string;
|
|
13
|
+
method: string;
|
|
14
|
+
headers: Record<string, string>;
|
|
15
|
+
body: string | null;
|
|
16
|
+
}
|
|
17
|
+
/** payment-core classifyJuspayRequest's verdict. `reason` is its fixed vocabulary; nothing the page wrote is echoed. */
|
|
18
|
+
export type JuspayDecision = {
|
|
19
|
+
decision: 'answer_tokenize';
|
|
20
|
+
reason: string;
|
|
21
|
+
host: string;
|
|
22
|
+
merchantId: string;
|
|
23
|
+
} | {
|
|
24
|
+
decision: 'pause' | 'continue' | 'abort';
|
|
25
|
+
reason: string;
|
|
26
|
+
};
|
|
27
|
+
export declare class JuspayCheckoutGate {
|
|
28
|
+
private readonly vault;
|
|
29
|
+
/** Each synthetic token this attachment answered a tokenize with, and the host and merchant it answered. */
|
|
30
|
+
private readonly issued;
|
|
31
|
+
constructor(vault: {
|
|
32
|
+
isCardRequest(url: string, method?: string): boolean;
|
|
33
|
+
} | undefined);
|
|
34
|
+
/** On while the registry recognizes a Juspay /txns: after a sync that declared juspay_txns.v1, for an org Juspay is on for. */
|
|
35
|
+
isEnabled(): boolean;
|
|
36
|
+
/** Whether this URL is on a Juspay host the gate judges: the Playwright route matcher's test. */
|
|
37
|
+
matches(url: string): boolean;
|
|
38
|
+
/** The Fetch.enable globs the CDP adapter arms beside the registry's own, while the gate is on. */
|
|
39
|
+
urlPatterns(): string[];
|
|
40
|
+
/**
|
|
41
|
+
* The verdict on a request, or null when it is not on a Juspay host or the gate is off. A POST
|
|
42
|
+
* whose body the adapter could not read (CDP reported one without its bytes, or Playwright
|
|
43
|
+
* reported the page's empty form post as no body) is judged as having no body by the classifier,
|
|
44
|
+
* so it passes only as this checkout's own pay/start redirect: a link an allowlisted answer names,
|
|
45
|
+
* on a host, and for the v2 link a merchant, that a token in `issued` was answered for. Anything
|
|
46
|
+
* else is refused for that request alone.
|
|
47
|
+
*/
|
|
48
|
+
classify(request: JuspayRequest): JuspayDecision | null;
|
|
49
|
+
/**
|
|
50
|
+
* Mint the synthetic token a placeholder tokenize is answered with, from 16 bytes of this
|
|
51
|
+
* runtime's cryptographic randomness, and remember it for the /txns that follows. It names no
|
|
52
|
+
* card and Juspay never issued it, so it pays nothing anywhere.
|
|
53
|
+
*/
|
|
54
|
+
issue(host: string, merchantId: string): {
|
|
55
|
+
token: string;
|
|
56
|
+
response: {
|
|
57
|
+
status: number;
|
|
58
|
+
headers: Record<string, string>;
|
|
59
|
+
body: string;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
/** A token whose answer never reached the page: no /txns may pause on it. */
|
|
63
|
+
forget(token: string): void;
|
|
64
|
+
/**
|
|
65
|
+
* Whether an approval must end with the request that raised it. Every Juspay /txns names its
|
|
66
|
+
* own order_id, and a page that clicks Pay again creates a new order, so an approval for one
|
|
67
|
+
* order never answers another order's request.
|
|
68
|
+
*/
|
|
69
|
+
bindsApproval(url: string, method: string): boolean;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The answer an approved Juspay /txns hands the page, or null. Only a 200 in the allowlisted
|
|
73
|
+
* shape passes (payment-core sanitizeJuspayTxnsResponse against the paused request: the paused
|
|
74
|
+
* order, a status Juspay approves with, and the bank's pay/start redirect on the paused host with
|
|
75
|
+
* no card token and no card number anywhere), and it is re-serialized here, so a field the API
|
|
76
|
+
* stored beyond that shape never reaches the page.
|
|
77
|
+
*/
|
|
78
|
+
export declare function juspayPageAnswer(status: number, body: string, request: {
|
|
79
|
+
url: string;
|
|
80
|
+
headers: Record<string, string>;
|
|
81
|
+
body: string;
|
|
82
|
+
}): string | null;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// Juspay Express Checkout in the checkout SDK: what one attachment keeps between the requests of
|
|
2
|
+
// the card flow Swiggy web ships. payment-core's juspay.js holds the protocol and its rules
|
|
3
|
+
// (vendored unchanged as juspay.generated.ts); nothing here decides what a body means.
|
|
4
|
+
//
|
|
5
|
+
// Swiggy's page sends the card in two form POSTs from its own document: /card/tokenize with the
|
|
6
|
+
// card, then /txns with the token Juspay returned and the CVV again. A real token needs no
|
|
7
|
+
// merchant secret and pays any order of that merchant for 15 minutes, so the agent's page must
|
|
8
|
+
// never hold one, and the agent's placeholder must never reach Juspay. The SDK therefore answers
|
|
9
|
+
// the placeholder tokenize itself, with a synthetic ctkn_agentcard token minted here and
|
|
10
|
+
// remembered with the host and merchant it was minted for, and pauses only the /txns that carries
|
|
11
|
+
// one of those tokens. The cardholder's device then sends both real requests, and the page
|
|
12
|
+
// receives the allowlisted /txns answer (juspayPageAnswer).
|
|
13
|
+
//
|
|
14
|
+
// Dark launch: the gate is on only while the registry this attachment runs on recognizes a
|
|
15
|
+
// Juspay /txns, which the API serves to a build that declares juspay_txns.v1 on syncRegistry(),
|
|
16
|
+
// and only for an org Agentcard turned Juspay on for. Off, every request to a Juspay host is
|
|
17
|
+
// handled exactly as it was before this module existed.
|
|
18
|
+
import { classifyJuspayRequest, juspaySyntheticToken, juspayTokenizeAnswer, sanitizeJuspayTxnsResponse, JUSPAY_API_HOSTS, JUSPAY_SIBLING_HOSTS, } from './juspay.generated.js';
|
|
19
|
+
export const JUSPAY_PSP = 'juspay';
|
|
20
|
+
/** The capability the API serves the Juspay recognizer behind (payment-core definitions.js). */
|
|
21
|
+
export const JUSPAY_CAPABILITY = 'juspay_txns.v1';
|
|
22
|
+
const HOSTS = [...JUSPAY_API_HOSTS, ...JUSPAY_SIBLING_HOSTS];
|
|
23
|
+
/**
|
|
24
|
+
* Fetch.enable globs for every host the gate judges. The registry arms api.juspay.in and
|
|
25
|
+
* sandbox.juspay.in already; api.juspay.io and api-ns1.juspay.in are Juspay's too and in no
|
|
26
|
+
* recognizer, so without these a card request there would never pause to be refused.
|
|
27
|
+
*/
|
|
28
|
+
export const JUSPAY_URL_PATTERNS = HOSTS.map((host) => `*${host}*`);
|
|
29
|
+
/** The /txns of each environment: the registry recognizing either one is what turns the gate on. */
|
|
30
|
+
const TXNS_URLS = JUSPAY_API_HOSTS.map((host) => `https://${host}/txns`);
|
|
31
|
+
/** Synthetic tokens one attachment remembers; past this, the oldest is forgotten first. */
|
|
32
|
+
const MAX_ISSUED = 64;
|
|
33
|
+
/** A Juspay host, in any letter case and with any trailing dot, which DNS reads as the same host. */
|
|
34
|
+
function juspayHost(url) {
|
|
35
|
+
try {
|
|
36
|
+
return HOSTS.includes(new URL(url).hostname.toLowerCase().replace(/\.+$/, ''));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export class JuspayCheckoutGate {
|
|
43
|
+
vault;
|
|
44
|
+
/** Each synthetic token this attachment answered a tokenize with, and the host and merchant it answered. */
|
|
45
|
+
issued = new Map();
|
|
46
|
+
constructor(vault) {
|
|
47
|
+
this.vault = vault;
|
|
48
|
+
}
|
|
49
|
+
/** On while the registry recognizes a Juspay /txns: after a sync that declared juspay_txns.v1, for an org Juspay is on for. */
|
|
50
|
+
isEnabled() {
|
|
51
|
+
try {
|
|
52
|
+
return TXNS_URLS.some((url) => this.vault?.isCardRequest(url, 'POST') === true);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Whether this URL is on a Juspay host the gate judges: the Playwright route matcher's test. */
|
|
59
|
+
matches(url) {
|
|
60
|
+
return juspayHost(url) && this.isEnabled();
|
|
61
|
+
}
|
|
62
|
+
/** The Fetch.enable globs the CDP adapter arms beside the registry's own, while the gate is on. */
|
|
63
|
+
urlPatterns() {
|
|
64
|
+
return this.isEnabled() ? [...JUSPAY_URL_PATTERNS] : [];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The verdict on a request, or null when it is not on a Juspay host or the gate is off. A POST
|
|
68
|
+
* whose body the adapter could not read (CDP reported one without its bytes, or Playwright
|
|
69
|
+
* reported the page's empty form post as no body) is judged as having no body by the classifier,
|
|
70
|
+
* so it passes only as this checkout's own pay/start redirect: a link an allowlisted answer names,
|
|
71
|
+
* on a host, and for the v2 link a merchant, that a token in `issued` was answered for. Anything
|
|
72
|
+
* else is refused for that request alone.
|
|
73
|
+
*/
|
|
74
|
+
classify(request) {
|
|
75
|
+
if (!this.matches(request.url))
|
|
76
|
+
return null;
|
|
77
|
+
const decision = classifyJuspayRequest(request, this.issued);
|
|
78
|
+
if (decision && request.body === null && String(request.method).toUpperCase() === 'POST'
|
|
79
|
+
&& !(decision.decision === 'continue' && decision.reason === 'pay_start')) {
|
|
80
|
+
return { decision: 'abort', reason: 'request_body_unreadable' };
|
|
81
|
+
}
|
|
82
|
+
return decision;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Mint the synthetic token a placeholder tokenize is answered with, from 16 bytes of this
|
|
86
|
+
* runtime's cryptographic randomness, and remember it for the /txns that follows. It names no
|
|
87
|
+
* card and Juspay never issued it, so it pays nothing anywhere.
|
|
88
|
+
*/
|
|
89
|
+
issue(host, merchantId) {
|
|
90
|
+
const token = juspaySyntheticToken(crypto.getRandomValues(new Uint8Array(16)));
|
|
91
|
+
if (this.issued.size >= MAX_ISSUED)
|
|
92
|
+
this.issued.delete(this.issued.keys().next().value);
|
|
93
|
+
this.issued.set(token, { host, merchantId });
|
|
94
|
+
return { token, response: juspayTokenizeAnswer(token) };
|
|
95
|
+
}
|
|
96
|
+
/** A token whose answer never reached the page: no /txns may pause on it. */
|
|
97
|
+
forget(token) {
|
|
98
|
+
this.issued.delete(token);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Whether an approval must end with the request that raised it. Every Juspay /txns names its
|
|
102
|
+
* own order_id, and a page that clicks Pay again creates a new order, so an approval for one
|
|
103
|
+
* order never answers another order's request.
|
|
104
|
+
*/
|
|
105
|
+
bindsApproval(url, method) {
|
|
106
|
+
return String(method).toUpperCase() === 'POST' && this.matches(url);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The answer an approved Juspay /txns hands the page, or null. Only a 200 in the allowlisted
|
|
111
|
+
* shape passes (payment-core sanitizeJuspayTxnsResponse against the paused request: the paused
|
|
112
|
+
* order, a status Juspay approves with, and the bank's pay/start redirect on the paused host with
|
|
113
|
+
* no card token and no card number anywhere), and it is re-serialized here, so a field the API
|
|
114
|
+
* stored beyond that shape never reaches the page.
|
|
115
|
+
*/
|
|
116
|
+
export function juspayPageAnswer(status, body, request) {
|
|
117
|
+
if (status !== 200)
|
|
118
|
+
return null;
|
|
119
|
+
// No token argument: like the API, the SDK never holds the real token the device's tokenize returned.
|
|
120
|
+
try {
|
|
121
|
+
return sanitizeJuspayTxnsResponse(body, request, undefined);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
declare var JUSPAY_API_HOSTS: readonly ("api.juspay.in" | "sandbox.juspay.in")[];
|
|
2
|
+
declare var JUSPAY_SIBLING_HOSTS: readonly string[];
|
|
3
|
+
declare var JUSPAY_SYNTHETIC_TOKEN: RegExp;
|
|
4
|
+
declare var JUSPAY_APPROVED_STATUSES: readonly string[];
|
|
5
|
+
declare var JUSPAY_REFUSED_STATUSES: readonly string[];
|
|
6
|
+
declare var JUSPAY_TOKENIZE_NETWORK: string;
|
|
7
|
+
declare function parseJuspayForm(body: any): {
|
|
8
|
+
key: string;
|
|
9
|
+
value: string;
|
|
10
|
+
valueStart: number;
|
|
11
|
+
valueEnd: number;
|
|
12
|
+
}[] | null;
|
|
13
|
+
declare function juspayEnvironment(url: any): "production" | "sandbox" | undefined;
|
|
14
|
+
declare function isJuspaySyntheticToken(value: any): boolean;
|
|
15
|
+
declare function juspaySyntheticToken(bytes: any): string;
|
|
16
|
+
declare function juspayTokenizeAnswer(token: any): {
|
|
17
|
+
status: number;
|
|
18
|
+
headers: {
|
|
19
|
+
"content-type": string;
|
|
20
|
+
};
|
|
21
|
+
body: string;
|
|
22
|
+
};
|
|
23
|
+
declare function juspayTxnsTemplateRefusal(url: any, headers: any, body: any): "card_token" | "format" | "merchant_id" | "card_security_code" | "merchant_mismatch" | "juspay_endpoint" | "content_type" | "unreadable_body" | "unsupported_field" | "missing_field" | "order_id" | "routing_id" | "payment_method_type" | "redirect_after_payment" | "save_to_locker" | "tokenize" | "card_nickname" | null;
|
|
24
|
+
declare function assertJuspayTxnsTemplate(url: any, headers: any, body: any): Readonly<{
|
|
25
|
+
environment: "production" | "sandbox" | undefined;
|
|
26
|
+
host: any;
|
|
27
|
+
txnsUrl: any;
|
|
28
|
+
tokenizeUrl: any;
|
|
29
|
+
orderId: string | undefined;
|
|
30
|
+
merchantId: string | undefined;
|
|
31
|
+
routingId: string | null;
|
|
32
|
+
contentType: string;
|
|
33
|
+
}>;
|
|
34
|
+
declare function classifyJuspayRequest(request: any, issued: any): {
|
|
35
|
+
decision: any;
|
|
36
|
+
reason: any;
|
|
37
|
+
} | null;
|
|
38
|
+
declare function juspayTokenizeRequest(request: any, card: any): {
|
|
39
|
+
url: any;
|
|
40
|
+
method: string;
|
|
41
|
+
headers: {
|
|
42
|
+
"x-routing-id"?: any;
|
|
43
|
+
"content-type": any;
|
|
44
|
+
"x-merchantid": any;
|
|
45
|
+
};
|
|
46
|
+
body: string;
|
|
47
|
+
};
|
|
48
|
+
declare function juspayTxnsRequest(request: any, token: any, cvc: any): {
|
|
49
|
+
url: any;
|
|
50
|
+
method: string;
|
|
51
|
+
headers: {
|
|
52
|
+
"x-routing-id"?: any;
|
|
53
|
+
"content-type": any;
|
|
54
|
+
"x-merchantid": any;
|
|
55
|
+
};
|
|
56
|
+
body: any;
|
|
57
|
+
};
|
|
58
|
+
declare function juspayResponseFacts(text: any): {
|
|
59
|
+
errorCode: string | null;
|
|
60
|
+
status: string | null;
|
|
61
|
+
};
|
|
62
|
+
declare function readJuspayTokenizeReply(status: any, text: any): {
|
|
63
|
+
ok: boolean;
|
|
64
|
+
token: string;
|
|
65
|
+
code?: undefined;
|
|
66
|
+
} | {
|
|
67
|
+
ok: boolean;
|
|
68
|
+
code: string;
|
|
69
|
+
token?: undefined;
|
|
70
|
+
};
|
|
71
|
+
declare function isJuspayTokenizeRefusal(code: any): boolean;
|
|
72
|
+
declare function sanitizeJuspayTxnsResponse(text: any, template: any, token: any): string;
|
|
73
|
+
declare function juspayTxnsOutcome(status: any, text: any, template: any, token: any): {
|
|
74
|
+
outcome: string;
|
|
75
|
+
reason: string;
|
|
76
|
+
code?: undefined;
|
|
77
|
+
body?: undefined;
|
|
78
|
+
} | {
|
|
79
|
+
outcome: string;
|
|
80
|
+
code: any;
|
|
81
|
+
reason?: undefined;
|
|
82
|
+
body?: undefined;
|
|
83
|
+
} | {
|
|
84
|
+
outcome: string;
|
|
85
|
+
body: string;
|
|
86
|
+
reason?: undefined;
|
|
87
|
+
code?: undefined;
|
|
88
|
+
};
|
|
89
|
+
export { JUSPAY_API_HOSTS, JUSPAY_APPROVED_STATUSES, JUSPAY_REFUSED_STATUSES, JUSPAY_SIBLING_HOSTS, JUSPAY_SYNTHETIC_TOKEN, JUSPAY_TOKENIZE_NETWORK, assertJuspayTxnsTemplate, classifyJuspayRequest, isJuspaySyntheticToken, isJuspayTokenizeRefusal, juspayEnvironment, juspayResponseFacts, juspaySyntheticToken, juspayTokenizeAnswer, juspayTokenizeRequest, juspayTxnsOutcome, juspayTxnsRequest, juspayTxnsTemplateRefusal, parseJuspayForm, readJuspayTokenizeReply, sanitizeJuspayTxnsResponse };
|