@agent-cards/sdk 0.21.0 → 0.23.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 +87 -2
- package/PREFLIGHT.md +32 -0
- package/README.md +1177 -23
- 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 +302 -56
- 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-facts.d.ts +96 -0
- package/dist/card-endpoint-facts.js +275 -0
- package/dist/card-endpoint-page.d.ts +54 -0
- package/dist/card-endpoint-page.js +69 -0
- package/dist/card-endpoint.d.ts +298 -0
- package/dist/card-endpoint.js +438 -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 +1155 -141
- package/dist/client.d.ts +456 -20
- package/dist/client.js +1072 -104
- 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 +30 -0
- package/dist/cybersource-flex.generated.d.ts +27 -1
- package/dist/cybersource-flex.generated.js +42 -2
- package/dist/cybersource-flex.js +46 -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/ekashu.d.ts +35 -0
- package/dist/ekashu.js +55 -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 +60 -6
- package/dist/lifecycle.js +122 -8
- package/dist/merchant-card-endpoints.generated.d.ts +122 -0
- package/dist/merchant-card-endpoints.generated.js +4261 -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 +81 -2
- package/dist/pre-claim.js +1023 -5
- package/dist/preflight-catalog.json +2267 -288
- package/dist/preflight-schemas.json +183 -6
- package/dist/preflight.generated.d.ts +1 -1
- package/dist/preflight.generated.js +243 -4
- package/dist/preparation.d.ts +12 -3
- package/dist/preparation.js +63 -12
- 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 +764 -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 +1413 -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/eprotect.js
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
// Worldpay eProtect (Vantiv / Litle PayPage): the adapters' side of its card registration.
|
|
2
|
+
//
|
|
3
|
+
// The vendor's browser script (eProtect-api2/3, litle-api2/3, and the Worldpay iframe, which runs
|
|
4
|
+
// them in a Worldpay-origin frame) encrypts the card in the page and sends it as ONE JSONP
|
|
5
|
+
// <script> GET to /eProtect/paypage; the answer is `<callback>({...})`. The rules that judge that
|
|
6
|
+
// request (the query grammar, the pinned keys, the failover and give-up reports, the answer
|
|
7
|
+
// allowlist) live in payment-core and reach this SDK as eprotect.generated.ts. This module holds
|
|
8
|
+
// only what an attachment decides from them:
|
|
9
|
+
// - which request on eProtect's hosts is the registration to pause for the vault;
|
|
10
|
+
// - which is the vendor's failover re-send of a registration the page already sent (aborted
|
|
11
|
+
// quietly: it carries the placeholder's ciphertext and is never a destination);
|
|
12
|
+
// - which is the vendor's own report that it gave up (/eProtect/ppstats 900 or 901), which ends
|
|
13
|
+
// the approval running for that registration;
|
|
14
|
+
// - the script answer the paused registration gets once the cardholder's device registered the
|
|
15
|
+
// real card: the registration Agentcard stored, wrapped in the callback the paused URL named.
|
|
16
|
+
import { EPROTECT_HOSTS, EPROTECT_PATH, EPROTECT_SECONDARY_HOST, eprotectGiveUp, eprotectJsonp, eprotectMerchantPin, eprotectOutcome, eprotectRequestFacts, eprotectSecondaryAttempt, isEprotectRequest, } from './eprotect.generated.js';
|
|
17
|
+
/** The processor id, as the registry and the API name it. */
|
|
18
|
+
export const EPROTECT_PSP = 'worldpay_eprotect';
|
|
19
|
+
/** The dark-launch capability the API serves the eProtect recognizer behind (payment-core definitions.js). */
|
|
20
|
+
export const EPROTECT_CAPABILITY = 'worldpay_eprotect_jsonp';
|
|
21
|
+
/** What Worldpay answers a registration with on both of its card hosts, and what the paused script gets. */
|
|
22
|
+
export const EPROTECT_SCRIPT_CONTENT_TYPE = 'application/x-javascript;charset=UTF-8';
|
|
23
|
+
const EPROTECT_HOSTNAMES = [EPROTECT_HOSTS.production, EPROTECT_HOSTS.sandbox, EPROTECT_SECONDARY_HOST];
|
|
24
|
+
/**
|
|
25
|
+
* Why a Worldpay eProtect checkout may not be prepared under `merchant`, or null when it may. On the
|
|
26
|
+
* production host the API admits only a paypageId payment-core pins for the merchant origin, under
|
|
27
|
+
* that pin's merchant name, the one the approval shows, and refuses another name
|
|
28
|
+
* (merchant_profile_mismatch) before any preparation exists. When this build pins the paypageId
|
|
29
|
+
* too, it refuses another name first, before any network call, as a Fiserv checkout must name its
|
|
30
|
+
* key pin's merchant. A paypageId this build does not pin is the API's to judge (unsupported_checkout
|
|
31
|
+
* with no pin); none is pinned on either side yet. The pre-live host takes only the guide's test
|
|
32
|
+
* cards and needs no pin. `pins` is for tests.
|
|
33
|
+
*/
|
|
34
|
+
export function eprotectCheckoutRefusal(input, pins) {
|
|
35
|
+
if (input.environment !== 'production')
|
|
36
|
+
return null;
|
|
37
|
+
const pin = eprotectMerchantPin(input.paypageId, input.merchantOrigin, pins);
|
|
38
|
+
return pin && pin.merchant !== input.merchant ? 'merchant_profile_mismatch' : null;
|
|
39
|
+
}
|
|
40
|
+
/** Which eProtect request this is, or null for a URL that is not on one of Worldpay eProtect's hosts. */
|
|
41
|
+
export function classifyEprotectRequest(url, method) {
|
|
42
|
+
let parsed;
|
|
43
|
+
try {
|
|
44
|
+
parsed = new URL(url);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
if (parsed.protocol !== 'https:' || parsed.port || parsed.username || parsed.password
|
|
50
|
+
|| !EPROTECT_HOSTNAMES.includes(parsed.hostname))
|
|
51
|
+
return null;
|
|
52
|
+
const get = typeof method === 'string' && method.toUpperCase() === 'GET';
|
|
53
|
+
// Every spelling of the registration path belongs to the registration family: the exact path
|
|
54
|
+
// carries the card, and any neighbour of it is nothing this SDK completes.
|
|
55
|
+
if (parsed.pathname.toLowerCase().startsWith(EPROTECT_PATH.toLowerCase())) {
|
|
56
|
+
const facts = get ? eprotectRequestFacts(url) : null;
|
|
57
|
+
if (facts)
|
|
58
|
+
return { kind: 'registration', paypageId: facts.paypageId, id: facts.id };
|
|
59
|
+
const repeat = get ? eprotectSecondaryAttempt(url) : null;
|
|
60
|
+
if (repeat)
|
|
61
|
+
return { kind: 'failover', paypageId: repeat.paypageId, id: repeat.id };
|
|
62
|
+
return { kind: 'unsupported' };
|
|
63
|
+
}
|
|
64
|
+
const report = get ? eprotectGiveUp(url) : null;
|
|
65
|
+
if (report)
|
|
66
|
+
return { kind: 'give_up', code: report.code, paypageId: report.paypageId, id: report.txnId };
|
|
67
|
+
return { kind: 'sibling' };
|
|
68
|
+
}
|
|
69
|
+
/** The registration GET exactly as payment-core admits it: its URL alone, with no body. */
|
|
70
|
+
export function isEprotectRegistration(request) {
|
|
71
|
+
return (request.method ?? 'POST').toUpperCase() === 'GET'
|
|
72
|
+
&& isEprotectRequest({ url: request.url, method: 'GET', body: request.body ?? '' });
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The answer a paused registration script gets, or null when the stored answer is not one to hand
|
|
76
|
+
* the page: Worldpay's own shape, `<callback>(<registration>)` under its script type, with the
|
|
77
|
+
* callback the paused URL named. The registration must be one payment-core's judge accepts for that
|
|
78
|
+
* exact URL (response 870, the page's own id, only allowlisted fields), byte for byte what the API
|
|
79
|
+
* stored after running the same judge.
|
|
80
|
+
*/
|
|
81
|
+
export function eprotectScriptAnswer(templateUrl, response) {
|
|
82
|
+
const facts = eprotectRequestFacts(templateUrl);
|
|
83
|
+
if (!facts || response.status !== 200 || typeof response.body !== 'string')
|
|
84
|
+
return null;
|
|
85
|
+
let body;
|
|
86
|
+
try {
|
|
87
|
+
body = eprotectJsonp(facts.callback, response.body);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
const verdict = eprotectOutcome(200, body, templateUrl, undefined);
|
|
93
|
+
if (verdict.outcome !== 'registered' || verdict.sanitizedJson !== response.body)
|
|
94
|
+
return null;
|
|
95
|
+
return { status: 200, headers: { 'content-type': EPROTECT_SCRIPT_CONTENT_TYPE }, body };
|
|
96
|
+
}
|
|
97
|
+
const attemptKey = (attempt) => JSON.stringify([attempt.paypageId, attempt.id]);
|
|
98
|
+
/**
|
|
99
|
+
* How long a paused registration's re-send is still recognized as a known repeat. The vendor
|
|
100
|
+
* scripts re-send 5 seconds after an unanswered primary and give up at the merchant's own timeout
|
|
101
|
+
* (10 to 15 seconds at the merchants this SDK covers), so a minute leaves room for a timer a busy
|
|
102
|
+
* page delays. A re-send that comes later still is aborted all the same, as unsupported (pre-claim).
|
|
103
|
+
*/
|
|
104
|
+
export const EPROTECT_REPEAT_WINDOW_MS = 60_000;
|
|
105
|
+
/** At most this many paused registrations are remembered at once; the oldest is forgotten first. */
|
|
106
|
+
export const EPROTECT_REPEAT_LIMIT = 64;
|
|
107
|
+
/**
|
|
108
|
+
* One attachment's eProtect state. A failover re-send or a give-up report names a registration by
|
|
109
|
+
* paypageId and id; each is matched against what this attachment itself paused and answered, never
|
|
110
|
+
* taken on the page's word. Inert (classify returns null) until the registry serves eProtect, which
|
|
111
|
+
* a client reaches only by syncing with the capability for an org the API enabled, so a build, an
|
|
112
|
+
* org or an API that never served it leaves every eProtect request exactly as before.
|
|
113
|
+
*/
|
|
114
|
+
export class EprotectGate {
|
|
115
|
+
vault;
|
|
116
|
+
now;
|
|
117
|
+
/** Paused registrations, oldest first, each with the time its re-send window closes. */
|
|
118
|
+
seen = new Map();
|
|
119
|
+
running = null;
|
|
120
|
+
answered = null;
|
|
121
|
+
constructor(vault, now = Date.now) {
|
|
122
|
+
this.vault = vault;
|
|
123
|
+
this.now = now;
|
|
124
|
+
}
|
|
125
|
+
/** What this request is, when the registry serves eProtect and the URL is on its hosts; null leaves it to the other gates. */
|
|
126
|
+
classify(url, method) {
|
|
127
|
+
if (typeof this.vault?.recognizesProcessor !== 'function' || !this.vault.recognizesProcessor(EPROTECT_PSP))
|
|
128
|
+
return null;
|
|
129
|
+
return classifyEprotectRequest(url, method);
|
|
130
|
+
}
|
|
131
|
+
/** Playwright's route predicate sees only the URL: route the registration family and the give-up reports, never the scripts. */
|
|
132
|
+
matches(url) {
|
|
133
|
+
const request = this.classify(url, 'GET');
|
|
134
|
+
return request !== null && request.kind !== 'sibling';
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* The page sent this registration and this attachment paused it: its re-send is then a known
|
|
138
|
+
* repeat for EPROTECT_REPEAT_WINDOW_MS. Seeing it again restarts that window. A long-lived
|
|
139
|
+
* attachment keeps at most EPROTECT_REPEAT_LIMIT of them, so repeated attempts never grow it.
|
|
140
|
+
*/
|
|
141
|
+
saw(attempt) {
|
|
142
|
+
const now = this.now();
|
|
143
|
+
this.forgetBefore(now);
|
|
144
|
+
const key = attemptKey(attempt);
|
|
145
|
+
this.seen.delete(key);
|
|
146
|
+
this.seen.set(key, now + EPROTECT_REPEAT_WINDOW_MS);
|
|
147
|
+
for (const oldest of this.seen.keys()) {
|
|
148
|
+
if (this.seen.size <= EPROTECT_REPEAT_LIMIT)
|
|
149
|
+
break;
|
|
150
|
+
this.seen.delete(oldest);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/** Drops every registration whose re-send window closed: the map is in window order. */
|
|
154
|
+
forgetBefore(now) {
|
|
155
|
+
for (const [key, until] of this.seen) {
|
|
156
|
+
if (until > now)
|
|
157
|
+
break;
|
|
158
|
+
this.seen.delete(key);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* A re-send of a registration this attachment paused, whether its approval is running, answered,
|
|
163
|
+
* or never started. The vendor script re-sends 5 seconds after an unanswered primary and has no
|
|
164
|
+
* error path, so a primary the adapters refused before any approval (no ready preparation, another
|
|
165
|
+
* paypageId, an approval already outstanding) or answered just as that timer fired is re-sent
|
|
166
|
+
* too. Such a re-send is aborted quietly, like one during the approval, and never replaces that
|
|
167
|
+
* refusal's own state with `unsupported`. A re-send of a registration this attachment never paused
|
|
168
|
+
* means the primary went somewhere it does not cover, and pre-claim aborts that one as unsupported.
|
|
169
|
+
* Both carry the placeholder's ciphertext, and both are aborted. A registration is remembered
|
|
170
|
+
* only for its re-send window (saw).
|
|
171
|
+
*/
|
|
172
|
+
repeats(attempt) {
|
|
173
|
+
this.forgetBefore(this.now());
|
|
174
|
+
return this.seen.has(attemptKey(attempt));
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* An approval is running for this paused request, when it is a registration; `stop` ends it as the
|
|
178
|
+
* page abandoning its request. A new attempt also retires the last answered registration: a
|
|
179
|
+
* give-up report for it now belongs to a checkout the lifecycle has moved past, and must not end
|
|
180
|
+
* the attempt that just began (see gaveUp).
|
|
181
|
+
*/
|
|
182
|
+
begin(url, method, stop) {
|
|
183
|
+
const request = classifyEprotectRequest(url, method);
|
|
184
|
+
this.running = request?.kind === 'registration' ? { key: attemptKey(request), stop } : null;
|
|
185
|
+
this.answered = null;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* The approval's answer reached this registration; `lost` reports that the page had already given
|
|
189
|
+
* up on it. Kept after the attempt ends, since the vendor's report can land just after the answer,
|
|
190
|
+
* and only until the next attempt begins.
|
|
191
|
+
*/
|
|
192
|
+
delivered(url, lost) {
|
|
193
|
+
const request = classifyEprotectRequest(url, 'GET');
|
|
194
|
+
if (request?.kind === 'registration')
|
|
195
|
+
this.answered = { key: attemptKey(request), lost };
|
|
196
|
+
}
|
|
197
|
+
/** The approval for the paused request ended, answered or not. */
|
|
198
|
+
end() { this.running = null; }
|
|
199
|
+
/**
|
|
200
|
+
* The vendor's give-up report: end the approval still running for that registration (the
|
|
201
|
+
* adapter cancels the authorization, which the API confirms only before the device registered
|
|
202
|
+
* the card, and aborts the paused script instead of answering it), or report that the answer
|
|
203
|
+
* already handed to it came too late. Returns which one, or null when the report names neither,
|
|
204
|
+
* including a registration answered before the current attempt began.
|
|
205
|
+
*/
|
|
206
|
+
gaveUp(attempt) {
|
|
207
|
+
const key = attemptKey(attempt);
|
|
208
|
+
if (this.running?.key === key) {
|
|
209
|
+
const { stop } = this.running;
|
|
210
|
+
this.running = null;
|
|
211
|
+
stop();
|
|
212
|
+
return 'running';
|
|
213
|
+
}
|
|
214
|
+
if (this.answered?.key === key) {
|
|
215
|
+
const { lost } = this.answered;
|
|
216
|
+
this.answered = null;
|
|
217
|
+
lost();
|
|
218
|
+
return 'answered';
|
|
219
|
+
}
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
}
|
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,11 +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, UnsupportedCapabilityError, PreparationRequiredError, AmountRequiredError, 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';
|
|
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
4
|
export type { GmoUnsupportedReason } from './gmo.js';
|
|
5
|
-
export type {
|
|
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';
|
|
6
13
|
export type { MicroformField, MicroformSidecar } from './cybersource-flex.js';
|
|
7
14
|
export { attachToCdp, attachToPlaywright, corsHeadersFor, corsDecision, withCorsHeaders } from './cdp.js';
|
|
8
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';
|
|
9
20
|
export type { CdpLike, AttachOptions, CorsOutcome } from './cdp.js';
|
|
10
21
|
export type { StripeCheckoutOptions, StripeCheckoutBlockedDetail, StripeCheckoutBlockStage, StripeCheckoutBlockReason } from './stripe-checkout.js';
|
|
11
22
|
export { substituteEncryptedFields, SubstitutionError } from './substitute.js';
|
|
@@ -15,10 +26,13 @@ export type { MerchantProfile, MerchantProfileStatus, MerchantRequestVerdict, Me
|
|
|
15
26
|
export { MerchantExchangeLog, merchantAmountExchanges, merchantAmountFromResponses, merchantChargeReport, merchantProfilePricedBySource, merchantTotalAtRelease, MERCHANT_EXCHANGES_MAX, } from './merchant-total.js';
|
|
16
27
|
export type { MerchantAmountCard, MerchantExchange, MerchantRequestSeen, MerchantTotalApproved, MerchantTotalCapture, MerchantTotalScope } from './merchant-total.js';
|
|
17
28
|
export { substituteFiservEnvelope } from './fiserv.js';
|
|
29
|
+
export { classifyVerifoneProfileRequest, substituteVerifoneBody } from './verifone.js';
|
|
30
|
+
export type { VerifoneProfile, VerifoneProfileStatus, VerifoneRequestVerdict, VerifoneSubstitutions } from './verifone.js';
|
|
18
31
|
export { hostedFormSubmittedPage, HOSTED_FORM_SUBMITTED_OUTCOME } from './hosted-form.js';
|
|
19
32
|
export type { HostedFormSubmittedPageInput, SyntheticPage } from './hosted-form.js';
|
|
20
33
|
export { BUILTIN_REGISTRY, cardUrlPatterns, findRecognizer, isLoopbackUrl, LOOPBACK_URL_PATTERNS } from './registry.js';
|
|
21
34
|
export type { Recognizer, CheckoutMode, RecognizerOptions } from './registry.js';
|
|
35
|
+
export type { PayrailsSidecar, PayrailsUnsupportedReason } from './payrails.js';
|
|
22
36
|
export type { CheckoutController, CheckoutState, MerchantResult, MerchantPaymentConfirmation, UserAction, LifecycleOptions, PaymentEndpointGuard, PausedCheckout, ResumeResult } from './lifecycle.js';
|
|
23
37
|
export { RequestRegistry, BUILTIN_REQUEST_BUILDERS, stripePaymentIntentConfirm, stripePaymentIntentConfirmRequest, stripeCardTokenRequest, stripePaymentMethodRequest } from './requests.js';
|
|
24
38
|
export type { RequestBuilder, BuildInput, MintedIntent } from './requests.js';
|
|
@@ -34,6 +48,6 @@ export type { WebhookEvent, AgentcardEvent, CheckoutAuthorizationEvent, Checkout
|
|
|
34
48
|
export { readReturnLink } from './voice-pkce.js';
|
|
35
49
|
export type { PkceCrypto } from './voice-pkce.js';
|
|
36
50
|
export { AgentcardError } from './voice-types.js';
|
|
37
|
-
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';
|
|
38
52
|
export { openStream, streamBuffer } from './voice-stream.generated.js';
|
|
39
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, UnsupportedCapabilityError, PreparationRequiredError, AmountRequiredError, 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 { 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 };
|