@agent-cards/sdk 0.23.19 → 0.23.20
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 +20 -0
- package/PREFLIGHT.md +2 -0
- package/README.md +34 -4
- package/dist/amadeus.d.ts +4 -2
- package/dist/amadeus.js +16 -3
- package/dist/buy.d.ts +84 -2
- package/dist/buy.js +16 -1
- package/dist/card-endpoint-facts.d.ts +2 -1
- package/dist/card-endpoint-facts.js +18 -9
- package/dist/card-endpoint.d.ts +20 -4
- package/dist/card-endpoint.js +38 -4
- package/dist/card-fields.generated.js +483 -17
- package/dist/cdp.d.ts +29 -0
- package/dist/cdp.js +302 -18
- package/dist/client.d.ts +30 -4
- package/dist/client.js +128 -13
- package/dist/hipay.generated.d.ts +56 -0
- package/dist/hipay.generated.js +389 -0
- package/dist/hold.d.ts +180 -0
- package/dist/hold.js +264 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/lifecycle.d.ts +10 -0
- package/dist/lifecycle.js +21 -0
- package/dist/merchant-card-endpoints.generated.js +102 -11
- package/dist/paddle-vgs.generated.d.ts +3 -2
- package/dist/paddle-vgs.generated.js +9 -5
- package/dist/pre-claim.d.ts +14 -0
- package/dist/pre-claim.js +76 -3
- package/dist/prepared-processor.d.ts +6 -2
- package/dist/prepared-processor.js +18 -2
- package/dist/primer.generated.js +510 -44
- package/dist/quickpay.d.ts +44 -0
- package/dist/quickpay.js +65 -0
- package/dist/stripe-checkout.generated.js +124 -2
- package/dist/twoc2p.d.ts +54 -0
- package/dist/twoc2p.generated.d.ts +33 -0
- package/dist/twoc2p.generated.js +1145 -0
- package/dist/twoc2p.js +85 -0
- package/dist/voice.d.ts +16 -13
- package/dist/voice.js +13 -10
- package/package.json +3 -3
package/dist/card-endpoint.js
CHANGED
|
@@ -46,7 +46,9 @@
|
|
|
46
46
|
// that sends the typed card again outside the card request is aborted in every status
|
|
47
47
|
// (cardEndpointResendFor). And the merchant's own record of the order, which its page
|
|
48
48
|
// reads from the endpoint origin, is recorded read-only (card-endpoint-facts.ts) and sent
|
|
49
|
-
// with the create, so the agent's amount is held to the merchant's total.
|
|
49
|
+
// with the create, so the agent's amount is held to the merchant's total. D-EDGE's card
|
|
50
|
+
// frame is read the same way from the payment hub around it, whose booking record says
|
|
51
|
+
// what the card pays now and whether the hotel charges it later.
|
|
50
52
|
//
|
|
51
53
|
// The endpoint URL (it carries cart, booking and instance ids), the paused body, the
|
|
52
54
|
// session and the answer are cardholder data even with no real card in them: no
|
|
@@ -121,9 +123,23 @@ const ROUTED_METHODS = [...new Set(PROFILES.flatMap((profile) => [profile.method
|
|
|
121
123
|
export function cardEndpointRouted(url) {
|
|
122
124
|
return ROUTED_METHODS.some((method) => cardEndpointFor(url, method) !== null || cardEndpointResendFor(url, method) !== null);
|
|
123
125
|
}
|
|
124
|
-
/**
|
|
126
|
+
/**
|
|
127
|
+
* The origins the record of each profile whose merchant keeps one comes from (its facts.origin, else its
|
|
128
|
+
* endpoint): the only responses card-endpoint-facts.ts records.
|
|
129
|
+
*/
|
|
125
130
|
export function cardEndpointFactsOrigins() {
|
|
126
|
-
return [...new Set(PROFILES.filter((profile) => profile.facts).map((profile) => profile.endpoint))];
|
|
131
|
+
return [...new Set(PROFILES.filter((profile) => profile.facts).map((profile) => profile.facts.origin ?? profile.endpoint))];
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The `:name` segment of a card path template a URL path gives, when the path has the template's
|
|
135
|
+
* shape (as many segments, every literal one equal); else null.
|
|
136
|
+
*/
|
|
137
|
+
function boundSegment(template, segments, name) {
|
|
138
|
+
const want = template.split('/');
|
|
139
|
+
if (want.length !== segments.length || !want.every((part, i) => (part.startsWith(':') ? segments[i] !== '' : part === segments[i])))
|
|
140
|
+
return null;
|
|
141
|
+
const at = want.indexOf(`:${name}`);
|
|
142
|
+
return at < 1 ? null : segments[at];
|
|
127
143
|
}
|
|
128
144
|
/**
|
|
129
145
|
* The checkout session a request on the endpoint of a profile with facts belongs to: the
|
|
@@ -133,6 +149,12 @@ export function cardEndpointFactsOrigins() {
|
|
|
133
149
|
* request. card-endpoint-facts.ts counts what it keeps, and what a checkout lost, by it.
|
|
134
150
|
* When the paths of two profiles on one origin both fit, the shorter session is the one:
|
|
135
151
|
* every request on a card request's session then gets the card request's own.
|
|
152
|
+
*
|
|
153
|
+
* For a profile whose record comes from its own origin (D-EDGE's payment hub beside the card
|
|
154
|
+
* frame), a request on that origin belongs to the session its last path segment names, the
|
|
155
|
+
* session id every hub URL ends in, and the profile's card request to the session its bind
|
|
156
|
+
* value names, both written on that origin ('https://pay.secure-hotel-booking.com/<id>'): the
|
|
157
|
+
* card post and the hub's own calls are one checkout, as payment-core's role rules read them.
|
|
136
158
|
*/
|
|
137
159
|
export function cardEndpointFactsSession(url) {
|
|
138
160
|
let parsed;
|
|
@@ -143,9 +165,21 @@ export function cardEndpointFactsSession(url) {
|
|
|
143
165
|
return null;
|
|
144
166
|
}
|
|
145
167
|
const segments = parsed.pathname.split('/');
|
|
168
|
+
for (const profile of PROFILES) {
|
|
169
|
+
const origin = profile.facts?.origin;
|
|
170
|
+
if (!origin)
|
|
171
|
+
continue;
|
|
172
|
+
if (parsed.origin === origin) {
|
|
173
|
+
const last = segments[segments.length - 1];
|
|
174
|
+
return last ? `${origin}/${last}` : null;
|
|
175
|
+
}
|
|
176
|
+
const bound = parsed.origin === profile.endpoint ? boundSegment(profile.path, segments, profile.facts.bind) : null;
|
|
177
|
+
if (bound)
|
|
178
|
+
return `${origin}/${bound}`;
|
|
179
|
+
}
|
|
146
180
|
let shortest = null;
|
|
147
181
|
for (const profile of PROFILES) {
|
|
148
|
-
if (!profile.facts || profile.endpoint !== parsed.origin)
|
|
182
|
+
if (!profile.facts || profile.facts.origin || profile.endpoint !== parsed.origin)
|
|
149
183
|
continue;
|
|
150
184
|
const template = profile.path.split('/');
|
|
151
185
|
const at = template.indexOf(`:${profile.facts.bind}`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
// Generated from @agent-cards/payment-core. Do not edit.
|
|
3
|
-
// artifact-sha256:
|
|
3
|
+
// artifact-sha256: 7e485110ac882bd8e19be7369be8487a532ae7dc93bde3bf660fecb1851f500e
|
|
4
4
|
// src/card-number-key.js
|
|
5
5
|
var CARD_NUMBER_KEY = /^(number|card_number|cardnumber|cardNum|card_num|pan)$/i;
|
|
6
6
|
// src/json-path.js
|
|
@@ -101,8 +101,8 @@ function parseConvergeBody(body) {
|
|
|
101
101
|
return parsed;
|
|
102
102
|
}
|
|
103
103
|
function convergeAmountCents(value) {
|
|
104
|
-
const
|
|
105
|
-
const m = typeof
|
|
104
|
+
const text3 = typeof value === "number" && Number.isFinite(value) ? String(value) : value;
|
|
105
|
+
const m = typeof text3 === "string" ? AMOUNT.exec(text3) : null;
|
|
106
106
|
if (!m)
|
|
107
107
|
return null;
|
|
108
108
|
const cents = Number(m[1]) * 100 + Number(((m[2] ?? "") + "00").slice(0, 2));
|
|
@@ -582,9 +582,9 @@ var K = /* @__PURE__ */ new Uint32Array([
|
|
|
582
582
|
3329325298
|
|
583
583
|
]);
|
|
584
584
|
var rotr = (x, n) => x >>> n | x << 32 - n;
|
|
585
|
-
function utf8(
|
|
585
|
+
function utf8(text3) {
|
|
586
586
|
const out = [];
|
|
587
|
-
for (const char of
|
|
587
|
+
for (const char of text3) {
|
|
588
588
|
let cp = char.codePointAt(0);
|
|
589
589
|
if (cp >= 55296 && cp <= 57343)
|
|
590
590
|
cp = 65533;
|
|
@@ -1368,14 +1368,14 @@ function readJson2(body) {
|
|
|
1368
1368
|
catch {
|
|
1369
1369
|
return { parsed: null, exact: false };
|
|
1370
1370
|
}
|
|
1371
|
-
let
|
|
1371
|
+
let exact2 = false;
|
|
1372
1372
|
try {
|
|
1373
|
-
|
|
1373
|
+
exact2 = body.length <= BODY_LIMIT6 && JSON.stringify(parsed) === body;
|
|
1374
1374
|
}
|
|
1375
1375
|
catch {
|
|
1376
|
-
|
|
1376
|
+
exact2 = false;
|
|
1377
1377
|
}
|
|
1378
|
-
return { parsed, exact };
|
|
1378
|
+
return { parsed, exact: exact2 };
|
|
1379
1379
|
}
|
|
1380
1380
|
function billingValue(value) {
|
|
1381
1381
|
if (value === UNDEFINED)
|
|
@@ -1430,14 +1430,14 @@ function attachType(parsed) {
|
|
|
1430
1430
|
return typeof type === "string" ? type : null;
|
|
1431
1431
|
}
|
|
1432
1432
|
function paymongoBodyVerdict(body, session) {
|
|
1433
|
-
const { parsed, exact } = readJson2(body);
|
|
1433
|
+
const { parsed, exact: exact2 } = readJson2(body);
|
|
1434
1434
|
const type = parsed === null ? null : attachType(parsed);
|
|
1435
1435
|
if (type !== "card") {
|
|
1436
1436
|
if (parsed === null)
|
|
1437
1437
|
return body === void 0 || body === null || body === "" ? CONTINUE4 : refuse10("paymongo_body_unsupported");
|
|
1438
1438
|
return namesCardValue(parsed) ? refuse10("paymongo_body_unsupported") : CONTINUE4;
|
|
1439
1439
|
}
|
|
1440
|
-
if (!
|
|
1440
|
+
if (!exact2)
|
|
1441
1441
|
return refuse10("paymongo_body_unsupported");
|
|
1442
1442
|
const code = judgeCardAttach(parsed, session);
|
|
1443
1443
|
return code === null ? CARD9 : refuse10(code);
|
|
@@ -1658,6 +1658,9 @@ function payrexxGateVerdict(url, body) {
|
|
|
1658
1658
|
const verdict = payrexxBodyVerdict(body);
|
|
1659
1659
|
return verdict.verdict === "card" && target.pspId !== PAYREXX_PAY_PSP_ID ? refuse12("payrexx_other_provider") : verdict;
|
|
1660
1660
|
}
|
|
1661
|
+
var PAYREXX_FOLLOW_UP_WINDOW_MS = 15 * 60 * 1e3;
|
|
1662
|
+
var PAYREXX_FOLLOW_UP_IDLE_MS = 60 * 1e3;
|
|
1663
|
+
var PAYREXX_FOLLOW_UP_CHALLENGE_MS = 11 * 60 * 1e3;
|
|
1661
1664
|
// src/komoju.js
|
|
1662
1665
|
var KOMOJU_PSP = "komoju";
|
|
1663
1666
|
var KOMOJU_HOST = "komoju.com";
|
|
@@ -2091,7 +2094,7 @@ var luhn2 = (digits) => {
|
|
|
2091
2094
|
return sum % 10 === 0;
|
|
2092
2095
|
};
|
|
2093
2096
|
var ANY_NETWORK = /^[2-6][0-9]{12,18}$/;
|
|
2094
|
-
var holdsCardShape = (
|
|
2097
|
+
var holdsCardShape = (text3, shape = NETWORK) => (text3.match(/[0-9]{13,}/g) ?? []).some((run) => run.length > 19 || shape.test(run) && luhn2(run));
|
|
2095
2098
|
var phone = (value) => typeof value === "string" && PHONE.test(value) && (value.match(/[0-9]/g) ?? []).length >= 6 && (value.match(/[0-9]/g) ?? []).length <= 15;
|
|
2096
2099
|
var refuse16 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
2097
2100
|
var CARD15 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
@@ -2319,13 +2322,13 @@ var printable = (value) => [...value].every((ch) => ch.charCodeAt(0) >= 32 && ch
|
|
|
2319
2322
|
function typed(value, limit = 256) {
|
|
2320
2323
|
return typeof value === "string" && value.length >= 1 && value.length <= limit && !PAN_LIKE4.test(value) && printable(value);
|
|
2321
2324
|
}
|
|
2322
|
-
function decodeBase64(
|
|
2323
|
-
if (typeof
|
|
2325
|
+
function decodeBase64(text3) {
|
|
2326
|
+
if (typeof text3 !== "string" || !BASE643.test(text3) || text3.length % 4 !== 0)
|
|
2324
2327
|
return null;
|
|
2325
2328
|
let bits = 0;
|
|
2326
2329
|
let value = 0;
|
|
2327
2330
|
let out = "";
|
|
2328
|
-
for (const ch of
|
|
2331
|
+
for (const ch of text3.replace(/=+$/, "")) {
|
|
2329
2332
|
value = (value << 6 | BASE64_ALPHABET.indexOf(ch)) & 16777215;
|
|
2330
2333
|
bits += 6;
|
|
2331
2334
|
if (bits >= 8) {
|
|
@@ -2335,8 +2338,8 @@ function decodeBase64(text2) {
|
|
|
2335
2338
|
}
|
|
2336
2339
|
return out;
|
|
2337
2340
|
}
|
|
2338
|
-
function soundDevice(
|
|
2339
|
-
const json = decodeBase64(
|
|
2341
|
+
function soundDevice(text3) {
|
|
2342
|
+
const json = decodeBase64(text3);
|
|
2340
2343
|
if (json === null)
|
|
2341
2344
|
return false;
|
|
2342
2345
|
let value;
|
|
@@ -2450,6 +2453,451 @@ function sumupBodyVerdict(body, url) {
|
|
|
2450
2453
|
return refuse17("sumup_card_saving_refused");
|
|
2451
2454
|
return CARD16;
|
|
2452
2455
|
}
|
|
2456
|
+
// src/twoc2p-secure-pay.js
|
|
2457
|
+
var SALTED = /* @__PURE__ */ Object.freeze([83, 97, 108, 116, 101, 100, 95, 95]);
|
|
2458
|
+
var B64 = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
2459
|
+
var FIELD_LIMIT = 1024;
|
|
2460
|
+
function decodeCanonical(text3) {
|
|
2461
|
+
if (typeof text3 !== "string" || text3.length === 0 || text3.length % 4 !== 0 || !B64.test(text3))
|
|
2462
|
+
return null;
|
|
2463
|
+
let binary;
|
|
2464
|
+
try {
|
|
2465
|
+
binary = atob(text3);
|
|
2466
|
+
}
|
|
2467
|
+
catch {
|
|
2468
|
+
return null;
|
|
2469
|
+
}
|
|
2470
|
+
if (btoa(binary) !== text3)
|
|
2471
|
+
return null;
|
|
2472
|
+
return Uint8Array.from(binary, (char) => char.charCodeAt(0));
|
|
2473
|
+
}
|
|
2474
|
+
function twoC2pSecurePayParts(value) {
|
|
2475
|
+
if (typeof value !== "string" || value.length > FIELD_LIMIT || !/^[0-9a-f]{4}/.test(value))
|
|
2476
|
+
return null;
|
|
2477
|
+
const length = parseInt(value.slice(0, 4), 16);
|
|
2478
|
+
if (length < 4 || 4 + length >= value.length)
|
|
2479
|
+
return null;
|
|
2480
|
+
const rsaText = value.slice(4, 4 + length);
|
|
2481
|
+
const rsa = decodeCanonical(rsaText);
|
|
2482
|
+
const cipher = decodeCanonical(value.slice(4 + length));
|
|
2483
|
+
if (!rsa || !cipher || cipher.length < 32 || cipher.length > 80 || cipher.length % 16 !== 0)
|
|
2484
|
+
return null;
|
|
2485
|
+
if (!SALTED.every((byte, at) => cipher[at] === byte))
|
|
2486
|
+
return null;
|
|
2487
|
+
return { rsaText, rsa, salt: cipher.slice(8, 16), blocks: (cipher.length - 16) / 16 };
|
|
2488
|
+
}
|
|
2489
|
+
function isTwoC2pPageField(value, keyBytes) {
|
|
2490
|
+
const parts = twoC2pSecurePayParts(value);
|
|
2491
|
+
if (!parts || !Number.isInteger(keyBytes) || keyBytes < 128)
|
|
2492
|
+
return false;
|
|
2493
|
+
const expected = Math.ceil(keyBytes / 3) * 4;
|
|
2494
|
+
return parts.rsaText.length === expected && (parts.rsa.length === keyBytes || parts.rsa.length === keyBytes - 1);
|
|
2495
|
+
}
|
|
2496
|
+
// src/twoc2p-keys.js
|
|
2497
|
+
var TWOC2P_KEYS = /* @__PURE__ */ Object.freeze({
|
|
2498
|
+
production: Object.freeze({
|
|
2499
|
+
spki: "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/1ljsxI+r6qQraTFrHfWNrV41vxumBF+4ILAG3WsN6HEBQU2wSUv/IyQmZkiys1ilOb+OOuQTH8OXMnqQg9E4epyePW3L7IeOieSbIIDeSX6UpTWmT/Fs7moWZkN8RpuCV0u87n3AY2tQbtcSqwEKi2sxzWLFwscoGn6N5yVIpQIDAQAB",
|
|
2500
|
+
sha256: "bb8f27929ce140c6ef0ec9c4a20d7ca0b83376bc35a501985dc40d16669384fe",
|
|
2501
|
+
script: Object.freeze({ url: "https://t.2c2p.com/SecurePayment/api/my2c2p.1.7.6.min.js", sha256: "4a745a37765a2e28e299d64f6ea5811aab27b176da61db6f840fa85d6a47e763" })
|
|
2502
|
+
}),
|
|
2503
|
+
sandbox: Object.freeze({
|
|
2504
|
+
spki: "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKakJC+2MSZikKoPzlNqXvJCuWNLhejg3gMRePSetYNNgnhyqFwwAR7t7i/B2QFZoixSYc2/23cJz0jA5O+q+Cu3fycqKlf1L9966+X3B9nyHe2eKQZr8KrcS/8+sEKcd0pLATY4AleW1iktuN+2oghrDKuv+aDNztWcOy+PTofwIDAQAB",
|
|
2505
|
+
sha256: "7f80c07f1d72db28ede10dae942940657c72dfa789836c9fdf283cba6feff2e6",
|
|
2506
|
+
script: Object.freeze({ url: "https://demo2.2c2p.com/2C2PFrontEnd/SecurePayment/api/my2c2p.1.7.6.min.js", sha256: "435723d92bfefb00607a56851967e0b745d52b8d49443de5f0000f0583fde5cc" })
|
|
2507
|
+
})
|
|
2508
|
+
});
|
|
2509
|
+
function twoC2pKey(environment2) {
|
|
2510
|
+
if (environment2 !== "production" && environment2 !== "sandbox")
|
|
2511
|
+
return null;
|
|
2512
|
+
return TWOC2P_KEYS[environment2] ?? null;
|
|
2513
|
+
}
|
|
2514
|
+
function twoC2pKeyBytes(environment2) {
|
|
2515
|
+
const key = twoC2pKey(environment2);
|
|
2516
|
+
if (!key)
|
|
2517
|
+
return null;
|
|
2518
|
+
try {
|
|
2519
|
+
return parseRsaPublicKey(key).size;
|
|
2520
|
+
}
|
|
2521
|
+
catch {
|
|
2522
|
+
return null;
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
// src/twoc2p.js
|
|
2526
|
+
var TWOC2P_PSP = "twoc2p";
|
|
2527
|
+
var TWOC2P_FIELD = "securePayToken";
|
|
2528
|
+
var TWOC2P_REVIEWED_BUILDS = /* @__PURE__ */ Object.freeze(["4.1", "4.2", "4.3", "4.4", "4.5"]);
|
|
2529
|
+
var record12 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2530
|
+
var refuse18 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
2531
|
+
var CARD17 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
2532
|
+
var CONTINUE8 = /* @__PURE__ */ Object.freeze({ verdict: "continue" });
|
|
2533
|
+
var PAYMENT_URL = /^https:\/\/(sandbox-)?pgwv4\.2c2p\.com\/payment\/(4\.[0-9]{1,2})\/Payment$/;
|
|
2534
|
+
function twoC2pPaymentTarget(url) {
|
|
2535
|
+
const match = typeof url === "string" ? PAYMENT_URL.exec(url) : null;
|
|
2536
|
+
if (!match)
|
|
2537
|
+
return null;
|
|
2538
|
+
return Object.freeze({ environment: match[1] ? "sandbox" : "production", version: match[2], reviewed: TWOC2P_REVIEWED_BUILDS.includes(match[2]) });
|
|
2539
|
+
}
|
|
2540
|
+
function twoC2pPaymentCarriesCard(body) {
|
|
2541
|
+
if (typeof body !== "string")
|
|
2542
|
+
return true;
|
|
2543
|
+
try {
|
|
2544
|
+
return JSON.stringify(JSON.parse(body)).includes(`"${TWOC2P_FIELD}"`);
|
|
2545
|
+
}
|
|
2546
|
+
catch {
|
|
2547
|
+
return true;
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
var ROOT_KEYS6 = /* @__PURE__ */ Object.freeze(["paymentToken", "clientIP", "locale", "responseReturnUrl", "clientID", "payment"]);
|
|
2551
|
+
var CODE_KEYS = /* @__PURE__ */ Object.freeze(["channelCode", "agentCode", "agentChannelCode"]);
|
|
2552
|
+
var DATA_KEYS2 = /* @__PURE__ */ Object.freeze([
|
|
2553
|
+
"name",
|
|
2554
|
+
"isIppChosen",
|
|
2555
|
+
"cardDetails",
|
|
2556
|
+
"loyaltyPoints",
|
|
2557
|
+
"fxRateID",
|
|
2558
|
+
"email",
|
|
2559
|
+
"mobileNo",
|
|
2560
|
+
"mobileNoPrefix",
|
|
2561
|
+
"customerNote",
|
|
2562
|
+
"paymentExpiry",
|
|
2563
|
+
"securePayToken",
|
|
2564
|
+
"cardTokenize",
|
|
2565
|
+
"accountTokenization",
|
|
2566
|
+
"token",
|
|
2567
|
+
"customerToken",
|
|
2568
|
+
"accountNo",
|
|
2569
|
+
"installmentPeriod",
|
|
2570
|
+
"interestType",
|
|
2571
|
+
"payLaterPeriod",
|
|
2572
|
+
"billingAddress1",
|
|
2573
|
+
"billingAddress2",
|
|
2574
|
+
"billingCity",
|
|
2575
|
+
"billingState",
|
|
2576
|
+
"billingCountryCode",
|
|
2577
|
+
"billingPostalCode",
|
|
2578
|
+
"riskInfo"
|
|
2579
|
+
]);
|
|
2580
|
+
var RISK_KEYS = /* @__PURE__ */ Object.freeze(["customer_id", "shipping_method", "deviceSessionId", "customData"]);
|
|
2581
|
+
var BODY_LIMIT14 = 16384;
|
|
2582
|
+
var CONTROL6 = /[\u0000-\u001f\u007f]/;
|
|
2583
|
+
var CARD_LIKE = /(?:[0-9][ _.:/-]*){12,}/;
|
|
2584
|
+
var PAYMENT_TOKEN = /^[A-Za-z0-9+/]{16,1000}={0,2}$/;
|
|
2585
|
+
var UUID2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2586
|
+
var IP = /^[0-9A-Fa-f.:]{2,45}$/;
|
|
2587
|
+
var LOCALE2 = /^[A-Za-z]{2,3}(?:[-_][A-Za-z0-9]{2,8})?$/;
|
|
2588
|
+
var AGENT = /^[A-Za-z0-9_]{1,32}$/;
|
|
2589
|
+
var RISK_TOKEN2 = /^[\x21-\x7e]{1,512}$/;
|
|
2590
|
+
var RETURN_URL = /^https:\/\/((?:sandbox-)?pgw-ui\.2c2p\.com)\/payment\/4\.[0-9]{1,2}(?:\/|\/index\.html)?#\/(?:info|mobile\/process)\/([A-Za-z0-9+/]{16,1000}={0,2})?$/;
|
|
2591
|
+
var PAGE_HOSTS = /* @__PURE__ */ Object.freeze({ production: "pgw-ui.2c2p.com", sandbox: "sandbox-pgw-ui.2c2p.com" });
|
|
2592
|
+
var returnUrlTaken = (value, paymentToken, environment2) => {
|
|
2593
|
+
if (value === void 0)
|
|
2594
|
+
return true;
|
|
2595
|
+
const match = typeof value === "string" ? RETURN_URL.exec(value) : null;
|
|
2596
|
+
return !!match && (match[2] === void 0 || match[2] === paymentToken) && (environment2 === void 0 || match[1] === PAGE_HOSTS[environment2]);
|
|
2597
|
+
};
|
|
2598
|
+
var inOrder2 = (value, order) => {
|
|
2599
|
+
let at = -1;
|
|
2600
|
+
for (const key of Object.keys(value)) {
|
|
2601
|
+
const next = order.indexOf(key);
|
|
2602
|
+
if (next <= at)
|
|
2603
|
+
return false;
|
|
2604
|
+
at = next;
|
|
2605
|
+
}
|
|
2606
|
+
return true;
|
|
2607
|
+
};
|
|
2608
|
+
var text2 = (value, limit) => typeof value === "string" && value.length <= limit && !CONTROL6.test(value) && !CARD_LIKE.test(value);
|
|
2609
|
+
var optionalText = (value, limit) => value === void 0 || text2(value, limit);
|
|
2610
|
+
function twoC2pBodyVerdict(body, keyBytes = 128, environment2 = void 0) {
|
|
2611
|
+
if (!twoC2pPaymentCarriesCard(body))
|
|
2612
|
+
return CONTINUE8;
|
|
2613
|
+
if (typeof body !== "string" || body.length > BODY_LIMIT14)
|
|
2614
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2615
|
+
let value;
|
|
2616
|
+
try {
|
|
2617
|
+
value = JSON.parse(body);
|
|
2618
|
+
}
|
|
2619
|
+
catch {
|
|
2620
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2621
|
+
}
|
|
2622
|
+
if (!record12(value) || JSON.stringify(value) !== body || !inOrder2(value, ROOT_KEYS6))
|
|
2623
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2624
|
+
if (typeof value.paymentToken !== "string" || !PAYMENT_TOKEN.test(value.paymentToken) || value.clientIP !== void 0 && !(typeof value.clientIP === "string" && IP.test(value.clientIP)) || value.locale !== void 0 && !(typeof value.locale === "string" && LOCALE2.test(value.locale)) || !returnUrlTaken(value.responseReturnUrl, value.paymentToken, environment2) || value.clientID !== void 0 && !(typeof value.clientID === "string" && UUID2.test(value.clientID)))
|
|
2625
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2626
|
+
const payment = value.payment;
|
|
2627
|
+
if (!record12(payment) || Object.keys(payment).join(",") !== "code,data")
|
|
2628
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2629
|
+
const code = payment.code;
|
|
2630
|
+
const data = payment.data;
|
|
2631
|
+
if (!record12(code) || !record12(data))
|
|
2632
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2633
|
+
if (Object.prototype.hasOwnProperty.call(code, "subChannelCode"))
|
|
2634
|
+
return refuse18("twoc2p_stored_card");
|
|
2635
|
+
if (code.channelCode === "IPP" || code.channelCode === "LIPP")
|
|
2636
|
+
return refuse18("twoc2p_installments");
|
|
2637
|
+
if (!inOrder2(code, CODE_KEYS) || code.channelCode === void 0)
|
|
2638
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2639
|
+
if (code.channelCode !== "CC")
|
|
2640
|
+
return refuse18("twoc2p_channel_unsupported");
|
|
2641
|
+
if ([code.agentCode, code.agentChannelCode].some((part) => part !== void 0 && !(typeof part === "string" && AGENT.test(part))))
|
|
2642
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2643
|
+
return dataVerdict(data, keyBytes, body);
|
|
2644
|
+
}
|
|
2645
|
+
function dataVerdict(data, keyBytes, body) {
|
|
2646
|
+
if (data.cardTokenize !== void 0 || data.accountTokenization !== void 0)
|
|
2647
|
+
return refuse18("twoc2p_keeps_card");
|
|
2648
|
+
if (data.token !== void 0 || data.customerToken !== void 0)
|
|
2649
|
+
return refuse18("twoc2p_stored_card");
|
|
2650
|
+
if (data.accountNo !== void 0)
|
|
2651
|
+
return refuse18("twoc2p_card_in_clear");
|
|
2652
|
+
const details = data.cardDetails;
|
|
2653
|
+
if (record12(details) && (details.cardNo !== void 0 || details.accountNo !== void 0))
|
|
2654
|
+
return refuse18("twoc2p_card_in_clear");
|
|
2655
|
+
if (record12(details) && Object.keys(details).some((key) => key !== "email"))
|
|
2656
|
+
return refuse18("twoc2p_stored_card");
|
|
2657
|
+
if (data.isIppChosen === true || data.installmentPeriod !== void 0 || data.interestType !== void 0 || data.payLaterPeriod !== void 0) {
|
|
2658
|
+
return refuse18("twoc2p_installments");
|
|
2659
|
+
}
|
|
2660
|
+
if (data.fxRateID !== void 0)
|
|
2661
|
+
return refuse18("twoc2p_currency_conversion");
|
|
2662
|
+
if (data.loyaltyPoints !== void 0 && !(Array.isArray(data.loyaltyPoints) && data.loyaltyPoints.length === 0)) {
|
|
2663
|
+
return refuse18("twoc2p_loyalty_redemption");
|
|
2664
|
+
}
|
|
2665
|
+
if (!inOrder2(data, DATA_KEYS2) || data.paymentExpiry !== void 0)
|
|
2666
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2667
|
+
if (typeof data.securePayToken !== "string" || !isTwoC2pPageField(data.securePayToken, keyBytes))
|
|
2668
|
+
return refuse18("twoc2p_field_unreviewed");
|
|
2669
|
+
if (body.split(data.securePayToken).length !== 2)
|
|
2670
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2671
|
+
if (data.isIppChosen !== void 0 && data.isIppChosen !== false)
|
|
2672
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2673
|
+
if (details !== void 0 && !(record12(details) && (details.email === void 0 || text2(details.email, 254))))
|
|
2674
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2675
|
+
if (!optionalText(data.name, 128) || !optionalText(data.email, 254) || !optionalText(data.customerNote, 255) || !(data.mobileNo === void 0 || typeof data.mobileNo === "string" && /^[0-9]{4,11}$/.test(data.mobileNo)) || !(data.mobileNoPrefix === void 0 || typeof data.mobileNoPrefix === "string" && /^\+?[0-9]{1,4}$/.test(data.mobileNoPrefix))) {
|
|
2676
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2677
|
+
}
|
|
2678
|
+
for (const key of ["billingAddress1", "billingAddress2", "billingCity", "billingState", "billingPostalCode"]) {
|
|
2679
|
+
if (!optionalText(data[key], 128))
|
|
2680
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2681
|
+
}
|
|
2682
|
+
if (data.billingCountryCode !== void 0 && !(typeof data.billingCountryCode === "string" && /^[A-Za-z]{2}$/.test(data.billingCountryCode))) {
|
|
2683
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2684
|
+
}
|
|
2685
|
+
const risk = data.riskInfo;
|
|
2686
|
+
if (risk !== void 0 && risk !== null && !(record12(risk) && Object.keys(risk).join(",") === RISK_KEYS.join(",") && risk.customer_id === "" && risk.shipping_method === "" && typeof risk.deviceSessionId === "string" && RISK_TOKEN2.test(risk.deviceSessionId) && record12(risk.customData) && Object.keys(risk.customData).length === 0)) {
|
|
2687
|
+
return refuse18("twoc2p_body_unsupported");
|
|
2688
|
+
}
|
|
2689
|
+
return CARD17;
|
|
2690
|
+
}
|
|
2691
|
+
// src/hipay.js
|
|
2692
|
+
var HIPAY_PSP = "hipay";
|
|
2693
|
+
var HIPAY_TOKEN_URLS = /* @__PURE__ */ Object.freeze({
|
|
2694
|
+
production: "https://secure2-vault.hipay-tpp.com/rest/v2/token",
|
|
2695
|
+
sandbox: "https://stage-secure2-vault.hipay-tpp.com/rest/v2/token"
|
|
2696
|
+
});
|
|
2697
|
+
var BODY_LIMIT15 = 2048;
|
|
2698
|
+
var HOSTED_KEYS = /* @__PURE__ */ Object.freeze(["multi_use", "card_expiry_month", "card_expiry_year", "card_number", "card_holder", "cvc"]);
|
|
2699
|
+
var HOSTED_KEYS_NO_HOLDER = /* @__PURE__ */ Object.freeze(["multi_use", "card_expiry_month", "card_expiry_year", "card_number", "cvc"]);
|
|
2700
|
+
var DIRECT_KEYS = /* @__PURE__ */ Object.freeze(["card_expiry_month", "card_expiry_year", "card_number", "card_holder", "cvc", "multi_use"]);
|
|
2701
|
+
var DIRECT_KEYS_NO_HOLDER = /* @__PURE__ */ Object.freeze(["card_expiry_month", "card_expiry_year", "card_number", "cvc", "multi_use"]);
|
|
2702
|
+
var CARD_SHAPES = /* @__PURE__ */ Object.freeze([HOSTED_KEYS, HOSTED_KEYS_NO_HOLDER, DIRECT_KEYS, DIRECT_KEYS_NO_HOLDER]);
|
|
2703
|
+
var NUMBER_ONLY_KEYS = /* @__PURE__ */ Object.freeze(["multi_use", "card_expiry_month", "card_expiry_year", "card_number"]);
|
|
2704
|
+
var CARD_NUMBER10 = /^[0-9]{12,19}$/;
|
|
2705
|
+
var SECURITY_CODE12 = /^[0-9]{3,4}$/;
|
|
2706
|
+
var MONTH8 = /^(?:0[1-9]|1[0-2])$/;
|
|
2707
|
+
var YEAR8 = /^20[0-9]{2}$/;
|
|
2708
|
+
var TEXT_LIMIT3 = 256;
|
|
2709
|
+
var CONTROL7 = /[\u0000-\u001f\u007f]/;
|
|
2710
|
+
var record13 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2711
|
+
var sameKeys7 = (value, keys) => {
|
|
2712
|
+
const own3 = Object.keys(value);
|
|
2713
|
+
return own3.length === keys.length && own3.every((key, at) => key === keys[at]);
|
|
2714
|
+
};
|
|
2715
|
+
var plainText3 = (value) => typeof value === "string" && value.length <= TEXT_LIMIT3 && !CONTROL7.test(value) && (value.match(/[0-9]/g) ?? []).length < 12;
|
|
2716
|
+
var refuse19 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
2717
|
+
var CARD18 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
2718
|
+
function hipayTokenEnvironment(url) {
|
|
2719
|
+
if (url === HIPAY_TOKEN_URLS.production)
|
|
2720
|
+
return "production";
|
|
2721
|
+
if (url === HIPAY_TOKEN_URLS.sandbox)
|
|
2722
|
+
return "sandbox";
|
|
2723
|
+
return null;
|
|
2724
|
+
}
|
|
2725
|
+
function isHipayTokenUrl(url) {
|
|
2726
|
+
return hipayTokenEnvironment(url) !== null;
|
|
2727
|
+
}
|
|
2728
|
+
function readBody9(body) {
|
|
2729
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT15)
|
|
2730
|
+
return null;
|
|
2731
|
+
let value;
|
|
2732
|
+
try {
|
|
2733
|
+
value = JSON.parse(body);
|
|
2734
|
+
if (!record13(value) || JSON.stringify(value) !== body)
|
|
2735
|
+
return null;
|
|
2736
|
+
}
|
|
2737
|
+
catch {
|
|
2738
|
+
return null;
|
|
2739
|
+
}
|
|
2740
|
+
return value;
|
|
2741
|
+
}
|
|
2742
|
+
function hipayBodyVerdict(body) {
|
|
2743
|
+
const value = readBody9(body);
|
|
2744
|
+
if (value === null)
|
|
2745
|
+
return refuse19("hipay_body_unsupported");
|
|
2746
|
+
if (sameKeys7(value, NUMBER_ONLY_KEYS))
|
|
2747
|
+
return refuse19("hipay_number_only");
|
|
2748
|
+
if (!CARD_SHAPES.some((keys) => sameKeys7(value, keys)))
|
|
2749
|
+
return refuse19("hipay_body_unsupported");
|
|
2750
|
+
if (typeof value.card_number !== "string" || !CARD_NUMBER10.test(value.card_number) || typeof value.cvc !== "string" || !SECURITY_CODE12.test(value.cvc) || typeof value.card_expiry_month !== "string" || !MONTH8.test(value.card_expiry_month) || typeof value.card_expiry_year !== "string" || !YEAR8.test(value.card_expiry_year) || "card_holder" in value && !plainText3(value.card_holder)) {
|
|
2751
|
+
return refuse19("hipay_body_unsupported");
|
|
2752
|
+
}
|
|
2753
|
+
if (value.multi_use === 1)
|
|
2754
|
+
return refuse19("hipay_keeps_card");
|
|
2755
|
+
return value.multi_use === 0 ? CARD18 : refuse19("hipay_body_unsupported");
|
|
2756
|
+
}
|
|
2757
|
+
// src/amazon-payment-services.js
|
|
2758
|
+
var APS_PSP = "amazon_payment_services";
|
|
2759
|
+
var APS_HOSTS = /* @__PURE__ */ Object.freeze({ "checkout.payfort.com": "production", "sbcheckout.payfort.com": "sandbox" });
|
|
2760
|
+
var APS_TOKENIZATION_PATH = "/FortAPI/paymentPage";
|
|
2761
|
+
var APS_SIGNED_FIELDS = /* @__PURE__ */ Object.freeze([
|
|
2762
|
+
"service_command",
|
|
2763
|
+
"access_code",
|
|
2764
|
+
"merchant_identifier",
|
|
2765
|
+
"merchant_reference",
|
|
2766
|
+
"language",
|
|
2767
|
+
"return_url",
|
|
2768
|
+
"signature"
|
|
2769
|
+
]);
|
|
2770
|
+
var APS_CARD_FIELDS = /* @__PURE__ */ Object.freeze(["card_number", "expiry_date", "card_security_code"]);
|
|
2771
|
+
var APS_OPTIONAL_FIELDS = /* @__PURE__ */ Object.freeze(["card_holder_name", "remember_me"]);
|
|
2772
|
+
var URL_LIMIT7 = 2048;
|
|
2773
|
+
var BODY_LIMIT16 = 32 * 1024;
|
|
2774
|
+
var exact = (pattern, value) => typeof value === "string" && pattern.exec(value)?.[0] === value;
|
|
2775
|
+
var controlFree = (value, max) => typeof value === "string" && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
|
|
2776
|
+
var SHAPES = /* @__PURE__ */ new Map([
|
|
2777
|
+
["service_command", (v) => v === "TOKENIZATION"],
|
|
2778
|
+
["access_code", (v) => exact(/^[A-Za-z0-9]{1,20}$/, v)],
|
|
2779
|
+
["merchant_identifier", (v) => exact(/^[A-Za-z0-9]{1,20}$/, v)],
|
|
2780
|
+
["merchant_reference", (v) => exact(/^[A-Za-z0-9._-]{1,40}$/, v)],
|
|
2781
|
+
["language", (v) => v === "en" || v === "ar"],
|
|
2782
|
+
// Hex SHA-256 (APS's default), SHA-512, or the 40 characters of the SHA-1 APS calls SHA-128.
|
|
2783
|
+
["signature", (v) => exact(/^(?:[0-9A-Fa-f]{40}|[0-9A-Fa-f]{64}|[0-9A-Fa-f]{128})$/, v)],
|
|
2784
|
+
["card_number", (v) => exact(/^[0-9]{12,19}$/, v)],
|
|
2785
|
+
["expiry_date", (v) => exact(/^[0-9]{2}(?:0[1-9]|1[0-2])$/, v)],
|
|
2786
|
+
["card_security_code", (v) => exact(/^[0-9]{3,4}$/, v)],
|
|
2787
|
+
["card_holder_name", (v) => controlFree(v, 255)],
|
|
2788
|
+
["remember_me", (v) => v === "YES" || v === "NO"]
|
|
2789
|
+
]);
|
|
2790
|
+
function apsTokenizationUrl(url) {
|
|
2791
|
+
if (typeof url !== "string" || url.length > URL_LIMIT7 || url.includes("?") || url.includes("#"))
|
|
2792
|
+
return null;
|
|
2793
|
+
let parsed;
|
|
2794
|
+
try {
|
|
2795
|
+
parsed = new URL(url);
|
|
2796
|
+
}
|
|
2797
|
+
catch {
|
|
2798
|
+
return null;
|
|
2799
|
+
}
|
|
2800
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || parsed.pathname !== APS_TOKENIZATION_PATH || !Object.prototype.hasOwnProperty.call(APS_HOSTS, parsed.hostname))
|
|
2801
|
+
return null;
|
|
2802
|
+
return Object.freeze({ host: parsed.hostname, environment: APS_HOSTS[parsed.hostname] });
|
|
2803
|
+
}
|
|
2804
|
+
function formEncode2(value) {
|
|
2805
|
+
let encoded;
|
|
2806
|
+
try {
|
|
2807
|
+
encoded = encodeURIComponent(value);
|
|
2808
|
+
}
|
|
2809
|
+
catch {
|
|
2810
|
+
return null;
|
|
2811
|
+
}
|
|
2812
|
+
return encoded.replace(/[!'()~]/g, (ch) => `%${ch.charCodeAt(0).toString(16).toUpperCase()}`).replace(/%20/g, "+");
|
|
2813
|
+
}
|
|
2814
|
+
function formDecode(raw) {
|
|
2815
|
+
if (!/^(?:[A-Za-z0-9*._+-]|%[0-9A-F]{2})*$/.test(raw))
|
|
2816
|
+
return null;
|
|
2817
|
+
let value;
|
|
2818
|
+
try {
|
|
2819
|
+
value = decodeURIComponent(raw.replace(/\+/g, "%20"));
|
|
2820
|
+
}
|
|
2821
|
+
catch {
|
|
2822
|
+
return null;
|
|
2823
|
+
}
|
|
2824
|
+
return formEncode2(value) === raw ? value : null;
|
|
2825
|
+
}
|
|
2826
|
+
function parseForm(body) {
|
|
2827
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT16)
|
|
2828
|
+
return null;
|
|
2829
|
+
const pairs = [];
|
|
2830
|
+
const values = /* @__PURE__ */ new Map();
|
|
2831
|
+
for (const chunk of body.split("&")) {
|
|
2832
|
+
const separator = chunk.indexOf("=");
|
|
2833
|
+
if (separator < 1)
|
|
2834
|
+
return null;
|
|
2835
|
+
const rawName = chunk.slice(0, separator), raw = chunk.slice(separator + 1);
|
|
2836
|
+
const name = formDecode(rawName), value = formDecode(raw);
|
|
2837
|
+
if (name === null || value === null || values.has(name))
|
|
2838
|
+
return null;
|
|
2839
|
+
pairs.push({ name, rawName, raw, value });
|
|
2840
|
+
values.set(name, value);
|
|
2841
|
+
}
|
|
2842
|
+
return { pairs, values };
|
|
2843
|
+
}
|
|
2844
|
+
function returnUrlAdmitted(value) {
|
|
2845
|
+
if (typeof value !== "string" || value.length > 400 || value.includes("#") || /[\u0000- \u007f]/.test(value))
|
|
2846
|
+
return false;
|
|
2847
|
+
let parsed;
|
|
2848
|
+
try {
|
|
2849
|
+
parsed = new URL(value);
|
|
2850
|
+
}
|
|
2851
|
+
catch {
|
|
2852
|
+
return false;
|
|
2853
|
+
}
|
|
2854
|
+
return parsed.protocol === "https:" && !parsed.username && !parsed.password && parsed.href === value;
|
|
2855
|
+
}
|
|
2856
|
+
function apsBodyRefusal(body) {
|
|
2857
|
+
const form = parseForm(body);
|
|
2858
|
+
if (!form)
|
|
2859
|
+
return "aps_body_unsupported";
|
|
2860
|
+
const has = (name) => form.values.has(name);
|
|
2861
|
+
if (has("token_name"))
|
|
2862
|
+
return "aps_saved_card_refused";
|
|
2863
|
+
if ([...form.values.keys()].some((name) => /^merchant_extra[1-5]?$|^agreement_id$|^recurring_/.test(name)))
|
|
2864
|
+
return "aps_recurring_refused";
|
|
2865
|
+
if (has("service_command") && form.values.get("service_command") !== "TOKENIZATION")
|
|
2866
|
+
return "aps_service_command_refused";
|
|
2867
|
+
const allowed = /* @__PURE__ */ new Set([...APS_SIGNED_FIELDS, ...APS_CARD_FIELDS, ...APS_OPTIONAL_FIELDS]);
|
|
2868
|
+
if (form.pairs.some(({ name }) => !allowed.has(name)))
|
|
2869
|
+
return "aps_body_unsupported";
|
|
2870
|
+
if (!returnUrlAdmitted(form.values.get("return_url")))
|
|
2871
|
+
return "aps_return_url_refused";
|
|
2872
|
+
for (const name of [...APS_SIGNED_FIELDS, ...APS_CARD_FIELDS]) {
|
|
2873
|
+
if (name !== "return_url" && !SHAPES.get(name)(form.values.get(name)))
|
|
2874
|
+
return "aps_body_unsupported";
|
|
2875
|
+
}
|
|
2876
|
+
for (const name of APS_OPTIONAL_FIELDS) {
|
|
2877
|
+
if (has(name) && !SHAPES.get(name)(form.values.get(name)))
|
|
2878
|
+
return "aps_body_unsupported";
|
|
2879
|
+
}
|
|
2880
|
+
return null;
|
|
2881
|
+
}
|
|
2882
|
+
function apsBodyVerdict(body, url) {
|
|
2883
|
+
if (url !== void 0 && !apsTokenizationUrl(url))
|
|
2884
|
+
return { verdict: "refuse", code: "aps_url_refused" };
|
|
2885
|
+
const form = parseForm(body);
|
|
2886
|
+
const names = form ? [...form.values.keys()] : typeof body === "string" ? body.split("&").map((chunk) => {
|
|
2887
|
+
try {
|
|
2888
|
+
return decodeURIComponent(chunk.split("=")[0].replace(/\+/g, " "));
|
|
2889
|
+
}
|
|
2890
|
+
catch {
|
|
2891
|
+
return APS_CARD_FIELDS[0];
|
|
2892
|
+
}
|
|
2893
|
+
}) : [APS_CARD_FIELDS[0]];
|
|
2894
|
+
const mentionsCard = !form && typeof body === "string" && APS_CARD_FIELDS.some((name) => body.toLowerCase().includes(name) || body.replace(/%([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16))).toLowerCase().includes(name));
|
|
2895
|
+
if (!mentionsCard && !names.some((name) => APS_CARD_FIELDS.includes(name.trim().toLowerCase())))
|
|
2896
|
+
return { verdict: "continue" };
|
|
2897
|
+
const code = apsBodyRefusal(body);
|
|
2898
|
+
return code ? { verdict: "refuse", code } : { verdict: "card" };
|
|
2899
|
+
}
|
|
2900
|
+
var ANSWER_LIMIT = 64 * 1024;
|
|
2453
2901
|
// src/card-fields.js
|
|
2454
2902
|
function processorGate(recognizer, url, body) {
|
|
2455
2903
|
if (recognizer && recognizer.psp === LYRA_PSP)
|
|
@@ -2461,6 +2909,11 @@ function processorGate(recognizer, url, body) {
|
|
|
2461
2909
|
}
|
|
2462
2910
|
if (recognizer && recognizer.psp === KOMOJU_PSP)
|
|
2463
2911
|
return komojuBodyVerdict(body, url);
|
|
2912
|
+
if (recognizer && recognizer.psp === HIPAY_PSP) {
|
|
2913
|
+
if (url !== void 0 && !isHipayTokenUrl(url))
|
|
2914
|
+
return { verdict: "refuse", code: "hipay_url_refused" };
|
|
2915
|
+
return hipayBodyVerdict(body);
|
|
2916
|
+
}
|
|
2464
2917
|
if (recognizer && recognizer.psp === PADDLE_VGS_PSP) {
|
|
2465
2918
|
if (url !== void 0 && !isPaddleVgsCardsUrl(url))
|
|
2466
2919
|
return { verdict: "refuse", code: "paddle_vgs_url_refused" };
|
|
@@ -2482,6 +2935,19 @@ function processorGate(recognizer, url, body) {
|
|
|
2482
2935
|
return { verdict: "refuse", code: "pay_nl_url_refused" };
|
|
2483
2936
|
return payNlBodyVerdict(body);
|
|
2484
2937
|
}
|
|
2938
|
+
if (recognizer && recognizer.psp === TWOC2P_PSP) {
|
|
2939
|
+
if (url === void 0)
|
|
2940
|
+
return twoC2pBodyVerdict(body);
|
|
2941
|
+
const target = twoC2pPaymentTarget(url);
|
|
2942
|
+
if (target === null)
|
|
2943
|
+
return { verdict: "refuse", code: "twoc2p_url_refused" };
|
|
2944
|
+
if (!target.reviewed)
|
|
2945
|
+
return twoC2pPaymentCarriesCard(body) ? { verdict: "refuse", code: "twoc2p_build_unreviewed" } : { verdict: "continue" };
|
|
2946
|
+
const keyBytes = twoC2pKeyBytes(target.environment);
|
|
2947
|
+
return keyBytes === null ? { verdict: "refuse", code: "twoc2p_field_unreviewed" } : twoC2pBodyVerdict(body, keyBytes, target.environment);
|
|
2948
|
+
}
|
|
2949
|
+
if (recognizer && recognizer.psp === APS_PSP)
|
|
2950
|
+
return apsBodyVerdict(body, url);
|
|
2485
2951
|
if (recognizer && recognizer.psp === PADDLE_TOKENEX_PSP) {
|
|
2486
2952
|
const target = url !== void 0 ? paddleTokenexPayTarget(url) : null;
|
|
2487
2953
|
if (url !== void 0 && target === null)
|