@agent-cards/sdk 0.24.0 → 0.24.2
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 +32 -0
- package/README.md +61 -4
- package/dist/adyen-merchant-hosted.generated.d.ts +1 -1
- package/dist/adyen-merchant-hosted.generated.js +128 -35
- package/dist/agent-amount.generated.js +1 -1
- package/dist/aurus.d.ts +33 -0
- package/dist/aurus.js +75 -0
- package/dist/builtin-registry.generated.js +1 -1
- package/dist/capabilities.generated.js +1 -1
- package/dist/card-fields.generated.js +1854 -440
- package/dist/cardlink-vpos.d.ts +43 -0
- package/dist/cardlink-vpos.js +90 -0
- package/dist/cdp.js +22 -0
- package/dist/checkout-com.generated.js +5 -1
- package/dist/client.d.ts +75 -0
- package/dist/client.js +75 -0
- package/dist/cybersource-flex.generated.d.ts +39 -1
- package/dist/cybersource-flex.generated.js +100 -11
- package/dist/eghl.d.ts +40 -0
- package/dist/eghl.js +72 -0
- package/dist/gmo.generated.js +7 -2
- package/dist/hosted-entry.js +2 -0
- package/dist/lifecycle.d.ts +10 -0
- package/dist/lifecycle.js +25 -0
- package/dist/paddle-tokenex.generated.js +7 -2
- package/dist/payrails.generated.js +7 -2
- package/dist/pre-claim.d.ts +5 -0
- package/dist/pre-claim.js +90 -2
- package/dist/preflight-catalog.json +179 -1
- package/dist/preflight-schemas.json +16 -0
- package/dist/preflight.generated.d.ts +5 -0
- package/dist/preflight.generated.js +49 -3
- package/dist/preparation.d.ts +7 -0
- package/dist/preparation.js +21 -0
- package/dist/primer.generated.js +1856 -442
- package/dist/shiji-sts.generated.js +7 -2
- package/dist/stripe-checkout.generated.js +1837 -475
- package/dist/substitutions.generated.js +94 -1
- package/dist/tap-payments.generated.js +7 -2
- package/dist/token-repeats.d.ts +32 -0
- package/dist/token-repeats.js +64 -0
- package/dist/twoc2p.generated.js +7 -2
- package/examples/preflight/kernel-native/inventory.json +1 -1
- package/package.json +2 -2
|
@@ -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: 2b384766928412dadfb553ebd4ae0ba3454599de5b60b5abcb0fd26775fb53b5
|
|
4
4
|
// src/deep-freeze.js
|
|
5
5
|
function deepFreeze(value) {
|
|
6
6
|
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
@@ -71,6 +71,182 @@ function registered(spec, parts) {
|
|
|
71
71
|
function registerProcessor(spec) {
|
|
72
72
|
return registered(spec, PARTS);
|
|
73
73
|
}
|
|
74
|
+
// src/processors/aurus.js
|
|
75
|
+
var AURUS_PSP = "aurus";
|
|
76
|
+
var AURUS_OPERATION = "aurus.card_request";
|
|
77
|
+
var AURUS_FRAME_HOST = /^pecst[0-9]{2}\.aurusepay\.com$/;
|
|
78
|
+
var AURUS_TOKEN_PATH = "/storeservices/ecom/oneTimeToken";
|
|
79
|
+
var AURUS_PARTS = /* @__PURE__ */ Object.freeze(["Param", "formFactorId", "txnDateTime", "encryptionFlag", "sha256Flag", "hmacAuthData", "payload"]);
|
|
80
|
+
var URL_LIMIT = 256;
|
|
81
|
+
var BODY_LIMIT = 32768;
|
|
82
|
+
var SERVER = /^es[0-9]{2}\.auruspay\.com$/;
|
|
83
|
+
var HEX = /^[0-9A-Fa-f]{2,8192}$/;
|
|
84
|
+
var FORM_FACTOR = /^[0-9]{1,16}$/;
|
|
85
|
+
var DATE_TIME = /^[0-9]{14}$/;
|
|
86
|
+
var FRAMED = /^STX[0-9]{1,6}\[FS\][0-9A-Fa-f]{2,16384}\[FS\]7[Bb][0-9A-Fa-f]{0,24576}7[Dd]ETX$/;
|
|
87
|
+
var refuse = (code) => Object.freeze({ verdict: "refuse", code });
|
|
88
|
+
var CARD = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
89
|
+
function aurusTokenUrl(url) {
|
|
90
|
+
if (typeof url !== "string" || url.length > URL_LIMIT || url.includes("#"))
|
|
91
|
+
return null;
|
|
92
|
+
let parsed;
|
|
93
|
+
try {
|
|
94
|
+
parsed = new URL(url);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !AURUS_FRAME_HOST.test(parsed.hostname) || parsed.pathname !== AURUS_TOKEN_PATH)
|
|
100
|
+
return null;
|
|
101
|
+
const query = parsed.search.startsWith("?") ? parsed.search.slice(1).split("&") : [];
|
|
102
|
+
if (query.length !== 2)
|
|
103
|
+
return null;
|
|
104
|
+
const [d1, d2] = query.map((pair) => pair.split("="));
|
|
105
|
+
if (d1.length !== 2 || d2.length !== 2 || d1[0] !== "d1" || d2[0] !== "d2" || !SERVER.test(d1[1]) || !SERVER.test(d2[1]))
|
|
106
|
+
return null;
|
|
107
|
+
return Object.freeze({ host: parsed.hostname });
|
|
108
|
+
}
|
|
109
|
+
var isAurusTokenUrl = (url) => aurusTokenUrl(url) !== null;
|
|
110
|
+
function readBody(body) {
|
|
111
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT)
|
|
112
|
+
return null;
|
|
113
|
+
const pairs = body.split("&");
|
|
114
|
+
if (pairs.length !== AURUS_PARTS.length)
|
|
115
|
+
return null;
|
|
116
|
+
const value = {};
|
|
117
|
+
for (const [at, pair] of pairs.entries()) {
|
|
118
|
+
const cut = pair.indexOf("=");
|
|
119
|
+
if (cut < 0 || pair.slice(0, cut) !== AURUS_PARTS[at])
|
|
120
|
+
return null;
|
|
121
|
+
value[AURUS_PARTS[at]] = pair.slice(cut + 1);
|
|
122
|
+
}
|
|
123
|
+
if (!HEX.test(value.Param) || !FORM_FACTOR.test(value.formFactorId) || !DATE_TIME.test(value.txnDateTime) || value.encryptionFlag !== "00" || value.sha256Flag !== "1" || !FRAMED.test(value.hmacAuthData) || !FRAMED.test(value.payload))
|
|
124
|
+
return null;
|
|
125
|
+
return value;
|
|
126
|
+
}
|
|
127
|
+
function aurusBodyVerdict(body) {
|
|
128
|
+
return readBody(body) === null ? refuse("aurus_body_unsupported") : CARD;
|
|
129
|
+
}
|
|
130
|
+
var aurus_default = /* @__PURE__ */ registerProcessor({
|
|
131
|
+
psp: AURUS_PSP,
|
|
132
|
+
definitions: [
|
|
133
|
+
{
|
|
134
|
+
psp: "aurus",
|
|
135
|
+
// The frame's card request, as the header above reads it. No sandbox host is known: Aurus's test instances were
|
|
136
|
+
// not read, so none is listed and no environment is pinned.
|
|
137
|
+
// Ships dark: served only to a client that declares `aurus_one_time_token`, and only for a company the backend's
|
|
138
|
+
// processor gate turns Aurus on for. `(?![\w/.%-])` ends the path for a consumer that tests `match` unanchored.
|
|
139
|
+
capability: "aurus_one_time_token",
|
|
140
|
+
match: "pecst[0-9]{2}\\.aurusepay\\.com/storeservices/ecom/oneTimeToken(?![\\w/.%-])",
|
|
141
|
+
hosts: ["^pecst[0-9]{2}\\.aurusepay\\.com$"],
|
|
142
|
+
encoding: "form",
|
|
143
|
+
// The frame's XHR marker. Origin, Referer and cookies never ride.
|
|
144
|
+
passthroughHeaders: ["^x-requested-with$"]
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
// Only the cardholder's device would send this card, after a person approves; no reviewed list names aurus.
|
|
148
|
+
refusedOperations: [AURUS_OPERATION],
|
|
149
|
+
// The frame mints a one-time token and reads nothing: the store's server charges it with its own credentials.
|
|
150
|
+
settlementReadback: {
|
|
151
|
+
answer: "none",
|
|
152
|
+
reason: "tokenization_credential_cannot_read_charges",
|
|
153
|
+
note: "The tokenization credential cannot read a charge; the shop charges the token later with its own credentials.",
|
|
154
|
+
source: "https://www.oreillyauto.com/checkout (Aurus's ecom iframe, read 2026-10-31)"
|
|
155
|
+
},
|
|
156
|
+
exactUrl: isAurusTokenUrl,
|
|
157
|
+
bodyGate: (url, body) => url !== void 0 && !isAurusTokenUrl(url) ? refuse("aurus_url_refused") : aurusBodyVerdict(body),
|
|
158
|
+
limitations: ["The card frame seals the card in the page under a public key its own script carries; the cardholder's device does not seal for Aurus yet, so a held request opens no approval that pays."]
|
|
159
|
+
});
|
|
160
|
+
// src/processors/bigcommerce.js
|
|
161
|
+
var BIGCOMMERCE_PSP = "bigcommerce";
|
|
162
|
+
var BIGCOMMERCE_OPERATION = "bigcommerce.card_request";
|
|
163
|
+
var BIGCOMMERCE_PAYMENTS_URL = "https://payments.bigcommerce.com/api/public/v1/orders/payments";
|
|
164
|
+
var BODY_LIMIT2 = 65536;
|
|
165
|
+
var CARD_KEYS = /* @__PURE__ */ new Set([
|
|
166
|
+
"account_name",
|
|
167
|
+
"month",
|
|
168
|
+
"number",
|
|
169
|
+
"verification_value",
|
|
170
|
+
"year",
|
|
171
|
+
"customer_code",
|
|
172
|
+
"three_d_secure",
|
|
173
|
+
"hosted_form_nonce"
|
|
174
|
+
]);
|
|
175
|
+
var OTHER_INSTRUMENTS = /* @__PURE__ */ Object.freeze(["bigpay_token", "credit_card_token", "credit_card_cryptogram"]);
|
|
176
|
+
var NUMBER = /^[0-9]{12,19}$/;
|
|
177
|
+
var CURRENCY = /^[A-Z]{3}$/;
|
|
178
|
+
var record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
179
|
+
var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
180
|
+
var refuse2 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
181
|
+
var CARD2 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
182
|
+
var CONTINUE = /* @__PURE__ */ Object.freeze({ verdict: "continue" });
|
|
183
|
+
function isBigcommercePaymentsUrl(url) {
|
|
184
|
+
return url === BIGCOMMERCE_PAYMENTS_URL;
|
|
185
|
+
}
|
|
186
|
+
function readBody2(body) {
|
|
187
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT2)
|
|
188
|
+
return null;
|
|
189
|
+
try {
|
|
190
|
+
const parsed = JSON.parse(body);
|
|
191
|
+
return record(parsed) && record(parsed.payment) ? parsed : null;
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function bigcommerceBodyVerdict(body, url) {
|
|
198
|
+
if (url !== void 0 && !isBigcommercePaymentsUrl(url))
|
|
199
|
+
return refuse2("bigcommerce_url_refused");
|
|
200
|
+
const parsed = readBody2(body);
|
|
201
|
+
if (!parsed)
|
|
202
|
+
return refuse2("bigcommerce_body_unsupported");
|
|
203
|
+
const { payment } = parsed;
|
|
204
|
+
if (!own(payment, "credit_card"))
|
|
205
|
+
return CONTINUE;
|
|
206
|
+
const card = payment.credit_card;
|
|
207
|
+
if (!record(card) || OTHER_INSTRUMENTS.some((key) => own(payment, key)) || Object.keys(card).some((key) => !CARD_KEYS.has(key)) || typeof card.number !== "string" || !NUMBER.test(card.number)) {
|
|
208
|
+
return refuse2("bigcommerce_body_unsupported");
|
|
209
|
+
}
|
|
210
|
+
if (payment.vault_payment_instrument === true)
|
|
211
|
+
return refuse2("bigcommerce_keep_on_file");
|
|
212
|
+
return CARD2;
|
|
213
|
+
}
|
|
214
|
+
function bigcommerceAmount(template) {
|
|
215
|
+
const parsed = record(template) ? readBody2(template.body) : null;
|
|
216
|
+
const order = parsed && record(parsed.order) ? parsed.order : null;
|
|
217
|
+
const total = order && record(order.totals) ? order.totals.grand_total : void 0;
|
|
218
|
+
if (!Number.isSafeInteger(total) || total <= 0 || typeof order.currency !== "string" || !CURRENCY.test(order.currency))
|
|
219
|
+
return null;
|
|
220
|
+
return { amountCents: total, currency: order.currency.toLowerCase() };
|
|
221
|
+
}
|
|
222
|
+
var bigcommerce_default = /* @__PURE__ */ registerProcessor({
|
|
223
|
+
psp: BIGCOMMERCE_PSP,
|
|
224
|
+
definitions: [
|
|
225
|
+
{
|
|
226
|
+
psp: "bigcommerce",
|
|
227
|
+
// The card request above. One host serves every BigCommerce store, test and live alike, so no sandbox host is
|
|
228
|
+
// marked. Ships dark: served only to a client that declares `bigcommerce_card_form`, for a company the backend's
|
|
229
|
+
// processor gate turns BigCommerce on for. `(?![\w/.%-])` ends the path for a consumer that tests `match`
|
|
230
|
+
// unanchored; the exact-URL rule holds the rest.
|
|
231
|
+
capability: "bigcommerce_card_form",
|
|
232
|
+
match: "payments\\.bigcommerce\\.com/api/public/v1/orders/payments(?![\\w/.%-])",
|
|
233
|
+
hosts: ["^payments\\.bigcommerce\\.com$"],
|
|
234
|
+
encoding: "json",
|
|
235
|
+
// The order's payment token and the JSON Accept. Origin, Referer and cookies never ride.
|
|
236
|
+
passthroughHeaders: ["^authorization$", "^accept$"],
|
|
237
|
+
jsonCardFields: [["payment", "credit_card", "number"]],
|
|
238
|
+
// A payment with no new card on the same URL continues untouched (bigcommerceBodyVerdict says which).
|
|
239
|
+
passWithoutCard: "payments\\.bigcommerce\\.com/api/public/v1/orders/payments"
|
|
240
|
+
}
|
|
241
|
+
],
|
|
242
|
+
// The request charges the store's gateway at once, so only the cardholder's device sends it, after a person approves.
|
|
243
|
+
refusedOperations: [BIGCOMMERCE_OPERATION],
|
|
244
|
+
// Not surveyed: reading a BigCommerce payment back takes the store's own API credentials, which Agentcard never holds.
|
|
245
|
+
settlementReadback: "not_surveyed",
|
|
246
|
+
exactUrl: isBigcommercePaymentsUrl,
|
|
247
|
+
bodyGate: (url, body) => bigcommerceBodyVerdict(body, url),
|
|
248
|
+
amount: bigcommerceAmount
|
|
249
|
+
});
|
|
74
250
|
// src/processors/bluesnap.js
|
|
75
251
|
var BLUESNAP_PSP = "bluesnap";
|
|
76
252
|
var BLUESNAP_OPERATION = "bluesnap.card_request";
|
|
@@ -78,16 +254,16 @@ var BLUESNAP_HOSTS = /* @__PURE__ */ Object.freeze({ 1: "ws1.bluesnap.com", 2: "
|
|
|
78
254
|
var BLUESNAP_SANDBOX_HOST = "sandpay.bluesnap.com";
|
|
79
255
|
var BLUESNAP_CARD_KEYS = /* @__PURE__ */ Object.freeze(["cvv", "ccNumber", "expDate"]);
|
|
80
256
|
var BLUESNAP_LEG_KEYS = /* @__PURE__ */ Object.freeze(["cvv", "expDate"]);
|
|
81
|
-
var
|
|
257
|
+
var BODY_LIMIT3 = 1024;
|
|
82
258
|
var TOKEN_URL = /^https:\/\/(ws1|ws2|sandpay)\.bluesnap\.com\/services\/2\/payment-fields-tokens\/([0-9a-f]{64}_[12]?)$/;
|
|
83
259
|
var CARD_NUMBER = /^[0-9]{12,19}$/;
|
|
84
260
|
var SECURITY_CODE = /^[0-9]{3,4}$/;
|
|
85
261
|
var EXPIRY = /^(?:0[1-9]|1[0-2])\/20[0-9]{2}$/;
|
|
86
262
|
var SAVED_CARD_KEYS = ["last4Digits", "lastFourDigits", "ccType"];
|
|
87
|
-
var
|
|
88
|
-
var
|
|
89
|
-
var
|
|
90
|
-
var
|
|
263
|
+
var record2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
264
|
+
var own2 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
265
|
+
var refuse3 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
266
|
+
var CARD3 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
91
267
|
var LEG = /* @__PURE__ */ Object.freeze({ verdict: "continue" });
|
|
92
268
|
function bluesnapTokenUrl(url) {
|
|
93
269
|
const match = typeof url === "string" ? TOKEN_URL.exec(url) : null;
|
|
@@ -99,62 +275,978 @@ function bluesnapTokenUrl(url) {
|
|
|
99
275
|
function isBluesnapTokenUrl(url) {
|
|
100
276
|
return bluesnapTokenUrl(url) !== null;
|
|
101
277
|
}
|
|
102
|
-
function
|
|
103
|
-
if (typeof body !== "string" || body === "" || body.length >
|
|
278
|
+
function readBody3(body) {
|
|
279
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT3)
|
|
104
280
|
return null;
|
|
105
281
|
try {
|
|
106
282
|
const value = JSON.parse(body);
|
|
107
|
-
return
|
|
283
|
+
return record2(value) && JSON.stringify(value) === body ? value : null;
|
|
108
284
|
}
|
|
109
285
|
catch {
|
|
110
286
|
return null;
|
|
111
287
|
}
|
|
112
288
|
}
|
|
113
289
|
function bluesnapBodyVerdict(body) {
|
|
114
|
-
const value =
|
|
290
|
+
const value = readBody3(body);
|
|
115
291
|
if (value === null)
|
|
116
|
-
return
|
|
292
|
+
return refuse3("bluesnap_body_unsupported");
|
|
117
293
|
const keys = Object.keys(value);
|
|
118
294
|
if (keys.some((key) => SAVED_CARD_KEYS.includes(key)))
|
|
119
|
-
return
|
|
295
|
+
return refuse3(own2(value, "ccNumber") ? "bluesnap_body_unsupported" : "bluesnap_saved_card");
|
|
120
296
|
if (keys.length === 0 || keys.some((key, i) => !BLUESNAP_CARD_KEYS.includes(key) || i > 0 && BLUESNAP_CARD_KEYS.indexOf(keys[i - 1]) >= BLUESNAP_CARD_KEYS.indexOf(key))) {
|
|
121
|
-
return
|
|
297
|
+
return refuse3("bluesnap_body_unsupported");
|
|
298
|
+
}
|
|
299
|
+
if (own2(value, "ccNumber") && !(typeof value.ccNumber === "string" && CARD_NUMBER.test(value.ccNumber)) || own2(value, "cvv") && !(typeof value.cvv === "string" && SECURITY_CODE.test(value.cvv)) || own2(value, "expDate") && !(typeof value.expDate === "string" && EXPIRY.test(value.expDate)))
|
|
300
|
+
return refuse3("bluesnap_body_unsupported");
|
|
301
|
+
return own2(value, "ccNumber") ? CARD3 : LEG;
|
|
302
|
+
}
|
|
303
|
+
var bluesnap_default = /* @__PURE__ */ registerProcessor({
|
|
304
|
+
psp: BLUESNAP_PSP,
|
|
305
|
+
definitions: [
|
|
306
|
+
{
|
|
307
|
+
psp: "bluesnap",
|
|
308
|
+
// The card fields' PUTs, as the header above reads them. The sandbox has its own server, so the device sends a
|
|
309
|
+
// test-mode request only documented test cards (hostEnvironmentPinned, device-replay.js S7). `(?![\w/.%-])`
|
|
310
|
+
// ends the token for a consumer that tests `match` unanchored; the exact-URL rule pins each server to its suffix.
|
|
311
|
+
// Ships dark: served only to a client that declares `bluesnap_hosted_payment_fields`, and the backend's gate turns
|
|
312
|
+
// it on for Agentcard's own company alone, in code.
|
|
313
|
+
capability: "bluesnap_hosted_payment_fields",
|
|
314
|
+
match: "(?:ws1|ws2|sandpay)\\.bluesnap\\.com/services/2/payment-fields-tokens/[0-9a-f]{64}_[12]?(?![\\w/.%-])",
|
|
315
|
+
hosts: ["^ws1\\.bluesnap\\.com$", "^ws2\\.bluesnap\\.com$", "^sandpay\\.bluesnap\\.com$"],
|
|
316
|
+
sandboxHosts: ["^sandpay\\.bluesnap\\.com$"],
|
|
317
|
+
hostEnvironmentPinned: true,
|
|
318
|
+
encoding: "json",
|
|
319
|
+
// The frames' own headers, each held to its shape by bluesnapRequestRefusal. Origin, Referer and cookies never
|
|
320
|
+
// ride (the frames send no cookie).
|
|
321
|
+
passthroughHeaders: ["^authorization$", "^bluesnap_version_header$", "^bluesnap_origin_version_header$", "^bluesnap_origin_header$"],
|
|
322
|
+
jsonCardFields: [["ccNumber"]],
|
|
323
|
+
// The expiry and code frames' PUTs: held by the checkout SDK and answered with the card request's answer.
|
|
324
|
+
splitCard: { absorb: [...BLUESNAP_LEG_KEYS], pass: [], siblingKeys: [] },
|
|
325
|
+
request: { method: "PUT", cardIn: "body", response: "json" }
|
|
326
|
+
}
|
|
327
|
+
],
|
|
328
|
+
// Only the cardholder's device sends the card, after a person approves; no reviewed list names bluesnap.
|
|
329
|
+
refusedOperations: [BLUESNAP_OPERATION],
|
|
330
|
+
// Not surveyed: the PUT moves no money, and the merchant's own charge is a server call Agentcard never sees.
|
|
331
|
+
settlementReadback: "not_surveyed",
|
|
332
|
+
exactUrl: isBluesnapTokenUrl,
|
|
333
|
+
bodyGate: (url, body) => url !== void 0 && !isBluesnapTokenUrl(url) ? { verdict: "refuse", code: "bluesnap_url_refused" } : bluesnapBodyVerdict(body)
|
|
334
|
+
});
|
|
335
|
+
// src/processors/ekashu.js
|
|
336
|
+
var EKASHU_HOSTS = Object.freeze(["live.ekashu.com", "test.ekashu.com"]);
|
|
337
|
+
var EKASHU_TEST_PANS = Object.freeze(["4100000000000100", "5100000000000107"]);
|
|
338
|
+
var EKASHU_SIGNED_FIELDS = Object.freeze([
|
|
339
|
+
"ekashu_3d_secure_verify",
|
|
340
|
+
"ekashu_amount",
|
|
341
|
+
"ekashu_amount_format",
|
|
342
|
+
"ekashu_auto_confirm",
|
|
343
|
+
"ekashu_callback_failure_url",
|
|
344
|
+
"ekashu_callback_include_post",
|
|
345
|
+
"ekashu_callback_success_url",
|
|
346
|
+
"ekashu_card_address_editable",
|
|
347
|
+
"ekashu_card_address_required",
|
|
348
|
+
"ekashu_card_address_verify",
|
|
349
|
+
"ekashu_card_email_address_mandatory",
|
|
350
|
+
"ekashu_card_phone_number_mandatory",
|
|
351
|
+
"ekashu_card_title_mandatory",
|
|
352
|
+
"ekashu_card_zip_code_verify",
|
|
353
|
+
"ekashu_currency",
|
|
354
|
+
"ekashu_delivery_address_editable",
|
|
355
|
+
"ekashu_delivery_address_required",
|
|
356
|
+
"ekashu_delivery_email_address_mandatory",
|
|
357
|
+
"ekashu_delivery_phone_number_mandatory",
|
|
358
|
+
"ekashu_delivery_title_mandatory",
|
|
359
|
+
"ekashu_description",
|
|
360
|
+
"ekashu_device",
|
|
361
|
+
"ekashu_duplicate_check",
|
|
362
|
+
"ekashu_duplicate_minutes",
|
|
363
|
+
"ekashu_failure_return_text",
|
|
364
|
+
"ekashu_failure_url",
|
|
365
|
+
"ekashu_hash_code_format",
|
|
366
|
+
"ekashu_hash_code_type",
|
|
367
|
+
"ekashu_hash_code_version",
|
|
368
|
+
"ekashu_include_post",
|
|
369
|
+
"ekashu_invoice_address_editable",
|
|
370
|
+
"ekashu_invoice_address_required",
|
|
371
|
+
"ekashu_invoice_email_address_mandatory",
|
|
372
|
+
"ekashu_invoice_phone_number_mandatory",
|
|
373
|
+
"ekashu_invoice_title_mandatory",
|
|
374
|
+
"ekashu_locale",
|
|
375
|
+
"ekashu_payment_methods",
|
|
376
|
+
"ekashu_reference",
|
|
377
|
+
"ekashu_request_type",
|
|
378
|
+
"ekashu_return_text",
|
|
379
|
+
"ekashu_seller_address",
|
|
380
|
+
"ekashu_seller_email_address",
|
|
381
|
+
"ekashu_seller_id",
|
|
382
|
+
"ekashu_seller_key",
|
|
383
|
+
"ekashu_seller_name",
|
|
384
|
+
"ekashu_shortcut_icon",
|
|
385
|
+
"ekashu_style_sheet",
|
|
386
|
+
"ekashu_success_url",
|
|
387
|
+
"ekashu_title",
|
|
388
|
+
"ekashu_verification_value_mask",
|
|
389
|
+
"ekashu_verification_value_verify",
|
|
390
|
+
"ekashu_viewport"
|
|
391
|
+
]);
|
|
392
|
+
var REQUIRED = Object.freeze([
|
|
393
|
+
"ekashu_seller_id",
|
|
394
|
+
"ekashu_seller_key",
|
|
395
|
+
"ekashu_amount",
|
|
396
|
+
"ekashu_currency",
|
|
397
|
+
"ekashu_reference",
|
|
398
|
+
"ekashu_hash_code",
|
|
399
|
+
"ekashu_hash_code_type",
|
|
400
|
+
"ekashu_hash_code_version",
|
|
401
|
+
"ekashu_success_url",
|
|
402
|
+
"ekashu_failure_url",
|
|
403
|
+
"ekashu_callback_success_url"
|
|
404
|
+
]);
|
|
405
|
+
var CARD_KEYS2 = Object.freeze([
|
|
406
|
+
"ekashu_card_number",
|
|
407
|
+
"ekashu_expires_end_month",
|
|
408
|
+
"ekashu_expires_end_year",
|
|
409
|
+
"ekashu_verification_value",
|
|
410
|
+
"ekashu_valid_from_month",
|
|
411
|
+
"ekashu_valid_from_year",
|
|
412
|
+
"ekashu_issue_number"
|
|
413
|
+
]);
|
|
414
|
+
var PAGE_KEYS = Object.freeze(["ekashu_stage", "ekashu_context", "ekashu_submission_id"]);
|
|
415
|
+
var STORED_KEYS = Object.freeze(["ekashu_card_hash", "ekashu_card_reference", "ekashu_cof_initiated_by", "ekashu_cof_reason", "ekashu_cof_id"]);
|
|
416
|
+
var REDIRECT_KEYS = Object.freeze(["ekashu_success_url", "ekashu_failure_url", "ekashu_return_url"]);
|
|
417
|
+
var CALLBACK_KEYS = Object.freeze(["ekashu_callback_success_url", "ekashu_callback_failure_url"]);
|
|
418
|
+
var MAX_ENTRY = 16 * 1024;
|
|
419
|
+
var MAX_PAGE = 256 * 1024;
|
|
420
|
+
var EKASHU_SELLERS = Object.freeze([
|
|
421
|
+
Object.freeze({ sellerId: "25060100", merchant: "Heathrow Drop-off", entryHost: "heathrowdropoff.apcoa.com", callbackHost: "incomingapi.apcoa.co.uk" })
|
|
422
|
+
]);
|
|
423
|
+
var CARD_FIELDS = Object.freeze({
|
|
424
|
+
number: "ekashu_card_number",
|
|
425
|
+
month: "ekashu_expires_end_month",
|
|
426
|
+
year: "ekashu_expires_end_year",
|
|
427
|
+
cvc: "ekashu_verification_value"
|
|
428
|
+
});
|
|
429
|
+
var NAME_FIELDS = Object.freeze({ first: "ekashu_card_first_name", last: "ekashu_card_last_name" });
|
|
430
|
+
var LEFT_EMPTY = Object.freeze(["ekashu_card_title", "ekashu_valid_from_month", "ekashu_valid_from_year", "ekashu_issue_number"]);
|
|
431
|
+
var VISIBLE = /* @__PURE__ */ new Set([...Object.values(CARD_FIELDS), ...Object.values(NAME_FIELDS), ...LEFT_EMPTY]);
|
|
432
|
+
// src/processors/redsys.js
|
|
433
|
+
var REDSYS_HOSTS = Object.freeze(["sis.redsys.es"]);
|
|
434
|
+
var REDSYS_ENTRY_PATHS = Object.freeze(["/sis/realizarPago", "/sis/realizarPago/utf-8"]);
|
|
435
|
+
var REDSYS_MERCHANTS = Object.freeze([]);
|
|
436
|
+
var MAX_ENTRY2 = 16 * 1024;
|
|
437
|
+
var MAX_PARAMETERS = 8 * 1024;
|
|
438
|
+
var FORM_KEY = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
|
|
439
|
+
var ENTRY_KEYS = Object.freeze(["Ds_SignatureVersion", "Ds_MerchantParameters", "Ds_Signature"]);
|
|
440
|
+
var REQUIRED2 = Object.freeze([
|
|
441
|
+
"DS_MERCHANT_AMOUNT",
|
|
442
|
+
"DS_MERCHANT_CURRENCY",
|
|
443
|
+
"DS_MERCHANT_MERCHANTCODE",
|
|
444
|
+
"DS_MERCHANT_ORDER",
|
|
445
|
+
"DS_MERCHANT_TERMINAL",
|
|
446
|
+
"DS_MERCHANT_TRANSACTIONTYPE",
|
|
447
|
+
"DS_MERCHANT_MERCHANTURL",
|
|
448
|
+
"DS_MERCHANT_URLOK",
|
|
449
|
+
"DS_MERCHANT_URLKO"
|
|
450
|
+
]);
|
|
451
|
+
var STORED = Object.freeze([
|
|
452
|
+
"DS_MERCHANT_IDENTIFIER",
|
|
453
|
+
"DS_MERCHANT_GROUP",
|
|
454
|
+
"DS_MERCHANT_COF_INI",
|
|
455
|
+
"DS_MERCHANT_COF_TYPE",
|
|
456
|
+
"DS_MERCHANT_COF_TXNID"
|
|
457
|
+
]);
|
|
458
|
+
var SPECIAL = Object.freeze([
|
|
459
|
+
"DS_MERCHANT_DIRECTPAYMENT",
|
|
460
|
+
"DS_MERCHANT_SUMTOTAL",
|
|
461
|
+
"DS_MERCHANT_DATEFRECUENCY",
|
|
462
|
+
"DS_MERCHANT_CHARGEEXPIRYDATE",
|
|
463
|
+
"DS_MERCHANT_IDOPER"
|
|
464
|
+
]);
|
|
465
|
+
var CARD_PARAMETERS = Object.freeze(["DS_MERCHANT_PAN", "DS_MERCHANT_EXPIRYDATE", "DS_MERCHANT_CVV2"]);
|
|
466
|
+
var CURRENCIES = Object.freeze({ 978: "eur", 840: "usd", 826: "gbp", 756: "chf" });
|
|
467
|
+
function decode(text3) {
|
|
468
|
+
return decodeURIComponent(text3.replace(/\+/g, " "));
|
|
469
|
+
}
|
|
470
|
+
function parseRedsysForm(body) {
|
|
471
|
+
if (typeof body !== "string" || body.length === 0 || body.length > MAX_ENTRY2 || /[^\x21-\x7e]/.test(body))
|
|
472
|
+
return null;
|
|
473
|
+
const pairs = [];
|
|
474
|
+
const seen = /* @__PURE__ */ new Set();
|
|
475
|
+
for (const chunk of body.split("&")) {
|
|
476
|
+
const eq = chunk.indexOf("=");
|
|
477
|
+
if (eq < 1)
|
|
478
|
+
return null;
|
|
479
|
+
let key;
|
|
480
|
+
let value;
|
|
481
|
+
try {
|
|
482
|
+
key = decode(chunk.slice(0, eq));
|
|
483
|
+
value = decode(chunk.slice(eq + 1));
|
|
484
|
+
}
|
|
485
|
+
catch {
|
|
486
|
+
return null;
|
|
487
|
+
}
|
|
488
|
+
if (!FORM_KEY.test(key) || value.length > MAX_PARAMETERS || /[\u0000-\u001f\u007f]/.test(value))
|
|
489
|
+
return null;
|
|
490
|
+
const folded = key.toLowerCase();
|
|
491
|
+
if (seen.has(folded))
|
|
492
|
+
return null;
|
|
493
|
+
seen.add(folded);
|
|
494
|
+
pairs.push({ key, value });
|
|
495
|
+
}
|
|
496
|
+
return pairs;
|
|
497
|
+
}
|
|
498
|
+
var MAX_PAGE2 = 256 * 1024;
|
|
499
|
+
var CARD_FIELDS2 = Object.freeze({
|
|
500
|
+
shown: "Sis_card-number",
|
|
501
|
+
expiry: "SIS_card-expiration",
|
|
502
|
+
cvc: "Sis_Tarjeta_CVV2",
|
|
503
|
+
holder: "cardholderName",
|
|
504
|
+
number: "Sis_Numero_Tarjeta",
|
|
505
|
+
month: "Sis_Caducidad_Tarjeta_Mes",
|
|
506
|
+
year: "Sis_Caducidad_Tarjeta_Anno"
|
|
507
|
+
});
|
|
508
|
+
var BROWSER_FIELDS = Object.freeze([
|
|
509
|
+
"browserJavaEnabled",
|
|
510
|
+
"browserJavascriptEnabled",
|
|
511
|
+
"browserLanguage",
|
|
512
|
+
"browserColorDepth",
|
|
513
|
+
"browserScreenHeight",
|
|
514
|
+
"browserScreenWidth",
|
|
515
|
+
"browserTZ",
|
|
516
|
+
"browserUserAgent"
|
|
517
|
+
]);
|
|
518
|
+
var AS_SERVED = Object.freeze(["cvvObligatorio", "threeDSCompInd", "fuc", "terminal", "merchantOrder", "bcancel"]);
|
|
519
|
+
var CARD_PAGE = /* @__PURE__ */ new Set([...Object.values(CARD_FIELDS2), ...BROWSER_FIELDS, ...AS_SERVED]);
|
|
520
|
+
var VISIBLE2 = /* @__PURE__ */ new Set([CARD_FIELDS2.shown, CARD_FIELDS2.expiry, CARD_FIELDS2.cvc, CARD_FIELDS2.holder]);
|
|
521
|
+
var METHOD_PAGE = /* @__PURE__ */ new Set(["resultadoMethod", ...BROWSER_FIELDS, "threeDSCompInd"]);
|
|
522
|
+
var REDSYS_REFUSALS = Object.freeze(["redsys_card_page", "redsys_3ds_challenge", "redsys_declined"]);
|
|
523
|
+
// src/processors/cardlink_vpos.js
|
|
524
|
+
var CARDLINK_VPOS_PSP = "cardlink_vpos";
|
|
525
|
+
var CARDLINK_VPOS_HOSTS = Object.freeze({
|
|
526
|
+
"vpos.eurocommerce.gr": "worldline",
|
|
527
|
+
"ecommerce.cardlink.gr": "cardlink",
|
|
528
|
+
"www.alphaecommerce.gr": "nexi"
|
|
529
|
+
});
|
|
530
|
+
var CARDLINK_VPOS_TEST_HOSTS = Object.freeze([
|
|
531
|
+
"eurocommerce-test.cardlink.gr",
|
|
532
|
+
"ecommerce-test.cardlink.gr",
|
|
533
|
+
"alphaecommerce-test.cardlink.gr"
|
|
534
|
+
]);
|
|
535
|
+
var CARDLINK_VPOS_ENTRY_PATH = "/vpos/shophandlermpi";
|
|
536
|
+
var CARDLINK_VPOS_MERCHANTS = Object.freeze([
|
|
537
|
+
Object.freeze({ merchant: "Holy Great Monastery of Vatopedi", mid: "0021713862", vposHost: "vpos.eurocommerce.gr", host: "www.vatopedi.gr" })
|
|
538
|
+
]);
|
|
539
|
+
var CARDLINK_VPOS_ENTRY_FIELDS = Object.freeze([
|
|
540
|
+
"version",
|
|
541
|
+
"mid",
|
|
542
|
+
"lang",
|
|
543
|
+
"deviceCategory",
|
|
544
|
+
"orderid",
|
|
545
|
+
"orderDesc",
|
|
546
|
+
"orderAmount",
|
|
547
|
+
"currency",
|
|
548
|
+
"payerEmail",
|
|
549
|
+
"payerPhone",
|
|
550
|
+
"billCountry",
|
|
551
|
+
"billState",
|
|
552
|
+
"billZip",
|
|
553
|
+
"billCity",
|
|
554
|
+
"billAddress",
|
|
555
|
+
"weight",
|
|
556
|
+
"dimensions",
|
|
557
|
+
"shipCountry",
|
|
558
|
+
"shipState",
|
|
559
|
+
"shipZip",
|
|
560
|
+
"shipCity",
|
|
561
|
+
"shipAddress",
|
|
562
|
+
"addFraudScore",
|
|
563
|
+
"maxPayRetries",
|
|
564
|
+
"reject3dsU",
|
|
565
|
+
"payMethod",
|
|
566
|
+
"trType",
|
|
567
|
+
"extInstallmentoffset",
|
|
568
|
+
"extInstallmentperiod",
|
|
569
|
+
"extRecurringfrequency",
|
|
570
|
+
"extRecurringenddate",
|
|
571
|
+
"blockScore",
|
|
572
|
+
"cssUrl",
|
|
573
|
+
"confirmUrl",
|
|
574
|
+
"cancelUrl",
|
|
575
|
+
"extTokenOptions",
|
|
576
|
+
"extToken",
|
|
577
|
+
"var1",
|
|
578
|
+
"var2",
|
|
579
|
+
"var3",
|
|
580
|
+
"var4",
|
|
581
|
+
"var5",
|
|
582
|
+
"var6",
|
|
583
|
+
"var7",
|
|
584
|
+
"var8",
|
|
585
|
+
"var9",
|
|
586
|
+
"digest"
|
|
587
|
+
]);
|
|
588
|
+
var KNOWN = new Set(CARDLINK_VPOS_ENTRY_FIELDS);
|
|
589
|
+
var REQUIRED3 = Object.freeze([
|
|
590
|
+
"version",
|
|
591
|
+
"mid",
|
|
592
|
+
"orderid",
|
|
593
|
+
"orderDesc",
|
|
594
|
+
"orderAmount",
|
|
595
|
+
"currency",
|
|
596
|
+
"payerEmail",
|
|
597
|
+
"confirmUrl",
|
|
598
|
+
"cancelUrl",
|
|
599
|
+
"digest"
|
|
600
|
+
]);
|
|
601
|
+
var STORED2 = Object.freeze(["extTokenOptions", "extToken"]);
|
|
602
|
+
var SPECIAL2 = Object.freeze(["extInstallmentoffset", "extInstallmentperiod", "extRecurringfrequency", "extRecurringenddate"]);
|
|
603
|
+
var CURRENCIES2 = Object.freeze({ EUR: "eur" });
|
|
604
|
+
var MAX_URL = 512;
|
|
605
|
+
var MAX_ENTRY3 = 8 * 1024;
|
|
606
|
+
var MAX_VALUE = 256;
|
|
607
|
+
var own3 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
608
|
+
var field = (name, reason) => ({ ok: false, code: "hosted_form_field_refused", field: name, reason });
|
|
609
|
+
function cardlinkVposEntryHost(raw) {
|
|
610
|
+
if (typeof raw !== "string" || raw.length > MAX_URL || raw.includes("?") || raw.includes("#"))
|
|
611
|
+
return null;
|
|
612
|
+
let url;
|
|
613
|
+
try {
|
|
614
|
+
url = new URL(raw);
|
|
615
|
+
}
|
|
616
|
+
catch {
|
|
617
|
+
return null;
|
|
122
618
|
}
|
|
123
|
-
if (
|
|
124
|
-
return
|
|
125
|
-
return
|
|
619
|
+
if (url.href !== raw || url.protocol !== "https:" || url.port || url.username || url.password || !own3(CARDLINK_VPOS_HOSTS, url.hostname) || url.pathname !== CARDLINK_VPOS_ENTRY_PATH)
|
|
620
|
+
return null;
|
|
621
|
+
return url.hostname;
|
|
622
|
+
}
|
|
623
|
+
function isCardlinkVposEntryUrl(raw) {
|
|
624
|
+
return cardlinkVposEntryHost(raw) !== null;
|
|
625
|
+
}
|
|
626
|
+
function parseCardlinkVposForm(body) {
|
|
627
|
+
if (typeof body !== "string" || body.length === 0 || body.length > MAX_ENTRY3 || /[^\x21-\x7e]/.test(body))
|
|
628
|
+
return null;
|
|
629
|
+
const pairs = [];
|
|
630
|
+
const seen = /* @__PURE__ */ new Set();
|
|
631
|
+
for (const chunk of body.split("&")) {
|
|
632
|
+
const eq = chunk.indexOf("=");
|
|
633
|
+
if (eq < 1)
|
|
634
|
+
return null;
|
|
635
|
+
let key;
|
|
636
|
+
let value;
|
|
637
|
+
try {
|
|
638
|
+
key = decodeURIComponent(chunk.slice(0, eq).replace(/\+/g, " "));
|
|
639
|
+
value = decodeURIComponent(chunk.slice(eq + 1).replace(/\+/g, " "));
|
|
640
|
+
}
|
|
641
|
+
catch {
|
|
642
|
+
return null;
|
|
643
|
+
}
|
|
644
|
+
if (!/^[A-Za-z_.][A-Za-z0-9_.-]{0,63}$/.test(key) || value.length > MAX_VALUE || /[\u0000-\u001f\u007f]/.test(value))
|
|
645
|
+
return null;
|
|
646
|
+
if (seen.has(key))
|
|
647
|
+
return null;
|
|
648
|
+
seen.add(key);
|
|
649
|
+
pairs.push({ key, value });
|
|
650
|
+
}
|
|
651
|
+
return pairs;
|
|
652
|
+
}
|
|
653
|
+
function cardlinkVposMerchant(mid, vposHost, merchants = CARDLINK_VPOS_MERCHANTS) {
|
|
654
|
+
if (typeof mid !== "string" || typeof vposHost !== "string" || !Array.isArray(merchants))
|
|
655
|
+
return null;
|
|
656
|
+
const found = merchants.filter((row) => !!row && typeof row.merchant === "string" && row.merchant.trim() !== "" && row.mid === mid && row.vposHost === vposHost && typeof row.host === "string" && row.host !== "");
|
|
657
|
+
return found.length === 1 ? found[0] : null;
|
|
658
|
+
}
|
|
659
|
+
function entryAmount(values) {
|
|
660
|
+
const amount = values.get("orderAmount");
|
|
661
|
+
const code = values.get("currency");
|
|
662
|
+
const currency = typeof code === "string" && own3(CURRENCIES2, code) ? CURRENCIES2[code] : null;
|
|
663
|
+
if (!currency || typeof amount !== "string" || !/^(?:0|[1-9]\d{0,11})(?:\.\d{1,2})?$/.test(amount))
|
|
664
|
+
return null;
|
|
665
|
+
const [whole, fraction = ""] = amount.split(".");
|
|
666
|
+
const cents = Number(whole) * 100 + Number(fraction.padEnd(2, "0"));
|
|
667
|
+
return Number.isSafeInteger(cents) && cents > 0 ? { amountCents: cents, currency } : null;
|
|
668
|
+
}
|
|
669
|
+
function httpsUrl(value) {
|
|
670
|
+
let url;
|
|
671
|
+
try {
|
|
672
|
+
url = new URL(value);
|
|
673
|
+
}
|
|
674
|
+
catch {
|
|
675
|
+
return null;
|
|
676
|
+
}
|
|
677
|
+
if (url.protocol !== "https:" || url.username || url.password || url.port || url.hash)
|
|
678
|
+
return null;
|
|
679
|
+
return url;
|
|
680
|
+
}
|
|
681
|
+
function checkCardlinkVposEntry(body, { url = null, merchants = CARDLINK_VPOS_MERCHANTS } = {}) {
|
|
682
|
+
const vposHost = cardlinkVposEntryHost(url);
|
|
683
|
+
if (!vposHost)
|
|
684
|
+
return field("(url)", "malformed_field");
|
|
685
|
+
const pairs = parseCardlinkVposForm(body);
|
|
686
|
+
if (!pairs)
|
|
687
|
+
return field("(body)", "malformed");
|
|
688
|
+
const values = new Map(pairs.map(({ key, value }) => [key, value]));
|
|
689
|
+
for (const { key } of pairs) {
|
|
690
|
+
if (KNOWN.has(key))
|
|
691
|
+
continue;
|
|
692
|
+
return field(key, /^(?:card[._]|cvv|cmd$|trid$|st$|paystep$|paymentmethod$)/i.test(key) ? "card_in_entry" : "not_an_entry");
|
|
693
|
+
}
|
|
694
|
+
const missing = REQUIRED3.filter((name) => !values.get(name));
|
|
695
|
+
if (missing.length)
|
|
696
|
+
return { ok: false, code: "hosted_form_template_incomplete", missing };
|
|
697
|
+
if (values.get("version") !== "2")
|
|
698
|
+
return field("version", "malformed");
|
|
699
|
+
if (!/^[A-Za-z0-9+/]{43}=$/.test(values.get("digest")))
|
|
700
|
+
return field("digest", "unsigned");
|
|
701
|
+
for (const name of STORED2)
|
|
702
|
+
if (values.has(name))
|
|
703
|
+
return field(name, "stored_credential");
|
|
704
|
+
for (const name of SPECIAL2)
|
|
705
|
+
if (values.get(name))
|
|
706
|
+
return field(name, "special_flow");
|
|
707
|
+
for (let i = 1; i <= 9; i += 1)
|
|
708
|
+
if (/moto\s*=\s*true/i.test(values.get(`var${i}`) ?? ""))
|
|
709
|
+
return field(`var${i}`, "moto");
|
|
710
|
+
if (values.has("trType") && values.get("trType") !== "1")
|
|
711
|
+
return field("trType", "not_a_sale");
|
|
712
|
+
const method = values.get("payMethod");
|
|
713
|
+
if (method)
|
|
714
|
+
return field("payMethod", /^iris$/i.test(method) ? "not_a_card_payment" : "special_flow");
|
|
715
|
+
const amount = entryAmount(values);
|
|
716
|
+
if (!amount)
|
|
717
|
+
return field(own3(CURRENCIES2, values.get("currency")) ? "orderAmount" : "currency", "malformed");
|
|
718
|
+
if (!/^\d{1,30}$/.test(values.get("mid")))
|
|
719
|
+
return field("mid", "malformed");
|
|
720
|
+
if (!/^[A-Za-z0-9]{1,50}$/.test(values.get("orderid")))
|
|
721
|
+
return field("orderid", "malformed");
|
|
722
|
+
const seller = cardlinkVposMerchant(values.get("mid"), vposHost, merchants);
|
|
723
|
+
if (!seller)
|
|
724
|
+
return field("mid", "seller_unreviewed");
|
|
725
|
+
for (const name of ["confirmUrl", "cancelUrl"]) {
|
|
726
|
+
const target = httpsUrl(values.get(name));
|
|
727
|
+
if (!target || target.hostname !== seller.host)
|
|
728
|
+
return field(name, "callback_host");
|
|
729
|
+
}
|
|
730
|
+
return {
|
|
731
|
+
ok: true,
|
|
732
|
+
pairs,
|
|
733
|
+
gated: false,
|
|
734
|
+
dedupe: [vposHost, values.get("mid"), values.get("orderid"), values.get("orderAmount"), values.get("currency")],
|
|
735
|
+
seller
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
function cardlinkVposEntryAmount(body) {
|
|
739
|
+
const pairs = parseCardlinkVposForm(body);
|
|
740
|
+
return pairs ? entryAmount(new Map(pairs.map(({ key, value }) => [key, value]))) : null;
|
|
741
|
+
}
|
|
742
|
+
var CARDLINK_VPOS_TDS2_FIELDS = Object.freeze([
|
|
743
|
+
"TDS2_Navigator_language",
|
|
744
|
+
"TDS2_Navigator_jsEnabled",
|
|
745
|
+
"TDS2_Navigator_javaEnabled",
|
|
746
|
+
"TDS2_Screen_colorDepth",
|
|
747
|
+
"TDS2_Screen_height",
|
|
748
|
+
"TDS2_Screen_width",
|
|
749
|
+
"TDS2_screen_pixelDepth",
|
|
750
|
+
"TDS2_TimezoneOffset"
|
|
751
|
+
]);
|
|
752
|
+
var PAGE_FIELDS = Object.freeze(["trid", "st", "payStep", "cmd", "startbonus", "bonusdata"]);
|
|
753
|
+
var WALLET_FIELDS = Object.freeze(["walletId", "applePayResponse"]);
|
|
754
|
+
var CARD4 = Object.freeze({ number: "card.pan", holder: "card.holderName", month: "card.expiryMonth", year: "card.expiryYear", cvc: "card.cvv" });
|
|
755
|
+
var TEXT_CONTROLS = /* @__PURE__ */ new Set([CARD4.number, CARD4.holder, CARD4.cvc]);
|
|
756
|
+
var SELECT_CONTROLS = /* @__PURE__ */ new Set([CARD4.month, CARD4.year]);
|
|
757
|
+
var MAX_PAGE3 = 256 * 1024;
|
|
758
|
+
var COOKIE_DOMAINS = Object.freeze({
|
|
759
|
+
"vpos.eurocommerce.gr": "eurocommerce.gr",
|
|
760
|
+
"ecommerce.cardlink.gr": "cardlink.gr",
|
|
761
|
+
"www.alphaecommerce.gr": "alphaecommerce.gr"
|
|
762
|
+
});
|
|
763
|
+
var POST_REQUIRED = Object.freeze(["trid", "st", "cmd", CARD4.number, CARD4.holder, CARD4.month, CARD4.year, CARD4.cvc, "makepayment"]);
|
|
764
|
+
var POST_EMPTY = Object.freeze(["payStep", "startbonus", "bonusdata", ...WALLET_FIELDS]);
|
|
765
|
+
var POST_ALLOWED = /* @__PURE__ */ new Set([...POST_REQUIRED, ...POST_EMPTY, "paymentMethod", ...CARDLINK_VPOS_TDS2_FIELDS]);
|
|
766
|
+
var CARDLINK_VPOS_REFUSALS = Object.freeze([
|
|
767
|
+
"cardlink_vpos_card_refused",
|
|
768
|
+
"cardlink_vpos_card_page",
|
|
769
|
+
"cardlink_vpos_3ds_challenge",
|
|
770
|
+
"cardlink_vpos_declined"
|
|
771
|
+
]);
|
|
772
|
+
var REFUSAL_FOR = Object.freeze({
|
|
773
|
+
card_refused: "cardlink_vpos_card_refused",
|
|
774
|
+
card_page: "cardlink_vpos_card_page",
|
|
775
|
+
challenge: "cardlink_vpos_3ds_challenge",
|
|
776
|
+
declined: "cardlink_vpos_declined"
|
|
777
|
+
});
|
|
778
|
+
var CARDLINK_VPOS_CAPABILITY = "cardlink_vpos_hosted_payment_page";
|
|
779
|
+
var CARDLINK_VPOS_OPERATION = "cardlink_vpos.hosted_sale";
|
|
780
|
+
var cardlink_vpos_default = /* @__PURE__ */ registerProcessor({
|
|
781
|
+
psp: CARDLINK_VPOS_PSP,
|
|
782
|
+
definitions: [
|
|
783
|
+
{
|
|
784
|
+
psp: "cardlink_vpos",
|
|
785
|
+
// The merchant's signed entry, as the header above reads it: a Document navigation that carries no card. The
|
|
786
|
+
// cardholder's device repeats it over the end-to-end TLS relay, fills the card into the page the VPOS returns
|
|
787
|
+
// and posts it in that same session, and the runtime resolves the paused navigation with the hosted_form notice.
|
|
788
|
+
// Only the entry path on the three live hosts is matched (isCardlinkVposEntryUrl). The card page posts to the same
|
|
789
|
+
// path, so the SDK fails every other post to these hosts in the agent's browser, and no placeholder card reaches
|
|
790
|
+
// the VPOS. The test hosts are listed so a live host classifies as live and the create refuses a test row there;
|
|
791
|
+
// no entry on them is paused. Ships dark: served only to a client that declares
|
|
792
|
+
// `cardlink_vpos_hosted_payment_page`, and gated off for every company the operator has not turned it on for.
|
|
793
|
+
capability: CARDLINK_VPOS_CAPABILITY,
|
|
794
|
+
match: "(?:vpos\\.eurocommerce\\.gr|ecommerce\\.cardlink\\.gr|www\\.alphaecommerce\\.gr)/vpos/shophandlermpi(?![\\w/.%;=!-])",
|
|
795
|
+
hosts: [
|
|
796
|
+
"^vpos\\.eurocommerce\\.gr$",
|
|
797
|
+
"^ecommerce\\.cardlink\\.gr$",
|
|
798
|
+
"^www\\.alphaecommerce\\.gr$",
|
|
799
|
+
"^eurocommerce-test\\.cardlink\\.gr$",
|
|
800
|
+
"^ecommerce-test\\.cardlink\\.gr$",
|
|
801
|
+
"^alphaecommerce-test\\.cardlink\\.gr$"
|
|
802
|
+
],
|
|
803
|
+
sandboxHosts: ["^eurocommerce-test\\.cardlink\\.gr$", "^ecommerce-test\\.cardlink\\.gr$", "^alphaecommerce-test\\.cardlink\\.gr$"],
|
|
804
|
+
hostEnvironmentPinned: true,
|
|
805
|
+
encoding: "form",
|
|
806
|
+
// A form navigation: no captured header is ever replayed.
|
|
807
|
+
passthroughHeaders: [],
|
|
808
|
+
mode: "hosted_form",
|
|
809
|
+
hostedForm: {
|
|
810
|
+
// The card goes into the VPOS's own page on the device, never into the entry, which must carry none
|
|
811
|
+
// (checkCardlinkVposEntry). The entry's rules come with this registration (hostedEntry below), so no policy is
|
|
812
|
+
// named here.
|
|
813
|
+
cardIn: "processor_page",
|
|
814
|
+
required: [...REQUIRED3],
|
|
815
|
+
// The card page's own fields, which the device fills on that page.
|
|
816
|
+
card: { number: "card.pan", month: "card.expiryMonth", year: "card.expiryYear", cvc: "card.cvv" },
|
|
817
|
+
// The host, the mid, the order id and the amount name one payment; the entry's rules read the host from its URL.
|
|
818
|
+
dedupe: ["(vposHost)", "mid", "orderid", "orderAmount", "currency"]
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
],
|
|
822
|
+
// Only the cardholder's device repeats an entry, after a person approves; no reviewed list names cardlink_vpos.
|
|
823
|
+
refusedOperations: [CARDLINK_VPOS_OPERATION],
|
|
824
|
+
// Not surveyed: the VPOS tells the merchant the result through the browser's return and a copy to its server, both
|
|
825
|
+
// signed under the merchant's secret, which Agentcard never holds.
|
|
826
|
+
settlementReadback: "not_surveyed",
|
|
827
|
+
exactUrl: isCardlinkVposEntryUrl,
|
|
828
|
+
hostedEntry: (body, { url }) => checkCardlinkVposEntry(body, { url }),
|
|
829
|
+
amount: (template) => template && isCardlinkVposEntryUrl(template.url) ? cardlinkVposEntryAmount(template.body) : null,
|
|
830
|
+
limitations: [
|
|
831
|
+
"The paused request is the merchant's signed entry form, which carries no card; the cardholder's device sends it to Cardlink's VPOS over the end-to-end TLS relay and fills the card into the page the VPOS returns.",
|
|
832
|
+
"Agentcard takes only a reviewed merchant's entry: its mid and the host it posts to name the merchant the cardholder is shown, and its confirm and cancel URLs must sit on that merchant's own host.",
|
|
833
|
+
"Agentcard takes one plain payment only and refuses an entry that asks for a stored card, installments, a recurring schedule, a pre-authorization, MOTO or a preselected payment method.",
|
|
834
|
+
"The VPOS runs EMV 3-D Secure on the card. A frictionless answer pays; a challenge ends the payment on the device with nothing charged.",
|
|
835
|
+
"The browser receives a submission notice, not the processor result."
|
|
836
|
+
]
|
|
837
|
+
});
|
|
838
|
+
// src/processors/eghl.js
|
|
839
|
+
var EGHL_PSP = "eghl";
|
|
840
|
+
var EGHL_OPERATION = "eghl.hosted_sale";
|
|
841
|
+
var EGHL_HOST = "securepay.e-ghl.com";
|
|
842
|
+
var EGHL_SANDBOX_HOST = "test2pay.ghl.com";
|
|
843
|
+
var LIVE_PATH = "/ipg/payment.aspx";
|
|
844
|
+
var SANDBOX_PATH = "/ipgsg/payment.aspx";
|
|
845
|
+
var MAX_URL2 = 8192;
|
|
846
|
+
var field2 = (name, reason) => ({ ok: false, code: "hosted_form_field_refused", field: name, reason });
|
|
847
|
+
function eghlEntry(raw) {
|
|
848
|
+
if (typeof raw !== "string" || raw.length > MAX_URL2 || raw.includes("#"))
|
|
849
|
+
return null;
|
|
850
|
+
let url;
|
|
851
|
+
try {
|
|
852
|
+
url = new URL(raw);
|
|
853
|
+
}
|
|
854
|
+
catch {
|
|
855
|
+
return null;
|
|
856
|
+
}
|
|
857
|
+
if (url.href !== raw || url.protocol !== "https:" || url.port || url.username || url.password || url.search.length < 2)
|
|
858
|
+
return null;
|
|
859
|
+
const path = url.pathname.toLowerCase();
|
|
860
|
+
const query = url.search.slice(1);
|
|
861
|
+
if (url.hostname === EGHL_HOST && path === LIVE_PATH)
|
|
862
|
+
return Object.freeze({ test: false, query });
|
|
863
|
+
if (url.hostname === EGHL_SANDBOX_HOST && path === SANDBOX_PATH)
|
|
864
|
+
return Object.freeze({ test: true, query });
|
|
865
|
+
return null;
|
|
866
|
+
}
|
|
867
|
+
function isEghlEntryUrl(raw) {
|
|
868
|
+
return eghlEntry(raw) !== null;
|
|
869
|
+
}
|
|
870
|
+
var EGHL_MERCHANTS = Object.freeze([
|
|
871
|
+
Object.freeze({ merchant: "BookXcess", serviceId: "BXS", payee: "BookXcess Sdn Bhd", returnHosts: Object.freeze(["shopify.ghl.com:11443"]), test: false })
|
|
872
|
+
]);
|
|
873
|
+
var SERVICE_ID = /^[A-Za-z0-9]{3}$/;
|
|
874
|
+
var HOST = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)+(?::[1-9]\d{0,4})?$/;
|
|
875
|
+
function eghlMerchant(serviceId, { test = false, merchants = EGHL_MERCHANTS } = {}) {
|
|
876
|
+
if (typeof serviceId !== "string" || !SERVICE_ID.test(serviceId) || !Array.isArray(merchants))
|
|
877
|
+
return null;
|
|
878
|
+
const found = merchants.filter((row) => !!row && typeof row.merchant === "string" && row.merchant.trim() !== "" && typeof row.payee === "string" && row.payee.trim() !== "" && row.serviceId === serviceId && row.test === test && Array.isArray(row.returnHosts) && row.returnHosts.length > 0 && row.returnHosts.every((host) => typeof host === "string" && HOST.test(host)));
|
|
879
|
+
return found.length === 1 ? found[0] : null;
|
|
880
|
+
}
|
|
881
|
+
var REQUIRED4 = Object.freeze([
|
|
882
|
+
"TransactionType",
|
|
883
|
+
"PymtMethod",
|
|
884
|
+
"ServiceID",
|
|
885
|
+
"PaymentID",
|
|
886
|
+
"OrderNumber",
|
|
887
|
+
"MerchantReturnURL",
|
|
888
|
+
"MerchantCallBackURL",
|
|
889
|
+
"Amount",
|
|
890
|
+
"CurrencyCode",
|
|
891
|
+
"HashValue"
|
|
892
|
+
]);
|
|
893
|
+
var CARD_KEYS3 = /* @__PURE__ */ new Set(["cardno", "cardexp", "cardcvv2", "cardholder", "param2", "param4", "cvv2", "epmonth2", "epyear2", "custocp"]);
|
|
894
|
+
var SECRET_KEYS = /* @__PURE__ */ new Set(["password"]);
|
|
895
|
+
var STORED_KEYS2 = /* @__PURE__ */ new Set([
|
|
896
|
+
"tokentype",
|
|
897
|
+
"token",
|
|
898
|
+
"cardid",
|
|
899
|
+
"precheckoutid",
|
|
900
|
+
"reqtoken",
|
|
901
|
+
"pairingtoken",
|
|
902
|
+
"reqverifier",
|
|
903
|
+
"pairingverifier",
|
|
904
|
+
"checkoutresourceurl"
|
|
905
|
+
]);
|
|
906
|
+
var SPECIAL_KEYS = /* @__PURE__ */ new Set(["eppmonth", "promocode"]);
|
|
907
|
+
var RESULT_KEYS = Object.freeze(["MerchantReturnURL", "MerchantCallBackURL", "MerchantApprovalURL", "MerchantUnApprovalURL"]);
|
|
908
|
+
var CURRENCIES3 = /* @__PURE__ */ new Set(["MYR", "SGD", "USD", "PHP", "THB"]);
|
|
909
|
+
var AMOUNT = /^(0|[1-9]\d{0,8})\.(\d{2})$/;
|
|
910
|
+
function httpsUrl2(value) {
|
|
911
|
+
let url;
|
|
912
|
+
try {
|
|
913
|
+
url = new URL(value);
|
|
914
|
+
}
|
|
915
|
+
catch {
|
|
916
|
+
return null;
|
|
917
|
+
}
|
|
918
|
+
if (url.protocol !== "https:" || url.username || url.password || url.hash)
|
|
919
|
+
return null;
|
|
920
|
+
return url;
|
|
921
|
+
}
|
|
922
|
+
function entryFields(text3) {
|
|
923
|
+
const pairs = parseRedsysForm(text3);
|
|
924
|
+
if (!pairs)
|
|
925
|
+
return null;
|
|
926
|
+
return { pairs, values: new Map(pairs.map(({ key, value }) => [key.toLowerCase(), value])) };
|
|
927
|
+
}
|
|
928
|
+
function entryAmount2(values) {
|
|
929
|
+
const currency = values.get("currencycode");
|
|
930
|
+
const amount = AMOUNT.exec(values.get("amount") ?? "");
|
|
931
|
+
if (!amount || typeof currency !== "string" || !CURRENCIES3.has(currency))
|
|
932
|
+
return null;
|
|
933
|
+
const cents = Number(amount[1]) * 100 + Number(amount[2]);
|
|
934
|
+
return cents > 0 && Number.isSafeInteger(cents) ? { amountCents: cents, currency: currency.toLowerCase() } : null;
|
|
935
|
+
}
|
|
936
|
+
function checkEghlEntry(body, { url = null, merchants = EGHL_MERCHANTS } = {}) {
|
|
937
|
+
if (body !== void 0 && body !== null && body !== "")
|
|
938
|
+
return field2("(body)", "not_an_entry");
|
|
939
|
+
const entry = eghlEntry(url);
|
|
940
|
+
if (!entry)
|
|
941
|
+
return field2("(url)", "malformed_field");
|
|
942
|
+
const fields = entryFields(entry.query);
|
|
943
|
+
if (!fields)
|
|
944
|
+
return field2("(query)", "malformed");
|
|
945
|
+
const { pairs, values } = fields;
|
|
946
|
+
for (const { key, value } of pairs) {
|
|
947
|
+
if (value === "")
|
|
948
|
+
continue;
|
|
949
|
+
const folded = key.toLowerCase();
|
|
950
|
+
if (CARD_KEYS3.has(folded))
|
|
951
|
+
return field2(key, "card_in_entry");
|
|
952
|
+
if (SECRET_KEYS.has(folded))
|
|
953
|
+
return field2(key, "not_an_entry");
|
|
954
|
+
if (STORED_KEYS2.has(folded))
|
|
955
|
+
return field2(key, "stored_credential");
|
|
956
|
+
if (SPECIAL_KEYS.has(folded))
|
|
957
|
+
return field2(key, "special_flow");
|
|
958
|
+
}
|
|
959
|
+
const missing = REQUIRED4.filter((name) => !values.get(name.toLowerCase()));
|
|
960
|
+
if (missing.length)
|
|
961
|
+
return { ok: false, code: "hosted_form_template_incomplete", missing };
|
|
962
|
+
if (values.get("transactiontype") !== "SALE")
|
|
963
|
+
return field2("TransactionType", "not_a_sale");
|
|
964
|
+
if (!["ANY", "CC"].includes(values.get("pymtmethod")))
|
|
965
|
+
return field2("PymtMethod", "special_flow");
|
|
966
|
+
if (!/^[0-9A-Fa-f]{64}$/.test(values.get("hashvalue")))
|
|
967
|
+
return field2("HashValue", "unsigned");
|
|
968
|
+
if (!entryAmount2(values))
|
|
969
|
+
return field2(CURRENCIES3.has(values.get("currencycode")) ? "Amount" : "CurrencyCode", "malformed");
|
|
970
|
+
if (!SERVICE_ID.test(values.get("serviceid")))
|
|
971
|
+
return field2("ServiceID", "malformed");
|
|
972
|
+
if (!/^[A-Za-z0-9._-]{1,20}$/.test(values.get("paymentid")))
|
|
973
|
+
return field2("PaymentID", "malformed");
|
|
974
|
+
if (values.get("ordernumber").length > 20)
|
|
975
|
+
return field2("OrderNumber", "malformed");
|
|
976
|
+
const pageTimeout = values.get("pagetimeout");
|
|
977
|
+
if (pageTimeout !== void 0 && !/^[1-9]\d{1,4}$/.test(pageTimeout))
|
|
978
|
+
return field2("PageTimeout", "malformed");
|
|
979
|
+
const seller = eghlMerchant(values.get("serviceid"), { test: entry.test, merchants });
|
|
980
|
+
if (!seller)
|
|
981
|
+
return field2("ServiceID", "seller_unreviewed");
|
|
982
|
+
for (const name of RESULT_KEYS) {
|
|
983
|
+
const value = values.get(name.toLowerCase());
|
|
984
|
+
if (!value)
|
|
985
|
+
continue;
|
|
986
|
+
const target = httpsUrl2(value);
|
|
987
|
+
if (!target || !seller.returnHosts.includes(target.host) || [EGHL_HOST, EGHL_SANDBOX_HOST].includes(target.hostname))
|
|
988
|
+
return field2(name, "callback_host");
|
|
989
|
+
}
|
|
990
|
+
return { ok: true, pairs, gated: false, dedupe: [values.get("serviceid"), values.get("paymentid")], sandbox: entry.test, seller };
|
|
991
|
+
}
|
|
992
|
+
function eghlEntryAmount(body, url) {
|
|
993
|
+
if (body !== void 0 && body !== null && body !== "")
|
|
994
|
+
return null;
|
|
995
|
+
const entry = eghlEntry(url);
|
|
996
|
+
const fields = entry ? entryFields(entry.query) : null;
|
|
997
|
+
return fields ? entryAmount2(fields.values) : null;
|
|
998
|
+
}
|
|
999
|
+
var MAX_PAGE4 = 1024 * 1024;
|
|
1000
|
+
var NEVER_SENT = new Set(["expressCheckoutType", "c2pRememberMeBrowser", "CustOCP", "CustRecurr", "CustAddress"].map((name) => name.toLowerCase()));
|
|
1001
|
+
var PAGE_REQUIRED = Object.freeze([
|
|
1002
|
+
"TransactionType",
|
|
1003
|
+
"ServiceID",
|
|
1004
|
+
"MerchantName",
|
|
1005
|
+
"PaymentID",
|
|
1006
|
+
"Amount",
|
|
1007
|
+
"BaseTxnAmount",
|
|
1008
|
+
"CurrencyCode",
|
|
1009
|
+
"BaseCurrencyCode",
|
|
1010
|
+
"HashValue",
|
|
1011
|
+
"Param2",
|
|
1012
|
+
"Param4",
|
|
1013
|
+
"CardExp",
|
|
1014
|
+
"CVV2",
|
|
1015
|
+
"PymtMethod"
|
|
1016
|
+
]);
|
|
1017
|
+
var EGHL_REFUSALS = Object.freeze(["eghl_failed", "eghl_cancelled"]);
|
|
1018
|
+
var MAX_ANSWER = 256 * 1024;
|
|
1019
|
+
var RESULT_FIELDS = Object.freeze(["TxnStatus", "ServiceID", "PaymentID", "Amount", "CurrencyCode"]);
|
|
1020
|
+
var eghl_default = /* @__PURE__ */ registerProcessor({
|
|
1021
|
+
psp: EGHL_PSP,
|
|
1022
|
+
definitions: [
|
|
1023
|
+
{
|
|
1024
|
+
psp: "eghl",
|
|
1025
|
+
// The merchant's entry to eGHL's payment page, as the header above reads it: a GET Document navigation whose
|
|
1026
|
+
// query names the payment and which carries no card. The cardholder's device repeats it over the end-to-end TLS
|
|
1027
|
+
// relay and pays on the page eGHL returns to it, and the runtime resolves the paused navigation with the
|
|
1028
|
+
// hosted_form notice. Only the entry is matched (isEghlEntryUrl): the card page's own card post goes to the same
|
|
1029
|
+
// path as a POST. The path is matched in any letter case, as IIS reads it; `(?![\\w/.%-])` ends it for a consumer
|
|
1030
|
+
// that tests `match` unanchored. Ships dark: served only to a client that declares `eghl_hosted_payment_page`, and
|
|
1031
|
+
// gated off for every company the operator has not allowlisted.
|
|
1032
|
+
capability: "eghl_hosted_payment_page",
|
|
1033
|
+
match: "securepay\\.e-ghl\\.com/[Ii][Pp][Gg]/[Pp][Aa][Yy][Mm][Ee][Nn][Tt]\\.[Aa][Ss][Pp][Xx](?![\\w/.%-])|test2pay\\.ghl\\.com/[Ii][Pp][Gg][Ss][Gg]/[Pp][Aa][Yy][Mm][Ee][Nn][Tt]\\.[Aa][Ss][Pp][Xx](?![\\w/.%-])",
|
|
1034
|
+
hosts: ["^securepay\\.e-ghl\\.com$", "^test2pay\\.ghl\\.com$"],
|
|
1035
|
+
sandboxHosts: ["^test2pay\\.ghl\\.com$"],
|
|
1036
|
+
hostEnvironmentPinned: true,
|
|
1037
|
+
// `encoding` describes the card page's own card post, which the device makes as the page does, since the entry
|
|
1038
|
+
// has no body. No captured header is ever replayed.
|
|
1039
|
+
encoding: "form",
|
|
1040
|
+
passthroughHeaders: [],
|
|
1041
|
+
// The paused request is the navigation itself, a GET with the payment in its query.
|
|
1042
|
+
request: { method: "GET", cardIn: "processor_page", response: "document" },
|
|
1043
|
+
mode: "hosted_form",
|
|
1044
|
+
hostedForm: {
|
|
1045
|
+
// The card goes into eGHL's page on the device, never into the entry (checkEghlEntry refuses one there). The
|
|
1046
|
+
// entry's own rules come with this registration (hostedEntry below), so no policy is named here.
|
|
1047
|
+
cardIn: "processor_page",
|
|
1048
|
+
required: ["TransactionType", "PymtMethod", "ServiceID", "PaymentID", "OrderNumber", "MerchantReturnURL", "MerchantCallBackURL", "Amount", "CurrencyCode", "HashValue"],
|
|
1049
|
+
// The card page's own inputs in its card form (frmProcessPayment, read card free on 2026-11-05): the number in
|
|
1050
|
+
// Param2, the expiry in CardExp as YYYYMM, which the page builds from its month and year selects, the code in
|
|
1051
|
+
// CVV2. The cardholder's name goes in Param4.
|
|
1052
|
+
card: { number: "Param2", expiry: "CardExp", cvc: "CVV2" },
|
|
1053
|
+
// eGHL takes one PaymentID once per merchant.
|
|
1054
|
+
dedupe: ["ServiceID", "PaymentID"]
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
],
|
|
1058
|
+
// Only the cardholder's device repeats an entry, after a person approves; no reviewed list names eghl.
|
|
1059
|
+
refusedOperations: [EGHL_OPERATION],
|
|
1060
|
+
// Not surveyed: eGHL tells the merchant's server the result (MerchantCallBackURL), and its return carries a hash only
|
|
1061
|
+
// the merchant can check.
|
|
1062
|
+
settlementReadback: "not_surveyed",
|
|
1063
|
+
exactUrl: isEghlEntryUrl,
|
|
1064
|
+
amount: (template) => template && typeof template === "object" ? eghlEntryAmount(template.body, template.url) : null,
|
|
1065
|
+
hostedEntry: (body, { url = null } = {}) => checkEghlEntry(body, { url }),
|
|
1066
|
+
limitations: [
|
|
1067
|
+
"The paused request is the merchant's redirect to eGHL's payment page, a GET whose query names the payment and carries no card; the cardholder's device repeats it over the end-to-end TLS relay and pays on the page eGHL returns.",
|
|
1068
|
+
"Agentcard takes an entry only for a merchant it reviewed, by the ServiceID inside the merchant's signed entry, and the approval names that merchant and the amount the entry names.",
|
|
1069
|
+
"eGHL runs 3-D Secure on the card. A challenge ends the payment on the device with nothing charged.",
|
|
1070
|
+
"eGHL sends the buyer to the merchant's return page with a result only the merchant can verify, so the browser receives a submission notice, not the processor result."
|
|
1071
|
+
]
|
|
1072
|
+
});
|
|
1073
|
+
// src/processors/frisbii.js
|
|
1074
|
+
var FRISBII_PSP = "frisbii";
|
|
1075
|
+
var FRISBII_OPERATION = "frisbii.card_request";
|
|
1076
|
+
var FRISBII_HOSTS = /* @__PURE__ */ Object.freeze({ "card.reepay.com": "reepay", "card.frisbii.com": "frisbii" });
|
|
1077
|
+
var FRISBII_TOKEN_PATH = "/v1/token/";
|
|
1078
|
+
var FRISBII_REFUSED_PATHS = /* @__PURE__ */ Object.freeze({
|
|
1079
|
+
"/v1/token/cof/": "frisbii_stored_card_unsupported",
|
|
1080
|
+
"/v1/token/create_click_to_pay": "frisbii_click_to_pay_unsupported"
|
|
1081
|
+
});
|
|
1082
|
+
var BODY_LIMIT4 = 8192;
|
|
1083
|
+
var URL_LIMIT2 = 256;
|
|
1084
|
+
var CARD_NUMBER2 = /^[0-9]{12,19}$/;
|
|
1085
|
+
var MONTH = /^(?:0[1-9]|1[0-2])$/;
|
|
1086
|
+
var YEAR = /^[0-9]{2}$/;
|
|
1087
|
+
var SECURITY_CODE2 = /^(?:[0-9]{3,4})?$/;
|
|
1088
|
+
var IDENTIFIER = /^[A-Za-z0-9_-]{8,128}$/;
|
|
1089
|
+
var SCA_RULES = /* @__PURE__ */ Object.freeze([
|
|
1090
|
+
"DO_NOT_USE_SCA",
|
|
1091
|
+
"MUST_USE_SCA_AUTH",
|
|
1092
|
+
"MUST_USE_SCA_PREAUTH",
|
|
1093
|
+
"USE_SCA_IF_AVAILABLE_AUTH",
|
|
1094
|
+
"USE_SCA_IF_AVAILABLE_PREAUTH"
|
|
1095
|
+
]);
|
|
1096
|
+
var BODY_ORDER = /* @__PURE__ */ Object.freeze([
|
|
1097
|
+
"number",
|
|
1098
|
+
"month",
|
|
1099
|
+
"year",
|
|
1100
|
+
"cvv",
|
|
1101
|
+
"cardTypeOverride",
|
|
1102
|
+
"click_to_pay_encrypt",
|
|
1103
|
+
"billing_address",
|
|
1104
|
+
"pkey",
|
|
1105
|
+
"recurring",
|
|
1106
|
+
"cardholder_name",
|
|
1107
|
+
"intent",
|
|
1108
|
+
"recurringAverageAmount",
|
|
1109
|
+
"agreementFilter",
|
|
1110
|
+
"strongAuthenticationRule",
|
|
1111
|
+
"tokenStrongAuthenticationRequest"
|
|
1112
|
+
]);
|
|
1113
|
+
var BODY_REQUIRED = /* @__PURE__ */ Object.freeze(["number", "month", "year", "cvv", "pkey", "recurring", "strongAuthenticationRule"]);
|
|
1114
|
+
var BODY_REFUSED = /* @__PURE__ */ Object.freeze(["cardTypeOverride", "click_to_pay_encrypt", "billing_address"]);
|
|
1115
|
+
var SCA_ORDER = /* @__PURE__ */ Object.freeze(["amount", "currency", "orderId", "orderText", "merchantScaData", "returnUrl", "tokenBrowserInfo"]);
|
|
1116
|
+
var BROWSER_ORDER = /* @__PURE__ */ Object.freeze([
|
|
1117
|
+
"javascriptEnabled",
|
|
1118
|
+
"challengeWindowSize",
|
|
1119
|
+
"colorDepth",
|
|
1120
|
+
"javaEnabled",
|
|
1121
|
+
"screenHeight",
|
|
1122
|
+
"screenWidth",
|
|
1123
|
+
"tz"
|
|
1124
|
+
]);
|
|
1125
|
+
var LABEL = /^[A-Za-z0-9_-]{1,64}$/;
|
|
1126
|
+
var record3 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1127
|
+
var own4 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
1128
|
+
var refuse4 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
1129
|
+
var CARD5 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
1130
|
+
var text = (value, max) => typeof value === "string" && value.length <= max;
|
|
1131
|
+
var absentOrNull = (value) => value === void 0 || value === null;
|
|
1132
|
+
var inOrder = (value, order) => Object.keys(value).every((key) => order.includes(key)) && Object.keys(value).join() === order.filter((key) => own4(value, key)).join();
|
|
1133
|
+
function frisbiiTokenUrl(url) {
|
|
1134
|
+
if (typeof url !== "string" || url.length > URL_LIMIT2 || url.includes("#"))
|
|
1135
|
+
return null;
|
|
1136
|
+
let parsed;
|
|
1137
|
+
try {
|
|
1138
|
+
parsed = new URL(url);
|
|
1139
|
+
}
|
|
1140
|
+
catch {
|
|
1141
|
+
return null;
|
|
1142
|
+
}
|
|
1143
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !own4(FRISBII_HOSTS, parsed.hostname) || parsed.pathname !== FRISBII_TOKEN_PATH)
|
|
1144
|
+
return null;
|
|
1145
|
+
const match = /^\?session=([A-Za-z0-9_-]{8,128})$/.exec(parsed.search);
|
|
1146
|
+
return match ? Object.freeze({ host: parsed.hostname, brand: FRISBII_HOSTS[parsed.hostname], session: match[1] }) : null;
|
|
1147
|
+
}
|
|
1148
|
+
var isFrisbiiTokenUrl = (url) => frisbiiTokenUrl(url) !== null;
|
|
1149
|
+
function frisbiiRefusedFlowUrl(url) {
|
|
1150
|
+
if (typeof url !== "string" || url.length > URL_LIMIT2 || url.includes("#"))
|
|
1151
|
+
return null;
|
|
1152
|
+
let parsed;
|
|
1153
|
+
try {
|
|
1154
|
+
parsed = new URL(url);
|
|
1155
|
+
}
|
|
1156
|
+
catch {
|
|
1157
|
+
return null;
|
|
1158
|
+
}
|
|
1159
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !own4(FRISBII_HOSTS, parsed.hostname) || !own4(FRISBII_REFUSED_PATHS, parsed.pathname))
|
|
1160
|
+
return null;
|
|
1161
|
+
return FRISBII_REFUSED_PATHS[parsed.pathname];
|
|
1162
|
+
}
|
|
1163
|
+
function luhn(digits2) {
|
|
1164
|
+
let sum = 0;
|
|
1165
|
+
for (let at = digits2.length - 1, double = false; at >= 0; at -= 1, double = !double) {
|
|
1166
|
+
let digit = digits2.charCodeAt(at) - 48;
|
|
1167
|
+
if (double)
|
|
1168
|
+
digit = digit * 2 > 9 ? digit * 2 - 9 : digit * 2;
|
|
1169
|
+
sum += digit;
|
|
1170
|
+
}
|
|
1171
|
+
return sum % 10 === 0;
|
|
1172
|
+
}
|
|
1173
|
+
function readBody4(body) {
|
|
1174
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT4)
|
|
1175
|
+
return null;
|
|
1176
|
+
try {
|
|
1177
|
+
const value = JSON.parse(body);
|
|
1178
|
+
return record3(value) && JSON.stringify(value) === body ? value : null;
|
|
1179
|
+
}
|
|
1180
|
+
catch {
|
|
1181
|
+
return null;
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
function browserInfo(info) {
|
|
1185
|
+
return record3(info) && Object.keys(info).join() === BROWSER_ORDER.join() && info.javascriptEnabled === true && typeof info.javaEnabled === "boolean" && /^size_[0-9]{3}x[0-9]{3}$/.test(info.challengeWindowSize) && [info.colorDepth, info.screenHeight, info.screenWidth].every((n) => Number.isSafeInteger(n) && n >= 0 && n <= 1e5) && Number.isSafeInteger(info.tz) && Math.abs(info.tz) <= 1440;
|
|
1186
|
+
}
|
|
1187
|
+
function scaBlock(block, target) {
|
|
1188
|
+
if (!record3(block) || !inOrder(block, SCA_ORDER) || !own4(block, "returnUrl") || !own4(block, "tokenBrowserInfo"))
|
|
1189
|
+
return false;
|
|
1190
|
+
if (!Number.isSafeInteger(block.amount) || block.amount < 0 || typeof block.currency !== "string" || !/^[A-Z]{3}$/.test(block.currency))
|
|
1191
|
+
return false;
|
|
1192
|
+
if (!(absentOrNull(block.orderId) || text(block.orderId, 128)) || !(absentOrNull(block.orderText) || text(block.orderText, 512)))
|
|
1193
|
+
return false;
|
|
1194
|
+
if (!(absentOrNull(block.merchantScaData) || record3(block.merchantScaData)))
|
|
1195
|
+
return false;
|
|
1196
|
+
if (!text(block.returnUrl, 2048) || !browserInfo(block.tokenBrowserInfo))
|
|
1197
|
+
return false;
|
|
1198
|
+
const back = /^https:\/\/checkout\.(reepay|frisbii)\.com\/return\.001\.html\?id=([A-Za-z0-9_-]{8,128})(?:&[A-Za-z0-9_.~%=+/-]*)*$/.exec(block.returnUrl);
|
|
1199
|
+
return back !== null && (target === null || back[1] === target.brand && back[2] === target.session);
|
|
126
1200
|
}
|
|
127
|
-
|
|
128
|
-
|
|
1201
|
+
function frisbiiBodyVerdict(body, url) {
|
|
1202
|
+
const value = readBody4(body);
|
|
1203
|
+
if (value === null || !inOrder(value, BODY_ORDER) || !BODY_REQUIRED.every((key) => own4(value, key)) || BODY_REFUSED.some((key) => own4(value, key)))
|
|
1204
|
+
return refuse4("frisbii_body_unsupported");
|
|
1205
|
+
if (value.recurring === true || value.intent === "CHARGE_AND_STORE")
|
|
1206
|
+
return refuse4("frisbii_card_on_file");
|
|
1207
|
+
const target = url === void 0 ? null : frisbiiTokenUrl(url);
|
|
1208
|
+
if (url !== void 0 && target === null)
|
|
1209
|
+
return refuse4("frisbii_body_unsupported");
|
|
1210
|
+
const sound = typeof value.number === "string" && CARD_NUMBER2.test(value.number) && luhn(value.number) && typeof value.month === "string" && MONTH.test(value.month) && typeof value.year === "string" && YEAR.test(value.year) && typeof value.cvv === "string" && SECURITY_CODE2.test(value.cvv) && typeof value.pkey === "string" && IDENTIFIER.test(value.pkey) && value.recurring === false && (value.cardholder_name === void 0 || text(value.cardholder_name, 64)) && (value.intent === void 0 || value.intent === "CHARGE") && (absentOrNull(value.recurringAverageAmount) || Number.isSafeInteger(value.recurringAverageAmount) && value.recurringAverageAmount >= 0) && (absentOrNull(value.agreementFilter) || typeof value.agreementFilter === "string" && LABEL.test(value.agreementFilter) || Array.isArray(value.agreementFilter) && value.agreementFilter.length <= 16 && value.agreementFilter.every((entry) => typeof entry === "string" && LABEL.test(entry))) && SCA_RULES.includes(value.strongAuthenticationRule) && (value.tokenStrongAuthenticationRequest === void 0 || scaBlock(value.tokenStrongAuthenticationRequest, target));
|
|
1211
|
+
return sound ? CARD5 : refuse4("frisbii_body_unsupported");
|
|
1212
|
+
}
|
|
1213
|
+
var frisbii_default = /* @__PURE__ */ registerProcessor({
|
|
1214
|
+
psp: FRISBII_PSP,
|
|
129
1215
|
definitions: [
|
|
130
1216
|
{
|
|
131
|
-
psp: "
|
|
132
|
-
// The
|
|
133
|
-
//
|
|
134
|
-
//
|
|
135
|
-
//
|
|
136
|
-
//
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
hostEnvironmentPinned: true,
|
|
1217
|
+
psp: "frisbii",
|
|
1218
|
+
// The hosted page's card request, as the header above reads it, on both brands' card hosts. A test account
|
|
1219
|
+
// shares the live hosts, so no sandbox host is marked. The match reads the host and the path and ends with it. It
|
|
1220
|
+
// also takes the page's two other card paths, /v1/token/cof/ and /v1/token/create_click_to_pay, so the pause
|
|
1221
|
+
// decision holds them, and the body gate refuses every body there; the exact-URL rule below holds the session
|
|
1222
|
+
// query of the card request. Ships dark: served only to a client that declares `frisbii_card_token`, and only for a company
|
|
1223
|
+
// the backend's processor gate turns Frisbii on for.
|
|
1224
|
+
capability: "frisbii_card_token",
|
|
1225
|
+
match: "card\\.(?:reepay|frisbii)\\.com/v1/token/(?:cof/|create_click_to_pay)?",
|
|
1226
|
+
hosts: ["^card\\.reepay\\.com$", "^card\\.frisbii\\.com$"],
|
|
142
1227
|
encoding: "json",
|
|
143
|
-
// The
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
jsonCardFields: [["ccNumber"]],
|
|
147
|
-
// The expiry and code frames' PUTs: held by the checkout SDK and answered with the card request's answer.
|
|
148
|
-
splitCard: { absorb: [...BLUESNAP_LEG_KEYS], pass: [], siblingKeys: [] },
|
|
149
|
-
request: { method: "PUT", cardIn: "body", response: "json" }
|
|
1228
|
+
// The page sends no header but its content type. Origin, Referer and cookies never ride.
|
|
1229
|
+
passthroughHeaders: [],
|
|
1230
|
+
jsonCardFields: [["number"]]
|
|
150
1231
|
}
|
|
151
1232
|
],
|
|
152
|
-
// Only the cardholder's device
|
|
153
|
-
refusedOperations: [
|
|
154
|
-
// Not surveyed: the
|
|
1233
|
+
// Only the cardholder's device would send this card, after a person approves; no reviewed list names frisbii.
|
|
1234
|
+
refusedOperations: [FRISBII_OPERATION],
|
|
1235
|
+
// Not surveyed: the card request mints a token and moves no money, and the page then charges the session with it
|
|
1236
|
+
// in a card-free request. Whether the session's own read (checkout-api /v1/checkout/<session>) can confirm that
|
|
1237
|
+
// charge was not read.
|
|
155
1238
|
settlementReadback: "not_surveyed",
|
|
156
|
-
exactUrl:
|
|
157
|
-
|
|
1239
|
+
exactUrl: (url) => isFrisbiiTokenUrl(url) || frisbiiRefusedFlowUrl(url) !== null,
|
|
1240
|
+
// A stored card's token and Click to Pay are refused whatever their body; the card request is judged by its body.
|
|
1241
|
+
bodyGate: (url, body) => {
|
|
1242
|
+
if (url === void 0)
|
|
1243
|
+
return frisbiiBodyVerdict(body);
|
|
1244
|
+
const flow = frisbiiRefusedFlowUrl(url);
|
|
1245
|
+
if (flow !== null)
|
|
1246
|
+
return refuse4(flow);
|
|
1247
|
+
return isFrisbiiTokenUrl(url) ? frisbiiBodyVerdict(body, url) : refuse4("frisbii_url_refused");
|
|
1248
|
+
},
|
|
1249
|
+
limitations: ["A live Frisbii card goes only to a merchant account a reviewed pin lists, and none is pinned yet."]
|
|
158
1250
|
});
|
|
159
1251
|
// src/processors/iyzico.js
|
|
160
1252
|
var IYZICO_PSP = "iyzico";
|
|
@@ -181,19 +1273,19 @@ var IYZICO_CARD_KEYS = /* @__PURE__ */ Object.freeze([
|
|
|
181
1273
|
"registerConsumerCard",
|
|
182
1274
|
"registerCard"
|
|
183
1275
|
]);
|
|
184
|
-
var
|
|
185
|
-
var
|
|
186
|
-
var
|
|
187
|
-
var
|
|
188
|
-
var
|
|
1276
|
+
var BODY_LIMIT5 = 4096;
|
|
1277
|
+
var CARD_NUMBER3 = /^[0-9]{12,19}$/;
|
|
1278
|
+
var SECURITY_CODE3 = /^[0-9]{3,4}$/;
|
|
1279
|
+
var MONTH2 = /^(?:0?[1-9]|1[0-2])$/;
|
|
1280
|
+
var YEAR2 = /^(?:[0-9]{2}|20[0-9]{2})$/;
|
|
189
1281
|
var PRICE = /^([1-9][0-9]{0,8}|0)(?:\.([0-9]{1,2}))?$/;
|
|
190
1282
|
var CHANNELS = /* @__PURE__ */ Object.freeze(["WEB", "MOBILE_WEB", "MOBILE_IOS", "MOBILE_ANDROID", "MOBILE_WINDOWS"]);
|
|
191
1283
|
var METADATA_KEYS = /* @__PURE__ */ Object.freeze(["lightRedesign", "pwiGrowthActionDisabled"]);
|
|
192
1284
|
var FLAG = /^[A-Za-z_]{1,16}$/;
|
|
193
1285
|
var HOLDER = /^[^\x00-\x1f\x7f0-9]{3,100}$/u;
|
|
194
|
-
var
|
|
195
|
-
var
|
|
196
|
-
var
|
|
1286
|
+
var record4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1287
|
+
var own5 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
1288
|
+
var inOrder2 = (value, keys) => {
|
|
197
1289
|
let at = 0;
|
|
198
1290
|
for (const name of Object.keys(value)) {
|
|
199
1291
|
while (at < keys.length && keys[at] !== name)
|
|
@@ -204,17 +1296,17 @@ var inOrder = (value, keys) => {
|
|
|
204
1296
|
}
|
|
205
1297
|
return true;
|
|
206
1298
|
};
|
|
207
|
-
var
|
|
208
|
-
var
|
|
1299
|
+
var refuse5 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
1300
|
+
var CARD6 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
209
1301
|
function isIyzicoCardUrl(url) {
|
|
210
1302
|
return typeof url === "string" && IYZICO_CARD_URLS.includes(url);
|
|
211
1303
|
}
|
|
212
|
-
function
|
|
213
|
-
if (typeof body !== "string" || body === "" || body.length >
|
|
1304
|
+
function readBody5(body) {
|
|
1305
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT5)
|
|
214
1306
|
return null;
|
|
215
1307
|
try {
|
|
216
1308
|
const value = JSON.parse(body);
|
|
217
|
-
return
|
|
1309
|
+
return record4(value) && JSON.stringify(value) === body ? value : null;
|
|
218
1310
|
}
|
|
219
1311
|
catch {
|
|
220
1312
|
return null;
|
|
@@ -226,26 +1318,26 @@ function hundredths(price) {
|
|
|
226
1318
|
return value > 0 ? value : null;
|
|
227
1319
|
}
|
|
228
1320
|
var holderName = (name) => typeof name === "string" && HOLDER.test(name) && name.trim().split(/\s+/).filter((word) => word.length > 1).length > 1;
|
|
229
|
-
var metadata = (value) =>
|
|
1321
|
+
var metadata = (value) => record4(value) && inOrder2(value, METADATA_KEYS) && Object.values(value).every((flag) => Array.isArray(flag) && flag.length === 1 && typeof flag[0] === "string" && FLAG.test(flag[0]));
|
|
230
1322
|
function iyzicoBodyVerdict(body) {
|
|
231
|
-
const value =
|
|
1323
|
+
const value = readBody5(body);
|
|
232
1324
|
if (value === null)
|
|
233
|
-
return
|
|
1325
|
+
return refuse5("iyzico_body_unsupported");
|
|
234
1326
|
const card = value.paymentCard;
|
|
235
|
-
if (
|
|
236
|
-
return
|
|
237
|
-
if (
|
|
238
|
-
return
|
|
239
|
-
if (
|
|
240
|
-
return
|
|
1327
|
+
if (record4(card) && (own5(card, "cardToken") || own5(card, "ucsToken") || own5(card, "consumerToken")) && !own5(card, "cardNumber"))
|
|
1328
|
+
return refuse5("iyzico_saved_card");
|
|
1329
|
+
if (own5(value, "dccPayment") || own5(value, "dccQueryRrn"))
|
|
1330
|
+
return refuse5("iyzico_dcc_refused");
|
|
1331
|
+
if (own5(value, "gsmNumber") || own5(value, "buyerProtected") && value.buyerProtected !== false || record4(card) && (own5(card, "registerCard") && card.registerCard !== 0 || own5(card, "registerConsumerCard") && card.registerConsumerCard !== false)) {
|
|
1332
|
+
return refuse5("iyzico_keeps_card");
|
|
241
1333
|
}
|
|
242
1334
|
if (Number.isSafeInteger(value.installment) && value.installment > 1)
|
|
243
|
-
return
|
|
244
|
-
if (!
|
|
245
|
-
return
|
|
246
|
-
if (!
|
|
247
|
-
return
|
|
248
|
-
return
|
|
1335
|
+
return refuse5("iyzico_installments_refused");
|
|
1336
|
+
if (!inOrder2(value, IYZICO_BODY_KEYS) || !["installment", "paidPrice", "paymentChannel", "paymentCard"].every((key) => own5(value, key)) || value.installment !== 1 || hundredths(value.paidPrice) === null || !CHANNELS.includes(value.paymentChannel) || own5(value, "pwiMetadata") && !metadata(value.pwiMetadata))
|
|
1337
|
+
return refuse5("iyzico_body_unsupported");
|
|
1338
|
+
if (!record4(card) || Object.keys(card).join() !== IYZICO_CARD_KEYS.join() || typeof card.cardNumber !== "string" || !CARD_NUMBER3.test(card.cardNumber) || !holderName(card.cardHolderName) || typeof card.expireYear !== "string" || !YEAR2.test(card.expireYear) || typeof card.expireMonth !== "string" || !MONTH2.test(card.expireMonth) || typeof card.cvc !== "string" || !SECURITY_CODE3.test(card.cvc))
|
|
1339
|
+
return refuse5("iyzico_body_unsupported");
|
|
1340
|
+
return CARD6;
|
|
249
1341
|
}
|
|
250
1342
|
var iyzico_default = /* @__PURE__ */ registerProcessor({
|
|
251
1343
|
psp: IYZICO_PSP,
|
|
@@ -278,7 +1370,7 @@ var iyzico_default = /* @__PURE__ */ registerProcessor({
|
|
|
278
1370
|
source: "https://docs.iyzico.com/en/payment-methods/checkoutform/cf-implementation/cf-retrieve"
|
|
279
1371
|
},
|
|
280
1372
|
exactUrl: isIyzicoCardUrl,
|
|
281
|
-
bodyGate: (url, body) => url !== void 0 && !isIyzicoCardUrl(url) ?
|
|
1373
|
+
bodyGate: (url, body) => url !== void 0 && !isIyzicoCardUrl(url) ? refuse5("iyzico_url_refused") : iyzicoBodyVerdict(body)
|
|
282
1374
|
});
|
|
283
1375
|
// src/processors/midtrans.js
|
|
284
1376
|
var MIDTRANS_PSP = "midtrans";
|
|
@@ -286,15 +1378,15 @@ var MIDTRANS_OPERATION = "midtrans.card_request";
|
|
|
286
1378
|
var MIDTRANS_TOKEN_URL = "https://api.midtrans.com/v2/token";
|
|
287
1379
|
var MIDTRANS_SANDBOX_TOKEN_URL = "https://api.sandbox.midtrans.com/v2/token";
|
|
288
1380
|
var MIDTRANS_TOKEN_KEYS = /* @__PURE__ */ Object.freeze(["card_cvv", "card_number", "card_exp_month", "card_exp_year", "installment_term"]);
|
|
289
|
-
var
|
|
290
|
-
var
|
|
291
|
-
var
|
|
292
|
-
var
|
|
293
|
-
var
|
|
1381
|
+
var BODY_LIMIT6 = 4096;
|
|
1382
|
+
var CARD_NUMBER4 = /^[0-9]{12,19}$/;
|
|
1383
|
+
var SECURITY_CODE4 = /^[0-9]{3,4}$/;
|
|
1384
|
+
var MONTH3 = /^(?:0[1-9]|1[0-2])$/;
|
|
1385
|
+
var YEAR3 = /^20[0-9]{2}$/;
|
|
294
1386
|
var TERM = /^[0-9]{1,3}$/;
|
|
295
|
-
var
|
|
296
|
-
var
|
|
297
|
-
var
|
|
1387
|
+
var record5 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1388
|
+
var own6 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
1389
|
+
var inOrder3 = (value, keys) => {
|
|
298
1390
|
let at = 0;
|
|
299
1391
|
for (const name of Object.keys(value)) {
|
|
300
1392
|
while (at < keys.length && keys[at] !== name)
|
|
@@ -305,18 +1397,18 @@ var inOrder2 = (value, keys) => {
|
|
|
305
1397
|
}
|
|
306
1398
|
return true;
|
|
307
1399
|
};
|
|
308
|
-
var
|
|
309
|
-
var
|
|
1400
|
+
var refuse6 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
1401
|
+
var CARD7 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
310
1402
|
function isMidtransTokenUrl(url) {
|
|
311
1403
|
return url === MIDTRANS_TOKEN_URL || url === MIDTRANS_SANDBOX_TOKEN_URL;
|
|
312
1404
|
}
|
|
313
|
-
function
|
|
314
|
-
if (typeof body !== "string" || body === "" || body.length >
|
|
1405
|
+
function readBody6(body) {
|
|
1406
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT6)
|
|
315
1407
|
return null;
|
|
316
1408
|
let value;
|
|
317
1409
|
try {
|
|
318
1410
|
value = JSON.parse(body);
|
|
319
|
-
if (!
|
|
1411
|
+
if (!record5(value) || JSON.stringify(value) !== body)
|
|
320
1412
|
return null;
|
|
321
1413
|
}
|
|
322
1414
|
catch {
|
|
@@ -325,20 +1417,20 @@ function readBody3(body) {
|
|
|
325
1417
|
return value;
|
|
326
1418
|
}
|
|
327
1419
|
function midtransBodyVerdict(body) {
|
|
328
|
-
const value =
|
|
329
|
-
if (value === null || !
|
|
330
|
-
if (
|
|
331
|
-
return
|
|
332
|
-
return
|
|
1420
|
+
const value = readBody6(body);
|
|
1421
|
+
if (value === null || !inOrder3(value, MIDTRANS_TOKEN_KEYS)) {
|
|
1422
|
+
if (record5(value) && (own6(value, "token_id") || own6(value, "two_click")) && !own6(value, "card_number"))
|
|
1423
|
+
return refuse6("midtrans_saved_card");
|
|
1424
|
+
return refuse6("midtrans_body_unsupported");
|
|
333
1425
|
}
|
|
334
|
-
if (!
|
|
335
|
-
return
|
|
1426
|
+
if (!own6(value, "card_cvv") || !own6(value, "card_number") || !own6(value, "card_exp_month") || !own6(value, "card_exp_year")) {
|
|
1427
|
+
return refuse6("midtrans_body_unsupported");
|
|
336
1428
|
}
|
|
337
|
-
if (typeof value.card_cvv !== "string" || !
|
|
338
|
-
return
|
|
339
|
-
if (
|
|
340
|
-
return
|
|
341
|
-
return
|
|
1429
|
+
if (typeof value.card_cvv !== "string" || !SECURITY_CODE4.test(value.card_cvv) || typeof value.card_number !== "string" || !CARD_NUMBER4.test(value.card_number) || typeof value.card_exp_month !== "string" || !MONTH3.test(value.card_exp_month) || typeof value.card_exp_year !== "string" || !YEAR3.test(value.card_exp_year))
|
|
1430
|
+
return refuse6("midtrans_body_unsupported");
|
|
1431
|
+
if (own6(value, "installment_term") && (typeof value.installment_term !== "string" || !TERM.test(value.installment_term)))
|
|
1432
|
+
return refuse6("midtrans_body_unsupported");
|
|
1433
|
+
return CARD7;
|
|
342
1434
|
}
|
|
343
1435
|
var midtrans_default = /* @__PURE__ */ registerProcessor({
|
|
344
1436
|
psp: MIDTRANS_PSP,
|
|
@@ -369,6 +1461,99 @@ var midtrans_default = /* @__PURE__ */ registerProcessor({
|
|
|
369
1461
|
exactUrl: isMidtransTokenUrl,
|
|
370
1462
|
bodyGate: (url, body) => url !== void 0 && !isMidtransTokenUrl(url) ? { verdict: "refuse", code: "midtrans_url_refused" } : midtransBodyVerdict(body)
|
|
371
1463
|
});
|
|
1464
|
+
// src/processors/monei.js
|
|
1465
|
+
var MONEI_PSP = "monei";
|
|
1466
|
+
var MONEI_OPERATION = "monei.card_request";
|
|
1467
|
+
var MONEI_TOKENS_URL = "https://api.monei.com/v1/tokens";
|
|
1468
|
+
var BODY_LIMIT7 = 1024;
|
|
1469
|
+
var PAYMENT_ID = /^(?:[0-9a-f]{32}|[0-9a-f]{40})$/;
|
|
1470
|
+
var MONEI_CARD_KEYS = /* @__PURE__ */ Object.freeze(["number", "expMonth", "expYear", "cvc"]);
|
|
1471
|
+
var NUMBER2 = /^[0-9]{12,19}$/;
|
|
1472
|
+
var MONTH4 = /^(?:0[1-9]|1[0-2])$/;
|
|
1473
|
+
var YEAR4 = /^[0-9]{2}$/;
|
|
1474
|
+
var CODE = /^[0-9]{3,4}$/;
|
|
1475
|
+
var record6 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1476
|
+
var keysAre = (value, keys) => {
|
|
1477
|
+
const found = Object.keys(value);
|
|
1478
|
+
return found.length === keys.length && found.every((key, at) => key === keys[at]);
|
|
1479
|
+
};
|
|
1480
|
+
var refuse7 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
1481
|
+
var CARD8 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
1482
|
+
function luhn2(digits2) {
|
|
1483
|
+
let sum = 0;
|
|
1484
|
+
for (let at = 0; at < digits2.length; at += 1) {
|
|
1485
|
+
let digit = Number(digits2[digits2.length - 1 - at]);
|
|
1486
|
+
if (at % 2 === 1) {
|
|
1487
|
+
digit *= 2;
|
|
1488
|
+
if (digit > 9)
|
|
1489
|
+
digit -= 9;
|
|
1490
|
+
}
|
|
1491
|
+
sum += digit;
|
|
1492
|
+
}
|
|
1493
|
+
return sum % 10 === 0;
|
|
1494
|
+
}
|
|
1495
|
+
function isMoneiTokensUrl(url) {
|
|
1496
|
+
return url === MONEI_TOKENS_URL;
|
|
1497
|
+
}
|
|
1498
|
+
function readBody7(body) {
|
|
1499
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT7)
|
|
1500
|
+
return null;
|
|
1501
|
+
try {
|
|
1502
|
+
const value = JSON.parse(body);
|
|
1503
|
+
return record6(value) && JSON.stringify(value) === body ? value : null;
|
|
1504
|
+
}
|
|
1505
|
+
catch {
|
|
1506
|
+
return null;
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
function moneiBodyVerdict(body, url) {
|
|
1510
|
+
if (url !== void 0 && !isMoneiTokensUrl(url))
|
|
1511
|
+
return refuse7("monei_url_refused");
|
|
1512
|
+
const value = readBody7(body);
|
|
1513
|
+
if (value === null || !keysAre(value, ["paymentId", "paymentMethod"]) || typeof value.paymentId !== "string" || !PAYMENT_ID.test(value.paymentId))
|
|
1514
|
+
return refuse7("monei_body_unsupported");
|
|
1515
|
+
const method = value.paymentMethod;
|
|
1516
|
+
if (!record6(method) || !keysAre(method, ["card"]) || !record6(method.card) || !keysAre(method.card, MONEI_CARD_KEYS))
|
|
1517
|
+
return refuse7("monei_body_unsupported");
|
|
1518
|
+
const { number, expMonth, expYear, cvc } = method.card;
|
|
1519
|
+
if (![number, expMonth, expYear, cvc].every((part) => typeof part === "string"))
|
|
1520
|
+
return refuse7("monei_body_unsupported");
|
|
1521
|
+
if (!NUMBER2.test(number) || !luhn2(number) || !MONTH4.test(expMonth) || !YEAR4.test(expYear) || !CODE.test(cvc))
|
|
1522
|
+
return refuse7("monei_body_unsupported");
|
|
1523
|
+
return CARD8;
|
|
1524
|
+
}
|
|
1525
|
+
var MONEI_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
1526
|
+
Object.freeze({ merchant: "Genuins", accountIds: Object.freeze(["8d58ab4c-4ad0-4053-b18f-79d80e9ee158"]), merchantUrls: Object.freeze(["https://genuins.com/"]) })
|
|
1527
|
+
]);
|
|
1528
|
+
var monei_default = /* @__PURE__ */ registerProcessor({
|
|
1529
|
+
psp: MONEI_PSP,
|
|
1530
|
+
definitions: [
|
|
1531
|
+
{
|
|
1532
|
+
psp: "monei",
|
|
1533
|
+
// The card frame's token request, as the header above reads it. One host serves test and live payments alike,
|
|
1534
|
+
// so no sandbox host is marked: MONEI's record of the payment names its mode, and the device sends a test payment
|
|
1535
|
+
// only MONEI's documented test cards (moneiDeviceRefusal). The frame sets no deadline on the fetch, so the
|
|
1536
|
+
// cardholder approves at the shopper's Pay. `(?![\w/.%-])` ends the path for a consumer that tests `match`
|
|
1537
|
+
// unanchored, and the exact-URL rule below holds the rest. Ships dark: served only to a client that declares
|
|
1538
|
+
// `monei_card_token`, and gated off for every company until the backend's gate names one.
|
|
1539
|
+
capability: "monei_card_token",
|
|
1540
|
+
match: "api\\.monei\\.com/v1/tokens(?![\\w/.%-])",
|
|
1541
|
+
hosts: ["^api\\.monei\\.com$"],
|
|
1542
|
+
encoding: "json",
|
|
1543
|
+
// The frame's two device headers. Origin, Referer and cookies never ride.
|
|
1544
|
+
passthroughHeaders: ["^x-client-env$", "^x-client-fingerprint$"],
|
|
1545
|
+
jsonCardFields: [["paymentMethod", "card", "number"]]
|
|
1546
|
+
}
|
|
1547
|
+
],
|
|
1548
|
+
// Only the cardholder's device sends a card, after a person approves; no reviewed list names monei.
|
|
1549
|
+
refusedOperations: [MONEI_OPERATION],
|
|
1550
|
+
// Not surveyed: the card request mints a token and moves no money; MONEI's confirm, which the page sends, charges it.
|
|
1551
|
+
settlementReadback: "not_surveyed",
|
|
1552
|
+
exactUrl: isMoneiTokensUrl,
|
|
1553
|
+
bodyGate: (url, body) => moneiBodyVerdict(body, url)
|
|
1554
|
+
// No amount reader: the request names none. MONEI's record of the payment names it, and the device holds that record
|
|
1555
|
+
// to the approved amount before it writes any card.
|
|
1556
|
+
});
|
|
372
1557
|
// src/processors/oceanpayment.js
|
|
373
1558
|
var OCEANPAYMENT_PSP = "oceanpayment";
|
|
374
1559
|
var OCEANPAYMENT_OPERATION = "oceanpayment.card_request";
|
|
@@ -398,10 +1583,10 @@ var OCEANPAYMENT_FORM_FIELDS = /* @__PURE__ */ Object.freeze([
|
|
|
398
1583
|
"methods",
|
|
399
1584
|
"reference"
|
|
400
1585
|
]);
|
|
401
|
-
var
|
|
402
|
-
var
|
|
1586
|
+
var URL_LIMIT3 = 2048;
|
|
1587
|
+
var BODY_LIMIT8 = 8192;
|
|
403
1588
|
var SEND_PAY = /^\/gateway\/sendPay;jsessionid=[A-Za-z0-9._!-]{16,128}$/;
|
|
404
|
-
var
|
|
1589
|
+
var own7 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
405
1590
|
var exact = (pattern, value) => typeof value === "string" && pattern.test(value);
|
|
406
1591
|
var CARD_RUN = /[0-9]{12}/;
|
|
407
1592
|
var printable = (max) => (value) => typeof value === "string" && value.length <= max && /^[\x20-\x7e]*$/.test(value) && !CARD_RUN.test(value);
|
|
@@ -439,7 +1624,7 @@ var SHAPES = /* @__PURE__ */ new Map([
|
|
|
439
1624
|
["button", (v) => v === ""]
|
|
440
1625
|
]);
|
|
441
1626
|
function oceanpaymentSendPayUrl(url) {
|
|
442
|
-
if (typeof url !== "string" || url.length >
|
|
1627
|
+
if (typeof url !== "string" || url.length > URL_LIMIT3 || url.includes("?") || url.includes("#"))
|
|
443
1628
|
return null;
|
|
444
1629
|
let parsed;
|
|
445
1630
|
try {
|
|
@@ -448,7 +1633,7 @@ function oceanpaymentSendPayUrl(url) {
|
|
|
448
1633
|
catch {
|
|
449
1634
|
return null;
|
|
450
1635
|
}
|
|
451
|
-
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !
|
|
1636
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !own7(OCEANPAYMENT_HOSTS, parsed.hostname) || !SEND_PAY.test(parsed.pathname))
|
|
452
1637
|
return null;
|
|
453
1638
|
return Object.freeze({ host: parsed.hostname, environment: OCEANPAYMENT_HOSTS[parsed.hostname] });
|
|
454
1639
|
}
|
|
@@ -476,7 +1661,7 @@ function formDecode(raw) {
|
|
|
476
1661
|
return formEncode(value) === raw ? value : null;
|
|
477
1662
|
}
|
|
478
1663
|
function readPairs(body) {
|
|
479
|
-
if (typeof body !== "string" || body === "" || body.length >
|
|
1664
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT8)
|
|
480
1665
|
return null;
|
|
481
1666
|
const pairs = [];
|
|
482
1667
|
for (const chunk of body.split("&")) {
|
|
@@ -561,7 +1746,7 @@ var PAYMENTWALL_PSP = "paymentwall";
|
|
|
561
1746
|
var PAYMENTWALL_OPERATION = "paymentwall.card_request";
|
|
562
1747
|
var PAYMENTWALL_TOKEN_URL = "https://pwgateway.com/api/token";
|
|
563
1748
|
var PAYMENTWALL_SANDBOX_TOKEN_URL = "https://api.paymentwall.com/api/brick/token";
|
|
564
|
-
var
|
|
1749
|
+
var BODY_LIMIT9 = 2048;
|
|
565
1750
|
var KEY = "public_key";
|
|
566
1751
|
var PUBLIC_KEY = /^(?:t_)?[A-Za-z0-9]{16,64}$/;
|
|
567
1752
|
var SHAPES2 = /* @__PURE__ */ Object.freeze({
|
|
@@ -571,9 +1756,9 @@ var SHAPES2 = /* @__PURE__ */ Object.freeze({
|
|
|
571
1756
|
"card[exp_year]": /^(?:[0-9]{2}|20[0-9]{2})$/,
|
|
572
1757
|
"card[cvv]": /^[0-9]{3,4}$/
|
|
573
1758
|
});
|
|
574
|
-
var
|
|
575
|
-
var
|
|
576
|
-
function
|
|
1759
|
+
var refuse8 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
1760
|
+
var CARD9 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
1761
|
+
function luhn3(digits2) {
|
|
577
1762
|
let sum = 0;
|
|
578
1763
|
for (let at = 0; at < digits2.length; at += 1) {
|
|
579
1764
|
let digit = Number(digits2[digits2.length - 1 - at]);
|
|
@@ -600,171 +1785,74 @@ function paymentwallKeyEnvironment(publicKey) {
|
|
|
600
1785
|
return publicKey.startsWith("t_") ? "sandbox" : "production";
|
|
601
1786
|
}
|
|
602
1787
|
function readPairs2(body) {
|
|
603
|
-
if (typeof body !== "string" || body === "" || body.length >
|
|
1788
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT9 || !/^[A-Za-z0-9_[\]=&]+$/.test(body))
|
|
604
1789
|
return null;
|
|
605
1790
|
const pairs = /* @__PURE__ */ new Map();
|
|
606
1791
|
for (const chunk of body.split("&")) {
|
|
607
1792
|
const eq = chunk.indexOf("=");
|
|
608
1793
|
if (eq <= 0 || chunk.indexOf("=", eq + 1) !== -1)
|
|
609
1794
|
return null;
|
|
610
|
-
const key = chunk.slice(0, eq);
|
|
611
|
-
if (pairs.has(key))
|
|
612
|
-
return null;
|
|
613
|
-
pairs.set(key, chunk.slice(eq + 1));
|
|
614
|
-
}
|
|
615
|
-
return pairs;
|
|
616
|
-
}
|
|
617
|
-
function paymentwallBodyVerdict(body, url) {
|
|
618
|
-
if (url !== void 0 && !isPaymentwallTokenUrl(url))
|
|
619
|
-
return
|
|
620
|
-
const pairs = readPairs2(body);
|
|
621
|
-
if (pairs === null)
|
|
622
|
-
return
|
|
623
|
-
if (pairs.has("card[token]") && !pairs.has("card[number]"))
|
|
624
|
-
return
|
|
625
|
-
const keys = Object.keys(SHAPES2);
|
|
626
|
-
if (pairs.size !== keys.length || !keys.every((key) => pairs.has(key) && SHAPES2[key].test(pairs.get(key)))) {
|
|
627
|
-
return
|
|
628
|
-
}
|
|
629
|
-
if (!
|
|
630
|
-
return
|
|
631
|
-
if (url !== void 0 && paymentwallKeyEnvironment(pairs.get(KEY)) !== paymentwallUrlEnvironment(url))
|
|
632
|
-
return
|
|
633
|
-
return
|
|
634
|
-
}
|
|
635
|
-
var paymentwall_default = /* @__PURE__ */ registerProcessor({
|
|
636
|
-
psp: PAYMENTWALL_PSP,
|
|
637
|
-
definitions: [
|
|
638
|
-
{
|
|
639
|
-
psp: "paymentwall",
|
|
640
|
-
// Brick's token request, as the header above reads it. A test key's request has its own host, so the device sends
|
|
641
|
-
// it only Paymentwall's documented test cards (hostEnvironmentPinned, device-replay.js S7). Ships dark: served only
|
|
642
|
-
// to a client that declares `paymentwall_card_token`, for a company the backend's gate turns it on for
|
|
643
|
-
// (checkout-processor-gate.ts), and the device sends a live card only under a key a reviewed pin names.
|
|
644
|
-
capability: "paymentwall_card_token",
|
|
645
|
-
match: "(?:pwgateway\\.com/api/token|api\\.paymentwall\\.com/api/brick/token)",
|
|
646
|
-
hosts: ["^pwgateway\\.com$", "^api\\.paymentwall\\.com$"],
|
|
647
|
-
sandboxHosts: ["^api\\.paymentwall\\.com$"],
|
|
648
|
-
hostEnvironmentPinned: true,
|
|
649
|
-
encoding: "form",
|
|
650
|
-
// Brick's XHR sets the form Content-Type alone, and that always rides. Origin, Referer and cookies never do.
|
|
651
|
-
passthroughHeaders: [],
|
|
652
|
-
cardFields: ["card[number]"]
|
|
653
|
-
}
|
|
654
|
-
],
|
|
655
|
-
// Only the cardholder's device sends a card request, after a person approves; no reviewed list names paymentwall.
|
|
656
|
-
refusedOperations: [PAYMENTWALL_OPERATION],
|
|
657
|
-
// Not surveyed: the token moves no money, and the charge that spends it happens out of this request.
|
|
658
|
-
settlementReadback: "not_surveyed",
|
|
659
|
-
exactUrl: isPaymentwallTokenUrl,
|
|
660
|
-
bodyGate: (url, body) => paymentwallBodyVerdict(body, url)
|
|
661
|
-
});
|
|
662
|
-
// src/processors/ekashu.js
|
|
663
|
-
var EKASHU_HOSTS = Object.freeze(["live.ekashu.com", "test.ekashu.com"]);
|
|
664
|
-
var EKASHU_TEST_PANS = Object.freeze(["4100000000000100", "5100000000000107"]);
|
|
665
|
-
var EKASHU_SIGNED_FIELDS = Object.freeze([
|
|
666
|
-
"ekashu_3d_secure_verify",
|
|
667
|
-
"ekashu_amount",
|
|
668
|
-
"ekashu_amount_format",
|
|
669
|
-
"ekashu_auto_confirm",
|
|
670
|
-
"ekashu_callback_failure_url",
|
|
671
|
-
"ekashu_callback_include_post",
|
|
672
|
-
"ekashu_callback_success_url",
|
|
673
|
-
"ekashu_card_address_editable",
|
|
674
|
-
"ekashu_card_address_required",
|
|
675
|
-
"ekashu_card_address_verify",
|
|
676
|
-
"ekashu_card_email_address_mandatory",
|
|
677
|
-
"ekashu_card_phone_number_mandatory",
|
|
678
|
-
"ekashu_card_title_mandatory",
|
|
679
|
-
"ekashu_card_zip_code_verify",
|
|
680
|
-
"ekashu_currency",
|
|
681
|
-
"ekashu_delivery_address_editable",
|
|
682
|
-
"ekashu_delivery_address_required",
|
|
683
|
-
"ekashu_delivery_email_address_mandatory",
|
|
684
|
-
"ekashu_delivery_phone_number_mandatory",
|
|
685
|
-
"ekashu_delivery_title_mandatory",
|
|
686
|
-
"ekashu_description",
|
|
687
|
-
"ekashu_device",
|
|
688
|
-
"ekashu_duplicate_check",
|
|
689
|
-
"ekashu_duplicate_minutes",
|
|
690
|
-
"ekashu_failure_return_text",
|
|
691
|
-
"ekashu_failure_url",
|
|
692
|
-
"ekashu_hash_code_format",
|
|
693
|
-
"ekashu_hash_code_type",
|
|
694
|
-
"ekashu_hash_code_version",
|
|
695
|
-
"ekashu_include_post",
|
|
696
|
-
"ekashu_invoice_address_editable",
|
|
697
|
-
"ekashu_invoice_address_required",
|
|
698
|
-
"ekashu_invoice_email_address_mandatory",
|
|
699
|
-
"ekashu_invoice_phone_number_mandatory",
|
|
700
|
-
"ekashu_invoice_title_mandatory",
|
|
701
|
-
"ekashu_locale",
|
|
702
|
-
"ekashu_payment_methods",
|
|
703
|
-
"ekashu_reference",
|
|
704
|
-
"ekashu_request_type",
|
|
705
|
-
"ekashu_return_text",
|
|
706
|
-
"ekashu_seller_address",
|
|
707
|
-
"ekashu_seller_email_address",
|
|
708
|
-
"ekashu_seller_id",
|
|
709
|
-
"ekashu_seller_key",
|
|
710
|
-
"ekashu_seller_name",
|
|
711
|
-
"ekashu_shortcut_icon",
|
|
712
|
-
"ekashu_style_sheet",
|
|
713
|
-
"ekashu_success_url",
|
|
714
|
-
"ekashu_title",
|
|
715
|
-
"ekashu_verification_value_mask",
|
|
716
|
-
"ekashu_verification_value_verify",
|
|
717
|
-
"ekashu_viewport"
|
|
718
|
-
]);
|
|
719
|
-
var REQUIRED = Object.freeze([
|
|
720
|
-
"ekashu_seller_id",
|
|
721
|
-
"ekashu_seller_key",
|
|
722
|
-
"ekashu_amount",
|
|
723
|
-
"ekashu_currency",
|
|
724
|
-
"ekashu_reference",
|
|
725
|
-
"ekashu_hash_code",
|
|
726
|
-
"ekashu_hash_code_type",
|
|
727
|
-
"ekashu_hash_code_version",
|
|
728
|
-
"ekashu_success_url",
|
|
729
|
-
"ekashu_failure_url",
|
|
730
|
-
"ekashu_callback_success_url"
|
|
731
|
-
]);
|
|
732
|
-
var CARD_KEYS = Object.freeze([
|
|
733
|
-
"ekashu_card_number",
|
|
734
|
-
"ekashu_expires_end_month",
|
|
735
|
-
"ekashu_expires_end_year",
|
|
736
|
-
"ekashu_verification_value",
|
|
737
|
-
"ekashu_valid_from_month",
|
|
738
|
-
"ekashu_valid_from_year",
|
|
739
|
-
"ekashu_issue_number"
|
|
740
|
-
]);
|
|
741
|
-
var PAGE_KEYS = Object.freeze(["ekashu_stage", "ekashu_context", "ekashu_submission_id"]);
|
|
742
|
-
var STORED_KEYS = Object.freeze(["ekashu_card_hash", "ekashu_card_reference", "ekashu_cof_initiated_by", "ekashu_cof_reason", "ekashu_cof_id"]);
|
|
743
|
-
var REDIRECT_KEYS = Object.freeze(["ekashu_success_url", "ekashu_failure_url", "ekashu_return_url"]);
|
|
744
|
-
var CALLBACK_KEYS = Object.freeze(["ekashu_callback_success_url", "ekashu_callback_failure_url"]);
|
|
745
|
-
var MAX_ENTRY = 16 * 1024;
|
|
746
|
-
var MAX_PAGE = 256 * 1024;
|
|
747
|
-
var EKASHU_SELLERS = Object.freeze([
|
|
748
|
-
Object.freeze({ sellerId: "25060100", merchant: "Heathrow Drop-off", entryHost: "heathrowdropoff.apcoa.com", callbackHost: "incomingapi.apcoa.co.uk" })
|
|
749
|
-
]);
|
|
750
|
-
var CARD_FIELDS = Object.freeze({
|
|
751
|
-
number: "ekashu_card_number",
|
|
752
|
-
month: "ekashu_expires_end_month",
|
|
753
|
-
year: "ekashu_expires_end_year",
|
|
754
|
-
cvc: "ekashu_verification_value"
|
|
1795
|
+
const key = chunk.slice(0, eq);
|
|
1796
|
+
if (pairs.has(key))
|
|
1797
|
+
return null;
|
|
1798
|
+
pairs.set(key, chunk.slice(eq + 1));
|
|
1799
|
+
}
|
|
1800
|
+
return pairs;
|
|
1801
|
+
}
|
|
1802
|
+
function paymentwallBodyVerdict(body, url) {
|
|
1803
|
+
if (url !== void 0 && !isPaymentwallTokenUrl(url))
|
|
1804
|
+
return refuse8("paymentwall_url_refused");
|
|
1805
|
+
const pairs = readPairs2(body);
|
|
1806
|
+
if (pairs === null)
|
|
1807
|
+
return refuse8("paymentwall_body_unsupported");
|
|
1808
|
+
if (pairs.has("card[token]") && !pairs.has("card[number]"))
|
|
1809
|
+
return refuse8("paymentwall_saved_card");
|
|
1810
|
+
const keys = Object.keys(SHAPES2);
|
|
1811
|
+
if (pairs.size !== keys.length || !keys.every((key) => pairs.has(key) && SHAPES2[key].test(pairs.get(key)))) {
|
|
1812
|
+
return refuse8("paymentwall_body_unsupported");
|
|
1813
|
+
}
|
|
1814
|
+
if (!luhn3(pairs.get("card[number]")))
|
|
1815
|
+
return refuse8("paymentwall_body_unsupported");
|
|
1816
|
+
if (url !== void 0 && paymentwallKeyEnvironment(pairs.get(KEY)) !== paymentwallUrlEnvironment(url))
|
|
1817
|
+
return refuse8("paymentwall_key_refused");
|
|
1818
|
+
return CARD9;
|
|
1819
|
+
}
|
|
1820
|
+
var paymentwall_default = /* @__PURE__ */ registerProcessor({
|
|
1821
|
+
psp: PAYMENTWALL_PSP,
|
|
1822
|
+
definitions: [
|
|
1823
|
+
{
|
|
1824
|
+
psp: "paymentwall",
|
|
1825
|
+
// Brick's token request, as the header above reads it. A test key's request has its own host, so the device sends
|
|
1826
|
+
// it only Paymentwall's documented test cards (hostEnvironmentPinned, device-replay.js S7). Ships dark: served only
|
|
1827
|
+
// to a client that declares `paymentwall_card_token`, for a company the backend's gate turns it on for
|
|
1828
|
+
// (checkout-processor-gate.ts), and the device sends a live card only under a key a reviewed pin names.
|
|
1829
|
+
capability: "paymentwall_card_token",
|
|
1830
|
+
match: "(?:pwgateway\\.com/api/token|api\\.paymentwall\\.com/api/brick/token)",
|
|
1831
|
+
hosts: ["^pwgateway\\.com$", "^api\\.paymentwall\\.com$"],
|
|
1832
|
+
sandboxHosts: ["^api\\.paymentwall\\.com$"],
|
|
1833
|
+
hostEnvironmentPinned: true,
|
|
1834
|
+
encoding: "form",
|
|
1835
|
+
// Brick's XHR sets the form Content-Type alone, and that always rides. Origin, Referer and cookies never do.
|
|
1836
|
+
passthroughHeaders: [],
|
|
1837
|
+
cardFields: ["card[number]"]
|
|
1838
|
+
}
|
|
1839
|
+
],
|
|
1840
|
+
// Only the cardholder's device sends a card request, after a person approves; no reviewed list names paymentwall.
|
|
1841
|
+
refusedOperations: [PAYMENTWALL_OPERATION],
|
|
1842
|
+
// Not surveyed: the token moves no money, and the charge that spends it happens out of this request.
|
|
1843
|
+
settlementReadback: "not_surveyed",
|
|
1844
|
+
exactUrl: isPaymentwallTokenUrl,
|
|
1845
|
+
bodyGate: (url, body) => paymentwallBodyVerdict(body, url)
|
|
755
1846
|
});
|
|
756
|
-
var NAME_FIELDS = Object.freeze({ first: "ekashu_card_first_name", last: "ekashu_card_last_name" });
|
|
757
|
-
var LEFT_EMPTY = Object.freeze(["ekashu_card_title", "ekashu_valid_from_month", "ekashu_valid_from_year", "ekashu_issue_number"]);
|
|
758
|
-
var VISIBLE = /* @__PURE__ */ new Set([...Object.values(CARD_FIELDS), ...Object.values(NAME_FIELDS), ...LEFT_EMPTY]);
|
|
759
1847
|
// src/processors/payplug.js
|
|
760
1848
|
var PAYPLUG_PSP = "payplug";
|
|
761
1849
|
var PAYPLUG_OPERATION = "payplug.hosted_sale";
|
|
762
1850
|
var PAYPLUG_HOST = "secure.payplug.com";
|
|
763
1851
|
var ENTRY_PATH = /^\/pay\/(?:(test)\/)?([A-Za-z0-9]{22})$/;
|
|
764
|
-
var
|
|
765
|
-
var
|
|
1852
|
+
var MAX_URL3 = 256;
|
|
1853
|
+
var field3 = (name, reason) => ({ ok: false, code: "hosted_form_field_refused", field: name, reason });
|
|
766
1854
|
function payplugEntry(raw) {
|
|
767
|
-
if (typeof raw !== "string" || raw.length >
|
|
1855
|
+
if (typeof raw !== "string" || raw.length > MAX_URL3 || raw.includes("?") || raw.includes("#"))
|
|
768
1856
|
return null;
|
|
769
1857
|
let url;
|
|
770
1858
|
try {
|
|
@@ -786,7 +1874,7 @@ var PAYPLUG_MERCHANTS = Object.freeze([
|
|
|
786
1874
|
]);
|
|
787
1875
|
var ACCOUNT_ID = /^[A-Za-z0-9-]{1,64}$/;
|
|
788
1876
|
function payplugMerchant(checkoutOrigin, merchants = PAYPLUG_MERCHANTS) {
|
|
789
|
-
if (typeof checkoutOrigin !== "string" || checkoutOrigin.length >
|
|
1877
|
+
if (typeof checkoutOrigin !== "string" || checkoutOrigin.length > MAX_URL3 || !Array.isArray(merchants))
|
|
790
1878
|
return null;
|
|
791
1879
|
let url;
|
|
792
1880
|
try {
|
|
@@ -802,16 +1890,16 @@ function payplugMerchant(checkoutOrigin, merchants = PAYPLUG_MERCHANTS) {
|
|
|
802
1890
|
}
|
|
803
1891
|
function checkPayplugEntry(body, { url = null, checkoutOrigin = null, merchants = PAYPLUG_MERCHANTS } = {}) {
|
|
804
1892
|
if (body !== void 0 && body !== null && body !== "")
|
|
805
|
-
return
|
|
1893
|
+
return field3("(body)", "not_an_entry");
|
|
806
1894
|
const entry = payplugEntry(url);
|
|
807
1895
|
if (!entry)
|
|
808
|
-
return
|
|
1896
|
+
return field3("(url)", "malformed_field");
|
|
809
1897
|
const seller = payplugMerchant(checkoutOrigin, merchants);
|
|
810
1898
|
if (!seller)
|
|
811
|
-
return
|
|
1899
|
+
return field3("(checkout_origin)", "seller_unreviewed");
|
|
812
1900
|
return { ok: true, pairs: [], gated: false, dedupe: [entry.id], paymentId: entry.id, sandbox: entry.test, seller };
|
|
813
1901
|
}
|
|
814
|
-
var
|
|
1902
|
+
var MAX_PAGE5 = 512 * 1024;
|
|
815
1903
|
var PAYPLUG_REFUSALS = Object.freeze(["payplug_failed", "payplug_expired", "payplug_cancelled"]);
|
|
816
1904
|
var payplug_default = /* @__PURE__ */ registerProcessor({
|
|
817
1905
|
psp: PAYPLUG_PSP,
|
|
@@ -861,11 +1949,132 @@ var payplug_default = /* @__PURE__ */ registerProcessor({
|
|
|
861
1949
|
"PayPlug sends the buyer to the merchant's return page whether the payment succeeded or not, so the browser receives a submission notice, not the processor result."
|
|
862
1950
|
]
|
|
863
1951
|
});
|
|
1952
|
+
// src/rsa-pkcs1v15.js
|
|
1953
|
+
var TYPED_ARRAY = Object.getPrototypeOf(Uint8Array.prototype);
|
|
1954
|
+
var typedArrayName = Object.getOwnPropertyDescriptor(TYPED_ARRAY, Symbol.toStringTag).get;
|
|
1955
|
+
// src/processors/paystack.js
|
|
1956
|
+
var PAYSTACK_PSP = "paystack";
|
|
1957
|
+
var PAYSTACK_OPERATION = "paystack.card_request";
|
|
1958
|
+
var PAYSTACK_CHARGE_URL = "https://standard.paystack.co/charge/";
|
|
1959
|
+
var PAYSTACK_BODY_KEYS = /* @__PURE__ */ Object.freeze([
|
|
1960
|
+
"clientdata",
|
|
1961
|
+
"last4",
|
|
1962
|
+
"trans",
|
|
1963
|
+
"access_code",
|
|
1964
|
+
"device",
|
|
1965
|
+
"offset",
|
|
1966
|
+
"remember_card",
|
|
1967
|
+
"card_holder_name",
|
|
1968
|
+
"transaction_type"
|
|
1969
|
+
]);
|
|
1970
|
+
var OPTIONAL = /* @__PURE__ */ new Set(["access_code", "card_holder_name", "transaction_type"]);
|
|
1971
|
+
var BODY_LIMIT10 = 4096;
|
|
1972
|
+
var CIPHERTEXT_BYTES = [62, 63, 64];
|
|
1973
|
+
var BASE64 = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
1974
|
+
var SHAPES3 = /* @__PURE__ */ Object.freeze({
|
|
1975
|
+
last4: /^[0-9]{4}$/,
|
|
1976
|
+
trans: /^[0-9]{1,20}$/,
|
|
1977
|
+
access_code: /^[A-Za-z0-9]{1,64}$/,
|
|
1978
|
+
device: /^[\x21-\x7e]{1,512}$/,
|
|
1979
|
+
offset: /^-?[0-9]{1,3}$/,
|
|
1980
|
+
remember_card: /^false$/,
|
|
1981
|
+
// A name carries no digit, so no card number can ride in it.
|
|
1982
|
+
card_holder_name: /^[^\x00-\x1f\x7f0-9]{1,128}$/u,
|
|
1983
|
+
transaction_type: /^[a-z_]{1,32}$/
|
|
1984
|
+
});
|
|
1985
|
+
var own8 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
1986
|
+
var refuse9 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
1987
|
+
function paystackFormValue(value) {
|
|
1988
|
+
return encodeURIComponent(String(value)).replace(/%20/g, "+").replace(/[!'()*~]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
|
|
1989
|
+
}
|
|
1990
|
+
function paystackFormBody(entries) {
|
|
1991
|
+
return entries.map(([key, value]) => `${paystackFormValue(key)}=${paystackFormValue(value)}`).join("&");
|
|
1992
|
+
}
|
|
1993
|
+
function isPaystackChargeUrl(url) {
|
|
1994
|
+
return url === PAYSTACK_CHARGE_URL;
|
|
1995
|
+
}
|
|
1996
|
+
function isCiphertext(value) {
|
|
1997
|
+
if (value.length % 4 !== 0 || !BASE64.test(value))
|
|
1998
|
+
return false;
|
|
1999
|
+
let binary;
|
|
2000
|
+
try {
|
|
2001
|
+
binary = atob(value);
|
|
2002
|
+
}
|
|
2003
|
+
catch {
|
|
2004
|
+
return false;
|
|
2005
|
+
}
|
|
2006
|
+
return btoa(binary) === value && CIPHERTEXT_BYTES.includes(binary.length);
|
|
2007
|
+
}
|
|
2008
|
+
function readForm(body) {
|
|
2009
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT10)
|
|
2010
|
+
return null;
|
|
2011
|
+
const entries = [];
|
|
2012
|
+
for (const part of body.split("&")) {
|
|
2013
|
+
const at = part.indexOf("=");
|
|
2014
|
+
if (at <= 0)
|
|
2015
|
+
return null;
|
|
2016
|
+
try {
|
|
2017
|
+
entries.push([decodeURIComponent(part.slice(0, at).replace(/\+/g, " ")), decodeURIComponent(part.slice(at + 1).replace(/\+/g, " "))]);
|
|
2018
|
+
}
|
|
2019
|
+
catch {
|
|
2020
|
+
return null;
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
return paystackFormBody(entries) === body ? entries : null;
|
|
2024
|
+
}
|
|
2025
|
+
function paystackBodyVerdict(body) {
|
|
2026
|
+
const entries = readForm(body);
|
|
2027
|
+
if (entries === null)
|
|
2028
|
+
return refuse9("paystack_body_unsupported");
|
|
2029
|
+
const keys = entries.map(([key]) => key);
|
|
2030
|
+
if (keys.includes("subscription"))
|
|
2031
|
+
return refuse9("paystack_subscription");
|
|
2032
|
+
if (keys.includes("remember_card") && entries.find(([key]) => key === "remember_card")[1] !== "false")
|
|
2033
|
+
return refuse9("paystack_saved_card");
|
|
2034
|
+
const expected = PAYSTACK_BODY_KEYS.filter((key) => !OPTIONAL.has(key) || keys.includes(key));
|
|
2035
|
+
if (keys.length !== expected.length || keys.some((key, i) => key !== expected[i]))
|
|
2036
|
+
return refuse9("paystack_body_unsupported");
|
|
2037
|
+
const fields = Object.fromEntries(entries);
|
|
2038
|
+
if (!isCiphertext(fields.clientdata))
|
|
2039
|
+
return refuse9("paystack_body_unsupported");
|
|
2040
|
+
for (const [key, shape] of Object.entries(SHAPES3)) {
|
|
2041
|
+
if (own8(fields, key) && !shape.test(fields[key]))
|
|
2042
|
+
return refuse9("paystack_body_unsupported");
|
|
2043
|
+
}
|
|
2044
|
+
return Object.freeze({ verdict: "card", fields: Object.freeze(fields) });
|
|
2045
|
+
}
|
|
2046
|
+
var paystack_default = /* @__PURE__ */ registerProcessor({
|
|
2047
|
+
psp: PAYSTACK_PSP,
|
|
2048
|
+
definitions: [
|
|
2049
|
+
{
|
|
2050
|
+
psp: "paystack",
|
|
2051
|
+
// The card page's charge, as the header above reads it. Live and test transactions share standard.paystack.co,
|
|
2052
|
+
// so no sandbox host is listed and no environment is pinned. Ships dark: served only to a client that declares
|
|
2053
|
+
// `paystack_pinned_key`, and only for a company the backend's processor gate turns Paystack on for.
|
|
2054
|
+
// `(?![\w/.%?#-])` ends the path for a consumer that tests `match` unanchored; the exact-URL rule takes no query.
|
|
2055
|
+
capability: "paystack_pinned_key",
|
|
2056
|
+
match: "standard\\.paystack\\.co/charge/(?![\\w/.%?#-])",
|
|
2057
|
+
hosts: ["^standard\\.paystack\\.co$"],
|
|
2058
|
+
encoding: "form",
|
|
2059
|
+
// The browser's language rides as the page sent it; Origin, Referer and cookies never do (the page sends no cookie).
|
|
2060
|
+
passthroughHeaders: ["^accept-language$"],
|
|
2061
|
+
cardFields: ["clientdata"]
|
|
2062
|
+
}
|
|
2063
|
+
],
|
|
2064
|
+
// Only the cardholder's device sends this charge, after a person approves; no reviewed list names paystack.
|
|
2065
|
+
refusedOperations: [PAYSTACK_OPERATION],
|
|
2066
|
+
// Not surveyed: reading a charge back takes the merchant's secret key, which Agentcard never holds.
|
|
2067
|
+
settlementReadback: "not_surveyed",
|
|
2068
|
+
exactUrl: isPaystackChargeUrl,
|
|
2069
|
+
bodyGate: (url, body) => url !== void 0 && !isPaystackChargeUrl(url) ? refuse9("paystack_url_refused") : paystackBodyVerdict(body),
|
|
2070
|
+
// No amount reader: the charge names none, so the agent's pair is the figure the cardholder approves.
|
|
2071
|
+
limitations: ["The charge names no merchant and no amount: Paystack's transaction binds both, so the cardholder approves the agent's figure for whichever Paystack merchant opened the checkout."]
|
|
2072
|
+
});
|
|
864
2073
|
// src/processors/processout.js
|
|
865
2074
|
var PROCESSOUT_PSP = "processout";
|
|
866
2075
|
var PROCESSOUT_OPERATION = "processout.card_request";
|
|
867
|
-
var
|
|
868
|
-
var
|
|
2076
|
+
var URL_LIMIT4 = 512;
|
|
2077
|
+
var BODY_LIMIT11 = 4096;
|
|
869
2078
|
var CARD_URL = /^https:\/\/api\.processout\.com\/cards\?legacyrequest=true&project_id=((?:test-)?proj_[A-Za-z0-9]{16,64})&x-Content-Type=application\/json&x-API-Version=1\.3\.0\.0&x-Authorization=Basic%20([A-Za-z0-9+/]{4,256}={0,2})$/;
|
|
870
2079
|
var PAGE_KEYS2 = /* @__PURE__ */ Object.freeze(["name", "contact", "preferred_scheme"]);
|
|
871
2080
|
var CONTACT_KEYS = /* @__PURE__ */ Object.freeze(["address1", "address2", "city", "state", "country_code", "zip"]);
|
|
@@ -880,31 +2089,31 @@ var DEVICE_KEYS = /* @__PURE__ */ Object.freeze([
|
|
|
880
2089
|
]);
|
|
881
2090
|
var PROCESSOUT_CARD_KEYS = /* @__PURE__ */ Object.freeze(["number", "exp_month", "exp_year", "cvc2"]);
|
|
882
2091
|
var BODY_KEYS = /* @__PURE__ */ new Set([...PAGE_KEYS2, "device", ...DEVICE_KEYS, ...PROCESSOUT_CARD_KEYS]);
|
|
883
|
-
var
|
|
884
|
-
var
|
|
885
|
-
var
|
|
886
|
-
var
|
|
2092
|
+
var NUMBER3 = /^[0-9]{12,19}$/;
|
|
2093
|
+
var MONTH5 = /^(?:[1-9]|1[0-2])$/;
|
|
2094
|
+
var YEAR5 = /^20[0-9]{2}$/;
|
|
2095
|
+
var CODE2 = /^[0-9]{3,4}$/;
|
|
887
2096
|
var TEXT_LIMIT = 256;
|
|
888
2097
|
var SCHEME = /^[A-Za-z][A-Za-z0-9 _-]{0,31}$/;
|
|
889
2098
|
var LANGUAGE2 = /^[A-Za-z]{1,8}(?:-[A-Za-z0-9]{1,8}){0,4}$/;
|
|
890
2099
|
var PAN_LIKE = /(?:[0-9][^0-9A-Za-z]*){12,}/;
|
|
891
|
-
var
|
|
892
|
-
var
|
|
893
|
-
var
|
|
894
|
-
var
|
|
895
|
-
var
|
|
896
|
-
function base64Of(
|
|
2100
|
+
var record7 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2101
|
+
var own9 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
2102
|
+
var refuse10 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
2103
|
+
var CARD10 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
2104
|
+
var BASE642 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
2105
|
+
function base64Of(text3) {
|
|
897
2106
|
let out = "";
|
|
898
|
-
for (let at = 0; at <
|
|
899
|
-
const a =
|
|
900
|
-
const b = at + 1 <
|
|
901
|
-
const c = at + 2 <
|
|
902
|
-
out +=
|
|
2107
|
+
for (let at = 0; at < text3.length; at += 3) {
|
|
2108
|
+
const a = text3.charCodeAt(at);
|
|
2109
|
+
const b = at + 1 < text3.length ? text3.charCodeAt(at + 1) : NaN;
|
|
2110
|
+
const c = at + 2 < text3.length ? text3.charCodeAt(at + 2) : NaN;
|
|
2111
|
+
out += BASE642[a >> 2] + BASE642[(a & 3) << 4 | (Number.isNaN(b) ? 0 : b >> 4)] + (Number.isNaN(b) ? "=" : BASE642[(b & 15) << 2 | (Number.isNaN(c) ? 0 : c >> 6)]) + (Number.isNaN(c) ? "=" : BASE642[c & 63]);
|
|
903
2112
|
}
|
|
904
2113
|
return out;
|
|
905
2114
|
}
|
|
906
2115
|
var basicOf = (projectId) => base64Of(`${projectId}:`);
|
|
907
|
-
function
|
|
2116
|
+
function luhn4(digits2) {
|
|
908
2117
|
let sum = 0;
|
|
909
2118
|
for (let at = 0; at < digits2.length; at += 1) {
|
|
910
2119
|
let digit = Number(digits2[digits2.length - 1 - at]);
|
|
@@ -918,7 +2127,7 @@ function luhn2(digits2) {
|
|
|
918
2127
|
return sum % 10 === 0;
|
|
919
2128
|
}
|
|
920
2129
|
function processoutCardTarget(url) {
|
|
921
|
-
if (typeof url !== "string" || url.length >
|
|
2130
|
+
if (typeof url !== "string" || url.length > URL_LIMIT4)
|
|
922
2131
|
return null;
|
|
923
2132
|
const match = CARD_URL.exec(url);
|
|
924
2133
|
if (!match || match[2] !== basicOf(match[1]))
|
|
@@ -928,12 +2137,12 @@ function processoutCardTarget(url) {
|
|
|
928
2137
|
function isProcessoutCardUrl(url) {
|
|
929
2138
|
return processoutCardTarget(url) !== null;
|
|
930
2139
|
}
|
|
931
|
-
function
|
|
932
|
-
if (typeof body !== "string" || body === "" || body.length >
|
|
2140
|
+
function readBody8(body) {
|
|
2141
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT11)
|
|
933
2142
|
return null;
|
|
934
2143
|
try {
|
|
935
2144
|
const value = JSON.parse(body);
|
|
936
|
-
return
|
|
2145
|
+
return record7(value) && JSON.stringify(value) === body ? value : null;
|
|
937
2146
|
}
|
|
938
2147
|
catch {
|
|
939
2148
|
return null;
|
|
@@ -951,31 +2160,31 @@ var DEVICE_RULES = /* @__PURE__ */ Object.freeze({
|
|
|
951
2160
|
});
|
|
952
2161
|
function soundDevice(value) {
|
|
953
2162
|
const device = value.device;
|
|
954
|
-
if (!
|
|
2163
|
+
if (!record7(device) || !own9(device, "request_origin") || !own9(device, "app_timezone_offset"))
|
|
955
2164
|
return false;
|
|
956
|
-
return DEVICE_KEYS.every((key) =>
|
|
2165
|
+
return DEVICE_KEYS.every((key) => own9(device, key) ? DEVICE_RULES[key](device[key]) && own9(value, key) && value[key] === device[key] : !own9(value, key)) && Object.keys(device).every((key) => DEVICE_KEYS.includes(key));
|
|
957
2166
|
}
|
|
958
2167
|
function soundPageData(value) {
|
|
959
|
-
if (
|
|
2168
|
+
if (own9(value, "name") && !pageText(value.name))
|
|
960
2169
|
return false;
|
|
961
|
-
if (
|
|
2170
|
+
if (own9(value, "preferred_scheme") && !(value.preferred_scheme === null || typeof value.preferred_scheme === "string" && SCHEME.test(value.preferred_scheme)))
|
|
962
2171
|
return false;
|
|
963
2172
|
const contact = value.contact;
|
|
964
|
-
return
|
|
2173
|
+
return record7(contact) && Object.keys(contact).every((key) => CONTACT_KEYS.includes(key) && pageText(contact[key]));
|
|
965
2174
|
}
|
|
966
2175
|
function processoutBodyVerdict(body, url) {
|
|
967
2176
|
if (url !== void 0 && processoutCardTarget(url) === null)
|
|
968
|
-
return
|
|
969
|
-
const value =
|
|
2177
|
+
return refuse10("processout_url_refused");
|
|
2178
|
+
const value = readBody8(body);
|
|
970
2179
|
if (value === null || !Object.keys(value).every((key) => BODY_KEYS.has(key)))
|
|
971
|
-
return
|
|
2180
|
+
return refuse10("processout_body_unsupported");
|
|
972
2181
|
if (!PROCESSOUT_CARD_KEYS.every((key) => typeof value[key] === "string"))
|
|
973
|
-
return
|
|
974
|
-
if (!
|
|
975
|
-
return
|
|
2182
|
+
return refuse10("processout_body_unsupported");
|
|
2183
|
+
if (!NUMBER3.test(value.number) || !luhn4(value.number) || !MONTH5.test(value.exp_month) || !YEAR5.test(value.exp_year) || !CODE2.test(value.cvc2))
|
|
2184
|
+
return refuse10("processout_body_unsupported");
|
|
976
2185
|
if (!soundPageData(value) || !soundDevice(value))
|
|
977
|
-
return
|
|
978
|
-
return
|
|
2186
|
+
return refuse10("processout_body_unsupported");
|
|
2187
|
+
return CARD10;
|
|
979
2188
|
}
|
|
980
2189
|
var processout_default = /* @__PURE__ */ registerProcessor({
|
|
981
2190
|
psp: PROCESSOUT_PSP,
|
|
@@ -1018,17 +2227,17 @@ var USAEPAY_HOSTS = /* @__PURE__ */ Object.freeze({
|
|
|
1018
2227
|
"sandbox.usaepay.com": "sandbox"
|
|
1019
2228
|
});
|
|
1020
2229
|
var USAEPAY_PAYMENT_KEYS_PATH = "/api/v2/pub/payment_keys";
|
|
1021
|
-
var
|
|
1022
|
-
var
|
|
1023
|
-
var
|
|
2230
|
+
var BODY_LIMIT12 = 512;
|
|
2231
|
+
var URL_LIMIT5 = 256;
|
|
2232
|
+
var CARD_NUMBER5 = /^[0-9]{13,19}$/;
|
|
1024
2233
|
var EXPIRATION = /^(?:0[1-9]|1[0-2])[0-9]{2}$/;
|
|
1025
|
-
var
|
|
1026
|
-
var
|
|
1027
|
-
var
|
|
1028
|
-
var
|
|
1029
|
-
var
|
|
2234
|
+
var SECURITY_CODE5 = /^(?:[0-9]{3,4})?$/;
|
|
2235
|
+
var record8 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2236
|
+
var own10 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
2237
|
+
var refuse11 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
2238
|
+
var CARD11 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
1030
2239
|
function usaepayPaymentKeysUrl(url) {
|
|
1031
|
-
if (typeof url !== "string" || url.length >
|
|
2240
|
+
if (typeof url !== "string" || url.length > URL_LIMIT5 || url.includes("?") || url.includes("#"))
|
|
1032
2241
|
return null;
|
|
1033
2242
|
let parsed;
|
|
1034
2243
|
try {
|
|
@@ -1037,12 +2246,12 @@ function usaepayPaymentKeysUrl(url) {
|
|
|
1037
2246
|
catch {
|
|
1038
2247
|
return null;
|
|
1039
2248
|
}
|
|
1040
|
-
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !
|
|
2249
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !own10(USAEPAY_HOSTS, parsed.hostname) || parsed.pathname !== USAEPAY_PAYMENT_KEYS_PATH)
|
|
1041
2250
|
return null;
|
|
1042
2251
|
return Object.freeze({ host: parsed.hostname, environment: USAEPAY_HOSTS[parsed.hostname] });
|
|
1043
2252
|
}
|
|
1044
2253
|
var isUsaepayPaymentKeysUrl = (url) => usaepayPaymentKeysUrl(url) !== null;
|
|
1045
|
-
function
|
|
2254
|
+
function luhn5(digits2) {
|
|
1046
2255
|
let sum = 0;
|
|
1047
2256
|
for (let at = digits2.length - 1, double = false; at >= 0; at -= 1, double = !double) {
|
|
1048
2257
|
let digit = digits2.charCodeAt(at) - 48;
|
|
@@ -1052,23 +2261,23 @@ function luhn3(digits2) {
|
|
|
1052
2261
|
}
|
|
1053
2262
|
return sum % 10 === 0;
|
|
1054
2263
|
}
|
|
1055
|
-
function
|
|
1056
|
-
if (typeof body !== "string" || body === "" || body.length >
|
|
2264
|
+
function readBody9(body) {
|
|
2265
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT12)
|
|
1057
2266
|
return null;
|
|
1058
2267
|
try {
|
|
1059
2268
|
const value = JSON.parse(body);
|
|
1060
|
-
return
|
|
2269
|
+
return record8(value) && JSON.stringify(value) === body ? value : null;
|
|
1061
2270
|
}
|
|
1062
2271
|
catch {
|
|
1063
2272
|
return null;
|
|
1064
2273
|
}
|
|
1065
2274
|
}
|
|
1066
2275
|
function usaepayBodyVerdict(body) {
|
|
1067
|
-
const value =
|
|
2276
|
+
const value = readBody9(body);
|
|
1068
2277
|
const card = value === null ? null : value.creditcard;
|
|
1069
|
-
if (value === null || Object.keys(value).join() !== "creditcard" || !
|
|
1070
|
-
return
|
|
1071
|
-
return
|
|
2278
|
+
if (value === null || Object.keys(value).join() !== "creditcard" || !record8(card) || Object.keys(card).join() !== "number,expiration,cvc" || typeof card.number !== "string" || !CARD_NUMBER5.test(card.number) || !luhn5(card.number) || typeof card.expiration !== "string" || !EXPIRATION.test(card.expiration) || typeof card.cvc !== "string" || !SECURITY_CODE5.test(card.cvc))
|
|
2279
|
+
return refuse11("usaepay_body_unsupported");
|
|
2280
|
+
return CARD11;
|
|
1072
2281
|
}
|
|
1073
2282
|
var usaepay_default = /* @__PURE__ */ registerProcessor({
|
|
1074
2283
|
psp: USAEPAY_PSP,
|
|
@@ -1100,9 +2309,204 @@ var usaepay_default = /* @__PURE__ */ registerProcessor({
|
|
|
1100
2309
|
source: "https://help.usaepay.info/developer/payjs-v2/ , https://help.usaepay.info/api/rest/"
|
|
1101
2310
|
},
|
|
1102
2311
|
exactUrl: isUsaepayPaymentKeysUrl,
|
|
1103
|
-
bodyGate: (url, body) => url !== void 0 && !isUsaepayPaymentKeysUrl(url) ?
|
|
2312
|
+
bodyGate: (url, body) => url !== void 0 && !isUsaepayPaymentKeysUrl(url) ? refuse11("usaepay_url_refused") : usaepayBodyVerdict(body)
|
|
1104
2313
|
// No amount reader: the request names none, so the agent's pair is the figure the cardholder approves.
|
|
1105
2314
|
});
|
|
2315
|
+
// src/processors/viva_wallet.js
|
|
2316
|
+
var VIVA_WALLET_PSP = "viva_wallet";
|
|
2317
|
+
var VIVA_WALLET_OPERATION = "viva_wallet.card_request";
|
|
2318
|
+
var VIVA_WALLET_HOSTS = /* @__PURE__ */ Object.freeze({ "www.vivapayments.com": "production", "demo.vivapayments.com": "sandbox" });
|
|
2319
|
+
var VIVA_WALLET_CHARGE_TOKENS_PATH = "/web2/checkout/v2/chargetokens";
|
|
2320
|
+
var VIVA_WALLET_BODY_KEYS = /* @__PURE__ */ Object.freeze([
|
|
2321
|
+
"orderCode",
|
|
2322
|
+
"amount",
|
|
2323
|
+
"currencyCode",
|
|
2324
|
+
"holderName",
|
|
2325
|
+
"holderMail",
|
|
2326
|
+
"cvc",
|
|
2327
|
+
"number",
|
|
2328
|
+
"expirationMonth",
|
|
2329
|
+
"expirationYear",
|
|
2330
|
+
"installments",
|
|
2331
|
+
"customer",
|
|
2332
|
+
"rememberCard",
|
|
2333
|
+
"friendlyName",
|
|
2334
|
+
"maskedNumber",
|
|
2335
|
+
"bankId",
|
|
2336
|
+
"selectedBrand",
|
|
2337
|
+
"cardholderBrandSelection",
|
|
2338
|
+
"dccOptions",
|
|
2339
|
+
"dccAccepted",
|
|
2340
|
+
"offerCodes",
|
|
2341
|
+
"loyaltySupported",
|
|
2342
|
+
"redeemedAmount",
|
|
2343
|
+
"retrievalReferenceNumber",
|
|
2344
|
+
"scaRequestedTransactionId",
|
|
2345
|
+
"merchantTrns",
|
|
2346
|
+
"captchaToken"
|
|
2347
|
+
]);
|
|
2348
|
+
var BODY_LIMIT13 = 16384;
|
|
2349
|
+
var URL_LIMIT6 = 256;
|
|
2350
|
+
var ORDER_CODE = /^[0-9]{16}$/;
|
|
2351
|
+
var CARD_NUMBER6 = /^[0-9]{13,19}$/;
|
|
2352
|
+
var MONTH6 = /^(?:0[1-9]|1[0-2])$/;
|
|
2353
|
+
var YEAR6 = /^[0-9]{2}$/;
|
|
2354
|
+
var SECURITY_CODE6 = /^[0-9]{3,4}$/;
|
|
2355
|
+
var CAPTCHA_TOKEN = /^[A-Za-z0-9_.-]{20,8192}$/;
|
|
2356
|
+
var MEMBER_NAME = /^[A-Za-z][A-Za-z0-9]{0,31}$/;
|
|
2357
|
+
var SHORT_ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
2358
|
+
var TEXT = /^[^\u0000-\u001f\u007f]{0,200}$/;
|
|
2359
|
+
var CARD_DIGITS = /[0-9]{12,}/;
|
|
2360
|
+
var record9 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2361
|
+
var own11 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
2362
|
+
var refuse12 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
2363
|
+
var CARD12 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
2364
|
+
var inOrder4 = (value, keys) => {
|
|
2365
|
+
let at = 0;
|
|
2366
|
+
for (const name of Object.keys(value)) {
|
|
2367
|
+
while (at < keys.length && keys[at] !== name)
|
|
2368
|
+
at += 1;
|
|
2369
|
+
if (at === keys.length)
|
|
2370
|
+
return false;
|
|
2371
|
+
at += 1;
|
|
2372
|
+
}
|
|
2373
|
+
return true;
|
|
2374
|
+
};
|
|
2375
|
+
var cardDigits = (text3) => CARD_DIGITS.test(text3.replace(/[^0-9A-Za-z]/g, ""));
|
|
2376
|
+
var plainText = (value) => typeof value === "string" && TEXT.test(value) && !cardDigits(value);
|
|
2377
|
+
var scalar = (value) => value === null || typeof value === "boolean" || Number.isSafeInteger(value) && Math.abs(value) < 1e9 || plainText(value);
|
|
2378
|
+
var flatRecord = (value, limit) => record9(value) && Object.keys(value).length <= limit && Object.entries(value).every(([key, item]) => MEMBER_NAME.test(key) && scalar(item));
|
|
2379
|
+
function vivaWalletChargeTokensUrl(url) {
|
|
2380
|
+
if (typeof url !== "string" || url.length > URL_LIMIT6 || url.includes("?") || url.includes("#"))
|
|
2381
|
+
return null;
|
|
2382
|
+
let parsed;
|
|
2383
|
+
try {
|
|
2384
|
+
parsed = new URL(url);
|
|
2385
|
+
}
|
|
2386
|
+
catch {
|
|
2387
|
+
return null;
|
|
2388
|
+
}
|
|
2389
|
+
if (parsed.href !== url || parsed.protocol !== "https:" || parsed.port || parsed.username || parsed.password || !own11(VIVA_WALLET_HOSTS, parsed.hostname) || parsed.pathname !== VIVA_WALLET_CHARGE_TOKENS_PATH)
|
|
2390
|
+
return null;
|
|
2391
|
+
return Object.freeze({ host: parsed.hostname, environment: VIVA_WALLET_HOSTS[parsed.hostname] });
|
|
2392
|
+
}
|
|
2393
|
+
var isVivaWalletChargeTokensUrl = (url) => vivaWalletChargeTokensUrl(url) !== null;
|
|
2394
|
+
function luhn6(digits2) {
|
|
2395
|
+
let sum = 0;
|
|
2396
|
+
for (let at = digits2.length - 1, double = false; at >= 0; at -= 1, double = !double) {
|
|
2397
|
+
let digit = digits2.charCodeAt(at) - 48;
|
|
2398
|
+
if (double)
|
|
2399
|
+
digit = digit * 2 > 9 ? digit * 2 - 9 : digit * 2;
|
|
2400
|
+
sum += digit;
|
|
2401
|
+
}
|
|
2402
|
+
return sum % 10 === 0;
|
|
2403
|
+
}
|
|
2404
|
+
function vivaWalletMaskedNumber(number) {
|
|
2405
|
+
return `${number.slice(0, 6)}${"X".repeat(Math.max(0, number.length - 10))}${number.slice(-4)}`;
|
|
2406
|
+
}
|
|
2407
|
+
function readBody10(body) {
|
|
2408
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT13)
|
|
2409
|
+
return null;
|
|
2410
|
+
try {
|
|
2411
|
+
const value = JSON.parse(body);
|
|
2412
|
+
return record9(value) && JSON.stringify(value) === body ? value : null;
|
|
2413
|
+
}
|
|
2414
|
+
catch {
|
|
2415
|
+
return null;
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2418
|
+
function currencyNumber(value) {
|
|
2419
|
+
if (Number.isSafeInteger(value) && value > 0 && value < 1e3)
|
|
2420
|
+
return value;
|
|
2421
|
+
return typeof value === "string" && /^[0-9]{3}$/.test(value) ? Number(value) : null;
|
|
2422
|
+
}
|
|
2423
|
+
function vivaWalletBodyVerdict(body) {
|
|
2424
|
+
const value = readBody10(body);
|
|
2425
|
+
if (value === null || !Object.keys(value).every((key) => VIVA_WALLET_BODY_KEYS.includes(key))) {
|
|
2426
|
+
return value !== null && (own11(value, "creditCardId") || own11(value, "token")) ? refuse12("viva_wallet_stored_card") : refuse12("viva_wallet_body_unsupported");
|
|
2427
|
+
}
|
|
2428
|
+
if (value.rememberCard !== false)
|
|
2429
|
+
return refuse12(value.rememberCard === true ? "viva_wallet_keep_on_file" : "viva_wallet_body_unsupported");
|
|
2430
|
+
if (value.dccAccepted === true)
|
|
2431
|
+
return refuse12("viva_wallet_currency_conversion");
|
|
2432
|
+
if (own11(value, "dccAccepted") && value.dccAccepted !== false)
|
|
2433
|
+
return refuse12("viva_wallet_body_unsupported");
|
|
2434
|
+
if (own11(value, "scaRequestedTransactionId"))
|
|
2435
|
+
return refuse12("viva_wallet_retry_refused");
|
|
2436
|
+
if (!(value.installments === 0 || value.installments === 1)) {
|
|
2437
|
+
return refuse12(Number.isSafeInteger(value.installments) && value.installments > 1 ? "viva_wallet_installments" : "viva_wallet_body_unsupported");
|
|
2438
|
+
}
|
|
2439
|
+
if (!inOrder4(value, VIVA_WALLET_BODY_KEYS) || ["offerCodes", "loyaltySupported", "redeemedAmount", "retrievalReferenceNumber", "merchantTrns"].some((key) => own11(value, key)))
|
|
2440
|
+
return refuse12("viva_wallet_body_unsupported");
|
|
2441
|
+
const number = value.number;
|
|
2442
|
+
const sound = typeof value.orderCode === "string" && ORDER_CODE.test(value.orderCode) && Number.isSafeInteger(value.amount) && value.amount > 0 && currencyNumber(value.currencyCode) !== null && plainText(value.holderName) && value.holderName.trim() !== "" && plainText(value.holderMail) && (value.cvc === null || typeof value.cvc === "string" && SECURITY_CODE6.test(value.cvc)) && typeof number === "string" && CARD_NUMBER6.test(number) && luhn6(number) && typeof value.expirationMonth === "string" && MONTH6.test(value.expirationMonth) && typeof value.expirationYear === "string" && YEAR6.test(value.expirationYear) && flatRecord(value.customer, 12) && (!own11(value, "friendlyName") || plainText(value.friendlyName)) && value.maskedNumber === vivaWalletMaskedNumber(number) && (!own11(value, "bankId") || typeof value.bankId === "string" && SHORT_ID.test(value.bankId) || Number.isSafeInteger(value.bankId) && value.bankId >= 0) && (!own11(value, "selectedBrand") || value.selectedBrand === null || flatRecord(value.selectedBrand, 16)) && (!own11(value, "cardholderBrandSelection") || typeof value.cardholderBrandSelection === "boolean") && (!own11(value, "dccOptions") || flatRecord(value.dccOptions, 16)) && (!own11(value, "captchaToken") || typeof value.captchaToken === "string" && CAPTCHA_TOKEN.test(value.captchaToken));
|
|
2443
|
+
return sound ? CARD12 : refuse12("viva_wallet_body_unsupported");
|
|
2444
|
+
}
|
|
2445
|
+
var VIVA_WALLET_CURRENCIES = /* @__PURE__ */ Object.freeze({
|
|
2446
|
+
978: "eur",
|
|
2447
|
+
826: "gbp",
|
|
2448
|
+
946: "ron",
|
|
2449
|
+
985: "pln",
|
|
2450
|
+
203: "czk",
|
|
2451
|
+
348: "huf",
|
|
2452
|
+
752: "sek",
|
|
2453
|
+
208: "dkk"
|
|
2454
|
+
});
|
|
2455
|
+
function vivaWalletAmount(body) {
|
|
2456
|
+
if (vivaWalletBodyVerdict(body).verdict !== "card")
|
|
2457
|
+
return null;
|
|
2458
|
+
const value = JSON.parse(body);
|
|
2459
|
+
const currency = VIVA_WALLET_CURRENCIES[currencyNumber(value.currencyCode)];
|
|
2460
|
+
return currency ? { amountCents: value.amount, currency } : null;
|
|
2461
|
+
}
|
|
2462
|
+
var VIVA_WALLET_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
2463
|
+
Object.freeze({
|
|
2464
|
+
id: "klimaka_donation",
|
|
2465
|
+
merchant: "Klimaka",
|
|
2466
|
+
tradeName: "ΚΛΙΜΑΚΑ ΑΜΚΕ",
|
|
2467
|
+
orderCodes: Object.freeze(["7871752880772607"]),
|
|
2468
|
+
origin: "https://www.vivapayments.com",
|
|
2469
|
+
currencyCode: 978
|
|
2470
|
+
}),
|
|
2471
|
+
Object.freeze({
|
|
2472
|
+
id: "desmos_donation",
|
|
2473
|
+
merchant: "Desmos",
|
|
2474
|
+
tradeName: "DESMOS",
|
|
2475
|
+
orderCodes: Object.freeze(["8156257435672606"]),
|
|
2476
|
+
origin: "https://www.vivapayments.com",
|
|
2477
|
+
currencyCode: 978
|
|
2478
|
+
})
|
|
2479
|
+
]);
|
|
2480
|
+
var CARD_MEMBERS = Object.freeze(["cvc", "number", "expirationMonth", "expirationYear", "maskedNumber"]);
|
|
2481
|
+
var viva_wallet_default = /* @__PURE__ */ registerProcessor({
|
|
2482
|
+
psp: VIVA_WALLET_PSP,
|
|
2483
|
+
definitions: [
|
|
2484
|
+
{
|
|
2485
|
+
psp: "viva_wallet",
|
|
2486
|
+
// The page's card request, as the header above reads it. demo.vivapayments.com is Viva's sandbox, pinned to test
|
|
2487
|
+
// rows, which send only Viva's documented test cards (hostEnvironmentPinned, device-replay.js S7).
|
|
2488
|
+
// Ships dark: served only to a client that declares `viva_smart_checkout_chargetoken`, and only for a company the
|
|
2489
|
+
// backend's processor gate turns Viva Wallet on for. `(?![\w/.%-])` ends the path for a consumer that tests `match`
|
|
2490
|
+
// unanchored.
|
|
2491
|
+
capability: "viva_smart_checkout_chargetoken",
|
|
2492
|
+
match: "(?:www|demo)\\.vivapayments\\.com/web2/checkout/v2/chargetokens(?![\\w/.%-])",
|
|
2493
|
+
hosts: ["^www\\.vivapayments\\.com$", "^demo\\.vivapayments\\.com$"],
|
|
2494
|
+
sandboxHosts: ["^demo\\.vivapayments\\.com$"],
|
|
2495
|
+
hostEnvironmentPinned: true,
|
|
2496
|
+
encoding: "json",
|
|
2497
|
+
// The page sends no Authorization; Origin, Referer, cookies and the reCAPTCHA state never ride.
|
|
2498
|
+
passthroughHeaders: [],
|
|
2499
|
+
jsonCardFields: [["number"]]
|
|
2500
|
+
}
|
|
2501
|
+
],
|
|
2502
|
+
// Only the cardholder's device sends this card, after a person approves; no reviewed list names viva_wallet.
|
|
2503
|
+
refusedOperations: [VIVA_WALLET_OPERATION],
|
|
2504
|
+
settlementReadback: "not_surveyed",
|
|
2505
|
+
exactUrl: isVivaWalletChargeTokensUrl,
|
|
2506
|
+
bodyGate: (url, body) => url !== void 0 && !isVivaWalletChargeTokensUrl(url) ? refuse12("viva_wallet_url_refused") : vivaWalletBodyVerdict(body),
|
|
2507
|
+
// The body names the order's amount in cents and its numeric currency, which the page's card-free charge repeats.
|
|
2508
|
+
amount: (template) => record9(template) && isVivaWalletChargeTokensUrl(template.url) ? vivaWalletAmount(template.body) : null
|
|
2509
|
+
});
|
|
1106
2510
|
// src/processors/vtex_payments.js
|
|
1107
2511
|
var VTEX_PAYMENTS_PSP = "vtex_payments";
|
|
1108
2512
|
var VTEX_PAYMENTS_OPERATION = "vtex_payments.card_request";
|
|
@@ -1151,27 +2555,27 @@ var VTEX_PAYMENTS_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
|
1151
2555
|
Object.freeze({ account: "alssports", origin: "https://www.als.com", merchant: "Al's Sporting Goods", currency: "USD" }),
|
|
1152
2556
|
Object.freeze({ account: "roadrunnersports", origin: "https://www.roadrunnersports.com", merchant: "Road Runner Sports", currency: "USD" })
|
|
1153
2557
|
]);
|
|
1154
|
-
var
|
|
2558
|
+
var BODY_LIMIT14 = 16384;
|
|
1155
2559
|
var ACCOUNT_HOST = /^([a-z0-9]{1,63})\.vtexvault\.com$/;
|
|
1156
2560
|
var PATH = /^\/api\/payments\/transactions\/([0-9A-Fa-f]{32})\/payments$/;
|
|
1157
2561
|
var ORDER_GROUP = /^[0-9]{6,24}$/;
|
|
1158
|
-
var
|
|
1159
|
-
var
|
|
1160
|
-
var
|
|
2562
|
+
var BASE643 = /^[A-Za-z0-9+/]{4,1020}={0,2}$/;
|
|
2563
|
+
var CARD_NUMBER7 = /^[0-9]{12,19}$/;
|
|
2564
|
+
var SECURITY_CODE7 = /^[0-9]{3,4}$/;
|
|
1161
2565
|
var DUE_DATE = /^(?:0[1-9]|1[0-2])\/[0-9]{2}$/;
|
|
1162
|
-
var
|
|
2566
|
+
var CURRENCY2 = /^[A-Z]{3}$/;
|
|
1163
2567
|
var TRANSACTION_ID = /^[0-9A-Fa-f]{32}$/;
|
|
1164
2568
|
var MERCHANT_NAME = /^[A-Za-z0-9_.-]{1,64}$/;
|
|
1165
|
-
var
|
|
2569
|
+
var SHORT_ID2 = /^[A-Za-z0-9_-]{1,64}$/;
|
|
1166
2570
|
var FINGERPRINT = /^[A-Za-z0-9_.:=+/-]{1,256}$/;
|
|
1167
|
-
var
|
|
1168
|
-
var
|
|
2571
|
+
var TEXT2 = /^[^\u0000-\u001f\u007f]{1,200}$/;
|
|
2572
|
+
var CARD_DIGITS2 = /[0-9]{12,}/;
|
|
1169
2573
|
var DEVICE_INFO_KEYS = Object.freeze(["sw", "sh", "cd", "tz", "lang", "java", "sourceApplication"]);
|
|
1170
|
-
var
|
|
1171
|
-
var
|
|
1172
|
-
var
|
|
1173
|
-
var
|
|
1174
|
-
var
|
|
2574
|
+
var record10 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2575
|
+
var own12 = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
2576
|
+
var refuse13 = (code) => Object.freeze({ verdict: "refuse", code });
|
|
2577
|
+
var CARD13 = /* @__PURE__ */ Object.freeze({ verdict: "card" });
|
|
2578
|
+
var inOrder5 = (value, keys) => {
|
|
1175
2579
|
let at = 0;
|
|
1176
2580
|
for (const name of Object.keys(value)) {
|
|
1177
2581
|
while (at < keys.length && keys[at] !== name)
|
|
@@ -1182,8 +2586,8 @@ var inOrder3 = (value, keys) => {
|
|
|
1182
2586
|
}
|
|
1183
2587
|
return true;
|
|
1184
2588
|
};
|
|
1185
|
-
var
|
|
1186
|
-
var
|
|
2589
|
+
var cardDigits2 = (text3) => CARD_DIGITS2.test(text3.replace(/[^0-9A-Za-z]/g, ""));
|
|
2590
|
+
var plainText2 = (value) => typeof value === "string" && TEXT2.test(value) && !cardDigits2(value);
|
|
1187
2591
|
var count = (value) => Number.isSafeInteger(value) && value >= 0;
|
|
1188
2592
|
var BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
1189
2593
|
function base64Text(input) {
|
|
@@ -1207,10 +2611,10 @@ function base64Text(input) {
|
|
|
1207
2611
|
}
|
|
1208
2612
|
return out;
|
|
1209
2613
|
}
|
|
1210
|
-
function deviceInfoSound(
|
|
1211
|
-
if (typeof
|
|
2614
|
+
function deviceInfoSound(text3) {
|
|
2615
|
+
if (typeof text3 !== "string" || !BASE643.test(text3))
|
|
1212
2616
|
return false;
|
|
1213
|
-
const decoded = base64Text(
|
|
2617
|
+
const decoded = base64Text(text3);
|
|
1214
2618
|
if (decoded === null)
|
|
1215
2619
|
return false;
|
|
1216
2620
|
let info;
|
|
@@ -1220,18 +2624,18 @@ function deviceInfoSound(text2) {
|
|
|
1220
2624
|
catch {
|
|
1221
2625
|
return false;
|
|
1222
2626
|
}
|
|
1223
|
-
if (!
|
|
2627
|
+
if (!record10(info) || !Object.keys(info).every((key) => DEVICE_INFO_KEYS.includes(key)))
|
|
1224
2628
|
return false;
|
|
1225
2629
|
for (const key of ["sw", "sh", "cd"])
|
|
1226
|
-
if (
|
|
2630
|
+
if (own12(info, key) && !(count(info[key]) && info[key] <= 1e5))
|
|
1227
2631
|
return false;
|
|
1228
|
-
if (
|
|
2632
|
+
if (own12(info, "tz") && !(Number.isSafeInteger(info.tz) && Math.abs(info.tz) <= 1440))
|
|
1229
2633
|
return false;
|
|
1230
|
-
if (
|
|
2634
|
+
if (own12(info, "lang") && !(typeof info.lang === "string" && /^[A-Za-z]{0,8}$/.test(info.lang)))
|
|
1231
2635
|
return false;
|
|
1232
|
-
if (
|
|
2636
|
+
if (own12(info, "java") && typeof info.java !== "boolean")
|
|
1233
2637
|
return false;
|
|
1234
|
-
return !
|
|
2638
|
+
return !own12(info, "sourceApplication") || typeof info.sourceApplication === "string" && /^[A-Za-z0-9_.-]{1,32}$/.test(info.sourceApplication);
|
|
1235
2639
|
}
|
|
1236
2640
|
function vtexPaymentsCardTarget(url) {
|
|
1237
2641
|
if (typeof url !== "string" || url.length > 8192)
|
|
@@ -1277,8 +2681,8 @@ function isVtexPaymentsCardUrl(url) {
|
|
|
1277
2681
|
const target = vtexPaymentsCardTarget(url);
|
|
1278
2682
|
return target !== null && !target.fallback;
|
|
1279
2683
|
}
|
|
1280
|
-
function
|
|
1281
|
-
if (typeof body !== "string" || body === "" || body.length >
|
|
2684
|
+
function readBody11(body) {
|
|
2685
|
+
if (typeof body !== "string" || body === "" || body.length > BODY_LIMIT14)
|
|
1282
2686
|
return null;
|
|
1283
2687
|
let value;
|
|
1284
2688
|
try {
|
|
@@ -1292,13 +2696,13 @@ function readBody6(body) {
|
|
|
1292
2696
|
return value;
|
|
1293
2697
|
}
|
|
1294
2698
|
function cardLine(line) {
|
|
1295
|
-
if (!
|
|
2699
|
+
if (!record10(line))
|
|
1296
2700
|
return false;
|
|
1297
|
-
const fields =
|
|
1298
|
-
return line.groupName === "creditCardPaymentGroup" || line.groupName === "debitCardPaymentGroup" ||
|
|
2701
|
+
const fields = record10(line.fields) ? line.fields : {};
|
|
2702
|
+
return line.groupName === "creditCardPaymentGroup" || line.groupName === "debitCardPaymentGroup" || own12(line, "accountId") || own12(fields, "accountId") || own12(fields, "cardNumber") || own12(fields, "validationCode") || own12(fields, "dueDate");
|
|
1299
2703
|
}
|
|
1300
2704
|
function addressSound(address) {
|
|
1301
|
-
if (!
|
|
2705
|
+
if (!record10(address) || !inOrder5(address, VTEX_PAYMENTS_ADDRESS_KEYS))
|
|
1302
2706
|
return false;
|
|
1303
2707
|
for (const [key, value] of Object.entries(address)) {
|
|
1304
2708
|
if (key === "addressType") {
|
|
@@ -1307,60 +2711,60 @@ function addressSound(address) {
|
|
|
1307
2711
|
continue;
|
|
1308
2712
|
}
|
|
1309
2713
|
if (key === "addressId") {
|
|
1310
|
-
if (!(typeof value === "string" &&
|
|
2714
|
+
if (!(typeof value === "string" && SHORT_ID2.test(value)))
|
|
1311
2715
|
return false;
|
|
1312
2716
|
continue;
|
|
1313
2717
|
}
|
|
1314
2718
|
if (value === null && (key === "complement" || key === "reference"))
|
|
1315
2719
|
continue;
|
|
1316
|
-
if (!(value === "" ||
|
|
2720
|
+
if (!(value === "" || plainText2(value)))
|
|
1317
2721
|
return false;
|
|
1318
2722
|
}
|
|
1319
2723
|
return true;
|
|
1320
2724
|
}
|
|
1321
2725
|
function fieldsSound(fields) {
|
|
1322
|
-
if (!
|
|
2726
|
+
if (!record10(fields) || !inOrder5(fields, VTEX_PAYMENTS_FIELD_KEYS) || own12(fields, "metadata"))
|
|
1323
2727
|
return false;
|
|
1324
|
-
if (!(typeof fields.cardNumber === "string" &&
|
|
2728
|
+
if (!(typeof fields.cardNumber === "string" && CARD_NUMBER7.test(fields.cardNumber)))
|
|
1325
2729
|
return false;
|
|
1326
|
-
if (!(typeof fields.validationCode === "string" &&
|
|
2730
|
+
if (!(typeof fields.validationCode === "string" && SECURITY_CODE7.test(fields.validationCode)))
|
|
1327
2731
|
return false;
|
|
1328
2732
|
if (!(typeof fields.dueDate === "string" && DUE_DATE.test(fields.dueDate)))
|
|
1329
2733
|
return false;
|
|
1330
|
-
if (!
|
|
2734
|
+
if (!plainText2(fields.holderName))
|
|
1331
2735
|
return false;
|
|
1332
|
-
if (
|
|
2736
|
+
if (own12(fields, "document") && !(fields.document === "" || plainText2(fields.document) && fields.document.length <= 32))
|
|
1333
2737
|
return false;
|
|
1334
|
-
if (
|
|
2738
|
+
if (own12(fields, "address") && !addressSound(fields.address))
|
|
1335
2739
|
return false;
|
|
1336
|
-
if (
|
|
2740
|
+
if (own12(fields, "deviceFingerprint") && !(typeof fields.deviceFingerprint === "string" && FINGERPRINT.test(fields.deviceFingerprint)))
|
|
1337
2741
|
return false;
|
|
1338
|
-
return !
|
|
2742
|
+
return !own12(fields, "addressId") || typeof fields.addressId === "string" && SHORT_ID2.test(fields.addressId);
|
|
1339
2743
|
}
|
|
1340
2744
|
function vtexPaymentsBodyVerdict(body, target) {
|
|
1341
|
-
const lines =
|
|
1342
|
-
if (lines === null || lines.length === 0 || !lines.every(
|
|
1343
|
-
return
|
|
2745
|
+
const lines = readBody11(body);
|
|
2746
|
+
if (lines === null || lines.length === 0 || !lines.every(record10))
|
|
2747
|
+
return refuse13("vtex_payments_body_unsupported");
|
|
1344
2748
|
const cards = lines.filter(cardLine);
|
|
1345
|
-
if (cards.some((line2) =>
|
|
1346
|
-
return
|
|
2749
|
+
if (cards.some((line2) => own12(line2, "accountId") || own12(line2.fields ?? {}, "accountId")))
|
|
2750
|
+
return refuse13("vtex_payments_saved_card");
|
|
1347
2751
|
if (cards.length === 0)
|
|
1348
|
-
return
|
|
1349
|
-
if (lines.length !== 1 ||
|
|
1350
|
-
return
|
|
2752
|
+
return refuse13("vtex_payments_body_unsupported");
|
|
2753
|
+
if (lines.length !== 1 || own12(lines[0], "id"))
|
|
2754
|
+
return refuse13("vtex_payments_split_payment");
|
|
1351
2755
|
const line = lines[0];
|
|
1352
|
-
if (!
|
|
1353
|
-
return
|
|
1354
|
-
if (!(typeof line.currencyCode === "string" &&
|
|
1355
|
-
return
|
|
1356
|
-
if (line.installments !== 1 || line.referenceValue !== line.value ||
|
|
1357
|
-
return
|
|
2756
|
+
if (!inOrder5(line, VTEX_PAYMENTS_LINE_KEYS) || line.groupName !== "creditCardPaymentGroup")
|
|
2757
|
+
return refuse13("vtex_payments_body_unsupported");
|
|
2758
|
+
if (!(typeof line.currencyCode === "string" && CURRENCY2.test(line.currencyCode)) || !own12(VTEX_PAYMENTS_NETWORKS, line.paymentSystem) || !Number.isSafeInteger(line.paymentSystem) || !(count(line.value) && line.value > 0))
|
|
2759
|
+
return refuse13("vtex_payments_body_unsupported");
|
|
2760
|
+
if (line.installments !== 1 || line.referenceValue !== line.value || own12(line, "installmentsInterestRate") && line.installmentsInterestRate !== 0 || own12(line, "installmentsValue") && line.installmentsValue !== line.value)
|
|
2761
|
+
return refuse13("vtex_payments_installments");
|
|
1358
2762
|
const transaction = line.transaction;
|
|
1359
|
-
if (!
|
|
1360
|
-
return
|
|
2763
|
+
if (!record10(transaction) || Object.keys(transaction).join() !== "id,merchantName" || !(typeof transaction.id === "string" && TRANSACTION_ID.test(transaction.id)) || !(typeof transaction.merchantName === "string" && MERCHANT_NAME.test(transaction.merchantName)))
|
|
2764
|
+
return refuse13("vtex_payments_body_unsupported");
|
|
1361
2765
|
if (target && transaction.id.toUpperCase() !== target.transactionId.toUpperCase())
|
|
1362
|
-
return
|
|
1363
|
-
return fieldsSound(line.fields) ?
|
|
2766
|
+
return refuse13("vtex_payments_split_payment");
|
|
2767
|
+
return fieldsSound(line.fields) ? CARD13 : refuse13("vtex_payments_body_unsupported");
|
|
1364
2768
|
}
|
|
1365
2769
|
function vtexPaymentsAmount(body) {
|
|
1366
2770
|
if (vtexPaymentsBodyVerdict(body).verdict !== "card")
|
|
@@ -1405,21 +2809,29 @@ var vtex_payments_default = /* @__PURE__ */ registerProcessor({
|
|
|
1405
2809
|
return vtexPaymentsBodyVerdict(body);
|
|
1406
2810
|
const target = vtexPaymentsCardTarget(url);
|
|
1407
2811
|
if (target === null)
|
|
1408
|
-
return
|
|
1409
|
-
return target.fallback ?
|
|
2812
|
+
return refuse13("vtex_payments_url_refused");
|
|
2813
|
+
return target.fallback ? refuse13("vtex_payments_fallback_refused") : vtexPaymentsBodyVerdict(body, target);
|
|
1410
2814
|
},
|
|
1411
|
-
amount: (template) =>
|
|
2815
|
+
amount: (template) => record10(template) && isVtexPaymentsCardUrl(template.url) ? vtexPaymentsAmount(template.body) : null
|
|
1412
2816
|
});
|
|
1413
2817
|
// src/processors/index.generated.js
|
|
1414
2818
|
var REGISTERED_MODULES = Object.freeze({
|
|
2819
|
+
aurus: aurus_default,
|
|
2820
|
+
bigcommerce: bigcommerce_default,
|
|
1415
2821
|
bluesnap: bluesnap_default,
|
|
2822
|
+
cardlink_vpos: cardlink_vpos_default,
|
|
2823
|
+
eghl: eghl_default,
|
|
2824
|
+
frisbii: frisbii_default,
|
|
1416
2825
|
iyzico: iyzico_default,
|
|
1417
2826
|
midtrans: midtrans_default,
|
|
2827
|
+
monei: monei_default,
|
|
1418
2828
|
oceanpayment: oceanpayment_default,
|
|
1419
2829
|
paymentwall: paymentwall_default,
|
|
1420
2830
|
payplug: payplug_default,
|
|
2831
|
+
paystack: paystack_default,
|
|
1421
2832
|
processout: processout_default,
|
|
1422
2833
|
usaepay: usaepay_default,
|
|
2834
|
+
viva_wallet: viva_wallet_default,
|
|
1423
2835
|
vtex_payments: vtex_payments_default
|
|
1424
2836
|
});
|
|
1425
2837
|
// src/registry.js
|
|
@@ -1508,16 +2920,28 @@ var PROCESSOR_DEFINITIONS = deepFreeze([
|
|
|
1508
2920
|
// Flow 1.226.0's card controller selects api or card-acquisition-gateway
|
|
1509
2921
|
// for the same card-token body and Bearer public-key Authorization.
|
|
1510
2922
|
// Native source: checkout-web-components.checkout.com/pages/1.226.0/index.html.
|
|
2923
|
+
// Checkout.com gives each merchant account a subdomain of its own, the base
|
|
2924
|
+
// URL prefix (alphanumeric: the first eight characters of the account's
|
|
2925
|
+
// client id after cli_), and both card frames use it when the merchant
|
|
2926
|
+
// names it. Frames 2.69.0 then sends the card to
|
|
2927
|
+
// <prefix>.api[.sandbox].checkout.com/tokens. Flow 1.235.0 sends it through
|
|
2928
|
+
// the devices API when the payment session turns that on: /cag/tokens, then
|
|
2929
|
+
// /tokens if the gateway call fails, on devices.api[.sandbox].checkout.com,
|
|
2930
|
+
// under the prefix or, on the hosted payments page, none. Any one
|
|
2931
|
+
// alphanumeric label is taken, so every merchant account works whatever its
|
|
2932
|
+
// prefix, and no second label or other path is.
|
|
2933
|
+
// Native sources: js.checkout.com/framesv2/?v=2.69.0 and
|
|
2934
|
+
// checkout-web-components.sandbox.checkout.com/pages/1.235.0/index.html.
|
|
1511
2935
|
// Endpoint recognition does not establish consumer-wallet, CVV-only,
|
|
1512
2936
|
// reusable-token, 3DS or merchant payment completion compatibility.
|
|
1513
|
-
match: "(
|
|
2937
|
+
match: "(?:card-acquisition-gateway(?:\\.sandbox)?\\.checkout\\.com/tokens|(?:[a-z0-9]+\\.)?api(?:\\.sandbox)?\\.checkout\\.com/tokens|(?:[a-z0-9]+\\.)?devices\\.api(?:\\.sandbox)?\\.checkout\\.com/(?:cag/)?tokens)",
|
|
1514
2938
|
hosts: [
|
|
1515
|
-
"^api\\.checkout\\.com$",
|
|
1516
|
-
"^api\\.sandbox\\.checkout\\.com$",
|
|
2939
|
+
"^(?:[a-z0-9]+\\.)?(?:devices\\.)?api\\.checkout\\.com$",
|
|
2940
|
+
"^(?:[a-z0-9]+\\.)?(?:devices\\.)?api\\.sandbox\\.checkout\\.com$",
|
|
1517
2941
|
"^card-acquisition-gateway\\.checkout\\.com$",
|
|
1518
2942
|
"^card-acquisition-gateway\\.sandbox\\.checkout\\.com$"
|
|
1519
2943
|
],
|
|
1520
|
-
sandboxHosts: ["^api\\.sandbox\\.checkout\\.com$", "^card-acquisition-gateway\\.sandbox\\.checkout\\.com$"],
|
|
2944
|
+
sandboxHosts: ["^(?:[a-z0-9]+\\.)?(?:devices\\.)?api\\.sandbox\\.checkout\\.com$", "^card-acquisition-gateway\\.sandbox\\.checkout\\.com$"],
|
|
1521
2945
|
encoding: "json",
|
|
1522
2946
|
passthroughHeaders: ["^authorization$"]
|
|
1523
2947
|
},
|
|
@@ -4460,9 +5884,6 @@ var PAYFAST_BODY_KEYS = /* @__PURE__ */ Object.freeze([
|
|
|
4460
5884
|
]);
|
|
4461
5885
|
var CAPTCHA_ANSWER = "g-recaptcha-response";
|
|
4462
5886
|
var UNANSWERED_KEYS = /* @__PURE__ */ Object.freeze(PAYFAST_BODY_KEYS.filter((key) => key !== CAPTCHA_ANSWER));
|
|
4463
|
-
// src/rsa-pkcs1v15.js
|
|
4464
|
-
var TYPED_ARRAY = Object.getPrototypeOf(Uint8Array.prototype);
|
|
4465
|
-
var typedArrayName = Object.getOwnPropertyDescriptor(TYPED_ARRAY, Symbol.toStringTag).get;
|
|
4466
5887
|
// src/paddle-keys.js
|
|
4467
5888
|
var PADDLE_TOKENEX_KEYS = /* @__PURE__ */ Object.freeze({
|
|
4468
5889
|
sandbox: Object.freeze({
|
|
@@ -4565,7 +5986,7 @@ var HIPAY_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
|
4565
5986
|
pin6({ id: "happybulle", merchant: "HappyBulle", origins: ["https://www.happybulle.com"], usernames: ["94683309.secure-gateway.hipay-tpp.com"] })
|
|
4566
5987
|
]);
|
|
4567
5988
|
// src/amazon-payment-services.js
|
|
4568
|
-
var
|
|
5989
|
+
var BODY_LIMIT15 = 32 * 1024;
|
|
4569
5990
|
var ANSWER_LIMIT = 64 * 1024;
|
|
4570
5991
|
// src/clover.js
|
|
4571
5992
|
var REQUIRED_KEYS = /* @__PURE__ */ Object.freeze(["encrypted_pan", "exp_month", "exp_year", "cvv", "first6", "last4", "brand"]);
|
|
@@ -4623,10 +6044,10 @@ var TOKENEX_IFRAME_ACCOUNT_NAMES = Object.freeze({
|
|
|
4623
6044
|
"test-htp.tokenex.com": Object.freeze({})
|
|
4624
6045
|
});
|
|
4625
6046
|
var exact2 = (pattern, value) => typeof value === "string" && pattern.exec(value)?.[0] === value;
|
|
4626
|
-
var
|
|
6047
|
+
var text2 = (value, max) => typeof value === "string" && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
|
|
4627
6048
|
var digits = (value, min, max) => typeof value === "string" && value.length >= min && value.length <= max && !/[^0-9]/.test(value);
|
|
4628
6049
|
var panLike = (value) => (value.match(/\p{Nd}/gu) ?? []).length >= 12;
|
|
4629
|
-
var plain = (value, max) =>
|
|
6050
|
+
var plain = (value, max) => text2(value, max) && !panLike(value);
|
|
4630
6051
|
var TOKENEX_ID = /^[0-9]{16}$/;
|
|
4631
6052
|
var AUTHENTICATION_KEY = /^[A-Za-z0-9+/]{43}=$/;
|
|
4632
6053
|
var TIMESTAMP = /^20[0-9]{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12][0-9]|3[01])(?:[01][0-9]|2[0-3])[0-5][0-9][0-5][0-9]$/;
|
|
@@ -4917,7 +6338,7 @@ var RECORD_MEMBERS = /* @__PURE__ */ Object.freeze({
|
|
|
4917
6338
|
]
|
|
4918
6339
|
});
|
|
4919
6340
|
// src/pin-payments.js
|
|
4920
|
-
var
|
|
6341
|
+
var CARD_KEYS4 = /* @__PURE__ */ Object.freeze(["name", "number", "cvc", "expiry_month", "expiry_year"]);
|
|
4921
6342
|
var ADDRESS_KEYS = /* @__PURE__ */ Object.freeze([
|
|
4922
6343
|
"address_line1",
|
|
4923
6344
|
"address_line2",
|
|
@@ -4928,7 +6349,7 @@ var ADDRESS_KEYS = /* @__PURE__ */ Object.freeze([
|
|
|
4928
6349
|
]);
|
|
4929
6350
|
var KEY2 = "publishable_api_key";
|
|
4930
6351
|
var METHOD = "_method";
|
|
4931
|
-
var DOCUMENTED = /* @__PURE__ */ new Set([KEY2, METHOD, ...
|
|
6352
|
+
var DOCUMENTED = /* @__PURE__ */ new Set([KEY2, METHOD, ...CARD_KEYS4, ...ADDRESS_KEYS]);
|
|
4932
6353
|
var TOKEN_FACTS = /* @__PURE__ */ Object.freeze([
|
|
4933
6354
|
"token",
|
|
4934
6355
|
"scheme",
|
|
@@ -4995,8 +6416,8 @@ var MESSAGES = Object.freeze({
|
|
|
4995
6416
|
dcp_field_config_unreviewed: "Refusing to pay: Agentcard has not reviewed this merchant's Amadeus card form yet. Nothing was sent."
|
|
4996
6417
|
});
|
|
4997
6418
|
var SDK_FLAVORS = Object.freeze(["Core-Sdk", "Angular-Web-Sdk"]);
|
|
4998
|
-
var
|
|
4999
|
-
var SDK_HOST = new RegExp(`^${
|
|
6419
|
+
var LABEL2 = "[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?";
|
|
6420
|
+
var SDK_HOST = new RegExp(`^${LABEL2}(?:\\.${LABEL2})+(?::[0-9]{1,5})?$`, "i");
|
|
5000
6421
|
var SDK_HEADERS = Object.freeze(["amadeus-checkout-sdk-version", "amadeus-checkout-sdk-host", "amadeus-checkout-sdk-flavor"]);
|
|
5001
6422
|
var SDK_DATA_KEYS = Object.freeze(["mopid", "mopdata", "fingerprint"]);
|
|
5002
6423
|
var SDK_MOPDATA_KEYS = Object.freeze(["pan", "CVV", "holdername", "expmonth", "expyear", "vendor", "address", "contact"]);
|
|
@@ -5015,65 +6436,6 @@ var DECLINE_LABELS = Object.freeze(["label_error_payment", "label_error_bin", "l
|
|
|
5015
6436
|
var EXPIRED_LABELS = Object.freeze(["session_timeout", "ppid_expired"]);
|
|
5016
6437
|
var REF_KEYS = Object.freeze(["recloc", "orderId", "mopId", "pri", "approvalcode", "externalId", "paymentMerchantReference", "prr"]);
|
|
5017
6438
|
var PAYMENT_INFORMATION_KEYS = Object.freeze(["approvalcode", "pri", "externalId", "mopId"]);
|
|
5018
|
-
// src/processors/redsys.js
|
|
5019
|
-
var REDSYS_HOSTS = Object.freeze(["sis.redsys.es"]);
|
|
5020
|
-
var REDSYS_ENTRY_PATHS = Object.freeze(["/sis/realizarPago", "/sis/realizarPago/utf-8"]);
|
|
5021
|
-
var REDSYS_MERCHANTS = Object.freeze([]);
|
|
5022
|
-
var MAX_ENTRY2 = 16 * 1024;
|
|
5023
|
-
var MAX_PARAMETERS = 8 * 1024;
|
|
5024
|
-
var ENTRY_KEYS = Object.freeze(["Ds_SignatureVersion", "Ds_MerchantParameters", "Ds_Signature"]);
|
|
5025
|
-
var REQUIRED2 = Object.freeze([
|
|
5026
|
-
"DS_MERCHANT_AMOUNT",
|
|
5027
|
-
"DS_MERCHANT_CURRENCY",
|
|
5028
|
-
"DS_MERCHANT_MERCHANTCODE",
|
|
5029
|
-
"DS_MERCHANT_ORDER",
|
|
5030
|
-
"DS_MERCHANT_TERMINAL",
|
|
5031
|
-
"DS_MERCHANT_TRANSACTIONTYPE",
|
|
5032
|
-
"DS_MERCHANT_MERCHANTURL",
|
|
5033
|
-
"DS_MERCHANT_URLOK",
|
|
5034
|
-
"DS_MERCHANT_URLKO"
|
|
5035
|
-
]);
|
|
5036
|
-
var STORED = Object.freeze([
|
|
5037
|
-
"DS_MERCHANT_IDENTIFIER",
|
|
5038
|
-
"DS_MERCHANT_GROUP",
|
|
5039
|
-
"DS_MERCHANT_COF_INI",
|
|
5040
|
-
"DS_MERCHANT_COF_TYPE",
|
|
5041
|
-
"DS_MERCHANT_COF_TXNID"
|
|
5042
|
-
]);
|
|
5043
|
-
var SPECIAL = Object.freeze([
|
|
5044
|
-
"DS_MERCHANT_DIRECTPAYMENT",
|
|
5045
|
-
"DS_MERCHANT_SUMTOTAL",
|
|
5046
|
-
"DS_MERCHANT_DATEFRECUENCY",
|
|
5047
|
-
"DS_MERCHANT_CHARGEEXPIRYDATE",
|
|
5048
|
-
"DS_MERCHANT_IDOPER"
|
|
5049
|
-
]);
|
|
5050
|
-
var CARD_PARAMETERS = Object.freeze(["DS_MERCHANT_PAN", "DS_MERCHANT_EXPIRYDATE", "DS_MERCHANT_CVV2"]);
|
|
5051
|
-
var CURRENCIES = Object.freeze({ 978: "eur", 840: "usd", 826: "gbp", 756: "chf" });
|
|
5052
|
-
var MAX_PAGE3 = 256 * 1024;
|
|
5053
|
-
var CARD_FIELDS2 = Object.freeze({
|
|
5054
|
-
shown: "Sis_card-number",
|
|
5055
|
-
expiry: "SIS_card-expiration",
|
|
5056
|
-
cvc: "Sis_Tarjeta_CVV2",
|
|
5057
|
-
holder: "cardholderName",
|
|
5058
|
-
number: "Sis_Numero_Tarjeta",
|
|
5059
|
-
month: "Sis_Caducidad_Tarjeta_Mes",
|
|
5060
|
-
year: "Sis_Caducidad_Tarjeta_Anno"
|
|
5061
|
-
});
|
|
5062
|
-
var BROWSER_FIELDS = Object.freeze([
|
|
5063
|
-
"browserJavaEnabled",
|
|
5064
|
-
"browserJavascriptEnabled",
|
|
5065
|
-
"browserLanguage",
|
|
5066
|
-
"browserColorDepth",
|
|
5067
|
-
"browserScreenHeight",
|
|
5068
|
-
"browserScreenWidth",
|
|
5069
|
-
"browserTZ",
|
|
5070
|
-
"browserUserAgent"
|
|
5071
|
-
]);
|
|
5072
|
-
var AS_SERVED = Object.freeze(["cvvObligatorio", "threeDSCompInd", "fuc", "terminal", "merchantOrder", "bcancel"]);
|
|
5073
|
-
var CARD_PAGE = /* @__PURE__ */ new Set([...Object.values(CARD_FIELDS2), ...BROWSER_FIELDS, ...AS_SERVED]);
|
|
5074
|
-
var VISIBLE2 = /* @__PURE__ */ new Set([CARD_FIELDS2.shown, CARD_FIELDS2.expiry, CARD_FIELDS2.cvc, CARD_FIELDS2.holder]);
|
|
5075
|
-
var METHOD_PAGE = /* @__PURE__ */ new Set(["resultadoMethod", ...BROWSER_FIELDS, "threeDSCompInd"]);
|
|
5076
|
-
var REDSYS_REFUSALS = Object.freeze(["redsys_card_page", "redsys_3ds_challenge", "redsys_declined"]);
|
|
5077
6439
|
// src/processors/quickpay.js
|
|
5078
6440
|
var QUICKPAY_HOSTS = Object.freeze(["payment.quickpay.net"]);
|
|
5079
6441
|
var QUICKPAY_MERCHANTS = Object.freeze([
|
|
@@ -5085,8 +6447,8 @@ var QUICKPAY_MERCHANTS = Object.freeze([
|
|
|
5085
6447
|
callbackHost: "shop.skandinaviskdyrepark.dk"
|
|
5086
6448
|
})
|
|
5087
6449
|
]);
|
|
5088
|
-
var
|
|
5089
|
-
var
|
|
6450
|
+
var MAX_ENTRY4 = 16 * 1024;
|
|
6451
|
+
var REQUIRED5 = Object.freeze([
|
|
5090
6452
|
"version",
|
|
5091
6453
|
"merchant_id",
|
|
5092
6454
|
"agreement_id",
|
|
@@ -5099,7 +6461,7 @@ var REQUIRED3 = Object.freeze([
|
|
|
5099
6461
|
"checksum"
|
|
5100
6462
|
]);
|
|
5101
6463
|
var SCALARS = /* @__PURE__ */ new Set([
|
|
5102
|
-
...
|
|
6464
|
+
...REQUIRED5,
|
|
5103
6465
|
"type",
|
|
5104
6466
|
"language",
|
|
5105
6467
|
"autocapture",
|
|
@@ -5117,12 +6479,12 @@ var SCALARS = /* @__PURE__ */ new Set([
|
|
|
5117
6479
|
"invoice_address_selection",
|
|
5118
6480
|
"shipping_address_selection"
|
|
5119
6481
|
]);
|
|
5120
|
-
var
|
|
5121
|
-
var
|
|
6482
|
+
var CURRENCIES4 = Object.freeze({ DKK: "dkk", EUR: "eur", USD: "usd", SEK: "sek", NOK: "nok", GBP: "gbp", CHF: "chf", PLN: "pln" });
|
|
6483
|
+
var MAX_PAGE6 = 256 * 1024;
|
|
5122
6484
|
var CARD_FIELDS3 = Object.freeze({ number: "cardnumber", month: "expiration[month]", year: "expiration[year]", cvc: "cvd", holder: "cardholder" });
|
|
5123
6485
|
var TYPED = /* @__PURE__ */ new Set([CARD_FIELDS3.number, CARD_FIELDS3.month, CARD_FIELDS3.year, CARD_FIELDS3.cvc]);
|
|
5124
6486
|
var CARD_PAGE2 = /* @__PURE__ */ new Set(["session_id", ...TYPED]);
|
|
5125
|
-
var
|
|
6487
|
+
var OPTIONAL2 = Object.freeze({ brand: "radio", "3d": "checkbox", cardholder: "text" });
|
|
5126
6488
|
var AUTH_FIELDS = Object.freeze([
|
|
5127
6489
|
"[auth]browserColorDepth",
|
|
5128
6490
|
"[auth]browserJavaEnabled",
|
|
@@ -5144,7 +6506,7 @@ var COMGATE_MERCHANTS = Object.freeze([
|
|
|
5144
6506
|
Object.freeze({ merchant: "Dárek pro Beskydy", origins: Object.freeze(["https://darekprobeskydy.info"]), merchantIds: Object.freeze([]) })
|
|
5145
6507
|
]);
|
|
5146
6508
|
var MAX_LOAD = 1024 * 1024;
|
|
5147
|
-
var
|
|
6509
|
+
var MAX_ANSWER2 = 64 * 1024;
|
|
5148
6510
|
var HEADER_NAMES = Object.freeze(["content-type", "x-cg-origin", "origin"]);
|
|
5149
6511
|
var COMGATE_REFUSALS = Object.freeze(["comgate_3ds_challenge", "comgate_declined"]);
|
|
5150
6512
|
// src/processors/przelewy24.js
|
|
@@ -5153,8 +6515,8 @@ var PRZELEWY24_SANDBOX_HOSTS = Object.freeze(["sandbox.przelewy24.pl"]);
|
|
|
5153
6515
|
var PRZELEWY24_MERCHANTS = Object.freeze([
|
|
5154
6516
|
Object.freeze({ id: "kupbilet", merchant: "KupBilet.pl", merchantId: null, origins: Object.freeze(["https://www.kupbilet.pl"]) })
|
|
5155
6517
|
]);
|
|
5156
|
-
var
|
|
5157
|
-
var
|
|
6518
|
+
var MAX_PAGE7 = 256 * 1024;
|
|
6519
|
+
var CURRENCIES5 = Object.freeze(["PLN", "EUR", "GBP", "USD", "CZK", "CHF", "DKK", "NOK", "SEK", "RON", "BGN", "HUF"]);
|
|
5158
6520
|
var PRZELEWY24_AJAX_HEADERS = Object.freeze({ Accept: "*/*", "X-Requested-With": "XMLHttpRequest" });
|
|
5159
6521
|
var MONTHS = Object.freeze(["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]);
|
|
5160
6522
|
var CARD_TYPES = Object.freeze([
|
|
@@ -5185,7 +6547,7 @@ var TRANSBANK_MERCHANTS = Object.freeze([
|
|
|
5185
6547
|
returnUrl: null
|
|
5186
6548
|
})
|
|
5187
6549
|
]);
|
|
5188
|
-
var
|
|
6550
|
+
var MAX_PAGE8 = 64 * 1024;
|
|
5189
6551
|
var JSON_HEADERS = Object.freeze({ "content-type": "application/json", accept: "application/json, text/plain, */*" });
|
|
5190
6552
|
var FORM_HEADERS = Object.freeze({ "content-type": "application/x-www-form-urlencoded", accept: "application/json, text/plain, */*" });
|
|
5191
6553
|
var TRANSBANK_REFUSALS = Object.freeze(["transbank_3ds_challenge", "transbank_aborted", "transbank_error"]);
|
|
@@ -5209,16 +6571,16 @@ var ENTRY_PATH2 = new RegExp(`^/payments/(${UUID_SOURCE})/click-to-pay/loading-a
|
|
|
5209
6571
|
var SIGNATURES = Object.freeze({ sha256: /^[0-9a-f]{64}$/, sha512: /^[0-9a-f]{128}$/ });
|
|
5210
6572
|
var PAYMENT_HIGHWAY_HOSTS = Object.freeze(["v1.api.paymenthighway.io"]);
|
|
5211
6573
|
var CARD_PAGE_PATH = new RegExp(`^/form/(${UUID_SOURCE})/pay_with_click_to_pay$`);
|
|
5212
|
-
var
|
|
6574
|
+
var MAX_PAGE9 = 256 * 1024;
|
|
5213
6575
|
var PAYTRAIL_CARD_HEADERS = Object.freeze({ "Content-Type": "application/json", "X-Requested-With": "PH-Form", Accept: "application/json" });
|
|
5214
6576
|
var PAYTRAIL_REFUSALS = Object.freeze(["paytrail_3ds_challenge", "paytrail_card_refused"]);
|
|
5215
6577
|
// src/processors/eximbay.js
|
|
5216
6578
|
var EXIMBAY_HOSTS = Object.freeze(["secureapi.eximbay.com", "secureapi.test.eximbay.com"]);
|
|
5217
6579
|
var EXIMBAY_MERCHANTS = Object.freeze([]);
|
|
5218
|
-
var
|
|
5219
|
-
var
|
|
5220
|
-
var
|
|
5221
|
-
var
|
|
6580
|
+
var MAX_ENTRY5 = 16 * 1024;
|
|
6581
|
+
var REQUIRED6 = Object.freeze(["ver", "mid", "txntype", "ref", "cur", "amt", "buyer", "email", "lang", "returnurl", "statusurl", "fgkey"]);
|
|
6582
|
+
var CURRENCIES6 = Object.freeze({ USD: 2, KRW: 0, JPY: 0, EUR: 2, GBP: 2, SGD: 2, HKD: 2, CAD: 2, AUD: 2, THB: 2 });
|
|
6583
|
+
var MAX_PAGE10 = 512 * 1024;
|
|
5222
6584
|
var ATTRS = `(?:[^>"']|"[^"]{0,1024}"|'[^']{0,1024}'){0,512}`;
|
|
5223
6585
|
var startTag = (name) => new RegExp(`<${name}(?=[\\t\\n\\f\\r />])${ATTRS}>`, "gi");
|
|
5224
6586
|
var FORM_START = startTag("form");
|
|
@@ -5271,8 +6633,8 @@ var RESULT_BINDS = Object.freeze(["mid", "txntype", "ref", "cur", "amt"]);
|
|
|
5271
6633
|
var BARION_HOSTS = Object.freeze(["secure.barion.com", "secure.test.barion.com"]);
|
|
5272
6634
|
var BARION_SANDBOX_HOSTS = Object.freeze(["secure.test.barion.com"]);
|
|
5273
6635
|
var BARION_SHOPS = Object.freeze([]);
|
|
5274
|
-
var
|
|
5275
|
-
var
|
|
6636
|
+
var MAX_PAGE11 = 512 * 1024;
|
|
6637
|
+
var CURRENCIES7 = Object.freeze(["HUF", "EUR", "USD", "CZK", "RON", "PLN"]);
|
|
5276
6638
|
var CARD_INPUTS = Object.freeze({ number: "cc-number", expiry: "cc-exp-date", cvc: "CardCVC", holder: "CardHolderName" });
|
|
5277
6639
|
var CHECKBOXES = Object.freeze(["RegisterUser", "AcceptedTerms", "HasEmailConsent"]);
|
|
5278
6640
|
var OTHER_INPUTS = Object.freeze({ FirstPassword: ["password"], RecaptchaToken: ["hidden"], __RequestVerificationToken: ["hidden"], Identifier: ["hidden"] });
|
|
@@ -5284,7 +6646,7 @@ var BARION_AJAX_HEADERS = Object.freeze({
|
|
|
5284
6646
|
var CARD_TYPES2 = Object.freeze([{ prefix: /^4/, type: 20 }, { prefix: /^5[1-5]|^2[2-7]/, type: 10 }, { prefix: /^3[47]/, type: 30 }]);
|
|
5285
6647
|
var COLOR_DEPTHS = Object.freeze([1, 4, 8, 15, 16, 24, 32, 48]);
|
|
5286
6648
|
var BARION_REFUSALS = Object.freeze(["barion_declined", "barion_3ds_challenge", "barion_sca_soft_decline"]);
|
|
5287
|
-
var
|
|
6649
|
+
var MAX_ANSWER3 = 64 * 1024;
|
|
5288
6650
|
var DECLINE_CODES = Object.freeze([
|
|
5289
6651
|
"CardError",
|
|
5290
6652
|
"CardExpired",
|
|
@@ -5323,7 +6685,7 @@ var SBPS_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
|
|
|
5323
6685
|
]);
|
|
5324
6686
|
var ERROR_TYPES = /* @__PURE__ */ Object.freeze(["03", "04", "05", "07", "99"]);
|
|
5325
6687
|
var ERROR_FIELDS = /* @__PURE__ */ Object.freeze(["001", "002", "003", "004", "005", "999"]);
|
|
5326
|
-
var SBPS_REFUSAL_CODES = /* @__PURE__ */ Object.freeze(ERROR_TYPES.flatMap((type) => ERROR_FIELDS.map((
|
|
6688
|
+
var SBPS_REFUSAL_CODES = /* @__PURE__ */ Object.freeze(ERROR_TYPES.flatMap((type) => ERROR_FIELDS.map((field4) => `${type}${field4}`)));
|
|
5327
6689
|
// src/recognition.js
|
|
5328
6690
|
var PATTERN_WITHOUT_CARD_FIELDS = Object.freeze({
|
|
5329
6691
|
stripe: "api\\.stripe\\.com/v1/(payment_methods|tokens|setup_intents/seti_\\w+/confirm|payment_intents/pi_\\w+/confirm)"
|
|
@@ -5514,18 +6876,18 @@ function parseStripeCheckoutContext(request) {
|
|
|
5514
6876
|
if (entries.length !== 1 || typeof entries[0][1] !== "string" || !/^[A-Za-z0-9_-]{1,1024}$/.test(entries[0][1]))
|
|
5515
6877
|
reject("context_invalid");
|
|
5516
6878
|
const encoded = entries[0][1];
|
|
5517
|
-
let
|
|
6879
|
+
let text3 = "", bits = 0, count2 = 0;
|
|
5518
6880
|
for (const char of encoded) {
|
|
5519
6881
|
bits = bits << 6 | alphabet.indexOf(char);
|
|
5520
6882
|
count2 += 6;
|
|
5521
6883
|
if (count2 >= 8) {
|
|
5522
6884
|
count2 -= 8;
|
|
5523
|
-
|
|
6885
|
+
text3 += String.fromCharCode(bits >>> count2 & 255);
|
|
5524
6886
|
}
|
|
5525
6887
|
}
|
|
5526
6888
|
let value;
|
|
5527
6889
|
try {
|
|
5528
|
-
value = context(JSON.parse(
|
|
6890
|
+
value = context(JSON.parse(text3));
|
|
5529
6891
|
}
|
|
5530
6892
|
catch {
|
|
5531
6893
|
reject("context_invalid");
|
|
@@ -5675,13 +7037,13 @@ function attachStripeCheckoutBilling(request, captured, options) {
|
|
|
5675
7037
|
const phase = classifyStripeCheckoutRequest(request, options);
|
|
5676
7038
|
if (phase?.phase !== "final" || !object(captured) || Object.keys(captured).length !== 3 || !["session_id", "synthetic_payment_method_id", "email"].every((key) => Object.hasOwn(captured, key)) || captured.session_id !== phase.session_id || captured.synthetic_payment_method_id !== phase.synthetic_payment_method_id || !billingEmail(captured.email))
|
|
5677
7039
|
reject("billing_binding");
|
|
5678
|
-
const
|
|
5679
|
-
const existing = form(request, finalFields).values.get(
|
|
7040
|
+
const field4 = "payment_method_data[billing_details][email]";
|
|
7041
|
+
const existing = form(request, finalFields).values.get(field4);
|
|
5680
7042
|
if (existing !== void 0 && existing !== captured.email)
|
|
5681
7043
|
reject("billing_conflict");
|
|
5682
7044
|
if (captured.email === null || existing !== void 0)
|
|
5683
7045
|
return { ...request };
|
|
5684
|
-
const body = `${request.body}&${encodeURIComponent(
|
|
7046
|
+
const body = `${request.body}&${encodeURIComponent(field4)}=${encodeURIComponent(captured.email)}`;
|
|
5685
7047
|
const result = { ...request, body };
|
|
5686
7048
|
classifyStripeCheckoutRequest(result, options);
|
|
5687
7049
|
return result;
|