@agent-cards/sdk 0.23.21 → 0.23.22
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 +14 -0
- package/PREFLIGHT.md +4 -0
- package/README.md +27 -1
- package/dist/amadeus-checkout.generated.d.ts +6 -1
- package/dist/amadeus-checkout.generated.js +26 -2
- package/dist/card-fields.generated.js +1391 -104
- package/dist/cdp.js +53 -18
- package/dist/client.d.ts +73 -6
- package/dist/client.js +164 -24
- package/dist/creditguard.generated.js +4 -2
- package/dist/cse-body.js +11 -0
- package/dist/ebanx.d.ts +1 -1
- package/dist/ebanx.js +1 -1
- package/dist/eximbay.d.ts +46 -0
- package/dist/eximbay.js +69 -0
- package/dist/lifecycle.d.ts +9 -4
- package/dist/lifecycle.js +16 -4
- package/dist/paygent.generated.d.ts +60 -0
- package/dist/paygent.generated.js +425 -0
- package/dist/payrexx.d.ts +91 -0
- package/dist/payrexx.generated.d.ts +91 -0
- package/dist/payrexx.generated.js +536 -0
- package/dist/payrexx.js +141 -0
- package/dist/pre-claim.d.ts +23 -0
- package/dist/pre-claim.js +131 -20
- package/dist/prepared-processor.d.ts +7 -2
- package/dist/prepared-processor.js +16 -2
- package/dist/primer.generated.js +1427 -140
- package/dist/stripe-checkout.generated.js +289 -21
- package/dist/toast-seal.generated.d.ts +37 -0
- package/dist/toast-seal.generated.js +625 -0
- package/dist/toast.generated.d.ts +41 -0
- package/dist/toast.generated.js +113 -0
- package/package.json +2 -2
package/dist/lifecycle.d.ts
CHANGED
|
@@ -159,6 +159,7 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
159
159
|
private stripeContinuationChecks;
|
|
160
160
|
/** The handoff in progress is WSPay's 3-D Secure step; see handedOff. */
|
|
161
161
|
private wspayChallenge;
|
|
162
|
+
private heldBeforeHandoff;
|
|
162
163
|
private stripeContinuedReason;
|
|
163
164
|
private approvedPaymentMethod;
|
|
164
165
|
private ownedShopOrderId;
|
|
@@ -191,7 +192,8 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
191
192
|
preparationFailed(error: CheckoutPreparationError): void;
|
|
192
193
|
isBlocked(): boolean;
|
|
193
194
|
/**
|
|
194
|
-
* An EBANX send left for the cardholder's device under this attachment's approval (pre-claim.ts ebanxFollowUp
|
|
195
|
+
* An EBANX or Payrexx send left for the cardholder's device under this attachment's approval (pre-claim.ts ebanxFollowUp,
|
|
196
|
+
* payrexxFollowUp). Until
|
|
195
197
|
* the returned function runs, once the send's answer reached the page or the send failed, reconcile() and
|
|
196
198
|
* retryAfterMerchantFailure() throw, as they do while a card request is active: a confirm may still pay. The returned
|
|
197
199
|
* function settles the send once, however often it runs.
|
|
@@ -200,7 +202,7 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
200
202
|
/** Whether a reconcile() is still waiting on the application's merchant resolver; pre-claim.ts claims no EBANX send then. */
|
|
201
203
|
isReconciling(): boolean;
|
|
202
204
|
/**
|
|
203
|
-
* Whether an EBANX send this attachment claimed is still out (followUpStarted). Both adapters refuse a new card
|
|
205
|
+
* Whether an EBANX or Payrexx send this attachment claimed is still out (followUpStarted). Both adapters refuse a new card
|
|
204
206
|
* request meanwhile, as they do while an approval is outstanding: a confirm that may pay is never hidden behind
|
|
205
207
|
* another payment's state.
|
|
206
208
|
*/
|
|
@@ -284,10 +286,13 @@ export declare class CheckoutLifecycle implements CheckoutController {
|
|
|
284
286
|
* paddle-vgs-pay.ts reasons), or the typed card that EBANX's 3-D Secure calls or
|
|
285
287
|
* its hosted page's confirm send again after the token, when no approved token
|
|
286
288
|
* request on this attachment covers that send or the cardholder's device did not
|
|
287
|
-
* send it (unsupported_ebanx_card_resend, ebanx.ts)
|
|
289
|
+
* send it (unsupported_ebanx_card_resend, ebanx.ts), or the typed card Payrexx's card
|
|
290
|
+
* frame sends again for a 3-D Secure step when no approved card request on this
|
|
291
|
+
* attachment covers that send or the cardholder's device did not send it
|
|
292
|
+
* (unsupported_payrexx_card_resend, payrexx.ts): once an approval exists the
|
|
288
293
|
* state keeps it, and only the hold changes.
|
|
289
294
|
*/
|
|
290
|
-
unsupported(reason?: 'unrecognized_payment_endpoint' | 'merchant_profile_observe' | 'merchant_request_unsupported' | GmoUnsupportedReason | 'microform_unsupported' | 'juspay_request_unsupported' | 'merchant_card_endpoint_not_enabled' | 'merchant_card_endpoint_resend_refused' | 'creditguard_three_d_secure' | 'unsupported_primer_sdk' | 'unsupported_primer_request' | PayrailsUnsupportedReason | ShijiStsUnsupportedReason | 'processor_card_page' | 'unsupported_paypal_hosted_fields' | PaypalCardFormReason | 'unsupported_cybersource_secure_acceptance' | PaddleVgsPayRefusal | 'unsupported_ebanx_card_resend'): void;
|
|
295
|
+
unsupported(reason?: 'unrecognized_payment_endpoint' | 'merchant_profile_observe' | 'merchant_request_unsupported' | GmoUnsupportedReason | 'microform_unsupported' | 'juspay_request_unsupported' | 'merchant_card_endpoint_not_enabled' | 'merchant_card_endpoint_resend_refused' | 'creditguard_three_d_secure' | 'unsupported_primer_sdk' | 'unsupported_primer_request' | PayrailsUnsupportedReason | ShijiStsUnsupportedReason | 'processor_card_page' | 'unsupported_paypal_hosted_fields' | PaypalCardFormReason | 'unsupported_cybersource_secure_acceptance' | PaddleVgsPayRefusal | 'unsupported_ebanx_card_resend' | 'unsupported_payrexx_card_resend'): void;
|
|
291
296
|
/**
|
|
292
297
|
* A card request that only a prepared checkout pays (an Adyen merchant
|
|
293
298
|
* profile's, or a Fiserv card capture) arrived with no preparation on this
|
package/dist/lifecycle.js
CHANGED
|
@@ -57,6 +57,9 @@ export class CheckoutLifecycle {
|
|
|
57
57
|
stripeContinuationChecks = 0;
|
|
58
58
|
/** The handoff in progress is WSPay's 3-D Secure step; see handedOff. */
|
|
59
59
|
wspayChallenge = false;
|
|
60
|
+
// Whether the attachment held when the handoff in progress began (prepareHandoff): a hold raised after that, while
|
|
61
|
+
// the answer was still landing, survives handedOff.
|
|
62
|
+
heldBeforeHandoff = false;
|
|
60
63
|
// What the continuation that went through confirmed: a payment, or a card save.
|
|
61
64
|
stripeContinuedReason = 'stripe_payment_continued';
|
|
62
65
|
// The payment method a Stripe /v1/payment_methods approval returned: see approvedStripePaymentMethod.
|
|
@@ -120,7 +123,8 @@ export class CheckoutLifecycle {
|
|
|
120
123
|
}
|
|
121
124
|
isBlocked() { return this.held || this.cancelled; }
|
|
122
125
|
/**
|
|
123
|
-
* An EBANX send left for the cardholder's device under this attachment's approval (pre-claim.ts ebanxFollowUp
|
|
126
|
+
* An EBANX or Payrexx send left for the cardholder's device under this attachment's approval (pre-claim.ts ebanxFollowUp,
|
|
127
|
+
* payrexxFollowUp). Until
|
|
124
128
|
* the returned function runs, once the send's answer reached the page or the send failed, reconcile() and
|
|
125
129
|
* retryAfterMerchantFailure() throw, as they do while a card request is active: a confirm may still pay. The returned
|
|
126
130
|
* function settles the send once, however often it runs.
|
|
@@ -136,7 +140,7 @@ export class CheckoutLifecycle {
|
|
|
136
140
|
/** Whether a reconcile() is still waiting on the application's merchant resolver; pre-claim.ts claims no EBANX send then. */
|
|
137
141
|
isReconciling() { return this.reconciliation !== null; }
|
|
138
142
|
/**
|
|
139
|
-
* Whether an EBANX send this attachment claimed is still out (followUpStarted). Both adapters refuse a new card
|
|
143
|
+
* Whether an EBANX or Payrexx send this attachment claimed is still out (followUpStarted). Both adapters refuse a new card
|
|
140
144
|
* request meanwhile, as they do while an approval is outstanding: a confirm that may pay is never hidden behind
|
|
141
145
|
* another payment's state.
|
|
142
146
|
*/
|
|
@@ -283,7 +287,10 @@ export class CheckoutLifecycle {
|
|
|
283
287
|
* paddle-vgs-pay.ts reasons), or the typed card that EBANX's 3-D Secure calls or
|
|
284
288
|
* its hosted page's confirm send again after the token, when no approved token
|
|
285
289
|
* request on this attachment covers that send or the cardholder's device did not
|
|
286
|
-
* send it (unsupported_ebanx_card_resend, ebanx.ts)
|
|
290
|
+
* send it (unsupported_ebanx_card_resend, ebanx.ts), or the typed card Payrexx's card
|
|
291
|
+
* frame sends again for a 3-D Secure step when no approved card request on this
|
|
292
|
+
* attachment covers that send or the cardholder's device did not send it
|
|
293
|
+
* (unsupported_payrexx_card_resend, payrexx.ts): once an approval exists the
|
|
287
294
|
* state keeps it, and only the hold changes.
|
|
288
295
|
*/
|
|
289
296
|
unsupported(reason = 'unrecognized_payment_endpoint') {
|
|
@@ -305,6 +312,7 @@ export class CheckoutLifecycle {
|
|
|
305
312
|
this.set({ ...this.state, status: 'failed', reason: 'preparation_required' });
|
|
306
313
|
}
|
|
307
314
|
prepareHandoff(replay, requestUrl) {
|
|
315
|
+
this.heldBeforeHandoff = this.held;
|
|
308
316
|
this.wspayChallenge = isWspayChallenge(requestUrl, replay);
|
|
309
317
|
this.handoffs.push(requestUrl);
|
|
310
318
|
if (replay.mode === 'token' && replay.executionMode === 'autopilot' && replay.shopOrderId) {
|
|
@@ -422,10 +430,14 @@ export class CheckoutLifecycle {
|
|
|
422
430
|
return;
|
|
423
431
|
}
|
|
424
432
|
const mismatch = (!replay.mode || replay.mode === 'token') && replay.amountVerified === false;
|
|
433
|
+
// A hold raised while the answer was still landing stands: the page may send its first follow-up the moment the
|
|
434
|
+
// answer lands, and an EBANX or Payrexx send that fails then stops the approval's follow-ups for good
|
|
435
|
+
// (pre-claim.ts), so a new card request must not reopen the checkout under an approval that cannot finish.
|
|
436
|
+
const heldDuringHandoff = this.held && !this.heldBeforeHandoff;
|
|
425
437
|
// A card endpoint answer means the merchant already holds the card: its page's own
|
|
426
438
|
// retry, or a step-up that sends the card again, is refused until the application
|
|
427
439
|
// reconciles the order, exactly as for a hosted form the device submitted.
|
|
428
|
-
this.held = !!this.options.requireMerchantResult || replay.mode === 'hosted_form' || replay.mode === 'card_endpoint' || mismatch || this.unboundStripeToken;
|
|
440
|
+
this.held = heldDuringHandoff || !!this.options.requireMerchantResult || replay.mode === 'hosted_form' || replay.mode === 'card_endpoint' || mismatch || this.unboundStripeToken;
|
|
429
441
|
if (mismatch)
|
|
430
442
|
this.stripeTokenPrepared = false;
|
|
431
443
|
this.set({ status: 'awaiting_merchant', authorizationId: replay.authorizationId, mode: replay.mode ?? 'token',
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
declare var PAYGENT_PSP: string;
|
|
2
|
+
declare var PAYGENT_CAPABILITY: string;
|
|
3
|
+
declare var PAYGENT_OPERATION: string;
|
|
4
|
+
declare var PAYGENT_TOKEN_HOSTS: Readonly<{
|
|
5
|
+
production: readonly string[];
|
|
6
|
+
sandbox: readonly string[];
|
|
7
|
+
}>;
|
|
8
|
+
declare var PAYGENT_TOKEN_PATH: string;
|
|
9
|
+
declare var PAYGENT_CONTENT_TYPE: string;
|
|
10
|
+
declare var PAYGENT_BODY_KEYS: readonly string[];
|
|
11
|
+
declare var PAYGENT_REFUSAL_CODES: readonly string[];
|
|
12
|
+
declare function paygentEnvironment(url: any): "production" | "sandbox" | null;
|
|
13
|
+
declare function isPaygentTokenUrl(url: any): boolean;
|
|
14
|
+
declare function paygentBodyVerdict(body: any): Readonly<{
|
|
15
|
+
verdict: "refuse";
|
|
16
|
+
code: any;
|
|
17
|
+
}> | Readonly<{
|
|
18
|
+
verdict: "card";
|
|
19
|
+
}>;
|
|
20
|
+
declare function paygentRequestVerdict(url: any, body: any): Readonly<{
|
|
21
|
+
verdict: "refuse";
|
|
22
|
+
code: any;
|
|
23
|
+
}> | Readonly<{
|
|
24
|
+
verdict: "card";
|
|
25
|
+
}>;
|
|
26
|
+
declare function paygentRequestRefusal(request: any): any;
|
|
27
|
+
declare function paygentMerchantId(body: any): string | null;
|
|
28
|
+
declare function paygentBodyMerchant(body: any): {
|
|
29
|
+
merchantId: string;
|
|
30
|
+
tokenKey: string;
|
|
31
|
+
} | null;
|
|
32
|
+
declare function paygentPreparationUrl(environment: any): string;
|
|
33
|
+
declare var PAYGENT_MERCHANT_PINS: readonly any[];
|
|
34
|
+
declare function paygentMerchantPin(merchantOrigin: any, merchant: any, pins?: readonly any[]): any;
|
|
35
|
+
declare function paygentMerchantRefusal(environment: any, merchantOrigin: any, merchant: any, facts?: {}, pins?: readonly any[]): "unsupported_environment" | "paygent_merchant_unreviewed" | "paygent_currency_mismatch" | "paygent_merchant_mismatch" | null;
|
|
36
|
+
declare function isPreparedPaygentRequest(url: any, method: any, body: any, environment: any, headers: any, binding?: {}, pins?: readonly any[]): boolean;
|
|
37
|
+
declare function injectPaygentCard(body: any, card: any): {
|
|
38
|
+
body: string;
|
|
39
|
+
where: any[];
|
|
40
|
+
};
|
|
41
|
+
declare var PAYGENT_ANSWER_REFUSAL_CODES: readonly string[];
|
|
42
|
+
declare function paygentAnswerOutcome(status: any, text: any, card: any): {
|
|
43
|
+
outcome: string;
|
|
44
|
+
code: any;
|
|
45
|
+
reason?: undefined;
|
|
46
|
+
body?: undefined;
|
|
47
|
+
} | {
|
|
48
|
+
outcome: string;
|
|
49
|
+
reason: string | undefined;
|
|
50
|
+
code?: undefined;
|
|
51
|
+
body?: undefined;
|
|
52
|
+
} | {
|
|
53
|
+
outcome: string;
|
|
54
|
+
body: string;
|
|
55
|
+
code?: undefined;
|
|
56
|
+
reason?: undefined;
|
|
57
|
+
};
|
|
58
|
+
declare function paygentRefusalCode(text: any): any;
|
|
59
|
+
declare function paygentRefusalMessage(code: any): any;
|
|
60
|
+
export { PAYGENT_ANSWER_REFUSAL_CODES, PAYGENT_BODY_KEYS, PAYGENT_CAPABILITY, PAYGENT_CONTENT_TYPE, PAYGENT_MERCHANT_PINS, PAYGENT_OPERATION, PAYGENT_PSP, PAYGENT_REFUSAL_CODES, PAYGENT_TOKEN_HOSTS, PAYGENT_TOKEN_PATH, injectPaygentCard, isPaygentTokenUrl, isPreparedPaygentRequest, paygentAnswerOutcome, paygentBodyMerchant, paygentBodyVerdict, paygentEnvironment, paygentMerchantId, paygentMerchantPin, paygentMerchantRefusal, paygentPreparationUrl, paygentRefusalCode, paygentRefusalMessage, paygentRequestRefusal, paygentRequestVerdict };
|
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
// Generated from @agent-cards/payment-core. Do not edit.
|
|
3
|
+
// artifact-sha256: 32d9a3f112e2704eacabb2954570a746bef5547c8fd865a4db14b2bd0cd1d936
|
|
4
|
+
// src/sha256.js
|
|
5
|
+
var K = /* @__PURE__ */ new Uint32Array([
|
|
6
|
+
1116352408,
|
|
7
|
+
1899447441,
|
|
8
|
+
3049323471,
|
|
9
|
+
3921009573,
|
|
10
|
+
961987163,
|
|
11
|
+
1508970993,
|
|
12
|
+
2453635748,
|
|
13
|
+
2870763221,
|
|
14
|
+
3624381080,
|
|
15
|
+
310598401,
|
|
16
|
+
607225278,
|
|
17
|
+
1426881987,
|
|
18
|
+
1925078388,
|
|
19
|
+
2162078206,
|
|
20
|
+
2614888103,
|
|
21
|
+
3248222580,
|
|
22
|
+
3835390401,
|
|
23
|
+
4022224774,
|
|
24
|
+
264347078,
|
|
25
|
+
604807628,
|
|
26
|
+
770255983,
|
|
27
|
+
1249150122,
|
|
28
|
+
1555081692,
|
|
29
|
+
1996064986,
|
|
30
|
+
2554220882,
|
|
31
|
+
2821834349,
|
|
32
|
+
2952996808,
|
|
33
|
+
3210313671,
|
|
34
|
+
3336571891,
|
|
35
|
+
3584528711,
|
|
36
|
+
113926993,
|
|
37
|
+
338241895,
|
|
38
|
+
666307205,
|
|
39
|
+
773529912,
|
|
40
|
+
1294757372,
|
|
41
|
+
1396182291,
|
|
42
|
+
1695183700,
|
|
43
|
+
1986661051,
|
|
44
|
+
2177026350,
|
|
45
|
+
2456956037,
|
|
46
|
+
2730485921,
|
|
47
|
+
2820302411,
|
|
48
|
+
3259730800,
|
|
49
|
+
3345764771,
|
|
50
|
+
3516065817,
|
|
51
|
+
3600352804,
|
|
52
|
+
4094571909,
|
|
53
|
+
275423344,
|
|
54
|
+
430227734,
|
|
55
|
+
506948616,
|
|
56
|
+
659060556,
|
|
57
|
+
883997877,
|
|
58
|
+
958139571,
|
|
59
|
+
1322822218,
|
|
60
|
+
1537002063,
|
|
61
|
+
1747873779,
|
|
62
|
+
1955562222,
|
|
63
|
+
2024104815,
|
|
64
|
+
2227730452,
|
|
65
|
+
2361852424,
|
|
66
|
+
2428436474,
|
|
67
|
+
2756734187,
|
|
68
|
+
3204031479,
|
|
69
|
+
3329325298
|
|
70
|
+
]);
|
|
71
|
+
var rotr = (x, n) => x >>> n | x << 32 - n;
|
|
72
|
+
function utf8(text) {
|
|
73
|
+
const out = [];
|
|
74
|
+
for (const char of text) {
|
|
75
|
+
let cp = char.codePointAt(0);
|
|
76
|
+
if (cp >= 55296 && cp <= 57343)
|
|
77
|
+
cp = 65533;
|
|
78
|
+
if (cp < 128)
|
|
79
|
+
out.push(cp);
|
|
80
|
+
else if (cp < 2048)
|
|
81
|
+
out.push(192 | cp >> 6, 128 | cp & 63);
|
|
82
|
+
else if (cp < 65536)
|
|
83
|
+
out.push(224 | cp >> 12, 128 | cp >> 6 & 63, 128 | cp & 63);
|
|
84
|
+
else
|
|
85
|
+
out.push(240 | cp >> 18, 128 | cp >> 12 & 63, 128 | cp >> 6 & 63, 128 | cp & 63);
|
|
86
|
+
}
|
|
87
|
+
return Uint8Array.from(out);
|
|
88
|
+
}
|
|
89
|
+
function sha256Hex(input) {
|
|
90
|
+
const isBytes = Object.prototype.toString.call(input) === "[object Uint8Array]";
|
|
91
|
+
if (typeof input !== "string" && !isBytes)
|
|
92
|
+
throw new TypeError("sha256Hex takes a string or a Uint8Array.");
|
|
93
|
+
const bytes = typeof input === "string" ? utf8(input) : input;
|
|
94
|
+
const length = bytes.length;
|
|
95
|
+
const padded = new Uint8Array((length + 8 >> 6) + 1 << 6);
|
|
96
|
+
padded.set(bytes);
|
|
97
|
+
padded[length] = 128;
|
|
98
|
+
const view = new DataView(padded.buffer);
|
|
99
|
+
view.setUint32(padded.length - 8, Math.floor(length / 536870912));
|
|
100
|
+
view.setUint32(padded.length - 4, length << 3 >>> 0);
|
|
101
|
+
const H = new Uint32Array([1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]);
|
|
102
|
+
const W = new Uint32Array(64);
|
|
103
|
+
for (let offset = 0; offset < padded.length; offset += 64) {
|
|
104
|
+
for (let t = 0; t < 16; t++)
|
|
105
|
+
W[t] = view.getUint32(offset + t * 4);
|
|
106
|
+
for (let t = 16; t < 64; t++) {
|
|
107
|
+
const s0 = rotr(W[t - 15], 7) ^ rotr(W[t - 15], 18) ^ W[t - 15] >>> 3;
|
|
108
|
+
const s1 = rotr(W[t - 2], 17) ^ rotr(W[t - 2], 19) ^ W[t - 2] >>> 10;
|
|
109
|
+
W[t] = W[t - 16] + s0 + W[t - 7] + s1 >>> 0;
|
|
110
|
+
}
|
|
111
|
+
let a = H[0], b = H[1], c = H[2], d = H[3], e = H[4], f = H[5], g = H[6], h = H[7];
|
|
112
|
+
for (let t = 0; t < 64; t++) {
|
|
113
|
+
const t1 = h + (rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25)) + (e & f ^ ~e & g) + K[t] + W[t] >>> 0;
|
|
114
|
+
const t2 = (rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22)) + (a & b ^ a & c ^ b & c) >>> 0;
|
|
115
|
+
h = g;
|
|
116
|
+
g = f;
|
|
117
|
+
f = e;
|
|
118
|
+
e = d + t1 >>> 0;
|
|
119
|
+
d = c;
|
|
120
|
+
c = b;
|
|
121
|
+
b = a;
|
|
122
|
+
a = t1 + t2 >>> 0;
|
|
123
|
+
}
|
|
124
|
+
H[0] += a;
|
|
125
|
+
H[1] += b;
|
|
126
|
+
H[2] += c;
|
|
127
|
+
H[3] += d;
|
|
128
|
+
H[4] += e;
|
|
129
|
+
H[5] += f;
|
|
130
|
+
H[6] += g;
|
|
131
|
+
H[7] += h;
|
|
132
|
+
}
|
|
133
|
+
return Array.from(H, (word) => word.toString(16).padStart(8, "0")).join("");
|
|
134
|
+
}
|
|
135
|
+
// src/paygent.js
|
|
136
|
+
var PAYGENT_PSP = "paygent";
|
|
137
|
+
var PAYGENT_CAPABILITY = "paygent_token";
|
|
138
|
+
var PAYGENT_OPERATION = "paygent.card_request";
|
|
139
|
+
var PAYGENT_TOKEN_HOSTS = /* @__PURE__ */ Object.freeze({
|
|
140
|
+
production: Object.freeze(["token.paygent.co.jp"]),
|
|
141
|
+
sandbox: Object.freeze(["sandbox.paygent.co.jp"])
|
|
142
|
+
});
|
|
143
|
+
var PAYGENT_TOKEN_PATH = "/n/token/request";
|
|
144
|
+
var PAYGENT_CONTENT_TYPE = "text/plain;charset=UTF-8";
|
|
145
|
+
var PAYGENT_BODY_KEYS = /* @__PURE__ */ Object.freeze([
|
|
146
|
+
"merchant_id",
|
|
147
|
+
"token_generate_key",
|
|
148
|
+
"card_number",
|
|
149
|
+
"card_expire_year",
|
|
150
|
+
"card_expire_month",
|
|
151
|
+
"card_cvc",
|
|
152
|
+
"card_name"
|
|
153
|
+
]);
|
|
154
|
+
var PAYGENT_REFUSAL_CODES = /* @__PURE__ */ Object.freeze([
|
|
155
|
+
"paygent_url_refused",
|
|
156
|
+
"paygent_headers_refused",
|
|
157
|
+
"paygent_cvc_only",
|
|
158
|
+
"paygent_key_environment",
|
|
159
|
+
"paygent_body_unsupported"
|
|
160
|
+
]);
|
|
161
|
+
var BODY_LIMIT = 2048;
|
|
162
|
+
var URL_LIMIT = 128;
|
|
163
|
+
var MERCHANT_ID = /^[0-9]{5,6}$/;
|
|
164
|
+
var LIVE_KEY = /^live_[A-Za-z0-9]{24}$/;
|
|
165
|
+
var SANDBOX_KEY = /^(?!live_)[a-z]{1,8}_[A-Za-z0-9]{24}$/;
|
|
166
|
+
var NUMBER = /^[0-9]{12,19}$/;
|
|
167
|
+
var YEAR = /^[0-9]{2}$/;
|
|
168
|
+
var MONTH = /^(?:0?[1-9]|1[0-2])$/;
|
|
169
|
+
var SECURITY_CODE = /^[0-9]{3,4}$/;
|
|
170
|
+
var HOLDER = /^[A-Za-z][A-Za-z .'-]{0,44}$/;
|
|
171
|
+
var PAGE_HOLDER = /^(?:[A-Za-z][A-Za-z .'-]{0,44})?$/;
|
|
172
|
+
var CONTENT_TYPE = /^text\/plain; ?charset=utf-8$/i;
|
|
173
|
+
var record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
174
|
+
var refuse = (code) => Object.freeze({ verdict: "refuse", code });
|
|
175
|
+
var CARD = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
176
|
+
function paygentEnvironment(url) {
|
|
177
|
+
if (typeof url !== "string" || url.length > URL_LIMIT || url.includes("?") || url.includes("#"))
|
|
178
|
+
return null;
|
|
179
|
+
let parsed;
|
|
180
|
+
try {
|
|
181
|
+
parsed = new URL(url);
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || parsed.pathname !== PAYGENT_TOKEN_PATH)
|
|
187
|
+
return null;
|
|
188
|
+
if (PAYGENT_TOKEN_HOSTS.production.includes(parsed.hostname))
|
|
189
|
+
return "production";
|
|
190
|
+
if (PAYGENT_TOKEN_HOSTS.sandbox.includes(parsed.hostname))
|
|
191
|
+
return "sandbox";
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
function isPaygentTokenUrl(url) {
|
|
195
|
+
return paygentEnvironment(url) !== null;
|
|
196
|
+
}
|
|
197
|
+
function readBody(body) {
|
|
198
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT)
|
|
199
|
+
return null;
|
|
200
|
+
try {
|
|
201
|
+
const pairs = body.split("&").map((chunk) => {
|
|
202
|
+
const eq = chunk.indexOf("=");
|
|
203
|
+
if (eq <= 0)
|
|
204
|
+
throw new URIError("not a pair");
|
|
205
|
+
return [chunk.slice(0, eq), decodeURIComponent(chunk.slice(eq + 1))];
|
|
206
|
+
});
|
|
207
|
+
return pairs.map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join("&") === body ? pairs : null;
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
var CVC_ONLY_KEYS = /* @__PURE__ */ Object.freeze(["merchant_id", "token_generate_key", "card_cvc", "cvc_only_flg"]);
|
|
214
|
+
var sameKeys = (pairs, keys) => pairs.length === keys.length && pairs.every(([key], at) => key === keys[at]);
|
|
215
|
+
function judgeBody(body) {
|
|
216
|
+
const pairs = readBody(body);
|
|
217
|
+
if (pairs === null)
|
|
218
|
+
return { code: "paygent_body_unsupported", pairs: null };
|
|
219
|
+
if (sameKeys(pairs, CVC_ONLY_KEYS))
|
|
220
|
+
return { code: "paygent_cvc_only", pairs: null };
|
|
221
|
+
if (!sameKeys(pairs, PAYGENT_BODY_KEYS))
|
|
222
|
+
return { code: "paygent_body_unsupported", pairs: null };
|
|
223
|
+
const value = Object.fromEntries(pairs);
|
|
224
|
+
if (!MERCHANT_ID.test(value.merchant_id) || !(LIVE_KEY.test(value.token_generate_key) || SANDBOX_KEY.test(value.token_generate_key)) || !NUMBER.test(value.card_number) || !YEAR.test(value.card_expire_year) || !MONTH.test(value.card_expire_month) || !SECURITY_CODE.test(value.card_cvc) || !PAGE_HOLDER.test(value.card_name)) {
|
|
225
|
+
return { code: "paygent_body_unsupported", pairs: null };
|
|
226
|
+
}
|
|
227
|
+
return { code: null, pairs };
|
|
228
|
+
}
|
|
229
|
+
function paygentBodyVerdict(body) {
|
|
230
|
+
const { code } = judgeBody(body);
|
|
231
|
+
return code === null ? CARD : refuse(code);
|
|
232
|
+
}
|
|
233
|
+
function paygentRequestVerdict(url, body) {
|
|
234
|
+
const environment = paygentEnvironment(url);
|
|
235
|
+
if (environment === null)
|
|
236
|
+
return refuse("paygent_url_refused");
|
|
237
|
+
const { code, pairs } = judgeBody(body);
|
|
238
|
+
if (code !== null)
|
|
239
|
+
return refuse(code);
|
|
240
|
+
const key = pairs[1][1];
|
|
241
|
+
return (environment === "production" ? LIVE_KEY : SANDBOX_KEY).test(key) ? CARD : refuse("paygent_key_environment");
|
|
242
|
+
}
|
|
243
|
+
function paygentRequestRefusal(request) {
|
|
244
|
+
if (!record(request) || request.method !== "POST" || !isPaygentTokenUrl(request.url))
|
|
245
|
+
return "paygent_url_refused";
|
|
246
|
+
const headers = /* @__PURE__ */ new Map();
|
|
247
|
+
for (const [name, value] of Object.entries(record(request.headers) ? request.headers : {})) {
|
|
248
|
+
const lower = name.toLowerCase();
|
|
249
|
+
if (headers.has(lower) || typeof value !== "string")
|
|
250
|
+
return "paygent_headers_refused";
|
|
251
|
+
headers.set(lower, value);
|
|
252
|
+
}
|
|
253
|
+
const contentType = headers.get("content-type");
|
|
254
|
+
if (contentType === void 0 || !CONTENT_TYPE.test(contentType))
|
|
255
|
+
return "paygent_headers_refused";
|
|
256
|
+
const verdict = paygentRequestVerdict(request.url, request.body);
|
|
257
|
+
return verdict.verdict === "card" ? null : verdict.code;
|
|
258
|
+
}
|
|
259
|
+
function paygentMerchantId(body) {
|
|
260
|
+
const { code, pairs } = judgeBody(body);
|
|
261
|
+
return code === null ? pairs[0][1] : null;
|
|
262
|
+
}
|
|
263
|
+
function paygentBodyMerchant(body) {
|
|
264
|
+
const { code, pairs } = judgeBody(body);
|
|
265
|
+
return code === null ? { merchantId: pairs[0][1], tokenKey: pairs[1][1] } : null;
|
|
266
|
+
}
|
|
267
|
+
function paygentPreparationUrl(environment) {
|
|
268
|
+
if (environment !== "production" && environment !== "sandbox")
|
|
269
|
+
throw new Error("unsupported_preparation_environment");
|
|
270
|
+
return `https://${PAYGENT_TOKEN_HOSTS[environment][0]}${PAYGENT_TOKEN_PATH}`;
|
|
271
|
+
}
|
|
272
|
+
var pin = (fields) => Object.freeze({ ...fields, origins: Object.freeze([...fields.origins]) });
|
|
273
|
+
var PAYGENT_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
274
|
+
pin({
|
|
275
|
+
id: "fundex_tcs_eng",
|
|
276
|
+
merchant: "Tokyo Chinese School",
|
|
277
|
+
merchantId: "60362",
|
|
278
|
+
keySha256: "6073dee112b1e4089025d1c1f3c4cfad818c314a81943ffa55b839cb2df51018",
|
|
279
|
+
origins: ["https://fundexapp.jp"],
|
|
280
|
+
currency: "jpy"
|
|
281
|
+
})
|
|
282
|
+
]);
|
|
283
|
+
function paygentMerchantPin(merchantOrigin, merchant, pins = PAYGENT_MERCHANT_PINS) {
|
|
284
|
+
if (typeof merchantOrigin !== "string" || typeof merchant !== "string" || !Array.isArray(pins))
|
|
285
|
+
return null;
|
|
286
|
+
return pins.find((entry) => !!entry && Array.isArray(entry.origins) && entry.origins.includes(merchantOrigin) && entry.merchant === merchant) ?? null;
|
|
287
|
+
}
|
|
288
|
+
function paygentMerchantRefusal(environment, merchantOrigin, merchant, facts = {}, pins = PAYGENT_MERCHANT_PINS) {
|
|
289
|
+
if (environment === "sandbox")
|
|
290
|
+
return null;
|
|
291
|
+
if (environment !== "production")
|
|
292
|
+
return "unsupported_environment";
|
|
293
|
+
const found = paygentMerchantPin(merchantOrigin, merchant, pins);
|
|
294
|
+
if (!found)
|
|
295
|
+
return "paygent_merchant_unreviewed";
|
|
296
|
+
const given = record(facts) ? facts : {};
|
|
297
|
+
if (given.currency !== void 0 && given.currency !== found.currency)
|
|
298
|
+
return "paygent_currency_mismatch";
|
|
299
|
+
if (given.merchantId !== void 0 && given.merchantId !== found.merchantId)
|
|
300
|
+
return "paygent_merchant_mismatch";
|
|
301
|
+
if (given.tokenKey !== void 0 && (typeof given.tokenKey !== "string" || typeof found.keySha256 !== "string" || sha256Hex(given.tokenKey) !== found.keySha256))
|
|
302
|
+
return "paygent_merchant_mismatch";
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
function isPreparedPaygentRequest(url, method, body, environment, headers, binding = {}, pins = PAYGENT_MERCHANT_PINS) {
|
|
306
|
+
if (environment !== "production" && environment !== "sandbox" || paygentEnvironment(url) !== environment || paygentRequestRefusal({ url, method, headers, body }) !== null)
|
|
307
|
+
return false;
|
|
308
|
+
const given = record(binding) ? binding : {};
|
|
309
|
+
const facts = paygentBodyMerchant(body);
|
|
310
|
+
return facts !== null && paygentMerchantRefusal(environment, given.merchantOrigin, given.merchant, facts, pins) === null;
|
|
311
|
+
}
|
|
312
|
+
var digits = (value, min, max) => typeof value === "string" && value.length >= min && value.length <= max && !/[^0-9]/.test(value);
|
|
313
|
+
var whole = (value, min, max) => {
|
|
314
|
+
if (Number.isSafeInteger(value) && value >= 0)
|
|
315
|
+
return value;
|
|
316
|
+
return digits(value, min, max) ? Number(value) : NaN;
|
|
317
|
+
};
|
|
318
|
+
var cardYear = (year) => year >= 0 && year <= 99 || year >= 2e3 && year <= 2099;
|
|
319
|
+
var AMEX = /^3[47]/;
|
|
320
|
+
var FILL_REFUSAL = "Could not fill the card fields for Paygent. Nothing was sent.";
|
|
321
|
+
function injectPaygentCard(body, card) {
|
|
322
|
+
const { code, pairs } = judgeBody(body);
|
|
323
|
+
if (code !== null)
|
|
324
|
+
throw new Error(paygentRefusalMessage(code));
|
|
325
|
+
const month = card ? whole(card.month, 1, 2) : NaN;
|
|
326
|
+
const year = card ? whole(card.year, 2, 4) : NaN;
|
|
327
|
+
if (!card || !digits(card.number, 12, 19) || !(month >= 1 && month <= 12) || !cardYear(year) || !digits(card.cvc, AMEX.test(card.number) ? 4 : 3, AMEX.test(card.number) ? 4 : 3)) {
|
|
328
|
+
throw new Error(FILL_REFUSAL);
|
|
329
|
+
}
|
|
330
|
+
const written = {
|
|
331
|
+
card_number: card.number,
|
|
332
|
+
card_expire_year: String(year % 100).padStart(2, "0"),
|
|
333
|
+
card_expire_month: String(month).padStart(2, "0"),
|
|
334
|
+
card_cvc: card.cvc
|
|
335
|
+
};
|
|
336
|
+
if (pairs[6][1] !== "" && typeof card.name === "string" && HOLDER.test(card.name))
|
|
337
|
+
written.card_name = card.name;
|
|
338
|
+
const where = [];
|
|
339
|
+
const filled = pairs.map(([key, value]) => {
|
|
340
|
+
if (!Object.prototype.hasOwnProperty.call(written, key))
|
|
341
|
+
return `${key}=${encodeURIComponent(value)}`;
|
|
342
|
+
where.push(key);
|
|
343
|
+
return `${key}=${encodeURIComponent(written[key])}`;
|
|
344
|
+
});
|
|
345
|
+
return { body: filled.join("&"), where };
|
|
346
|
+
}
|
|
347
|
+
var PAYGENT_ANSWER_REFUSAL_CODES = /* @__PURE__ */ Object.freeze([
|
|
348
|
+
"1100",
|
|
349
|
+
"1200",
|
|
350
|
+
"1300",
|
|
351
|
+
"1301",
|
|
352
|
+
"1400",
|
|
353
|
+
"1401",
|
|
354
|
+
"1500",
|
|
355
|
+
"1501",
|
|
356
|
+
"1502",
|
|
357
|
+
"1600",
|
|
358
|
+
"1601",
|
|
359
|
+
"1700"
|
|
360
|
+
]);
|
|
361
|
+
var ANSWER_LIMIT = 4096;
|
|
362
|
+
var TOKEN = /^[A-Za-z0-9+/=_.-]{8,256}$/;
|
|
363
|
+
var MASKED = /^(?=.{12,19}$)[0-9]{0,6}[*Xx]{2,}[0-9]{4}$/;
|
|
364
|
+
var VALID_UNTIL = /^[0-9][0-9 :/.T-]{7,31}$/;
|
|
365
|
+
var FINGERPRINT = /^[A-Za-z0-9+/=_.-]{1,256}$/;
|
|
366
|
+
var TOKEN_KEYS = /* @__PURE__ */ Object.freeze(["token", "masked_card_number", "valid_until", "fingerprint"]);
|
|
367
|
+
var HC = /^[A-Za-z0-9+/=_.-]{1,256}$/;
|
|
368
|
+
function readAnswer(status, text) {
|
|
369
|
+
if (status !== 200)
|
|
370
|
+
return { kind: "unknown", reason: status >= 500 ? "server_error" : "paygent_answer_status" };
|
|
371
|
+
if (typeof text !== "string" || text.length > ANSWER_LIMIT)
|
|
372
|
+
return { kind: "unknown", reason: "paygent_answer_unreadable" };
|
|
373
|
+
let answer;
|
|
374
|
+
try {
|
|
375
|
+
answer = JSON.parse(text);
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
return { kind: "unknown", reason: "paygent_answer_unreadable" };
|
|
379
|
+
}
|
|
380
|
+
if (!record(answer) || typeof answer.result !== "string")
|
|
381
|
+
return { kind: "unknown", reason: "paygent_answer_unreadable" };
|
|
382
|
+
if (answer.result !== "0000") {
|
|
383
|
+
return PAYGENT_ANSWER_REFUSAL_CODES.includes(answer.result) ? { kind: "refused", code: answer.result } : { kind: "unknown", reason: "paygent_answer_unknown_result" };
|
|
384
|
+
}
|
|
385
|
+
const card = answer.tokenizedCardObject;
|
|
386
|
+
if (!record(card) || typeof card.token !== "string" || !TOKEN.test(card.token) || typeof card.masked_card_number !== "string" || !MASKED.test(card.masked_card_number) || typeof card.valid_until !== "string" || !VALID_UNTIL.test(card.valid_until) || card.fingerprint !== void 0 && (typeof card.fingerprint !== "string" || !FINGERPRINT.test(card.fingerprint))) {
|
|
387
|
+
return { kind: "unknown", reason: "paygent_token_unconfirmed" };
|
|
388
|
+
}
|
|
389
|
+
if (answer.hc !== void 0 && (typeof answer.hc !== "string" || !HC.test(answer.hc))) {
|
|
390
|
+
return { kind: "unknown", reason: "paygent_token_unconfirmed" };
|
|
391
|
+
}
|
|
392
|
+
return { kind: "token", answer: card, hc: answer.hc };
|
|
393
|
+
}
|
|
394
|
+
var rebuild = (card, hc) => JSON.stringify({ result: "0000", tokenizedCardObject: Object.fromEntries(TOKEN_KEYS.filter((key) => card[key] !== void 0).map((key) => [key, card[key]])), ...hc !== void 0 ? { hc } : {} });
|
|
395
|
+
function paygentAnswerOutcome(status, text, card) {
|
|
396
|
+
const read = readAnswer(status, text);
|
|
397
|
+
if (read.kind === "refused")
|
|
398
|
+
return { outcome: "refused", code: read.code };
|
|
399
|
+
if (read.kind !== "token")
|
|
400
|
+
return { outcome: "unknown", reason: read.reason };
|
|
401
|
+
if (card) {
|
|
402
|
+
const number = String(card.number);
|
|
403
|
+
const masked = read.answer.masked_card_number;
|
|
404
|
+
const inPlace = masked.length === number.length && [...masked].every((ch, at) => !/[0-9]/.test(ch) || ch === number[at]);
|
|
405
|
+
if (!inPlace || [...TOKEN_KEYS.map((key) => read.answer[key]), read.hc].some((value) => typeof value === "string" && value.includes(number))) {
|
|
406
|
+
return { outcome: "unknown", reason: "paygent_token_mismatch" };
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return { outcome: "approved", body: rebuild(read.answer, read.hc) };
|
|
410
|
+
}
|
|
411
|
+
function paygentRefusalCode(text) {
|
|
412
|
+
const read = readAnswer(200, text);
|
|
413
|
+
return read.kind === "refused" ? read.code : null;
|
|
414
|
+
}
|
|
415
|
+
var REFUSAL_MESSAGES = /* @__PURE__ */ Object.freeze({
|
|
416
|
+
paygent_url_refused: "Refusing to pay: this Paygent card request does not go to Paygent's token address exactly as Paygent's script sends it. Nothing was sent.",
|
|
417
|
+
paygent_headers_refused: "Refusing to pay: this Paygent card request does not carry Paygent's own content type. Nothing was sent.",
|
|
418
|
+
paygent_cvc_only: "Refusing to pay: this Paygent request is for a card the merchant keeps on file, not a card from your Vault. Nothing was sent.",
|
|
419
|
+
paygent_key_environment: "Refusing to pay: this Paygent card request uses a test key on Paygent's live address, or a live key on its test address. Nothing was sent.",
|
|
420
|
+
paygent_body_unsupported: "Refusing to pay: this is not the card request of Paygent's token script. Nothing was sent."
|
|
421
|
+
});
|
|
422
|
+
function paygentRefusalMessage(code) {
|
|
423
|
+
return Object.prototype.hasOwnProperty.call(REFUSAL_MESSAGES, code) ? REFUSAL_MESSAGES[code] : REFUSAL_MESSAGES.paygent_body_unsupported;
|
|
424
|
+
}
|
|
425
|
+
export { PAYGENT_ANSWER_REFUSAL_CODES, PAYGENT_BODY_KEYS, PAYGENT_CAPABILITY, PAYGENT_CONTENT_TYPE, PAYGENT_MERCHANT_PINS, PAYGENT_OPERATION, PAYGENT_PSP, PAYGENT_REFUSAL_CODES, PAYGENT_TOKEN_HOSTS, PAYGENT_TOKEN_PATH, injectPaygentCard, isPaygentTokenUrl, isPreparedPaygentRequest, paygentAnswerOutcome, paygentBodyMerchant, paygentBodyVerdict, paygentEnvironment, paygentMerchantId, paygentMerchantPin, paygentMerchantRefusal, paygentPreparationUrl, paygentRefusalCode, paygentRefusalMessage, paygentRequestRefusal, paygentRequestVerdict };
|