@agent-cards/sdk 0.23.12 → 0.23.14

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +38 -1
  2. package/LICENSE +38 -0
  3. package/PREFLIGHT.md +1 -1
  4. package/README.md +53 -14
  5. package/dist/adyen-merchant-hosted.generated.js +2 -2
  6. package/dist/builtin-registry.generated.js +1 -1
  7. package/dist/card-fields.generated.js +843 -3
  8. package/dist/cdp.js +101 -13
  9. package/dist/client.d.ts +91 -2
  10. package/dist/client.js +205 -13
  11. package/dist/creditguard.generated.d.ts +100 -2
  12. package/dist/creditguard.generated.js +333 -3
  13. package/dist/datatrans.generated.d.ts +19 -4
  14. package/dist/datatrans.generated.js +15 -3
  15. package/dist/ebanx.d.ts +107 -0
  16. package/dist/ebanx.generated.d.ts +78 -0
  17. package/dist/ebanx.generated.js +577 -0
  18. package/dist/ebanx.js +159 -0
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.js +2 -0
  21. package/dist/lifecycle.d.ts +35 -3
  22. package/dist/lifecycle.js +38 -3
  23. package/dist/paddle-tokenex.d.ts +56 -0
  24. package/dist/paddle-tokenex.generated.d.ts +67 -0
  25. package/dist/paddle-tokenex.generated.js +951 -0
  26. package/dist/paddle-tokenex.js +95 -0
  27. package/dist/paddle-vgs-pay.d.ts +55 -0
  28. package/dist/paddle-vgs-pay.js +115 -0
  29. package/dist/paddle-vgs.generated.d.ts +29 -1
  30. package/dist/paddle-vgs.generated.js +124 -5
  31. package/dist/paysafe.generated.d.ts +5 -7
  32. package/dist/paysafe.generated.js +50 -18
  33. package/dist/pre-claim.d.ts +46 -1
  34. package/dist/pre-claim.js +338 -17
  35. package/dist/preparation.d.ts +13 -0
  36. package/dist/preparation.js +22 -0
  37. package/dist/prepared-processor.js +6 -2
  38. package/dist/primer.generated.js +878 -38
  39. package/dist/redsys.d.ts +42 -0
  40. package/dist/redsys.js +68 -0
  41. package/dist/stripe-checkout.generated.js +479 -11
  42. package/package.json +9 -6
@@ -0,0 +1,951 @@
1
+ // @ts-nocheck
2
+ // Generated from @agent-cards/payment-core. Do not edit.
3
+ // artifact-sha256: c9116965f8802329701f18adf6519c9111857dfc4329e4f59d7666de150fb5a4
4
+ // src/sha256.js
5
+ var K = /* @__PURE__ */ new Uint32Array([
6
+ 1116352408,
7
+ 1899447441,
8
+ 3049323471,
9
+ 3921009573,
10
+ 961987163,
11
+ 1508970993,
12
+ 2453635748,
13
+ 2870763221,
14
+ 3624381080,
15
+ 310598401,
16
+ 607225278,
17
+ 1426881987,
18
+ 1925078388,
19
+ 2162078206,
20
+ 2614888103,
21
+ 3248222580,
22
+ 3835390401,
23
+ 4022224774,
24
+ 264347078,
25
+ 604807628,
26
+ 770255983,
27
+ 1249150122,
28
+ 1555081692,
29
+ 1996064986,
30
+ 2554220882,
31
+ 2821834349,
32
+ 2952996808,
33
+ 3210313671,
34
+ 3336571891,
35
+ 3584528711,
36
+ 113926993,
37
+ 338241895,
38
+ 666307205,
39
+ 773529912,
40
+ 1294757372,
41
+ 1396182291,
42
+ 1695183700,
43
+ 1986661051,
44
+ 2177026350,
45
+ 2456956037,
46
+ 2730485921,
47
+ 2820302411,
48
+ 3259730800,
49
+ 3345764771,
50
+ 3516065817,
51
+ 3600352804,
52
+ 4094571909,
53
+ 275423344,
54
+ 430227734,
55
+ 506948616,
56
+ 659060556,
57
+ 883997877,
58
+ 958139571,
59
+ 1322822218,
60
+ 1537002063,
61
+ 1747873779,
62
+ 1955562222,
63
+ 2024104815,
64
+ 2227730452,
65
+ 2361852424,
66
+ 2428436474,
67
+ 2756734187,
68
+ 3204031479,
69
+ 3329325298
70
+ ]);
71
+ var rotr = (x, n) => x >>> n | x << 32 - n;
72
+ function utf8(text) {
73
+ const out = [];
74
+ for (const char of text) {
75
+ let cp = char.codePointAt(0);
76
+ if (cp >= 55296 && cp <= 57343)
77
+ cp = 65533;
78
+ if (cp < 128)
79
+ out.push(cp);
80
+ else if (cp < 2048)
81
+ out.push(192 | cp >> 6, 128 | cp & 63);
82
+ else if (cp < 65536)
83
+ out.push(224 | cp >> 12, 128 | cp >> 6 & 63, 128 | cp & 63);
84
+ else
85
+ out.push(240 | cp >> 18, 128 | cp >> 12 & 63, 128 | cp >> 6 & 63, 128 | cp & 63);
86
+ }
87
+ return Uint8Array.from(out);
88
+ }
89
+ function sha256Hex(input) {
90
+ const isBytes = Object.prototype.toString.call(input) === "[object Uint8Array]";
91
+ if (typeof input !== "string" && !isBytes)
92
+ throw new TypeError("sha256Hex takes a string or a Uint8Array.");
93
+ const bytes = typeof input === "string" ? utf8(input) : input;
94
+ const length = bytes.length;
95
+ const padded = new Uint8Array((length + 8 >> 6) + 1 << 6);
96
+ padded.set(bytes);
97
+ padded[length] = 128;
98
+ const view = new DataView(padded.buffer);
99
+ view.setUint32(padded.length - 8, Math.floor(length / 536870912));
100
+ view.setUint32(padded.length - 4, length << 3 >>> 0);
101
+ const H = new Uint32Array([1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]);
102
+ const W = new Uint32Array(64);
103
+ for (let offset = 0; offset < padded.length; offset += 64) {
104
+ for (let t = 0; t < 16; t++)
105
+ W[t] = view.getUint32(offset + t * 4);
106
+ for (let t = 16; t < 64; t++) {
107
+ const s0 = rotr(W[t - 15], 7) ^ rotr(W[t - 15], 18) ^ W[t - 15] >>> 3;
108
+ const s1 = rotr(W[t - 2], 17) ^ rotr(W[t - 2], 19) ^ W[t - 2] >>> 10;
109
+ W[t] = W[t - 16] + s0 + W[t - 7] + s1 >>> 0;
110
+ }
111
+ let a = H[0], b = H[1], c = H[2], d = H[3], e = H[4], f = H[5], g = H[6], h = H[7];
112
+ for (let t = 0; t < 64; t++) {
113
+ const t1 = h + (rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25)) + (e & f ^ ~e & g) + K[t] + W[t] >>> 0;
114
+ const t2 = (rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22)) + (a & b ^ a & c ^ b & c) >>> 0;
115
+ h = g;
116
+ g = f;
117
+ f = e;
118
+ e = d + t1 >>> 0;
119
+ d = c;
120
+ c = b;
121
+ b = a;
122
+ a = t1 + t2 >>> 0;
123
+ }
124
+ H[0] += a;
125
+ H[1] += b;
126
+ H[2] += c;
127
+ H[3] += d;
128
+ H[4] += e;
129
+ H[5] += f;
130
+ H[6] += g;
131
+ H[7] += h;
132
+ }
133
+ return Array.from(H, (word) => word.toString(16).padStart(8, "0")).join("");
134
+ }
135
+ // src/rsa-pkcs1v15.js
136
+ var RsaPkcs1v15Error = class extends Error {
137
+ constructor(reason) {
138
+ super("RSA PKCS#1 v1.5 encryption refused.");
139
+ this.name = "RsaPkcs1v15Error";
140
+ this.code = "rsa_pkcs1v15_refused";
141
+ this.reason = reason;
142
+ }
143
+ };
144
+ var refuse = (reason) => new RsaPkcs1v15Error(reason);
145
+ var BASE64 = /^[A-Za-z0-9+/]+={0,2}$/;
146
+ var SHA256_HEX = /^[0-9a-f]{64}$/;
147
+ var RSA_ALGORITHM = [48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0];
148
+ var MODULUS_BYTES = [128, 256, 384, 512];
149
+ var MIN_PADDING = 8;
150
+ var MAX_DRAWS = 16;
151
+ var TYPED_ARRAY = Object.getPrototypeOf(Uint8Array.prototype);
152
+ var typedArrayName = Object.getOwnPropertyDescriptor(TYPED_ARRAY, Symbol.toStringTag).get;
153
+ function parseRsaPublicKey(key) {
154
+ const spki = key && typeof key === "object" ? key.spki : void 0;
155
+ const pin2 = key && typeof key === "object" ? key.sha256 : void 0;
156
+ if (typeof spki !== "string" || spki.length > 1024 || spki.length % 4 !== 0 || !BASE64.test(spki))
157
+ throw refuse("key");
158
+ if (typeof pin2 !== "string" || !SHA256_HEX.test(pin2))
159
+ throw refuse("key");
160
+ let binary;
161
+ try {
162
+ binary = atob(spki);
163
+ }
164
+ catch {
165
+ throw refuse("key");
166
+ }
167
+ if (btoa(binary) !== spki)
168
+ throw refuse("key");
169
+ const der = Uint8Array.from(binary, (c) => c.charCodeAt(0));
170
+ if (sha256Hex(der) !== pin2)
171
+ throw refuse("key");
172
+ const outer = readElement(der, 0, 48);
173
+ if (outer.end !== der.length || outer.start + RSA_ALGORITHM.length > der.length)
174
+ throw refuse("key");
175
+ if (!RSA_ALGORITHM.every((byte, i) => der[outer.start + i] === byte))
176
+ throw refuse("key");
177
+ const bits = readElement(der, outer.start + RSA_ALGORITHM.length, 3);
178
+ if (bits.end !== outer.end || bits.start === bits.end || der[bits.start] !== 0)
179
+ throw refuse("key");
180
+ const rsa = readElement(der, bits.start + 1, 48);
181
+ if (rsa.end !== bits.end)
182
+ throw refuse("key");
183
+ const modulus = readPositiveInteger(der, rsa.start);
184
+ const exponent = readPositiveInteger(der, modulus.end);
185
+ if (exponent.end !== rsa.end)
186
+ throw refuse("key");
187
+ const n = modulus.bytes;
188
+ if (!MODULUS_BYTES.includes(n.length) || !(n[0] & 128) || !(n[n.length - 1] & 1))
189
+ throw refuse("key");
190
+ const e = exponent.bytes;
191
+ if (e.length !== 3 || e[0] !== 1 || e[1] !== 0 || e[2] !== 1)
192
+ throw refuse("key");
193
+ return Object.freeze({ n: toBigInt(n), e: 65537n, size: n.length });
194
+ }
195
+ function rsaesPkcs1v15Encrypt(key, message, random) {
196
+ const { n, e, size } = parseRsaPublicKey(key);
197
+ if (typedArrayName.call(message) !== "Uint8Array")
198
+ throw refuse("message");
199
+ let bytes;
200
+ try {
201
+ bytes = new Uint8Array(message);
202
+ }
203
+ catch {
204
+ throw refuse("message");
205
+ }
206
+ const em = new Uint8Array(size);
207
+ try {
208
+ if (bytes.length > size - MIN_PADDING - 3)
209
+ throw refuse("message");
210
+ em[1] = 2;
211
+ fillNonZero(em.subarray(2, size - bytes.length - 1), random);
212
+ em.set(bytes, size - bytes.length);
213
+ return toBytes(modPow(toBigInt(em), e, n), size);
214
+ }
215
+ finally {
216
+ em.fill(0);
217
+ bytes.fill(0);
218
+ }
219
+ }
220
+ function readElement(der, at, tag) {
221
+ if (at + 2 > der.length || der[at] !== tag)
222
+ throw refuse("key");
223
+ let length = der[at + 1];
224
+ let start = at + 2;
225
+ if (length & 128) {
226
+ const count = length & 127;
227
+ if (count === 0 || count > 2 || start + count > der.length || der[start] === 0)
228
+ throw refuse("key");
229
+ length = count === 1 ? der[start] : der[start] * 256 + der[start + 1];
230
+ if (length < 128)
231
+ throw refuse("key");
232
+ start += count;
233
+ }
234
+ if (start + length > der.length)
235
+ throw refuse("key");
236
+ return { start, end: start + length };
237
+ }
238
+ function readPositiveInteger(der, at) {
239
+ const { start, end } = readElement(der, at, 2);
240
+ if (end === start || der[start] & 128)
241
+ throw refuse("key");
242
+ if (der[start] === 0 && (end - start === 1 || !(der[start + 1] & 128)))
243
+ throw refuse("key");
244
+ return { bytes: der.subarray(der[start] === 0 ? start + 1 : start, end), end };
245
+ }
246
+ function fillNonZero(target, random) {
247
+ if (!random || typeof random.getRandomValues !== "function")
248
+ throw refuse("random");
249
+ const draw = new Uint8Array(target.length);
250
+ let filled = 0;
251
+ try {
252
+ for (let round = 0; round < MAX_DRAWS && filled < target.length; round++) {
253
+ draw.fill(0);
254
+ random.getRandomValues(draw);
255
+ for (let i = 0; i < draw.length && filled < target.length; i++)
256
+ if (draw[i] !== 0)
257
+ target[filled++] = draw[i];
258
+ }
259
+ }
260
+ catch {
261
+ throw refuse("random");
262
+ }
263
+ finally {
264
+ draw.fill(0);
265
+ }
266
+ if (filled < target.length)
267
+ throw refuse("random");
268
+ }
269
+ function toBigInt(bytes) {
270
+ let hex = "";
271
+ for (let i = 0; i < bytes.length; i++)
272
+ hex += (bytes[i] < 16 ? "0" : "") + bytes[i].toString(16);
273
+ return BigInt(`0x${hex}`);
274
+ }
275
+ function toBytes(value, size) {
276
+ const hex = value.toString(16).padStart(size * 2, "0");
277
+ const out = new Uint8Array(size);
278
+ for (let i = 0; i < size; i++)
279
+ out[i] = parseInt(hex.slice(2 * i, 2 * i + 2), 16);
280
+ return out;
281
+ }
282
+ function modPow(base, exponent, modulus) {
283
+ let result = 1n;
284
+ let square = base % modulus;
285
+ for (let rest = exponent; rest > 0n; rest >>= 1n) {
286
+ if (rest & 1n)
287
+ result = result * square % modulus;
288
+ square = square * square % modulus;
289
+ }
290
+ return result;
291
+ }
292
+ // src/paddle-keys.js
293
+ var PADDLE_TOKENEX_KEYS = /* @__PURE__ */ Object.freeze({
294
+ sandbox: Object.freeze({
295
+ spki: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvWpIQFjQQCPpaIlJKpegirp5kLkzLB1AxHmnLk73D3TJbAGqr1QmlsWDBtMPMRpdzzUM7ZwX3kzhIuATV4Pe7RKp3nZlVmcrT0YCQXBrTwqZNh775z58GP2kZs+gVfNqBampJPzSB/hB62KkByhECn6grrRjiAVwJyZVEvs/2vrxaEpO+aE16emtX12RgI5JdzdOiNyZEQteU6zRBRJEocPWVxExaOpVVVJ5+UnW0LcalzA+lRGRTrQJ5JguAPiAOzRPTK/lYFFpCAl/F8wtoAVG1c8zO2NcQ0Pko+fmeidRFxJ/did2btV+9Mkze3mBphwFmvnxa35LF+Cs/XJHDwIDAQAB",
296
+ sha256: "877d29a008ed9998d6035032870c63dcc4cbf37ca22cb50b0cc9fe2250a9e3dc"
297
+ }),
298
+ production: Object.freeze({
299
+ spki: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8gGPMwBRPuVyJReZGIkWH/+Bf5pnpDN1bSR2cLYLXVT8CaSnTw74qeboSnktgYCi1D9R3Bj2fYzTIwGGZb8KinLdxwbqZmHwrE9cFhCaHbG/E0PbqQGhXP2vbniZTT4M0i0Cbi7ES3Bw5zqNbIZZnX041QEpxLvIyWPKZCX+fBogNMhWfCF779aclChjHkwZMsufThVWE9xklWGxXiytx5aL4I5JPxq0I7cAkZGGs4aF/GxWwPaq7R3wPikJQ0YHnCMfcURzl2Hnw/inqyMy+JB6djTq2/BdzMAhWTh3cDWq9Xu+gEkb/QCd0n1yYIdKuDISlk/AfHdWe34IvzhVyQIDAQAB",
300
+ sha256: "92529bd289bb24d52a1bdcc42edc9ac0bb1dacbb58f7568573d44771e1287762"
301
+ })
302
+ });
303
+ function paddleTokenexKey(environment) {
304
+ if (environment !== "sandbox" && environment !== "production")
305
+ return null;
306
+ return PADDLE_TOKENEX_KEYS[environment] ?? null;
307
+ }
308
+ function paddleTokenexKeyBytes(environment) {
309
+ const key = paddleTokenexKey(environment);
310
+ if (!key)
311
+ return null;
312
+ try {
313
+ return parseRsaPublicKey(key).size;
314
+ }
315
+ catch {
316
+ return null;
317
+ }
318
+ }
319
+ // src/paddle-vgs.js
320
+ var CARD_NUMBER = /^[0-9]{12,19}$/;
321
+ var record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
322
+ var pin = (fields) => Object.freeze({
323
+ ...fields,
324
+ origins: Object.freeze([...fields.origins]),
325
+ sellerClaim: fields.sellerClaim ? Object.freeze({ ...fields.sellerClaim }) : null
326
+ });
327
+ var PADDLE_VGS_MERCHANT_PINS = /* @__PURE__ */ Object.freeze([
328
+ pin({ id: "rectangle_pro", merchant: "Rectangle Pro", origins: ["https://rectangleapp.com"], sellerClaim: null })
329
+ ]);
330
+ var PADDLE_VGS_CARD_NETWORKS = /* @__PURE__ */ Object.freeze(["visa", "mastercard", "amex"]);
331
+ function cardNetwork(number) {
332
+ if (typeof number !== "string" || !CARD_NUMBER.test(number))
333
+ return null;
334
+ const two = Number(number.slice(0, 2));
335
+ const four = Number(number.slice(0, 4));
336
+ if (number[0] === "4")
337
+ return "visa";
338
+ if (two >= 51 && two <= 55 || four >= 2221 && four <= 2720)
339
+ return "mastercard";
340
+ if (two === 34 || two === 37)
341
+ return "amex";
342
+ return null;
343
+ }
344
+ var storedBrand = (brand) => typeof brand === "string" && brand !== "" ? brand.toLowerCase() : null;
345
+ var PAY_BRANDS = /* @__PURE__ */ Object.freeze({ visa: "visa", mastercard: "master", amex: "american_express" });
346
+ var FACT_KEYS = /* @__PURE__ */ Object.freeze(["card_first_six", "card_last_four", "expiry_month", "expiry_year", "card_brand"]);
347
+ var FIRST_SIX = /^[0-9]{6}$/;
348
+ var LAST_FOUR = /^[0-9]{4}$/;
349
+ var fullYear = (year) => {
350
+ const value = Number(year);
351
+ return Number.isInteger(value) && value >= 0 && value <= 99 ? 2e3 + value : value;
352
+ };
353
+ var expiryMonth = (month) => Number.isInteger(month) && month >= 1 && month <= 12;
354
+ var expiryYear = (year) => Number.isInteger(year) && year >= 2e3 && year <= 2099;
355
+ function paddleVgsCardFacts(card) {
356
+ const number = card ? String(card.number) : "";
357
+ const network = cardNetwork(number);
358
+ const month = card ? Number(card.month) : NaN;
359
+ const year = card ? fullYear(card.year) : NaN;
360
+ if (network === null || !expiryMonth(month) || !expiryYear(year))
361
+ throw new Error("Could not read this card's details for Paddle. Nothing was sent.");
362
+ return Object.freeze({ card_first_six: number.slice(0, 6), card_last_four: number.slice(-4), expiry_month: month, expiry_year: year, card_brand: PAY_BRANDS[network] });
363
+ }
364
+ function paddleVgsCardFactsOf(value) {
365
+ if (!record(value))
366
+ return null;
367
+ const keys = Object.keys(value);
368
+ if (keys.length !== FACT_KEYS.length || !FACT_KEYS.every((key) => keys.includes(key)))
369
+ return null;
370
+ const { card_first_six: firstSix, card_last_four: lastFour, expiry_month: month, expiry_year: year, card_brand: brand } = value;
371
+ const network = typeof firstSix === "string" && FIRST_SIX.test(firstSix) ? cardNetwork(`${firstSix}000000`) : null;
372
+ if (network === null || PAY_BRANDS[network] !== brand || typeof lastFour !== "string" || !LAST_FOUR.test(lastFour) || !expiryMonth(month) || !expiryYear(year))
373
+ return null;
374
+ return Object.freeze({ card_first_six: firstSix, card_last_four: lastFour, expiry_month: month, expiry_year: year, card_brand: brand });
375
+ }
376
+ function paddleVgsCardFactsAgree(facts, stored) {
377
+ const read = paddleVgsCardFactsOf(facts);
378
+ if (!read)
379
+ return false;
380
+ const card = record(stored) ? stored : {};
381
+ const network = Object.keys(PAY_BRANDS).find((name) => PAY_BRANDS[name] === read.card_brand);
382
+ const brand = storedBrand(card.brand);
383
+ return !(typeof card.last4 === "string" && LAST_FOUR.test(card.last4) && card.last4 !== read.card_last_four) && (brand === null || brand === network) && !(Number.isInteger(card.expiryMonth) && card.expiryMonth !== read.expiry_month) && !(Number.isInteger(card.expiryYear) && card.expiryYear % 100 !== read.expiry_year % 100);
384
+ }
385
+ var METADATA_KEYS = /* @__PURE__ */ Object.freeze(["cardholder_name", ...FACT_KEYS]);
386
+ // src/adyen-jwe.js
387
+ var ADYEN_JWE_HEADER = { alg: "RSA-OAEP-256", enc: "A256GCM", version: "1" };
388
+ var BASE64URL = /^[A-Za-z0-9_-]+$/;
389
+ function isAdyenJweCompact(s) {
390
+ if (typeof s !== "string" || s.length > 2048)
391
+ return false;
392
+ const parts = s.split(".");
393
+ if (parts.length !== 5)
394
+ return false;
395
+ const [header, encryptedKey, iv, ciphertext, tag] = parts;
396
+ if (!parts.every((p) => p.length > 0 && BASE64URL.test(p)))
397
+ return false;
398
+ if (encryptedKey.length !== 342 || iv.length !== 16 || tag.length !== 22)
399
+ return false;
400
+ if (ciphertext.length > 1024)
401
+ return false;
402
+ return isAdyenJweHeader(header);
403
+ }
404
+ function isAdyenJweHeader(segment) {
405
+ if (!BASE64URL.test(segment) || segment.length > 128)
406
+ return false;
407
+ let parsed;
408
+ try {
409
+ parsed = JSON.parse(new TextDecoder().decode(Uint8Array.from(atob(segment.replace(/-/g, "+").replace(/_/g, "/")), (c) => c.charCodeAt(0))));
410
+ }
411
+ catch {
412
+ return false;
413
+ }
414
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
415
+ return false;
416
+ const obj = parsed;
417
+ const keys = Object.keys(obj).sort();
418
+ if (keys.join(",") !== "alg,enc,version")
419
+ return false;
420
+ return obj.alg === ADYEN_JWE_HEADER.alg && obj.enc === ADYEN_JWE_HEADER.enc && obj.version === ADYEN_JWE_HEADER.version;
421
+ }
422
+ // src/json-path.js
423
+ var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
424
+ function isPlainObject(v) {
425
+ return !!v && typeof v === "object" && !Array.isArray(v);
426
+ }
427
+ var MAX_PATH_STEPS = 16;
428
+ function isJsonPath(path) {
429
+ return Array.isArray(path) && path.length <= MAX_PATH_STEPS && path.every((step) => typeof step === "string" ? step.length > 0 && !FORBIDDEN_KEYS.has(step) : Number.isSafeInteger(step) && step >= 0);
430
+ }
431
+ function jsonAt(root, path) {
432
+ let node = root;
433
+ for (const step of path) {
434
+ if (typeof step === "string") {
435
+ if (!isPlainObject(node) || FORBIDDEN_KEYS.has(step) || !Object.prototype.hasOwnProperty.call(node, step))
436
+ return { found: false };
437
+ }
438
+ else if (!Array.isArray(node) || !Number.isSafeInteger(step) || step < 0 || step >= node.length) {
439
+ return { found: false };
440
+ }
441
+ node = node[step];
442
+ }
443
+ return { found: true, value: node };
444
+ }
445
+ function roundTrips(parsed, body) {
446
+ try {
447
+ return JSON.stringify(parsed) === body;
448
+ }
449
+ catch {
450
+ return false;
451
+ }
452
+ }
453
+ function sameSteps(a, b) {
454
+ return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((step, i) => step === b[i]);
455
+ }
456
+ function pathsOverlap(a, b) {
457
+ const n = Math.min(a.length, b.length);
458
+ for (let i = 0; i < n; i += 1)
459
+ if (a[i] !== b[i])
460
+ return false;
461
+ return true;
462
+ }
463
+ function describePath(path) {
464
+ return path.length ? path.map((step) => typeof step === "number" ? `[${step}]` : `.${step}`).join("").replace(/^\./, "") : "(root)";
465
+ }
466
+ // src/substitution-primitives.js
467
+ var SubstitutionError = class extends Error {
468
+ constructor(message) {
469
+ super(message);
470
+ this.name = "SubstitutionError";
471
+ }
472
+ };
473
+ var SWAP_MEMBERS = /* @__PURE__ */ new Set(["path", "fields", "remove", "set"]);
474
+ function checkedSet(set, path, names, remove) {
475
+ if (!Array.isArray(set))
476
+ throw new SubstitutionError("substitutions.set is not a list");
477
+ const entries = [...set].map((raw) => {
478
+ const entry = isPlainObject(raw) ? Object.fromEntries(Object.entries(raw)) : null;
479
+ if (!entry || Object.keys(entry).sort().join(",") !== "path,value")
480
+ throw new SubstitutionError("a set entry is not a {path, value}");
481
+ const at = Array.isArray(entry.path) ? [...entry.path] : entry.path;
482
+ if (!isJsonPath(at) || at.length === 0 || typeof at[at.length - 1] !== "string")
483
+ throw new SubstitutionError("refusing set path");
484
+ const value = entry.value;
485
+ if (value !== null && !["string", "boolean"].includes(typeof value) && !(typeof value === "number" && Number.isFinite(value))) {
486
+ throw new SubstitutionError(`the set value at ${describePath(at)} is not a string, number, boolean or null`);
487
+ }
488
+ const key = at[at.length - 1];
489
+ if (sameSteps(at.slice(0, -1), path) && (names.includes(key) || remove.includes(key))) {
490
+ throw new SubstitutionError(`the set entry at ${describePath(at)} writes over an encrypted field or a removed key`);
491
+ }
492
+ return { path: at, value };
493
+ });
494
+ for (const [i, a] of entries.entries()) {
495
+ for (const b of entries.slice(i + 1)) {
496
+ if (pathsOverlap(a.path, b.path))
497
+ throw new SubstitutionError(`two set entries write at ${describePath(a.path)}`);
498
+ }
499
+ }
500
+ return entries;
501
+ }
502
+ var ADYEN_JWE = /* @__PURE__ */ Object.freeze({ accepts: isAdyenJweCompact, label: "an Adyen JWE" });
503
+ function swapMerchantHostedFields(body, spec, ciphertext = ADYEN_JWE) {
504
+ if (!isPlainObject(spec))
505
+ throw new SubstitutionError("refusing a substitution that is not an object");
506
+ for (const member of Object.keys(spec)) {
507
+ if (!SWAP_MEMBERS.has(member))
508
+ throw new SubstitutionError(`unexpected substitution member ${member}`);
509
+ }
510
+ const path = Array.isArray(spec.path) ? [...spec.path] : spec.path;
511
+ const fields = isPlainObject(spec.fields) ? Object.fromEntries(Object.entries(spec.fields)) : null;
512
+ const remove = Array.isArray(spec.remove) ? [...spec.remove] : spec.remove ?? [];
513
+ if (!isJsonPath(path))
514
+ throw new SubstitutionError("refusing substitution path");
515
+ if (!fields || Object.keys(fields).length === 0)
516
+ throw new SubstitutionError("substitutions carry no fields");
517
+ const names = Object.keys(fields);
518
+ const values = names.map((name) => fields[name]);
519
+ for (const name of names) {
520
+ if (FORBIDDEN_KEYS.has(name))
521
+ throw new SubstitutionError(`refusing substitution field ${name}`);
522
+ if (!ciphertext.accepts(fields[name]))
523
+ throw new SubstitutionError(`substitution for ${name} is not ${ciphertext.label}`);
524
+ }
525
+ if (!Array.isArray(remove))
526
+ throw new SubstitutionError("substitutions.remove is not a list");
527
+ for (const key of remove) {
528
+ if (typeof key !== "string" || !key || FORBIDDEN_KEYS.has(key))
529
+ throw new SubstitutionError(`refusing removal of ${String(key)}`);
530
+ if (names.includes(key))
531
+ throw new SubstitutionError(`substitution field ${key} is also listed for removal`);
532
+ }
533
+ if (new Set(remove).size !== remove.length)
534
+ throw new SubstitutionError("substitutions.remove names a key twice");
535
+ const set = checkedSet(spec.set ?? [], path, names, remove);
536
+ if (typeof body !== "string")
537
+ throw new SubstitutionError("the paused body is not JSON");
538
+ let parsed;
539
+ try {
540
+ parsed = JSON.parse(body);
541
+ }
542
+ catch {
543
+ throw new SubstitutionError("the paused body is not JSON");
544
+ }
545
+ if (!isPlainObject(parsed))
546
+ throw new SubstitutionError("the paused body is not a JSON object");
547
+ const holder = jsonAt(parsed, path);
548
+ if (!holder.found || !isPlainObject(holder.value))
549
+ throw new SubstitutionError(`the paused body has no object at ${describePath(path)}`);
550
+ const swaps = /* @__PURE__ */ new Map();
551
+ for (const name of names) {
552
+ const dummy = Object.prototype.hasOwnProperty.call(holder.value, name) ? holder.value[name] : void 0;
553
+ if (typeof dummy !== "string")
554
+ throw new SubstitutionError(`the paused body has no string field ${name} at ${describePath(path)}`);
555
+ if (!ciphertext.accepts(dummy))
556
+ throw new SubstitutionError(`the paused field ${name} is not ${ciphertext.label}`);
557
+ if (swaps.has(dummy))
558
+ throw new SubstitutionError("two paused fields carry the same ciphertext");
559
+ swaps.set(dummy, fields[name]);
560
+ }
561
+ const dummies = [...swaps.keys()];
562
+ if (new Set(values).size !== values.length || values.some((value) => swaps.has(value))) {
563
+ throw new SubstitutionError("two ciphertexts in this substitution are the same");
564
+ }
565
+ const texts = [...dummies, ...values];
566
+ for (const a of texts)
567
+ for (const b of texts)
568
+ if (a !== b && b.includes(a))
569
+ throw new SubstitutionError("one ciphertext is part of another");
570
+ if ((remove.length > 0 || set.length > 0) && !roundTrips(parsed, body)) {
571
+ throw new SubstitutionError("the paused body does not round-trip through JSON, so it cannot be edited");
572
+ }
573
+ for (const entry of set) {
574
+ const parent = jsonAt(parsed, entry.path.slice(0, -1));
575
+ if (!parent.found || !isPlainObject(parent.value)) {
576
+ throw new SubstitutionError(`the paused body has no object at ${describePath(entry.path.slice(0, -1))} to write a value in`);
577
+ }
578
+ const key = entry.path[entry.path.length - 1];
579
+ const current = Object.prototype.hasOwnProperty.call(parent.value, key) ? parent.value[key] : void 0;
580
+ if (current !== null && typeof current === "object") {
581
+ throw new SubstitutionError(`refusing to write over the object at ${describePath(entry.path)}`);
582
+ }
583
+ }
584
+ const seen = /* @__PURE__ */ new Set();
585
+ const pattern = new RegExp(dummies.map((text) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|"), "g");
586
+ const swapped = body.replace(pattern, (text) => {
587
+ seen.add(text);
588
+ return swaps.get(text);
589
+ });
590
+ if (seen.size !== dummies.length)
591
+ throw new SubstitutionError("a paused field is not written verbatim in the body");
592
+ let out;
593
+ try {
594
+ out = JSON.parse(swapped);
595
+ }
596
+ catch {
597
+ throw new SubstitutionError("the substituted body is not JSON");
598
+ }
599
+ const written = jsonAt(out, path);
600
+ if (!written.found || !isPlainObject(written.value) || names.some((name) => written.value[name] !== fields[name]) || dummies.some((dummy) => swapped.includes(dummy))) {
601
+ throw new SubstitutionError(`the substitution did not land at ${describePath(path)}`);
602
+ }
603
+ if (remove.length === 0 && set.length === 0)
604
+ return swapped;
605
+ for (const key of remove)
606
+ if (Object.prototype.hasOwnProperty.call(written.value, key))
607
+ delete written.value[key];
608
+ for (const entry of set) {
609
+ const parent = jsonAt(out, entry.path.slice(0, -1));
610
+ if (!parent.found || !isPlainObject(parent.value))
611
+ throw new SubstitutionError(`the set entry at ${describePath(entry.path)} did not land`);
612
+ parent.value[entry.path[entry.path.length - 1]] = entry.value;
613
+ }
614
+ return JSON.stringify(out);
615
+ }
616
+ // src/paddle-tokenex.js
617
+ var PADDLE_TOKENEX_PSP = "paddle_tokenex";
618
+ var PADDLE_TOKENEX_CAPABILITY = "paddle_tokenex_pay";
619
+ var PADDLE_TOKENEX_OPERATION = "paddle_tokenex.encrypted_card";
620
+ var PADDLE_TOKENEX_SCHEME = "rsa-pkcs1v15";
621
+ var PADDLE_TOKENEX_FIELDS = /* @__PURE__ */ Object.freeze(["encrypted_card_number", "encrypted_cvv"]);
622
+ var PADDLE_TOKENEX_FACT_KEYS = /* @__PURE__ */ Object.freeze(["card_first_six", "card_last_four", "expiry_month", "expiry_year", "card_brand"]);
623
+ var PADDLE_TOKENEX_CARD_NETWORKS = PADDLE_VGS_CARD_NETWORKS;
624
+ var PADDLE_TOKENEX_REFUSAL_CODES = /* @__PURE__ */ Object.freeze([
625
+ "paddle_tokenex_pay_unsupported",
626
+ "paddle_tokenex_card_unsupported",
627
+ "paddle_tokenex_card_mismatch",
628
+ "paddle_tokenex_key_unavailable"
629
+ ]);
630
+ var record2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
631
+ var sameKeys = (value, keys) => {
632
+ const own = Object.keys(value);
633
+ return own.length === keys.length && own.every((key, at) => key === keys[at]);
634
+ };
635
+ var refuse2 = (code) => Object.freeze({ verdict: "refuse", code });
636
+ var CARD = /* @__PURE__ */ Object.freeze({ verdict: "card" });
637
+ var CONTINUE = /* @__PURE__ */ Object.freeze({ verdict: "continue" });
638
+ var PAY_URL = /^https:\/\/(sandbox-)?checkout-service\.paddle\.com\/(checkout|transaction-checkout)\/[A-Za-z0-9_-]{1,64}\/pay$/;
639
+ function paddleTokenexPayTarget(url) {
640
+ const match = typeof url === "string" ? PAY_URL.exec(url) : null;
641
+ return match ? Object.freeze({ environment: match[1] ? "sandbox" : "production", line: match[2] === "checkout" ? "classic" : "billing" }) : null;
642
+ }
643
+ function paddleTokenexPayCarriesCard(body) {
644
+ if (typeof body !== "string")
645
+ return true;
646
+ try {
647
+ return JSON.stringify(JSON.parse(body)).includes('"tokenex_card"');
648
+ }
649
+ catch {
650
+ return true;
651
+ }
652
+ }
653
+ var FRAME_BRANDS = /* @__PURE__ */ Object.freeze(["visa", "master", "american_express", "discover", "diners_club", "jcb", "maestro", "dankort", "unionpay", "unknown"]);
654
+ var NAME_LIMIT = 256;
655
+ var CONTROL = /[\u0000-\u001f\u007f]/;
656
+ var FIRST_SIX2 = /^[0-9]{6}$/;
657
+ var LAST_FOUR2 = /^[0-9]{4}$/;
658
+ var BASE642 = /^[A-Za-z0-9+/]+={0,2}$/;
659
+ var PAN_LIKE = /(?:[0-9][ _.:-]*){12,}/;
660
+ var cardLikeName = (name) => (name.match(/[0-9]/g) ?? []).length >= 12;
661
+ var expiryMonth2 = (month) => Number.isInteger(month) && month >= 1 && month <= 12;
662
+ var expiryYear2 = (year) => Number.isInteger(year) && year >= 2e3 && year <= 2099;
663
+ var PAY_BODY_LIMIT = 16384;
664
+ var PAY_DATA_KEYS = /* @__PURE__ */ Object.freeze(["payment_method_type", "payment_method_data"]);
665
+ var PAY_CARD_KEYS = /* @__PURE__ */ Object.freeze(["metadata", "three_d_s", "tokenex_card"]);
666
+ var METADATA_KEYS2 = /* @__PURE__ */ Object.freeze(["cardholder_name", ...PADDLE_TOKENEX_FACT_KEYS]);
667
+ var CARD_KEYS = /* @__PURE__ */ Object.freeze(["encrypted_card_number", "encrypted_cvv"]);
668
+ var BROWSER_INFO = /^[A-Za-z0-9+/]{1,4096}={0,2}$/;
669
+ var RADAR_TOKEN = /^[\x21-\x7e]{1,512}$/;
670
+ var COUNTRY_CODE = /^[A-Za-z]{2}$/;
671
+ var FRONTEND_HOST = /^https:\/\/[\x21-\x7e]{1,1024}$/;
672
+ var radarKeys = (value) => sameKeys(value, ["token", "country_code"]) || sameKeys(value, ["country_code", "token"]);
673
+ function isBase64OfBytes(value, bytes) {
674
+ if (typeof value !== "string" || value.length !== Math.ceil(bytes / 3) * 4 || !BASE642.test(value))
675
+ return false;
676
+ const pad = value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0;
677
+ return value.length / 4 * 3 - pad === bytes && btoa(atob(value)) === value;
678
+ }
679
+ function ciphertextInteger(value) {
680
+ const binary = atob(value);
681
+ let hex = "";
682
+ for (let i = 0; i < binary.length; i++)
683
+ hex += binary.charCodeAt(i).toString(16).padStart(2, "0");
684
+ return BigInt(`0x${hex}`);
685
+ }
686
+ function isPaddleTokenexCiphertextUnderKey(value, environment) {
687
+ const key = paddleTokenexKey(environment);
688
+ const bytes = paddleTokenexKeyBytes(environment);
689
+ if (!key || !bytes || !isBase64OfBytes(value, bytes))
690
+ return false;
691
+ const n = parseRsaPublicKey(key).n;
692
+ const c = ciphertextInteger(value);
693
+ return c > 1n && c < n;
694
+ }
695
+ function isPaddleTokenexCiphertext(value, environment) {
696
+ const bytes = paddleTokenexKeyBytes(environment);
697
+ return bytes !== null && isBase64OfBytes(value, bytes);
698
+ }
699
+ function readPay(body, line, environment) {
700
+ if (typeof body !== "string" || body === "" || body.length > PAY_BODY_LIMIT)
701
+ return null;
702
+ let value;
703
+ try {
704
+ value = JSON.parse(body);
705
+ if (!record2(value) || JSON.stringify(value) !== body)
706
+ return null;
707
+ }
708
+ catch {
709
+ return null;
710
+ }
711
+ const data = value.data;
712
+ if (!sameKeys(value, ["data"]) || !record2(data) || !(sameKeys(data, PAY_DATA_KEYS) || sameKeys(data, [...PAY_DATA_KEYS, "checkout"])) || data.payment_method_type !== (line === "classic" ? "CARD" : "card"))
713
+ return null;
714
+ if (data.checkout !== void 0 && !(record2(data.checkout) && sameKeys(data.checkout, ["frontend_host"]) && typeof data.checkout.frontend_host === "string" && FRONTEND_HOST.test(data.checkout.frontend_host)))
715
+ return null;
716
+ const method = data.payment_method_data;
717
+ const card = record2(method) && sameKeys(method, ["card"]) ? method.card : null;
718
+ if (!record2(card) || !(sameKeys(card, PAY_CARD_KEYS) || sameKeys(card, [...PAY_CARD_KEYS, "session_tracking"])))
719
+ return null;
720
+ const metadata = card.metadata;
721
+ if (!record2(metadata) || !sameKeys(metadata, METADATA_KEYS2) || typeof metadata.cardholder_name !== "string" || metadata.cardholder_name.length > NAME_LIMIT || CONTROL.test(metadata.cardholder_name) || cardLikeName(metadata.cardholder_name) || typeof metadata.card_first_six !== "string" || !FIRST_SIX2.test(metadata.card_first_six) || typeof metadata.card_last_four !== "string" || !LAST_FOUR2.test(metadata.card_last_four) || !expiryMonth2(metadata.expiry_month) || !expiryYear2(metadata.expiry_year) || !FRAME_BRANDS.includes(metadata.card_brand))
722
+ return null;
723
+ const details = card.three_d_s;
724
+ if (!record2(details) || !sameKeys(details, ["browser_info"]) || typeof details.browser_info !== "string" || !BROWSER_INFO.test(details.browser_info))
725
+ return null;
726
+ const tokenex = card.tokenex_card;
727
+ if (!record2(tokenex) || !sameKeys(tokenex, CARD_KEYS))
728
+ return null;
729
+ for (const name of CARD_KEYS) {
730
+ const blob = tokenex[name];
731
+ if (environment === void 0) {
732
+ if (typeof blob !== "string" || !BASE642.test(blob) || blob.length < 4 || blob.length > 4096)
733
+ return null;
734
+ }
735
+ else if (!isPaddleTokenexCiphertext(blob, environment))
736
+ return null;
737
+ }
738
+ if (tokenex.encrypted_card_number === tokenex.encrypted_cvv)
739
+ return null;
740
+ if (card.session_tracking !== void 0) {
741
+ const tracking = card.session_tracking;
742
+ const radar = record2(tracking) && sameKeys(tracking, ["stripe_radar"]) ? tracking.stripe_radar : null;
743
+ if (!record2(radar) || !radarKeys(radar) || typeof radar.token !== "string" || !RADAR_TOKEN.test(radar.token) || typeof radar.country_code !== "string" || !COUNTRY_CODE.test(radar.country_code))
744
+ return null;
745
+ }
746
+ return value;
747
+ }
748
+ function paddleTokenexRequestRefusal(request, environment) {
749
+ if (!record2(request) || typeof request.method !== "string" || request.method.toUpperCase() !== "POST")
750
+ return "paddle_tokenex_pay_unsupported";
751
+ const target = paddleTokenexPayTarget(request.url);
752
+ if (!target || environment !== void 0 && target.environment !== environment)
753
+ return "paddle_tokenex_pay_unsupported";
754
+ return readPay(request.body, target.line, environment) === null ? "paddle_tokenex_pay_unsupported" : null;
755
+ }
756
+ function isPaddleTokenexCardRequest(request) {
757
+ return record2(request) && paddleTokenexPayCarriesCard(request.body) && paddleTokenexRequestRefusal(request) === null;
758
+ }
759
+ function paddleTokenexBodyVerdict(body, line) {
760
+ if (!paddleTokenexPayCarriesCard(body))
761
+ return CONTINUE;
762
+ for (const candidate of line === "classic" || line === "billing" ? [line] : ["classic", "billing"]) {
763
+ if (readPay(body, candidate) !== null)
764
+ return CARD;
765
+ }
766
+ return refuse2("paddle_tokenex_pay_unsupported");
767
+ }
768
+ var REFUSAL_MESSAGES = /* @__PURE__ */ Object.freeze({
769
+ paddle_tokenex_pay_unsupported: "Refusing to pay: this is not the card payment Paddle's checkout sends. Nothing was sent.",
770
+ paddle_tokenex_card_unsupported: "Refusing to pay: Paddle cannot charge this card network here. Nothing was sent.",
771
+ paddle_tokenex_card_mismatch: "Refusing to pay: this Paddle payment names a card expiry or network that is not your card's. Nothing was sent.",
772
+ // The cardholder cannot act on key pinning, so this message stays plain. The code and
773
+ // encryptPaddleTokenexCard's JSDoc carry the precise reason: no TokenEx key is pinned for this
774
+ // environment (paddle-keys.js).
775
+ paddle_tokenex_key_unavailable: "Refusing to pay: Agentcard cannot pay this checkout right now. Try again later. Nothing was sent."
776
+ });
777
+ function paddleTokenexRefusalMessage(code) {
778
+ return Object.prototype.hasOwnProperty.call(REFUSAL_MESSAGES, code) ? REFUSAL_MESSAGES[code] : REFUSAL_MESSAGES.paddle_tokenex_pay_unsupported;
779
+ }
780
+ function paddleTokenexStoredCardRefusal(brand) {
781
+ const network = typeof brand === "string" && brand !== "" ? brand.toLowerCase() : null;
782
+ return network === null || PADDLE_TOKENEX_CARD_NETWORKS.some((name) => name === network) ? null : "paddle_tokenex_card_unsupported";
783
+ }
784
+ function tokenexError(code) {
785
+ const error = (
786
+ /** @type {Error & { code: string }} */
787
+ new Error(paddleTokenexRefusalMessage(code)));
788
+ error.code = code;
789
+ return error;
790
+ }
791
+ function encryptPaddleTokenexCard(card, environment, facilities = {}) {
792
+ const key = paddleTokenexKey(environment);
793
+ if (!key)
794
+ throw tokenexError("paddle_tokenex_key_unavailable");
795
+ let facts;
796
+ try {
797
+ facts = paddleVgsCardFacts(card);
798
+ }
799
+ catch {
800
+ throw tokenexError("paddle_tokenex_card_unsupported");
801
+ }
802
+ const random = facilities.crypto ?? globalThis.crypto;
803
+ const number = String(card.number);
804
+ const cvc = String(card.cvc);
805
+ const encrypt = (text) => {
806
+ const message = new TextEncoder().encode(text);
807
+ try {
808
+ return base64(rsaesPkcs1v15Encrypt(key, message, random));
809
+ }
810
+ finally {
811
+ message.fill(0);
812
+ }
813
+ };
814
+ return Object.freeze({ encrypted_card_number: encrypt(number), encrypted_cvv: encrypt(cvc), ...facts });
815
+ }
816
+ function base64(bytes) {
817
+ let binary = "";
818
+ for (let i = 0; i < bytes.length; i++)
819
+ binary += String.fromCharCode(bytes[i]);
820
+ return btoa(binary);
821
+ }
822
+ function paddleTokenexSubstitutionOf(value, environment) {
823
+ if (!record2(value))
824
+ return null;
825
+ const keys = Object.keys(value);
826
+ const all = [...PADDLE_TOKENEX_FIELDS, ...PADDLE_TOKENEX_FACT_KEYS];
827
+ if (keys.length !== all.length || !all.every((key) => keys.includes(key)))
828
+ return null;
829
+ for (const name of PADDLE_TOKENEX_FIELDS)
830
+ if (!isPaddleTokenexCiphertextUnderKey(value[name], environment))
831
+ return null;
832
+ if (value.encrypted_card_number === value.encrypted_cvv)
833
+ return null;
834
+ const facts = paddleVgsCardFactsOf({
835
+ card_first_six: value.card_first_six,
836
+ card_last_four: value.card_last_four,
837
+ expiry_month: value.expiry_month,
838
+ expiry_year: value.expiry_year,
839
+ card_brand: value.card_brand
840
+ });
841
+ if (!facts)
842
+ return null;
843
+ return Object.freeze({ encrypted_card_number: value.encrypted_card_number, encrypted_cvv: value.encrypted_cvv, ...facts });
844
+ }
845
+ var tokenexCiphertext = (environment) => Object.freeze({ accepts: (value) => isPaddleTokenexCiphertextUnderKey(value, environment), label: "a Paddle TokenEx ciphertext under the pinned key" });
846
+ var CARD_PATH = /* @__PURE__ */ Object.freeze(["data", "payment_method_data", "card"]);
847
+ var TOKENEX_PATH = /* @__PURE__ */ Object.freeze([...CARD_PATH, "tokenex_card"]);
848
+ function substitutePaddleTokenex(url, body, substitution) {
849
+ const target = paddleTokenexPayTarget(url);
850
+ if (!target)
851
+ throw new SubstitutionError("the paused request is not a Paddle TokenEx /pay");
852
+ const environment = target.environment;
853
+ const paused = readPay(body, target.line, environment);
854
+ if (!paused)
855
+ throw new SubstitutionError("the paused Paddle /pay is not the shape the vault fills");
856
+ const sub = paddleTokenexSubstitutionOf(substitution, environment);
857
+ if (!sub)
858
+ throw new SubstitutionError("the substitution is not two TokenEx ciphertexts under the pinned key and five card facts");
859
+ const placeholder = paused.data.payment_method_data.card.tokenex_card;
860
+ for (const name of PADDLE_TOKENEX_FIELDS) {
861
+ if (sub[name] === placeholder.encrypted_card_number || sub[name] === placeholder.encrypted_cvv) {
862
+ throw new SubstitutionError("a ciphertext in this substitution is already in the paused /pay");
863
+ }
864
+ }
865
+ const out = swapMerchantHostedFields(body, {
866
+ path: TOKENEX_PATH,
867
+ fields: { encrypted_card_number: sub.encrypted_card_number, encrypted_cvv: sub.encrypted_cvv },
868
+ set: PADDLE_TOKENEX_FACT_KEYS.map((key) => ({ path: [...CARD_PATH, "metadata", key], value: sub[key] }))
869
+ }, tokenexCiphertext(environment));
870
+ const written = readPay(out, target.line, environment);
871
+ if (!written)
872
+ throw new SubstitutionError("the substitution did not land in the frame's /pay shape");
873
+ const card = written.data.payment_method_data.card;
874
+ if (card.tokenex_card.encrypted_card_number !== sub.encrypted_card_number || card.tokenex_card.encrypted_cvv !== sub.encrypted_cvv || PADDLE_TOKENEX_FACT_KEYS.some((key) => card.metadata[key] !== sub[key])) {
875
+ throw new SubstitutionError("the substitution did not write the card and its facts");
876
+ }
877
+ return out;
878
+ }
879
+ function paddleTokenexKeyUsable(authorization) {
880
+ if (!record2(authorization) || !record2(authorization.cse))
881
+ return false;
882
+ const cse = authorization.cse;
883
+ if (cse.psp !== PADDLE_TOKENEX_PSP || cse.scheme !== PADDLE_TOKENEX_SCHEME)
884
+ return false;
885
+ if (cse.public_key != null || cse.client_key != null || Object.prototype.hasOwnProperty.call(cse, "merchant_hosted"))
886
+ return false;
887
+ const target = paddleTokenexPayTarget(authorization.url);
888
+ if (!target || cse.environment !== target.environment || authorization.sandbox !== (target.environment === "sandbox"))
889
+ return false;
890
+ return paddleTokenexKeyBytes(target.environment) !== null;
891
+ }
892
+ function paddleTokenexSubstitutionsRefusal(template, substitution) {
893
+ const refuseWith = (message) => ({ code: "invalid_substitutions", message });
894
+ if (!record2(template))
895
+ return refuseWith("This authorization is not a Paddle TokenEx /pay.");
896
+ const target = paddleTokenexPayTarget(template.url);
897
+ if (!target)
898
+ return refuseWith("This authorization is not a Paddle TokenEx /pay.");
899
+ const paused = readPay(template.body, target.line, target.environment);
900
+ if (!paused)
901
+ return refuseWith("The paused Paddle /pay is not the shape the vault fills.");
902
+ const sub = paddleTokenexSubstitutionOf(substitution, target.environment);
903
+ if (!sub)
904
+ return refuseWith("substitutions must carry two TokenEx ciphertexts under the pinned key and five card facts.");
905
+ const placeholder = paused.data.payment_method_data.card.tokenex_card;
906
+ if (PADDLE_TOKENEX_FIELDS.some((name) => sub[name] === placeholder.encrypted_card_number || sub[name] === placeholder.encrypted_cvv)) {
907
+ return refuseWith("substitutions must be new ciphertexts, neither already in the paused /pay.");
908
+ }
909
+ return null;
910
+ }
911
+ var ANSWER_LIMIT = 65536;
912
+ var REFUSAL_CODE = /^[A-Za-z0-9_.:-]{1,64}$/;
913
+ var MAX_CODE_DIGITS = 11;
914
+ function readAnswer(text) {
915
+ if (typeof text !== "string" || text === "" || text.length > ANSWER_LIMIT)
916
+ return null;
917
+ try {
918
+ const value = JSON.parse(text);
919
+ return record2(value) ? value : null;
920
+ }
921
+ catch {
922
+ return null;
923
+ }
924
+ }
925
+ var boundedCode = (value) => typeof value === "string" && REFUSAL_CODE.test(value) && (value.match(/[0-9]/g) ?? []).length <= MAX_CODE_DIGITS && !PAN_LIKE.test(value) ? value : null;
926
+ function paddleTokenexRefusalCode(text) {
927
+ const answer = readAnswer(text);
928
+ if (!answer)
929
+ return null;
930
+ const first = Array.isArray(answer.errors) && record2(answer.errors[0]) ? answer.errors[0] : null;
931
+ return boundedCode(first && first.error_code) ?? boundedCode(first && first.code) ?? boundedCode(answer.error_code) ?? boundedCode(answer.code);
932
+ }
933
+ function needs3ds(answer) {
934
+ const action = record2(answer) && record2(answer.data) ? answer.data.required_action : record2(answer) ? answer.required_action : null;
935
+ return record2(action) && typeof action.type === "string" && /(^|_)card$/.test(action.type);
936
+ }
937
+ function paddleTokenexAnswerOutcome(status, text) {
938
+ if (!Number.isInteger(status))
939
+ return { outcome: "unknown", reason: "paddle_tokenex_unconfirmed" };
940
+ if (status >= 500)
941
+ return { outcome: "unknown", reason: "server_error" };
942
+ if (status >= 400)
943
+ return { outcome: "refused", code: paddleTokenexRefusalCode(text) ?? `http_${status}` };
944
+ if (status !== 200 && status !== 201)
945
+ return { outcome: "unknown", reason: "paddle_tokenex_unconfirmed" };
946
+ const answer = readAnswer(text);
947
+ if (answer === null)
948
+ return { outcome: "unknown", reason: "paddle_tokenex_unconfirmed" };
949
+ return needs3ds(answer) ? { outcome: "challenge" } : { outcome: "approved" };
950
+ }
951
+ export { PADDLE_TOKENEX_CAPABILITY, PADDLE_TOKENEX_CARD_NETWORKS, PADDLE_TOKENEX_FACT_KEYS, PADDLE_TOKENEX_FIELDS, PADDLE_TOKENEX_OPERATION, PADDLE_TOKENEX_PSP, PADDLE_TOKENEX_REFUSAL_CODES, PADDLE_TOKENEX_SCHEME, encryptPaddleTokenexCard, isPaddleTokenexCardRequest, isPaddleTokenexCiphertext, isPaddleTokenexCiphertextUnderKey, paddleTokenexAnswerOutcome, paddleTokenexBodyVerdict, paddleVgsCardFactsAgree as paddleTokenexCardFactsAgree, paddleTokenexKeyUsable, paddleTokenexPayCarriesCard, paddleTokenexPayTarget, paddleTokenexRefusalCode, paddleTokenexRefusalMessage, paddleTokenexRequestRefusal, paddleTokenexStoredCardRefusal, paddleTokenexSubstitutionOf, paddleTokenexSubstitutionsRefusal, substitutePaddleTokenex };