cinetpay-seamless 0.1.4 → 0.1.5

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/README.md CHANGED
@@ -36,7 +36,7 @@ npm install cinetpay-seamless
36
36
  ### CDN
37
37
 
38
38
  ```html
39
- <script src="https://unpkg.com/cinetpay-seamless@0.1.4/dist/cinetpay-seamless.umd.cjs"></script>
39
+ <script src="https://unpkg.com/cinetpay-seamless@0.1.5/dist/cinetpay-seamless.umd.cjs"></script>
40
40
  ```
41
41
 
42
42
  ## Démarrage rapide
@@ -44,7 +44,7 @@ npm install cinetpay-seamless
44
44
  ```typescript
45
45
  import { CinetPaySeamless } from 'cinetpay-seamless'
46
46
 
47
- // 1. Obtenir le paymentToken depuis votre backend
47
+ // 1. Obtenir le paymentToken et, idéalement, paymentUrl depuis votre backend
48
48
  const { paymentToken, paymentUrl } = await fetch('/api/pay', {
49
49
  method: 'POST',
50
50
  headers: { 'Content-Type': 'application/json' },
@@ -54,7 +54,7 @@ const { paymentToken, paymentUrl } = await fetch('/api/pay', {
54
54
  // 2. Ouvrir la popup
55
55
  CinetPaySeamless.open({
56
56
  paymentToken,
57
- paymentUrl, // recommandé si votre backend renvoie l'URL CinetPay exacte
57
+ paymentUrl, // recommandé en production: URL CinetPay exacte renvoyée par l'API
58
58
  onPaymentSuccess: (data) => {
59
59
  console.log('Paiement réussi !', data.amount, data.currency)
60
60
  },
@@ -69,7 +69,7 @@ CinetPaySeamless.open({
69
69
  ```html
70
70
  <button id="pay-btn">Payer 5 000 XOF</button>
71
71
 
72
- <script src="https://unpkg.com/cinetpay-seamless@0.1.4/dist/cinetpay-seamless.umd.cjs"></script>
72
+ <script src="https://unpkg.com/cinetpay-seamless@0.1.5/dist/cinetpay-seamless.umd.cjs"></script>
73
73
  <script>
74
74
  document.getElementById('pay-btn').addEventListener('click', function() {
75
75
  // Appeler votre backend pour obtenir le paymentToken
@@ -168,6 +168,39 @@ Ouvre la popup de paiement CinetPay.
168
168
  | `onClose` | `({ status }) => void` | - | Modal fermé |
169
169
  | `onError` | `(error) => void` | - | Erreur technique |
170
170
 
171
+ ### Éviter les 404 en production
172
+
173
+ En production, privilégiez toujours l'URL complète renvoyée par CinetPay dans la
174
+ réponse de `POST /v1/payment` (`payment_url`). Ne reconstruisez pas vous-même une
175
+ URL checkout si cette URL est disponible.
176
+
177
+ ```typescript
178
+ // Backend: renvoyer les deux champs utiles au frontend
179
+ res.json({
180
+ paymentToken: payment.paymentToken ?? payment.payment_token,
181
+ paymentUrl: payment.paymentUrl ?? payment.payment_url,
182
+ })
183
+
184
+ // Frontend: ouvrir l'URL exacte CinetPay
185
+ CinetPaySeamless.open({
186
+ paymentToken,
187
+ paymentUrl,
188
+ environment: 'production',
189
+ })
190
+ ```
191
+
192
+ Le SDK accepte aussi les noms bruts CinetPay côté JavaScript :
193
+
194
+ ```javascript
195
+ CinetPaySeamless.open({
196
+ payment_token: data.payment_token,
197
+ payment_url: data.payment_url,
198
+ })
199
+ ```
200
+
201
+ Si `paymentUrl` / `payment_url` est fourni, il est prioritaire et le SDK ne
202
+ reconstruit pas `https://secure.cinetpay.co/checkout/{paymentToken}`.
203
+
171
204
  ### `CinetPaySeamless.on(event, handler)`
172
205
 
173
206
  | Événement | Donnée | Description |
@@ -295,8 +328,8 @@ app.post('/api/pay', async (req, res) => {
295
328
  }, 'CI')
296
329
 
297
330
  res.json({
298
- paymentToken: payment.paymentToken,
299
- paymentUrl: payment.paymentUrl,
331
+ paymentToken: payment.paymentToken ?? payment.payment_token,
332
+ paymentUrl: payment.paymentUrl ?? payment.payment_url,
300
333
  })
301
334
  })
302
335
  ```
@@ -544,7 +577,7 @@ async function pay() {
544
577
  <meta charset="UTF-8">
545
578
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
546
579
  <title>Paiement</title>
547
- <script src="https://unpkg.com/cinetpay-seamless@0.1.4/dist/cinetpay-seamless.umd.cjs"></script>
580
+ <script src="https://unpkg.com/cinetpay-seamless@0.1.5/dist/cinetpay-seamless.umd.cjs"></script>
548
581
  </head>
549
582
  <body>
550
583
  <form id="payment-form">
@@ -645,7 +678,7 @@ CinetPaySeamless.open({ paymentToken: 'abc...', debug: true })
645
678
 
646
679
  ```
647
680
  [CinetPay Seamless] CinetPaySeamless.open() called
648
- [CinetPay Seamless] Opening popup { paymentUrl: 'https://secure.cinetpay.co/checkout/abc...' }
681
+ [CinetPay Seamless] Opening popup { paymentUrl: 'https://secure.cinetpay.co/payment/abc...' }
649
682
  [CinetPay Seamless] Iframe loaded — checkout ready
650
683
  [CinetPay Seamless] Payment response: ACCEPTED { amount: 5000, currency: 'XOF', ... }
651
684
  [CinetPay Seamless] Payment accepted
@@ -1,4 +1,4 @@
1
- const y = `
1
+ const g = `
2
2
  .cp-seamless-overlay {
3
3
  position: fixed;
4
4
  inset: 0;
@@ -79,7 +79,7 @@ const y = `
79
79
  }
80
80
 
81
81
  `;
82
- const n = class n {
82
+ const a = class a {
83
83
  constructor(t) {
84
84
  this.overlay = null, this.popup = null, this.pollTimer = null, this.statusTimer = null, this.closeTimer = null, this.messageHandler = null, this.lastStatus = "UNKNOWN", this.lastDispatchKey = "", this.finalStatusDispatched = !1, this.statusCheckInFlight = !1, this.isClosing = !1, this.previousBodyOverflow = "", this.logger = t.logger, this.emitter = t.emitter, this.onReadyCallback = t.onReady, this.onPaymentSuccessCallback = t.onPaymentSuccess, this.onPaymentFailedCallback = t.onPaymentFailed, this.onPaymentPendingCallback = t.onPaymentPending, this.onCloseCallback = t.onClose, this.onErrorCallback = t.onError, this.statusChecker = t.statusChecker, this.statusPollInterval = Math.max(
85
85
  1e3,
@@ -127,16 +127,16 @@ const n = class n {
127
127
  }
128
128
  static childRecords(t) {
129
129
  const e = [];
130
- for (const i of ["details", "transaction", "payment", "result", "data"]) {
131
- const s = t[i];
132
- n.isRecord(s) && e.push(s);
130
+ for (const s of ["details", "transaction", "payment", "result", "data"]) {
131
+ const n = t[s];
132
+ a.isRecord(n) && e.push(n);
133
133
  }
134
134
  return e.push(t), e;
135
135
  }
136
136
  static findValue(t, e) {
137
- for (const i of n.childRecords(t))
138
- for (const s of e)
139
- if (i[s] !== void 0 && i[s] !== null) return i[s];
137
+ for (const s of a.childRecords(t))
138
+ for (const n of e)
139
+ if (s[n] !== void 0 && s[n] !== null) return s[n];
140
140
  }
141
141
  static asString(t) {
142
142
  if (t != null)
@@ -160,9 +160,9 @@ const n = class n {
160
160
  }
161
161
  }
162
162
  static normalizeStatus(t, e) {
163
- const i = t == null ? void 0 : t.trim().toUpperCase().replace(/[\s-]+/g, "_");
164
- if (i) {
165
- if (["ACCEPTED", "SUCCESS", "SUCCEEDED", "SUCCESSFUL", "PAID", "VALIDATED", "APPROVED"].includes(i))
163
+ const s = t == null ? void 0 : t.trim().toUpperCase().replace(/[\s-]+/g, "_");
164
+ if (s) {
165
+ if (["ACCEPTED", "SUCCESS", "SUCCEEDED", "SUCCESSFUL", "PAID", "VALIDATED", "APPROVED"].includes(s))
166
166
  return "ACCEPTED";
167
167
  if ([
168
168
  "REFUSED",
@@ -176,11 +176,11 @@ const n = class n {
176
176
  "CANCELLED",
177
177
  "CANCEL",
178
178
  "INSUFFICIENT_BALANCE"
179
- ].includes(i))
179
+ ].includes(s))
180
180
  return "REFUSED";
181
- if (["PENDING", "INITIATED", "EXPIRED"].includes(i))
182
- return i;
183
- if (["WAITING", "PROCESSING", "IN_PROGRESS"].includes(i))
181
+ if (["PENDING", "INITIATED", "EXPIRED"].includes(s))
182
+ return s;
183
+ if (["WAITING", "PROCESSING", "IN_PROGRESS"].includes(s))
184
184
  return "PENDING";
185
185
  }
186
186
  switch (e) {
@@ -202,39 +202,39 @@ const n = class n {
202
202
  return t === "ACCEPTED" || t === "REFUSED";
203
203
  }
204
204
  static buildPaymentResponse(t) {
205
- const e = n.asString(n.findValue(t, [
205
+ const e = a.asString(a.findValue(t, [
206
206
  "status",
207
207
  "transaction_status",
208
208
  "trans_status",
209
209
  "payment_status"
210
- ])), i = n.asOptionalNumber(n.findValue(t, ["code"])), s = n.normalizeStatus(e, i);
210
+ ])), s = a.asOptionalNumber(a.findValue(t, ["code"])), n = a.normalizeStatus(e, s);
211
211
  return {
212
- amount: n.asNumber(n.findValue(t, ["amount"])),
213
- currency: n.asString(n.findValue(t, ["currency"])) ?? "",
214
- status: s,
212
+ amount: a.asNumber(a.findValue(t, ["amount"])),
213
+ currency: a.asString(a.findValue(t, ["currency"])) ?? "",
214
+ status: n,
215
215
  rawStatus: e,
216
- apiCode: i,
217
- paymentMethod: n.asString(n.findValue(t, ["payment_method", "paymentMethod"])) ?? "",
218
- description: n.asString(n.findValue(t, ["description", "designation", "message"])) ?? "",
219
- metadata: n.asString(n.findValue(t, ["metadata", "custom"])),
220
- operatorId: n.asString(n.findValue(t, ["operator_id", "operatorId"])),
221
- paymentDate: n.asString(n.findValue(t, ["payment_date", "paymentDate"])),
222
- transactionId: n.asString(n.findValue(t, ["transaction_id", "transactionId", "merchant_transaction_id"])) ?? ""
216
+ apiCode: s,
217
+ paymentMethod: a.asString(a.findValue(t, ["payment_method", "paymentMethod"])) ?? "",
218
+ description: a.asString(a.findValue(t, ["description", "designation", "message"])) ?? "",
219
+ metadata: a.asString(a.findValue(t, ["metadata", "custom"])),
220
+ operatorId: a.asString(a.findValue(t, ["operator_id", "operatorId"])),
221
+ paymentDate: a.asString(a.findValue(t, ["payment_date", "paymentDate"])),
222
+ transactionId: a.asString(a.findValue(t, ["transaction_id", "transactionId", "merchant_transaction_id"])) ?? ""
223
223
  };
224
224
  }
225
225
  /** Dispatche la réponse vers le bon callback selon le statut. */
226
226
  dispatchResponse(t) {
227
- var s, r, o;
228
- const e = `${t.status}:${t.rawStatus ?? ""}:${t.apiCode ?? ""}`, i = n.isFinalStatus(t.status);
229
- if (!(i && this.finalStatusDispatched) && e !== this.lastDispatchKey)
230
- switch (this.lastDispatchKey = e, this.lastStatus = t.status, i && (this.finalStatusDispatched = !0, this.stopStatusPolling()), this.logger.debug(`Payment response: ${t.status}`, {
227
+ var n, r, o;
228
+ const e = `${t.status}:${t.rawStatus ?? ""}:${t.apiCode ?? ""}`, s = a.isFinalStatus(t.status);
229
+ if (!(s && this.finalStatusDispatched) && e !== this.lastDispatchKey)
230
+ switch (this.lastDispatchKey = e, this.lastStatus = t.status, s && (this.finalStatusDispatched = !0, this.stopStatusPolling()), this.logger.debug(`Payment response: ${t.status}`, {
231
231
  amount: t.amount,
232
232
  currency: t.currency,
233
233
  transactionId: t.transactionId,
234
234
  paymentMethod: t.paymentMethod
235
235
  }), t.status) {
236
236
  case "ACCEPTED":
237
- this.logger.debug("Payment accepted"), this.emitter.emit("payment.success", t), (s = this.onPaymentSuccessCallback) == null || s.call(this, t);
237
+ this.logger.debug("Payment accepted"), this.emitter.emit("payment.success", t), (n = this.onPaymentSuccessCallback) == null || n.call(this, t);
238
238
  break;
239
239
  case "REFUSED":
240
240
  this.logger.warn("Payment refused"), this.emitter.emit("payment.failed", t), (r = this.onPaymentFailedCallback) == null || r.call(this, t);
@@ -250,7 +250,7 @@ const n = class n {
250
250
  injectStyles() {
251
251
  if (document.getElementById("cp-seamless-styles")) return;
252
252
  const t = document.createElement("style");
253
- t.id = "cp-seamless-styles", t.textContent = y, document.head.appendChild(t);
253
+ t.id = "cp-seamless-styles", t.textContent = g, document.head.appendChild(t);
254
254
  }
255
255
  createOverlay() {
256
256
  this.overlay = document.createElement("div"), this.overlay.className = "cp-seamless-overlay";
@@ -258,10 +258,10 @@ const n = class n {
258
258
  t.className = "cp-seamless-wrapper";
259
259
  const e = document.createElement("div");
260
260
  e.className = "cp-seamless-waiting";
261
- const i = document.createElement("div");
262
- i.className = "cp-seamless-spinner", e.appendChild(i);
263
- const s = document.createElement("p");
264
- s.className = "cp-seamless-waiting-title", s.textContent = "Paiement en cours...", e.appendChild(s);
261
+ const s = document.createElement("div");
262
+ s.className = "cp-seamless-spinner", e.appendChild(s);
263
+ const n = document.createElement("p");
264
+ n.className = "cp-seamless-waiting-title", n.textContent = "Paiement en cours...", e.appendChild(n);
265
265
  const r = document.createElement("p");
266
266
  r.className = "cp-seamless-waiting-msg", r.textContent = "Finalisez votre paiement dans la fenêtre CinetPay.", e.appendChild(r);
267
267
  const o = document.createElement("button");
@@ -271,22 +271,22 @@ const n = class n {
271
271
  * Ouvre la popup centrée sur l'écran.
272
272
  */
273
273
  openPopup(t) {
274
- var o, u;
275
- const s = Math.max(0, (screen.width - 500) / 2), r = Math.max(0, (screen.height - 700) / 2);
274
+ var o, h;
275
+ const n = Math.max(0, (screen.width - 500) / 2), r = Math.max(0, (screen.height - 700) / 2);
276
276
  if (this.popup = window.open(
277
277
  t,
278
278
  "CinetPayCheckout",
279
- `width=500,height=700,left=${s},top=${r},scrollbars=yes,resizable=yes`
279
+ `width=500,height=700,left=${n},top=${r},scrollbars=yes,resizable=yes`
280
280
  ), !this.popup) {
281
281
  this.logger.error("Popup blocked by browser");
282
- const h = {
282
+ const p = {
283
283
  code: "POPUP_BLOCKED",
284
284
  message: "La fenêtre de paiement a été bloquée par le navigateur. Autorisez les popups pour ce site."
285
285
  };
286
- this.emitter.emit("error", h), (o = this.onErrorCallback) == null || o.call(this, h), this.close();
286
+ this.emitter.emit("error", p), (o = this.onErrorCallback) == null || o.call(this, p), this.close();
287
287
  return;
288
288
  }
289
- this.logger.debug("Popup opened"), this.emitter.emit("ready"), (u = this.onReadyCallback) == null || u.call(this);
289
+ this.logger.debug("Popup opened"), this.emitter.emit("ready"), (h = this.onReadyCallback) == null || h.call(this);
290
290
  }
291
291
  /**
292
292
  * Poll toutes les 500ms pour détecter si la popup a été fermée
@@ -316,12 +316,12 @@ const n = class n {
316
316
  this.statusCheckInFlight = !0;
317
317
  try {
318
318
  this.logger.debug("Checking payment status", { reason: t });
319
- const i = await this.statusChecker();
320
- if (!n.isRecord(i)) return;
321
- const s = n.buildPaymentResponse(i), r = (e = s.rawStatus) == null ? void 0 : e.trim().toUpperCase();
322
- (s.status !== "UNKNOWN" || r && r !== "OK") && this.dispatchResponse(s), n.isFinalStatus(s.status) && this.finishClose();
323
- } catch (i) {
324
- this.logger.warn("Payment status check failed", i);
319
+ const s = await this.statusChecker();
320
+ if (!a.isRecord(s)) return;
321
+ const n = a.buildPaymentResponse(s), r = (e = n.rawStatus) == null ? void 0 : e.trim().toUpperCase();
322
+ (n.status !== "UNKNOWN" || r && r !== "OK") && this.dispatchResponse(n), a.isFinalStatus(n.status) && this.finishClose();
323
+ } catch (s) {
324
+ this.logger.warn("Payment status check failed", s);
325
325
  } finally {
326
326
  this.statusCheckInFlight = !1;
327
327
  }
@@ -330,28 +330,28 @@ const n = class n {
330
330
  /** Écoute les messages postMessage de la popup CinetPay. */
331
331
  listenForMessages() {
332
332
  this.messageHandler = (t) => {
333
- var e, i;
334
- if (n.ALLOWED_ORIGINS.some((s) => t.origin === s))
333
+ var e, s;
334
+ if (a.ALLOWED_ORIGINS.some((n) => t.origin === n))
335
335
  try {
336
- const s = typeof t.data == "string" ? JSON.parse(t.data) : t.data;
337
- if (!n.isRecord(s)) return;
338
- const r = n.buildPaymentResponse(s), o = (e = r.rawStatus) == null ? void 0 : e.trim().toUpperCase();
336
+ const n = typeof t.data == "string" ? JSON.parse(t.data) : t.data;
337
+ if (!a.isRecord(n)) return;
338
+ const r = a.buildPaymentResponse(n), o = (e = r.rawStatus) == null ? void 0 : e.trim().toUpperCase();
339
339
  (r.status !== "UNKNOWN" || o && o !== "OK") && this.dispatchResponse(r);
340
- const u = n.findValue(s, ["error"]), h = n.asString(n.findValue(s, ["code"]));
341
- if (u || h === "ERROR") {
340
+ const h = a.findValue(n, ["error"]), p = a.asString(a.findValue(n, ["code"]));
341
+ if (h || p === "ERROR") {
342
342
  const d = {
343
- code: h ?? "UNKNOWN",
344
- message: n.asString(n.findValue(s, ["message"])) ?? n.asString(u) ?? "An error occurred"
343
+ code: p ?? "UNKNOWN",
344
+ message: a.asString(a.findValue(n, ["message"])) ?? a.asString(h) ?? "An error occurred"
345
345
  };
346
- this.logger.error("Payment error from popup", d), this.emitter.emit("error", d), (i = this.onErrorCallback) == null || i.call(this, d);
346
+ this.logger.error("Payment error from popup", d), this.emitter.emit("error", d), (s = this.onErrorCallback) == null || s.call(this, d);
347
347
  }
348
- (s.action === "CLOSE" || s.type === "close") && this.close();
348
+ (n.action === "CLOSE" || n.type === "close") && this.close();
349
349
  } catch {
350
350
  }
351
351
  }, window.addEventListener("message", this.messageHandler);
352
352
  }
353
353
  };
354
- n.ALLOWED_ORIGINS = [
354
+ a.ALLOWED_ORIGINS = [
355
355
  "https://secure.cinetpay.net",
356
356
  "https://secure.cinetpay.co",
357
357
  "https://secure.cinetpay.com",
@@ -361,9 +361,9 @@ n.ALLOWED_ORIGINS = [
361
361
  "https://api.cinetpay.net",
362
362
  "https://api.cinetpay.co"
363
363
  ];
364
- let m = n;
364
+ let m = a;
365
365
  const l = "[CinetPay Seamless]";
366
- class g {
366
+ class S {
367
367
  constructor(t) {
368
368
  this.enabled = t;
369
369
  }
@@ -380,7 +380,7 @@ class g {
380
380
  this.enabled && (e !== void 0 ? console.error(`${l} ${t}`, e) : console.error(`${l} ${t}`));
381
381
  }
382
382
  }
383
- class S {
383
+ class C {
384
384
  constructor() {
385
385
  this.listeners = /* @__PURE__ */ new Map();
386
386
  }
@@ -408,8 +408,8 @@ class S {
408
408
  * @param handler - Référence du handler à supprimer
409
409
  */
410
410
  off(t, e) {
411
- var i;
412
- (i = this.listeners.get(t)) == null || i.delete(e);
411
+ var s;
412
+ (s = this.listeners.get(t)) == null || s.delete(e);
413
413
  }
414
414
  /**
415
415
  * Enregistre un handler qui ne sera appelé qu'une seule fois.
@@ -425,21 +425,21 @@ class S {
425
425
  * ```
426
426
  */
427
427
  once(t, e) {
428
- const i = ((...s) => {
429
- this.off(t, i), e(...s);
428
+ const s = ((...n) => {
429
+ this.off(t, s), e(...n);
430
430
  });
431
- this.on(t, i);
431
+ this.on(t, s);
432
432
  }
433
433
  /**
434
434
  * Émet un événement — appelle tous les handlers enregistrés.
435
435
  * @internal
436
436
  */
437
437
  emit(t, ...e) {
438
- const i = this.listeners.get(t);
439
- if (i)
440
- for (const s of i)
438
+ const s = this.listeners.get(t);
439
+ if (s)
440
+ for (const n of s)
441
441
  try {
442
- s(...e);
442
+ n(...e);
443
443
  } catch {
444
444
  }
445
445
  }
@@ -451,41 +451,47 @@ class S {
451
451
  this.listeners.clear();
452
452
  }
453
453
  }
454
- const f = {
454
+ const y = {
455
455
  sandbox: "https://secure.cinetpay.net",
456
456
  production: "https://secure.cinetpay.co"
457
457
  };
458
- function c(a, t) {
459
- const e = a;
460
- for (const s of t) {
461
- const r = e[s];
458
+ function c(i, t) {
459
+ const e = i;
460
+ for (const n of t) {
461
+ const r = e[n];
462
462
  if (typeof r == "function") return r;
463
463
  }
464
- const i = new Set(t.map((s) => s.toLowerCase()));
465
- for (const [s, r] of Object.entries(e))
466
- if (i.has(s.toLowerCase()) && typeof r == "function")
464
+ const s = new Set(t.map((n) => n.toLowerCase()));
465
+ for (const [n, r] of Object.entries(e))
466
+ if (s.has(n.toLowerCase()) && typeof r == "function")
467
467
  return r;
468
468
  }
469
- function p(a, t) {
470
- const e = a;
471
- for (const s of t)
472
- if (e[s] !== void 0) return e[s];
473
- const i = new Set(t.map((s) => s.toLowerCase()));
474
- for (const [s, r] of Object.entries(e))
475
- if (i.has(s.toLowerCase())) return r;
469
+ function u(i, t) {
470
+ const e = i;
471
+ for (const n of t)
472
+ if (e[n] !== void 0) return e[n];
473
+ const s = new Set(t.map((n) => n.toLowerCase()));
474
+ for (const [n, r] of Object.entries(e))
475
+ if (s.has(n.toLowerCase())) return r;
476
476
  }
477
- function C(a) {
478
- const t = { paymentToken: a.paymentToken }, e = c(a, [
477
+ function f(i) {
478
+ return u(i, ["paymentToken", "payment_token"]);
479
+ }
480
+ function E(i) {
481
+ return u(i, ["paymentUrl", "paymentURL", "payment_url", "checkoutUrl", "checkout_url"]);
482
+ }
483
+ function P(i) {
484
+ const t = { paymentToken: f(i) ?? "" }, e = c(i, [
479
485
  "checkStatus",
480
486
  "checkPaymentStatus",
481
487
  "checkTransactionStatus"
482
488
  ]);
483
489
  if (e)
484
490
  return () => e(t);
485
- const i = p(a, ["statusUrl", "statusURL"]);
486
- if (i)
491
+ const s = u(i, ["statusUrl", "statusURL"]);
492
+ if (s)
487
493
  return async () => {
488
- const s = typeof i == "function" ? i(t) : i, r = await fetch(s, {
494
+ const n = typeof s == "function" ? s(t) : s, r = await fetch(n, {
489
495
  method: "GET",
490
496
  credentials: "same-origin",
491
497
  headers: { Accept: "application/json" }
@@ -495,17 +501,20 @@ function C(a) {
495
501
  return r.json();
496
502
  };
497
503
  }
498
- function E(a) {
499
- const t = p(a, ["paymentUrl", "checkoutUrl"]);
504
+ function b(i) {
505
+ const t = E(i);
500
506
  if (t) return t;
501
- const e = p(a, ["environment", "env"]) ?? "sandbox";
502
- return `${(p(a, ["checkoutBaseUrl", "secureBaseUrl"]) ?? f[e] ?? f.sandbox).replace(/\/+$/, "")}/checkout/${a.paymentToken}`;
507
+ const e = f(i);
508
+ if (!e)
509
+ throw new Error("Invalid paymentToken format — expected alphanumeric string (10-128 chars)");
510
+ const s = u(i, ["environment", "env"]) ?? "sandbox";
511
+ return `${(u(i, ["checkoutBaseUrl", "secureBaseUrl"]) ?? y[s] ?? y.sandbox).replace(/\/+$/, "")}/checkout/${e}`;
503
512
  }
504
- const P = {
513
+ const k = {
505
514
  /** Instance du checkout actuellement ouvert */
506
515
  _checkout: null,
507
516
  /** Event emitter partagé */
508
- _emitter: new S(),
517
+ _emitter: new C(),
509
518
  /**
510
519
  * Enregistre un listener d'événement (style événementiel).
511
520
  *
@@ -521,20 +530,20 @@ const P = {
521
530
  * unsub() // Se désabonner
522
531
  * ```
523
532
  */
524
- on(a, t) {
525
- return this._emitter.on(a, t);
533
+ on(i, t) {
534
+ return this._emitter.on(i, t);
526
535
  },
527
536
  /**
528
537
  * Supprime un listener.
529
538
  */
530
- off(a, t) {
531
- this._emitter.off(a, t);
539
+ off(i, t) {
540
+ this._emitter.off(i, t);
532
541
  },
533
542
  /**
534
543
  * Enregistre un listener appelé une seule fois.
535
544
  */
536
- once(a, t) {
537
- this._emitter.once(a, t);
545
+ once(i, t) {
546
+ this._emitter.once(i, t);
538
547
  },
539
548
  /**
540
549
  * Ouvre le checkout CinetPay.
@@ -556,26 +565,28 @@ const P = {
556
565
  * })
557
566
  * ```
558
567
  */
559
- open(a) {
568
+ open(i) {
560
569
  this.close();
561
- const t = new g(a.debug ?? !1);
562
- if (t.debug("CinetPaySeamless.open() called"), !/^[a-zA-Z0-9_-]{10,128}$/.test(a.paymentToken))
570
+ const t = new S(i.debug ?? !1);
571
+ t.debug("CinetPaySeamless.open() called");
572
+ const e = f(i);
573
+ if (e && !/^[a-zA-Z0-9_-]{10,128}$/.test(e))
563
574
  throw new Error("Invalid paymentToken format — expected alphanumeric string (10-128 chars)");
564
- const e = E(a);
575
+ const s = b(i);
565
576
  this._checkout = new m({
566
577
  logger: t,
567
578
  emitter: this._emitter,
568
- statusChecker: C(a),
569
- statusPollInterval: p(a, ["statusPollInterval", "statusCheckInterval"]),
570
- onReady: c(a, ["onReady"]),
571
- onPaymentSuccess: c(a, [
579
+ statusChecker: P(i),
580
+ statusPollInterval: u(i, ["statusPollInterval", "statusCheckInterval"]),
581
+ onReady: c(i, ["onReady"]),
582
+ onPaymentSuccess: c(i, [
572
583
  "onPaymentSuccess",
573
584
  "onSuccess",
574
585
  "onPaymentsuccess",
575
586
  "onpaymentSuccess",
576
587
  "onpaymentsuccess"
577
588
  ]),
578
- onPaymentFailed: c(a, [
589
+ onPaymentFailed: c(i, [
579
590
  "onPaymentFailed",
580
591
  "onPaymentFail",
581
592
  "onPaymentFailure",
@@ -584,21 +595,21 @@ const P = {
584
595
  "onpaymentFailed",
585
596
  "onpaymentfailed"
586
597
  ]),
587
- onPaymentPending: c(a, ["onPaymentPending", "onPending"]),
588
- onClose: c(a, ["onClose"]),
589
- onError: c(a, ["onError"])
590
- }), this._checkout.open(e);
598
+ onPaymentPending: c(i, ["onPaymentPending", "onPending"]),
599
+ onClose: c(i, ["onClose"]),
600
+ onError: c(i, ["onError"])
601
+ }), this._checkout.open(s);
591
602
  },
592
603
  /**
593
604
  * Ferme le checkout (popup + overlay).
594
605
  */
595
606
  close() {
596
- var a;
597
- (a = this._checkout) == null || a.close(), this._checkout = null;
607
+ var i;
608
+ (i = this._checkout) == null || i.close(), this._checkout = null;
598
609
  }
599
610
  };
600
- typeof window < "u" && (window.CinetPaySeamless = P);
611
+ typeof window < "u" && (window.CinetPaySeamless = k);
601
612
  export {
602
- P as CinetPaySeamless
613
+ k as CinetPaySeamless
603
614
  };
604
615
  //# sourceMappingURL=cinetpay-seamless.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cinetpay-seamless.js","sources":["../src/styles.ts","../src/checkout.ts","../src/logger.ts","../src/emitter.ts","../src/index.ts"],"sourcesContent":["/**\n * Styles CSS du checkout CinetPay Seamless (mode popup).\n */\nexport const STYLES = `\n.cp-seamless-overlay {\n position: fixed;\n inset: 0;\n z-index: 999999;\n background: rgba(0, 0, 0, 0.7);\n backdrop-filter: blur(6px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n transition: opacity 0.3s ease;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n.cp-seamless-overlay.cp-visible {\n opacity: 1;\n}\n\n.cp-seamless-wrapper {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Waiting screen (pendant que la popup est ouverte) */\n.cp-seamless-waiting {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 20px;\n text-align: center;\n padding: 40px;\n}\n\n.cp-seamless-waiting-title {\n color: #fff;\n font-size: 22px;\n font-weight: 600;\n margin: 0;\n}\n\n.cp-seamless-waiting-msg {\n color: rgba(255, 255, 255, 0.7);\n font-size: 15px;\n margin: 0;\n max-width: 320px;\n line-height: 1.5;\n}\n\n.cp-seamless-spinner {\n width: 48px;\n height: 48px;\n border: 3px solid rgba(255, 255, 255, 0.2);\n border-top-color: #e8530e;\n border-radius: 50%;\n animation: cp-spin 0.8s linear infinite;\n}\n\n@keyframes cp-spin {\n to { transform: rotate(360deg); }\n}\n\n.cp-seamless-cancel-btn {\n margin-top: 12px;\n padding: 10px 28px;\n background: rgba(255, 255, 255, 0.12);\n color: rgba(255, 255, 255, 0.8);\n border: 1px solid rgba(255, 255, 255, 0.2);\n border-radius: 8px;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.cp-seamless-cancel-btn:hover {\n background: rgba(255, 255, 255, 0.2);\n color: #fff;\n}\n\n`\n","import { STYLES } from './styles'\nimport type { PaymentResponse, PaymentError, PaymentStatus } from './types'\nimport { Logger } from './logger'\nimport { EventEmitter } from './emitter'\n\ntype StatusChecker = () => Promise<unknown>\n\n/** @internal Options du constructeur Checkout */\nexport interface CheckoutOptions {\n onReady?: () => void\n onPaymentSuccess?: (data: PaymentResponse) => void\n onPaymentFailed?: (data: PaymentResponse) => void\n onPaymentPending?: (data: PaymentResponse) => void\n onClose?: (data: { status: string }) => void\n onError?: (error: PaymentError) => void\n statusChecker?: StatusChecker\n statusPollInterval?: number\n logger: Logger\n emitter: EventEmitter\n}\n\n/** @internal Intervalle de polling pour vérifier si la popup est fermée */\nconst POPUP_POLL_INTERVAL = 500\n/** @internal Intervalle par défaut pour vérifier le statut via le backend marchand */\nconst STATUS_POLL_INTERVAL = 3000\n/** @internal Évite un polling trop agressif depuis le navigateur */\nconst MIN_STATUS_POLL_INTERVAL = 1000\n\n/**\n * Gère le checkout CinetPay via une popup window + overlay.\n *\n * Flow :\n * 1. Affiche un overlay sombre avec un message d'attente\n * 2. Ouvre la page de checkout dans une popup (window.open)\n * 3. Poll la popup pour détecter sa fermeture\n * 4. Écoute les messages postMessage de la popup\n * 5. Ferme l'overlay et dispatche les callbacks\n *\n * @internal Utilisé par {@link CinetPaySeamless}. Ne pas instancier directement.\n */\nexport class Checkout {\n private overlay: HTMLDivElement | null = null\n private popup: Window | null = null\n private pollTimer: ReturnType<typeof setInterval> | null = null\n private statusTimer: ReturnType<typeof setInterval> | null = null\n private closeTimer: ReturnType<typeof setTimeout> | null = null\n private messageHandler: ((event: MessageEvent) => void) | null = null\n private lastStatus = 'UNKNOWN'\n private lastDispatchKey = ''\n private finalStatusDispatched = false\n private statusCheckInFlight = false\n private isClosing = false\n private previousBodyOverflow = ''\n\n private onReadyCallback?: () => void\n private onPaymentSuccessCallback?: (data: PaymentResponse) => void\n private onPaymentFailedCallback?: (data: PaymentResponse) => void\n private onPaymentPendingCallback?: (data: PaymentResponse) => void\n private onCloseCallback?: (data: { status: string }) => void\n private onErrorCallback?: (error: PaymentError) => void\n private statusChecker?: StatusChecker\n private statusPollInterval: number\n private logger: Logger\n private emitter: EventEmitter\n\n constructor(options: CheckoutOptions) {\n this.logger = options.logger\n this.emitter = options.emitter\n this.onReadyCallback = options.onReady\n this.onPaymentSuccessCallback = options.onPaymentSuccess\n this.onPaymentFailedCallback = options.onPaymentFailed\n this.onPaymentPendingCallback = options.onPaymentPending\n this.onCloseCallback = options.onClose\n this.onErrorCallback = options.onError\n this.statusChecker = options.statusChecker\n this.statusPollInterval = Math.max(\n MIN_STATUS_POLL_INTERVAL,\n options.statusPollInterval ?? STATUS_POLL_INTERVAL,\n )\n }\n\n /**\n * Ouvre la popup de checkout et affiche l'overlay d'attente.\n *\n * @param paymentUrl - URL complète de la page de checkout CinetPay\n */\n open(paymentUrl: string): void {\n this.logger.debug('Opening checkout popup', { paymentUrl })\n this.injectStyles()\n this.createOverlay()\n this.openPopup(paymentUrl)\n if (!this.popup) return\n\n this.listenForMessages()\n this.startPolling()\n this.startStatusPolling()\n\n requestAnimationFrame(() => {\n this.overlay?.classList.add('cp-visible')\n })\n\n this.previousBodyOverflow = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n }\n\n /**\n * Ferme la popup et l'overlay.\n */\n close(): void {\n if (this.closeTimer || this.isClosing) return\n\n if (!this.statusChecker || this.finalStatusDispatched) {\n this.finishClose()\n return\n }\n\n this.isClosing = true\n\n void this.checkStatus('close').finally(() => {\n this.finishClose()\n })\n }\n\n private finishClose(): void {\n if (this.closeTimer) return\n this.stopPolling()\n this.stopStatusPolling()\n\n if (this.messageHandler) {\n window.removeEventListener('message', this.messageHandler)\n this.messageHandler = null\n }\n\n if (this.popup && !this.popup.closed) {\n this.popup.close()\n }\n this.popup = null\n\n if (this.overlay) {\n const overlay = this.overlay\n this.overlay = null\n overlay.classList.remove('cp-visible')\n this.closeTimer = setTimeout(() => {\n overlay.remove()\n this.closeTimer = null\n this.isClosing = false\n\n if (!document.querySelector('.cp-seamless-overlay')) {\n document.body.style.overflow = this.previousBodyOverflow\n }\n\n this.logger.debug('Checkout closed', { lastStatus: this.lastStatus })\n this.emitter.emit('close', { status: this.lastStatus })\n this.onCloseCallback?.({ status: this.lastStatus })\n }, 300)\n } else {\n this.isClosing = false\n }\n }\n\n private static isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n }\n\n private static childRecords(data: Record<string, unknown>): Record<string, unknown>[] {\n const records: Record<string, unknown>[] = []\n for (const key of ['details', 'transaction', 'payment', 'result', 'data']) {\n const child = data[key]\n if (Checkout.isRecord(child)) records.push(child)\n }\n records.push(data)\n return records\n }\n\n private static findValue(data: Record<string, unknown>, keys: string[]): unknown {\n for (const record of Checkout.childRecords(data)) {\n for (const key of keys) {\n if (record[key] !== undefined && record[key] !== null) return record[key]\n }\n }\n return undefined\n }\n\n private static asString(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined\n return String(value)\n }\n\n private static asNumber(value: unknown): number {\n if (typeof value === 'number') return Number.isFinite(value) ? value : 0\n if (typeof value === 'string') {\n const parsed = Number(value.replace(/\\s/g, ''))\n return Number.isFinite(parsed) ? parsed : 0\n }\n return 0\n }\n\n private static asOptionalNumber(value: unknown): number | undefined {\n if (value === undefined || value === null) return undefined\n if (typeof value === 'number') return Number.isFinite(value) ? value : undefined\n if (typeof value === 'string') {\n const parsed = Number(value.trim())\n return Number.isFinite(parsed) ? parsed : undefined\n }\n return undefined\n }\n\n private static normalizeStatus(rawStatus?: string, apiCode?: number): PaymentStatus {\n const normalized = rawStatus?.trim().toUpperCase().replace(/[\\s-]+/g, '_')\n\n if (normalized) {\n if (['ACCEPTED', 'SUCCESS', 'SUCCEEDED', 'SUCCESSFUL', 'PAID', 'VALIDATED', 'APPROVED'].includes(normalized)) {\n return 'ACCEPTED'\n }\n if ([\n 'REFUSED',\n 'FAILED',\n 'FAIL',\n 'FAILURE',\n 'DENIED',\n 'DECLINED',\n 'REJECTED',\n 'CANCELED',\n 'CANCELLED',\n 'CANCEL',\n 'INSUFFICIENT_BALANCE',\n ].includes(normalized)) {\n return 'REFUSED'\n }\n if (['PENDING', 'INITIATED', 'EXPIRED'].includes(normalized)) {\n return normalized as PaymentStatus\n }\n if (['WAITING', 'PROCESSING', 'IN_PROGRESS'].includes(normalized)) {\n return 'PENDING'\n }\n }\n\n switch (apiCode) {\n case 100:\n return 'ACCEPTED'\n case 2010:\n case 2005:\n return 'REFUSED'\n case 2001:\n return 'INITIATED'\n case 2002:\n return 'PENDING'\n case 2003:\n return 'EXPIRED'\n }\n\n return 'UNKNOWN'\n }\n\n private static isFinalStatus(status: PaymentStatus): boolean {\n return status === 'ACCEPTED' || status === 'REFUSED'\n }\n\n private static buildPaymentResponse(data: Record<string, unknown>): PaymentResponse {\n const rawStatus = Checkout.asString(Checkout.findValue(data, [\n 'status',\n 'transaction_status',\n 'trans_status',\n 'payment_status',\n ]))\n const apiCode = Checkout.asOptionalNumber(Checkout.findValue(data, ['code']))\n const status = Checkout.normalizeStatus(rawStatus, apiCode)\n\n return {\n amount: Checkout.asNumber(Checkout.findValue(data, ['amount'])),\n currency: Checkout.asString(Checkout.findValue(data, ['currency'])) ?? '',\n status,\n rawStatus,\n apiCode,\n paymentMethod: Checkout.asString(Checkout.findValue(data, ['payment_method', 'paymentMethod'])) ?? '',\n description: Checkout.asString(Checkout.findValue(data, ['description', 'designation', 'message'])) ?? '',\n metadata: Checkout.asString(Checkout.findValue(data, ['metadata', 'custom'])),\n operatorId: Checkout.asString(Checkout.findValue(data, ['operator_id', 'operatorId'])),\n paymentDate: Checkout.asString(Checkout.findValue(data, ['payment_date', 'paymentDate'])),\n transactionId: Checkout.asString(Checkout.findValue(data, ['transaction_id', 'transactionId', 'merchant_transaction_id'])) ?? '',\n }\n }\n\n /** Dispatche la réponse vers le bon callback selon le statut. */\n private dispatchResponse(response: PaymentResponse): void {\n const dispatchKey = `${response.status}:${response.rawStatus ?? ''}:${response.apiCode ?? ''}`\n const isFinalStatus = Checkout.isFinalStatus(response.status)\n\n if (isFinalStatus && this.finalStatusDispatched) return\n if (dispatchKey === this.lastDispatchKey) return\n\n this.lastDispatchKey = dispatchKey\n this.lastStatus = response.status\n if (isFinalStatus) {\n this.finalStatusDispatched = true\n this.stopStatusPolling()\n }\n\n this.logger.debug(`Payment response: ${response.status}`, {\n amount: response.amount,\n currency: response.currency,\n transactionId: response.transactionId,\n paymentMethod: response.paymentMethod,\n })\n\n switch (response.status) {\n case 'ACCEPTED':\n this.logger.debug('Payment accepted')\n this.emitter.emit('payment.success', response)\n this.onPaymentSuccessCallback?.(response)\n break\n case 'REFUSED':\n this.logger.warn('Payment refused')\n this.emitter.emit('payment.failed', response)\n this.onPaymentFailedCallback?.(response)\n break\n case 'PENDING':\n case 'INITIATED':\n case 'EXPIRED':\n default:\n this.logger.debug(`Payment pending: ${response.status}`)\n this.emitter.emit('payment.pending', response)\n this.onPaymentPendingCallback?.(response)\n break\n }\n }\n\n private injectStyles(): void {\n if (document.getElementById('cp-seamless-styles')) return\n const styleEl = document.createElement('style')\n styleEl.id = 'cp-seamless-styles'\n styleEl.textContent = STYLES\n document.head.appendChild(styleEl)\n }\n\n private createOverlay(): void {\n this.overlay = document.createElement('div')\n this.overlay.className = 'cp-seamless-overlay'\n\n const wrapper = document.createElement('div')\n wrapper.className = 'cp-seamless-wrapper'\n\n // Spinner + message\n const waiting = document.createElement('div')\n waiting.className = 'cp-seamless-waiting'\n\n const spinner = document.createElement('div')\n spinner.className = 'cp-seamless-spinner'\n waiting.appendChild(spinner)\n\n const title = document.createElement('p')\n title.className = 'cp-seamless-waiting-title'\n title.textContent = 'Paiement en cours...'\n waiting.appendChild(title)\n\n const msg = document.createElement('p')\n msg.className = 'cp-seamless-waiting-msg'\n msg.textContent = 'Finalisez votre paiement dans la fenêtre CinetPay.'\n waiting.appendChild(msg)\n\n // Bouton fermer\n const cancelBtn = document.createElement('button')\n cancelBtn.className = 'cp-seamless-cancel-btn'\n cancelBtn.textContent = 'Annuler'\n cancelBtn.addEventListener('click', () => this.close())\n waiting.appendChild(cancelBtn)\n\n wrapper.appendChild(waiting)\n this.overlay.appendChild(wrapper)\n document.body.appendChild(this.overlay)\n }\n\n /**\n * Ouvre la popup centrée sur l'écran.\n */\n private openPopup(paymentUrl: string): void {\n const width = 500\n const height = 700\n const left = Math.max(0, (screen.width - width) / 2)\n const top = Math.max(0, (screen.height - height) / 2)\n\n this.popup = window.open(\n paymentUrl,\n 'CinetPayCheckout',\n `width=${width},height=${height},left=${left},top=${top},scrollbars=yes,resizable=yes`,\n )\n\n if (!this.popup) {\n this.logger.error('Popup blocked by browser')\n const err: PaymentError = {\n code: 'POPUP_BLOCKED',\n message: 'La fenêtre de paiement a été bloquée par le navigateur. Autorisez les popups pour ce site.',\n }\n this.emitter.emit('error', err)\n this.onErrorCallback?.(err)\n this.close()\n return\n }\n\n this.logger.debug('Popup opened')\n this.emitter.emit('ready')\n this.onReadyCallback?.()\n }\n\n /**\n * Poll toutes les 500ms pour détecter si la popup a été fermée\n * (par l'utilisateur ou après redirection).\n */\n private startPolling(): void {\n this.pollTimer = setInterval(() => {\n if (this.popup && this.popup.closed) {\n this.logger.debug('Popup closed by user or redirect')\n this.stopPolling()\n\n // Laisser un court délai pour que le postMessage arrive avant le close\n setTimeout(() => {\n if (this.overlay) {\n this.close()\n }\n }, 500)\n }\n }, POPUP_POLL_INTERVAL)\n }\n\n private stopPolling(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer)\n this.pollTimer = null\n }\n }\n\n private startStatusPolling(): void {\n if (!this.statusChecker) return\n\n void this.checkStatus('open')\n\n this.statusTimer = setInterval(() => {\n void this.checkStatus('interval')\n }, this.statusPollInterval)\n }\n\n private stopStatusPolling(): void {\n if (this.statusTimer) {\n clearInterval(this.statusTimer)\n this.statusTimer = null\n }\n }\n\n private async checkStatus(reason: string): Promise<void> {\n if (!this.statusChecker || this.statusCheckInFlight || this.finalStatusDispatched) return\n\n this.statusCheckInFlight = true\n try {\n this.logger.debug('Checking payment status', { reason })\n const data = await this.statusChecker()\n if (!Checkout.isRecord(data)) return\n\n const response = Checkout.buildPaymentResponse(data)\n const rawStatus = response.rawStatus?.trim().toUpperCase()\n if (response.status !== 'UNKNOWN' || (rawStatus && rawStatus !== 'OK')) {\n this.dispatchResponse(response)\n }\n\n if (Checkout.isFinalStatus(response.status)) {\n this.finishClose()\n }\n } catch (error) {\n this.logger.warn('Payment status check failed', error)\n } finally {\n this.statusCheckInFlight = false\n }\n }\n\n /** Origines autorisées pour les messages postMessage */\n private static readonly ALLOWED_ORIGINS = [\n 'https://secure.cinetpay.net',\n 'https://secure.cinetpay.co',\n 'https://secure.cinetpay.com',\n 'https://checkout.cinetpay.net',\n 'https://checkout.cinetpay.co',\n 'https://checkout.cinetpay.com',\n 'https://api.cinetpay.net',\n 'https://api.cinetpay.co',\n ]\n\n /** Écoute les messages postMessage de la popup CinetPay. */\n private listenForMessages(): void {\n this.messageHandler = (event: MessageEvent) => {\n if (!Checkout.ALLOWED_ORIGINS.some((o) => event.origin === o)) {\n return\n }\n\n try {\n const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data\n if (!Checkout.isRecord(data)) return\n\n const response = Checkout.buildPaymentResponse(data)\n const rawStatus = response.rawStatus?.trim().toUpperCase()\n if (response.status !== 'UNKNOWN' || (rawStatus && rawStatus !== 'OK')) {\n this.dispatchResponse(response)\n }\n\n const error = Checkout.findValue(data, ['error'])\n const code = Checkout.asString(Checkout.findValue(data, ['code']))\n if (error || code === 'ERROR') {\n const err: PaymentError = {\n code: code ?? 'UNKNOWN',\n message: Checkout.asString(Checkout.findValue(data, ['message'])) ?? Checkout.asString(error) ?? 'An error occurred',\n }\n this.logger.error('Payment error from popup', err)\n this.emitter.emit('error', err)\n this.onErrorCallback?.(err)\n }\n\n if (data.action === 'CLOSE' || data.type === 'close') {\n this.close()\n }\n } catch {\n // Ignorer les messages non-JSON\n }\n }\n\n window.addEventListener('message', this.messageHandler)\n }\n}\n","/** Préfixe des messages de log */\nconst PREFIX = '[CinetPay Seamless]'\n\n/**\n * Logger interne du SDK Seamless.\n * Désactivé par défaut. Activable via `debug: true` dans la config.\n *\n * Tous les logs utilisent le préfixe `[CinetPay Seamless]` pour être\n * facilement filtrables dans la console du navigateur.\n */\nexport class Logger {\n private enabled: boolean\n\n constructor(enabled: boolean) {\n this.enabled = enabled\n }\n\n /** Log de debug — requêtes, réponses, événements */\n debug(message: string, data?: unknown): void {\n if (!this.enabled) return\n if (data !== undefined) {\n console.debug(`${PREFIX} ${message}`, data)\n } else {\n console.debug(`${PREFIX} ${message}`)\n }\n }\n\n /** Log d'avertissement — credentials exposés, statuts inattendus */\n warn(message: string, data?: unknown): void {\n if (!this.enabled) return\n if (data !== undefined) {\n console.warn(`${PREFIX} ${message}`, data)\n } else {\n console.warn(`${PREFIX} ${message}`)\n }\n }\n\n /** Log d'erreur — erreurs API, timeouts, postMessage invalides */\n error(message: string, data?: unknown): void {\n if (!this.enabled) return\n if (data !== undefined) {\n console.error(`${PREFIX} ${message}`, data)\n } else {\n console.error(`${PREFIX} ${message}`)\n }\n }\n}\n","import type { PaymentResponse, PaymentError } from './types'\n\n/**\n * Map des événements émis par le SDK Seamless.\n *\n * | Événement | Donnée | Quand |\n * |---|---|---|\n * | `ready` | — | Popup ouverte, passerelle prête |\n * | `payment.success` | `PaymentResponse` | Paiement accepté |\n * | `payment.failed` | `PaymentResponse` | Paiement refusé |\n * | `payment.pending` | `PaymentResponse` | En attente (PENDING, INITIATED, EXPIRED) |\n * | `close` | `{ status: string }` | Popup fermée, overlay retiré |\n * | `error` | `PaymentError` | Erreur technique |\n */\nexport interface EventMap {\n 'ready': void\n 'payment.success': PaymentResponse\n 'payment.failed': PaymentResponse\n 'payment.pending': PaymentResponse\n 'close': { status: string }\n 'error': PaymentError\n}\n\n/** Type des noms d'événements */\nexport type EventName = keyof EventMap\n\n/** Type d'un handler pour un événement donné */\ntype Handler<T> = T extends void ? () => void : (data: T) => void\n\n/**\n * Event emitter typé pour le SDK Seamless.\n *\n * Permet d'écouter les événements de paiement avec `on()` et `off()`,\n * style événementiel (`on('event', handler)`).\n *\n * @example\n * ```typescript\n * CinetPaySeamless.on('payment.success', (data) => {\n * console.log('Payé !', data.amount, data.currency)\n * })\n *\n * CinetPaySeamless.on('payment.failed', (data) => {\n * console.log('Refusé', data.transactionId)\n * })\n *\n * CinetPaySeamless.on('ready', () => {\n * console.log('Passerelle chargée')\n * })\n * ```\n */\nexport class EventEmitter {\n private listeners = new Map<string, Set<Function>>()\n\n /**\n * Enregistre un handler pour un événement.\n *\n * @param event - Nom de l'événement\n * @param handler - Fonction appelée quand l'événement est émis\n * @returns Fonction pour se désabonner (équivalent de `off(event, handler)`)\n *\n * @example\n * ```typescript\n * const unsubscribe = CinetPaySeamless.on('payment.success', (data) => { ... })\n * // Plus tard :\n * unsubscribe()\n * ```\n */\n on<E extends EventName>(event: E, handler: Handler<EventMap[E]>): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set())\n }\n this.listeners.get(event)!.add(handler)\n\n // Retourne une fonction de désabonnement\n return () => this.off(event, handler)\n }\n\n /**\n * Supprime un handler pour un événement.\n *\n * @param event - Nom de l'événement\n * @param handler - Référence du handler à supprimer\n */\n off<E extends EventName>(event: E, handler: Handler<EventMap[E]>): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n /**\n * Enregistre un handler qui ne sera appelé qu'une seule fois.\n *\n * @param event - Nom de l'événement\n * @param handler - Fonction appelée une seule fois\n *\n * @example\n * ```typescript\n * CinetPaySeamless.once('payment.success', (data) => {\n * // Appelé une seule fois\n * })\n * ```\n */\n once<E extends EventName>(event: E, handler: Handler<EventMap[E]>): void {\n const wrapper = ((...args: unknown[]) => {\n this.off(event, wrapper as Handler<EventMap[E]>)\n ;(handler as Function)(...args)\n }) as Handler<EventMap[E]>\n this.on(event, wrapper)\n }\n\n /**\n * Émet un événement — appelle tous les handlers enregistrés.\n * @internal\n */\n emit<E extends EventName>(event: E, ...args: EventMap[E] extends void ? [] : [EventMap[E]]): void {\n const handlers = this.listeners.get(event)\n if (!handlers) return\n for (const handler of handlers) {\n try {\n (handler as Function)(...args)\n } catch {\n // Ne pas bloquer les autres handlers si un throw\n }\n }\n }\n\n /**\n * Supprime tous les handlers pour tous les événements.\n * @internal\n */\n removeAll(): void {\n this.listeners.clear()\n }\n}\n","import { Checkout } from './checkout'\nimport type {\n SeamlessConfig,\n PaymentResponse,\n PaymentError,\n PaymentStatus,\n StatusCheckContext,\n SeamlessEnvironment,\n} from './types'\nimport { Logger } from './logger'\nimport { EventEmitter, type EventName, type EventMap } from './emitter'\n\nexport type {\n SeamlessConfig,\n PaymentResponse,\n PaymentError,\n PaymentStatus,\n StatusCheckContext,\n SeamlessEnvironment,\n}\nexport type { EventName, EventMap } from './emitter'\n\n/** @internal URLs de base de la passerelle de paiement sécurisée */\nconst SECURE_BASE_URLS: Record<SeamlessEnvironment, string> = {\n sandbox: 'https://secure.cinetpay.net',\n production: 'https://secure.cinetpay.co',\n}\n\n/** Récupère un callback en tolérant la casse pour les intégrations CDN/script tag. */\nfunction getCallback<T extends Function>(config: SeamlessConfig, names: string[]): T | undefined {\n const record = config as unknown as Record<string, unknown>\n\n for (const name of names) {\n const value = record[name]\n if (typeof value === 'function') return value as T\n }\n\n const lowerNames = new Set(names.map((name) => name.toLowerCase()))\n for (const [key, value] of Object.entries(record)) {\n if (lowerNames.has(key.toLowerCase()) && typeof value === 'function') {\n return value as T\n }\n }\n\n return undefined\n}\n\n/** Récupère une option en tolérant la casse pour les intégrations CDN/script tag. */\nfunction getOption<T>(config: SeamlessConfig, names: string[]): T | undefined {\n const record = config as unknown as Record<string, unknown>\n\n for (const name of names) {\n if (record[name] !== undefined) return record[name] as T\n }\n\n const lowerNames = new Set(names.map((name) => name.toLowerCase()))\n for (const [key, value] of Object.entries(record)) {\n if (lowerNames.has(key.toLowerCase())) return value as T\n }\n\n return undefined\n}\n\nfunction createStatusChecker(config: SeamlessConfig): (() => Promise<unknown>) | undefined {\n const context: StatusCheckContext = { paymentToken: config.paymentToken }\n const checkStatus = getCallback<(context: StatusCheckContext) => Promise<unknown>>(config, [\n 'checkStatus',\n 'checkPaymentStatus',\n 'checkTransactionStatus',\n ])\n\n if (checkStatus) {\n return () => checkStatus(context)\n }\n\n const statusUrl = getOption<SeamlessConfig['statusUrl']>(config, ['statusUrl', 'statusURL'])\n if (!statusUrl) return undefined\n\n return async () => {\n const url = typeof statusUrl === 'function' ? statusUrl(context) : statusUrl\n const response = await fetch(url, {\n method: 'GET',\n credentials: 'same-origin',\n headers: { Accept: 'application/json' },\n })\n\n if (!response.ok) {\n throw new Error(`Status check failed with HTTP ${response.status}`)\n }\n\n return response.json()\n }\n}\n\nfunction createPaymentUrl(config: SeamlessConfig): string {\n const explicitUrl = getOption<string>(config, ['paymentUrl', 'checkoutUrl'])\n if (explicitUrl) return explicitUrl\n\n const environment = getOption<SeamlessEnvironment>(config, ['environment', 'env']) ?? 'sandbox'\n const checkoutBaseUrl =\n getOption<string>(config, ['checkoutBaseUrl', 'secureBaseUrl']) ??\n SECURE_BASE_URLS[environment] ??\n SECURE_BASE_URLS.sandbox\n\n return `${checkoutBaseUrl.replace(/\\/+$/, '')}/checkout/${config.paymentToken}`\n}\n\n/**\n * CinetPay Seamless — paiement inline via popup window.\n *\n * Affiche un overlay d'attente et ouvre la passerelle de paiement\n * CinetPay dans une popup. Le client reste sur votre page.\n *\n * Le `paymentToken` est obtenu côté serveur via l'API CinetPay :\n *\n * ```typescript\n * // Frontend\n * CinetPaySeamless.open({\n * paymentToken: 'abc123...',\n * onPaymentSuccess: (data) => console.log('Payé !', data.amount),\n * })\n * ```\n *\n * Ou avec des event listeners (style événementiel) :\n *\n * ```typescript\n * CinetPaySeamless.on('payment.success', (data) => { ... })\n * CinetPaySeamless.open({ paymentToken: 'abc123...' })\n * ```\n */\nexport const CinetPaySeamless = {\n /** Instance du checkout actuellement ouvert */\n _checkout: null as Checkout | null,\n\n /** Event emitter partagé */\n _emitter: new EventEmitter(),\n\n /**\n * Enregistre un listener d'événement (style événementiel).\n *\n * @param event - Nom de l'événement\n * @param handler - Fonction appelée quand l'événement est émis\n * @returns Fonction de désabonnement\n *\n * @example\n * ```typescript\n * const unsub = CinetPaySeamless.on('payment.success', (data) => {\n * console.log('Payé !', data.amount, data.currency)\n * })\n * unsub() // Se désabonner\n * ```\n */\n on<E extends EventName>(\n event: E,\n handler: EventMap[E] extends void ? () => void : (data: EventMap[E]) => void,\n ): () => void {\n return this._emitter.on(event, handler)\n },\n\n /**\n * Supprime un listener.\n */\n off<E extends EventName>(\n event: E,\n handler: EventMap[E] extends void ? () => void : (data: EventMap[E]) => void,\n ): void {\n this._emitter.off(event, handler)\n },\n\n /**\n * Enregistre un listener appelé une seule fois.\n */\n once<E extends EventName>(\n event: E,\n handler: EventMap[E] extends void ? () => void : (data: EventMap[E]) => void,\n ): void {\n this._emitter.once(event, handler)\n },\n\n /**\n * Ouvre le checkout CinetPay.\n *\n * Affiche un overlay d'attente et ouvre la page de paiement dans une popup.\n * La popup est centrée sur l'écran (500x700px).\n *\n * @param config - Configuration avec `paymentToken` et callbacks optionnels\n * @throws {Error} Si le `paymentToken` a un format invalide\n *\n * @example\n * ```typescript\n * CinetPaySeamless.open({\n * paymentToken: 'abc123def456...',\n * debug: true,\n * onPaymentSuccess: (data) => console.log('Payé !', data.amount),\n * onPaymentFailed: (data) => console.log('Refusé'),\n * onClose: ({ status }) => console.log('Fermé:', status),\n * })\n * ```\n */\n open(config: SeamlessConfig): void {\n this.close()\n\n const logger = new Logger(config.debug ?? false)\n logger.debug('CinetPaySeamless.open() called')\n\n // Validation du paymentToken\n if (!/^[a-zA-Z0-9_-]{10,128}$/.test(config.paymentToken)) {\n throw new Error('Invalid paymentToken format — expected alphanumeric string (10-128 chars)')\n }\n\n const paymentUrl = createPaymentUrl(config)\n\n this._checkout = new Checkout({\n logger,\n emitter: this._emitter,\n statusChecker: createStatusChecker(config),\n statusPollInterval: getOption<number>(config, ['statusPollInterval', 'statusCheckInterval']),\n onReady: getCallback(config, ['onReady']),\n onPaymentSuccess: getCallback(config, [\n 'onPaymentSuccess',\n 'onSuccess',\n 'onPaymentsuccess',\n 'onpaymentSuccess',\n 'onpaymentsuccess',\n ]),\n onPaymentFailed: getCallback(config, [\n 'onPaymentFailed',\n 'onPaymentFail',\n 'onPaymentFailure',\n 'onFailed',\n 'onPaymentfailed',\n 'onpaymentFailed',\n 'onpaymentfailed',\n ]),\n onPaymentPending: getCallback(config, ['onPaymentPending', 'onPending']),\n onClose: getCallback(config, ['onClose']),\n onError: getCallback(config, ['onError']),\n })\n\n this._checkout.open(paymentUrl)\n },\n\n /**\n * Ferme le checkout (popup + overlay).\n */\n close(): void {\n this._checkout?.close()\n this._checkout = null\n },\n}\n\n// Auto-attach to window for CDN/script tag usage\nif (typeof window !== 'undefined') {\n (window as unknown as Record<string, unknown>).CinetPaySeamless = CinetPaySeamless\n}\n"],"names":["STYLES","_Checkout","options","paymentUrl","_a","overlay","value","data","records","key","child","keys","record","parsed","rawStatus","apiCode","normalized","status","response","_b","_c","dispatchKey","isFinalStatus","styleEl","wrapper","waiting","spinner","title","msg","cancelBtn","left","top","err","reason","error","event","o","code","Checkout","PREFIX","Logger","enabled","message","EventEmitter","handler","args","handlers","SECURE_BASE_URLS","getCallback","config","names","name","lowerNames","getOption","createStatusChecker","context","checkStatus","statusUrl","url","createPaymentUrl","explicitUrl","environment","CinetPaySeamless","logger"],"mappings":"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"}
1
+ {"version":3,"file":"cinetpay-seamless.js","sources":["../src/styles.ts","../src/checkout.ts","../src/logger.ts","../src/emitter.ts","../src/index.ts"],"sourcesContent":["/**\n * Styles CSS du checkout CinetPay Seamless (mode popup).\n */\nexport const STYLES = `\n.cp-seamless-overlay {\n position: fixed;\n inset: 0;\n z-index: 999999;\n background: rgba(0, 0, 0, 0.7);\n backdrop-filter: blur(6px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n transition: opacity 0.3s ease;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n.cp-seamless-overlay.cp-visible {\n opacity: 1;\n}\n\n.cp-seamless-wrapper {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Waiting screen (pendant que la popup est ouverte) */\n.cp-seamless-waiting {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 20px;\n text-align: center;\n padding: 40px;\n}\n\n.cp-seamless-waiting-title {\n color: #fff;\n font-size: 22px;\n font-weight: 600;\n margin: 0;\n}\n\n.cp-seamless-waiting-msg {\n color: rgba(255, 255, 255, 0.7);\n font-size: 15px;\n margin: 0;\n max-width: 320px;\n line-height: 1.5;\n}\n\n.cp-seamless-spinner {\n width: 48px;\n height: 48px;\n border: 3px solid rgba(255, 255, 255, 0.2);\n border-top-color: #e8530e;\n border-radius: 50%;\n animation: cp-spin 0.8s linear infinite;\n}\n\n@keyframes cp-spin {\n to { transform: rotate(360deg); }\n}\n\n.cp-seamless-cancel-btn {\n margin-top: 12px;\n padding: 10px 28px;\n background: rgba(255, 255, 255, 0.12);\n color: rgba(255, 255, 255, 0.8);\n border: 1px solid rgba(255, 255, 255, 0.2);\n border-radius: 8px;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.cp-seamless-cancel-btn:hover {\n background: rgba(255, 255, 255, 0.2);\n color: #fff;\n}\n\n`\n","import { STYLES } from './styles'\nimport type { PaymentResponse, PaymentError, PaymentStatus } from './types'\nimport { Logger } from './logger'\nimport { EventEmitter } from './emitter'\n\ntype StatusChecker = () => Promise<unknown>\n\n/** @internal Options du constructeur Checkout */\nexport interface CheckoutOptions {\n onReady?: () => void\n onPaymentSuccess?: (data: PaymentResponse) => void\n onPaymentFailed?: (data: PaymentResponse) => void\n onPaymentPending?: (data: PaymentResponse) => void\n onClose?: (data: { status: string }) => void\n onError?: (error: PaymentError) => void\n statusChecker?: StatusChecker\n statusPollInterval?: number\n logger: Logger\n emitter: EventEmitter\n}\n\n/** @internal Intervalle de polling pour vérifier si la popup est fermée */\nconst POPUP_POLL_INTERVAL = 500\n/** @internal Intervalle par défaut pour vérifier le statut via le backend marchand */\nconst STATUS_POLL_INTERVAL = 3000\n/** @internal Évite un polling trop agressif depuis le navigateur */\nconst MIN_STATUS_POLL_INTERVAL = 1000\n\n/**\n * Gère le checkout CinetPay via une popup window + overlay.\n *\n * Flow :\n * 1. Affiche un overlay sombre avec un message d'attente\n * 2. Ouvre la page de checkout dans une popup (window.open)\n * 3. Poll la popup pour détecter sa fermeture\n * 4. Écoute les messages postMessage de la popup\n * 5. Ferme l'overlay et dispatche les callbacks\n *\n * @internal Utilisé par {@link CinetPaySeamless}. Ne pas instancier directement.\n */\nexport class Checkout {\n private overlay: HTMLDivElement | null = null\n private popup: Window | null = null\n private pollTimer: ReturnType<typeof setInterval> | null = null\n private statusTimer: ReturnType<typeof setInterval> | null = null\n private closeTimer: ReturnType<typeof setTimeout> | null = null\n private messageHandler: ((event: MessageEvent) => void) | null = null\n private lastStatus = 'UNKNOWN'\n private lastDispatchKey = ''\n private finalStatusDispatched = false\n private statusCheckInFlight = false\n private isClosing = false\n private previousBodyOverflow = ''\n\n private onReadyCallback?: () => void\n private onPaymentSuccessCallback?: (data: PaymentResponse) => void\n private onPaymentFailedCallback?: (data: PaymentResponse) => void\n private onPaymentPendingCallback?: (data: PaymentResponse) => void\n private onCloseCallback?: (data: { status: string }) => void\n private onErrorCallback?: (error: PaymentError) => void\n private statusChecker?: StatusChecker\n private statusPollInterval: number\n private logger: Logger\n private emitter: EventEmitter\n\n constructor(options: CheckoutOptions) {\n this.logger = options.logger\n this.emitter = options.emitter\n this.onReadyCallback = options.onReady\n this.onPaymentSuccessCallback = options.onPaymentSuccess\n this.onPaymentFailedCallback = options.onPaymentFailed\n this.onPaymentPendingCallback = options.onPaymentPending\n this.onCloseCallback = options.onClose\n this.onErrorCallback = options.onError\n this.statusChecker = options.statusChecker\n this.statusPollInterval = Math.max(\n MIN_STATUS_POLL_INTERVAL,\n options.statusPollInterval ?? STATUS_POLL_INTERVAL,\n )\n }\n\n /**\n * Ouvre la popup de checkout et affiche l'overlay d'attente.\n *\n * @param paymentUrl - URL complète de la page de checkout CinetPay\n */\n open(paymentUrl: string): void {\n this.logger.debug('Opening checkout popup', { paymentUrl })\n this.injectStyles()\n this.createOverlay()\n this.openPopup(paymentUrl)\n if (!this.popup) return\n\n this.listenForMessages()\n this.startPolling()\n this.startStatusPolling()\n\n requestAnimationFrame(() => {\n this.overlay?.classList.add('cp-visible')\n })\n\n this.previousBodyOverflow = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n }\n\n /**\n * Ferme la popup et l'overlay.\n */\n close(): void {\n if (this.closeTimer || this.isClosing) return\n\n if (!this.statusChecker || this.finalStatusDispatched) {\n this.finishClose()\n return\n }\n\n this.isClosing = true\n\n void this.checkStatus('close').finally(() => {\n this.finishClose()\n })\n }\n\n private finishClose(): void {\n if (this.closeTimer) return\n this.stopPolling()\n this.stopStatusPolling()\n\n if (this.messageHandler) {\n window.removeEventListener('message', this.messageHandler)\n this.messageHandler = null\n }\n\n if (this.popup && !this.popup.closed) {\n this.popup.close()\n }\n this.popup = null\n\n if (this.overlay) {\n const overlay = this.overlay\n this.overlay = null\n overlay.classList.remove('cp-visible')\n this.closeTimer = setTimeout(() => {\n overlay.remove()\n this.closeTimer = null\n this.isClosing = false\n\n if (!document.querySelector('.cp-seamless-overlay')) {\n document.body.style.overflow = this.previousBodyOverflow\n }\n\n this.logger.debug('Checkout closed', { lastStatus: this.lastStatus })\n this.emitter.emit('close', { status: this.lastStatus })\n this.onCloseCallback?.({ status: this.lastStatus })\n }, 300)\n } else {\n this.isClosing = false\n }\n }\n\n private static isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n }\n\n private static childRecords(data: Record<string, unknown>): Record<string, unknown>[] {\n const records: Record<string, unknown>[] = []\n for (const key of ['details', 'transaction', 'payment', 'result', 'data']) {\n const child = data[key]\n if (Checkout.isRecord(child)) records.push(child)\n }\n records.push(data)\n return records\n }\n\n private static findValue(data: Record<string, unknown>, keys: string[]): unknown {\n for (const record of Checkout.childRecords(data)) {\n for (const key of keys) {\n if (record[key] !== undefined && record[key] !== null) return record[key]\n }\n }\n return undefined\n }\n\n private static asString(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined\n return String(value)\n }\n\n private static asNumber(value: unknown): number {\n if (typeof value === 'number') return Number.isFinite(value) ? value : 0\n if (typeof value === 'string') {\n const parsed = Number(value.replace(/\\s/g, ''))\n return Number.isFinite(parsed) ? parsed : 0\n }\n return 0\n }\n\n private static asOptionalNumber(value: unknown): number | undefined {\n if (value === undefined || value === null) return undefined\n if (typeof value === 'number') return Number.isFinite(value) ? value : undefined\n if (typeof value === 'string') {\n const parsed = Number(value.trim())\n return Number.isFinite(parsed) ? parsed : undefined\n }\n return undefined\n }\n\n private static normalizeStatus(rawStatus?: string, apiCode?: number): PaymentStatus {\n const normalized = rawStatus?.trim().toUpperCase().replace(/[\\s-]+/g, '_')\n\n if (normalized) {\n if (['ACCEPTED', 'SUCCESS', 'SUCCEEDED', 'SUCCESSFUL', 'PAID', 'VALIDATED', 'APPROVED'].includes(normalized)) {\n return 'ACCEPTED'\n }\n if ([\n 'REFUSED',\n 'FAILED',\n 'FAIL',\n 'FAILURE',\n 'DENIED',\n 'DECLINED',\n 'REJECTED',\n 'CANCELED',\n 'CANCELLED',\n 'CANCEL',\n 'INSUFFICIENT_BALANCE',\n ].includes(normalized)) {\n return 'REFUSED'\n }\n if (['PENDING', 'INITIATED', 'EXPIRED'].includes(normalized)) {\n return normalized as PaymentStatus\n }\n if (['WAITING', 'PROCESSING', 'IN_PROGRESS'].includes(normalized)) {\n return 'PENDING'\n }\n }\n\n switch (apiCode) {\n case 100:\n return 'ACCEPTED'\n case 2010:\n case 2005:\n return 'REFUSED'\n case 2001:\n return 'INITIATED'\n case 2002:\n return 'PENDING'\n case 2003:\n return 'EXPIRED'\n }\n\n return 'UNKNOWN'\n }\n\n private static isFinalStatus(status: PaymentStatus): boolean {\n return status === 'ACCEPTED' || status === 'REFUSED'\n }\n\n private static buildPaymentResponse(data: Record<string, unknown>): PaymentResponse {\n const rawStatus = Checkout.asString(Checkout.findValue(data, [\n 'status',\n 'transaction_status',\n 'trans_status',\n 'payment_status',\n ]))\n const apiCode = Checkout.asOptionalNumber(Checkout.findValue(data, ['code']))\n const status = Checkout.normalizeStatus(rawStatus, apiCode)\n\n return {\n amount: Checkout.asNumber(Checkout.findValue(data, ['amount'])),\n currency: Checkout.asString(Checkout.findValue(data, ['currency'])) ?? '',\n status,\n rawStatus,\n apiCode,\n paymentMethod: Checkout.asString(Checkout.findValue(data, ['payment_method', 'paymentMethod'])) ?? '',\n description: Checkout.asString(Checkout.findValue(data, ['description', 'designation', 'message'])) ?? '',\n metadata: Checkout.asString(Checkout.findValue(data, ['metadata', 'custom'])),\n operatorId: Checkout.asString(Checkout.findValue(data, ['operator_id', 'operatorId'])),\n paymentDate: Checkout.asString(Checkout.findValue(data, ['payment_date', 'paymentDate'])),\n transactionId: Checkout.asString(Checkout.findValue(data, ['transaction_id', 'transactionId', 'merchant_transaction_id'])) ?? '',\n }\n }\n\n /** Dispatche la réponse vers le bon callback selon le statut. */\n private dispatchResponse(response: PaymentResponse): void {\n const dispatchKey = `${response.status}:${response.rawStatus ?? ''}:${response.apiCode ?? ''}`\n const isFinalStatus = Checkout.isFinalStatus(response.status)\n\n if (isFinalStatus && this.finalStatusDispatched) return\n if (dispatchKey === this.lastDispatchKey) return\n\n this.lastDispatchKey = dispatchKey\n this.lastStatus = response.status\n if (isFinalStatus) {\n this.finalStatusDispatched = true\n this.stopStatusPolling()\n }\n\n this.logger.debug(`Payment response: ${response.status}`, {\n amount: response.amount,\n currency: response.currency,\n transactionId: response.transactionId,\n paymentMethod: response.paymentMethod,\n })\n\n switch (response.status) {\n case 'ACCEPTED':\n this.logger.debug('Payment accepted')\n this.emitter.emit('payment.success', response)\n this.onPaymentSuccessCallback?.(response)\n break\n case 'REFUSED':\n this.logger.warn('Payment refused')\n this.emitter.emit('payment.failed', response)\n this.onPaymentFailedCallback?.(response)\n break\n case 'PENDING':\n case 'INITIATED':\n case 'EXPIRED':\n default:\n this.logger.debug(`Payment pending: ${response.status}`)\n this.emitter.emit('payment.pending', response)\n this.onPaymentPendingCallback?.(response)\n break\n }\n }\n\n private injectStyles(): void {\n if (document.getElementById('cp-seamless-styles')) return\n const styleEl = document.createElement('style')\n styleEl.id = 'cp-seamless-styles'\n styleEl.textContent = STYLES\n document.head.appendChild(styleEl)\n }\n\n private createOverlay(): void {\n this.overlay = document.createElement('div')\n this.overlay.className = 'cp-seamless-overlay'\n\n const wrapper = document.createElement('div')\n wrapper.className = 'cp-seamless-wrapper'\n\n // Spinner + message\n const waiting = document.createElement('div')\n waiting.className = 'cp-seamless-waiting'\n\n const spinner = document.createElement('div')\n spinner.className = 'cp-seamless-spinner'\n waiting.appendChild(spinner)\n\n const title = document.createElement('p')\n title.className = 'cp-seamless-waiting-title'\n title.textContent = 'Paiement en cours...'\n waiting.appendChild(title)\n\n const msg = document.createElement('p')\n msg.className = 'cp-seamless-waiting-msg'\n msg.textContent = 'Finalisez votre paiement dans la fenêtre CinetPay.'\n waiting.appendChild(msg)\n\n // Bouton fermer\n const cancelBtn = document.createElement('button')\n cancelBtn.className = 'cp-seamless-cancel-btn'\n cancelBtn.textContent = 'Annuler'\n cancelBtn.addEventListener('click', () => this.close())\n waiting.appendChild(cancelBtn)\n\n wrapper.appendChild(waiting)\n this.overlay.appendChild(wrapper)\n document.body.appendChild(this.overlay)\n }\n\n /**\n * Ouvre la popup centrée sur l'écran.\n */\n private openPopup(paymentUrl: string): void {\n const width = 500\n const height = 700\n const left = Math.max(0, (screen.width - width) / 2)\n const top = Math.max(0, (screen.height - height) / 2)\n\n this.popup = window.open(\n paymentUrl,\n 'CinetPayCheckout',\n `width=${width},height=${height},left=${left},top=${top},scrollbars=yes,resizable=yes`,\n )\n\n if (!this.popup) {\n this.logger.error('Popup blocked by browser')\n const err: PaymentError = {\n code: 'POPUP_BLOCKED',\n message: 'La fenêtre de paiement a été bloquée par le navigateur. Autorisez les popups pour ce site.',\n }\n this.emitter.emit('error', err)\n this.onErrorCallback?.(err)\n this.close()\n return\n }\n\n this.logger.debug('Popup opened')\n this.emitter.emit('ready')\n this.onReadyCallback?.()\n }\n\n /**\n * Poll toutes les 500ms pour détecter si la popup a été fermée\n * (par l'utilisateur ou après redirection).\n */\n private startPolling(): void {\n this.pollTimer = setInterval(() => {\n if (this.popup && this.popup.closed) {\n this.logger.debug('Popup closed by user or redirect')\n this.stopPolling()\n\n // Laisser un court délai pour que le postMessage arrive avant le close\n setTimeout(() => {\n if (this.overlay) {\n this.close()\n }\n }, 500)\n }\n }, POPUP_POLL_INTERVAL)\n }\n\n private stopPolling(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer)\n this.pollTimer = null\n }\n }\n\n private startStatusPolling(): void {\n if (!this.statusChecker) return\n\n void this.checkStatus('open')\n\n this.statusTimer = setInterval(() => {\n void this.checkStatus('interval')\n }, this.statusPollInterval)\n }\n\n private stopStatusPolling(): void {\n if (this.statusTimer) {\n clearInterval(this.statusTimer)\n this.statusTimer = null\n }\n }\n\n private async checkStatus(reason: string): Promise<void> {\n if (!this.statusChecker || this.statusCheckInFlight || this.finalStatusDispatched) return\n\n this.statusCheckInFlight = true\n try {\n this.logger.debug('Checking payment status', { reason })\n const data = await this.statusChecker()\n if (!Checkout.isRecord(data)) return\n\n const response = Checkout.buildPaymentResponse(data)\n const rawStatus = response.rawStatus?.trim().toUpperCase()\n if (response.status !== 'UNKNOWN' || (rawStatus && rawStatus !== 'OK')) {\n this.dispatchResponse(response)\n }\n\n if (Checkout.isFinalStatus(response.status)) {\n this.finishClose()\n }\n } catch (error) {\n this.logger.warn('Payment status check failed', error)\n } finally {\n this.statusCheckInFlight = false\n }\n }\n\n /** Origines autorisées pour les messages postMessage */\n private static readonly ALLOWED_ORIGINS = [\n 'https://secure.cinetpay.net',\n 'https://secure.cinetpay.co',\n 'https://secure.cinetpay.com',\n 'https://checkout.cinetpay.net',\n 'https://checkout.cinetpay.co',\n 'https://checkout.cinetpay.com',\n 'https://api.cinetpay.net',\n 'https://api.cinetpay.co',\n ]\n\n /** Écoute les messages postMessage de la popup CinetPay. */\n private listenForMessages(): void {\n this.messageHandler = (event: MessageEvent) => {\n if (!Checkout.ALLOWED_ORIGINS.some((o) => event.origin === o)) {\n return\n }\n\n try {\n const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data\n if (!Checkout.isRecord(data)) return\n\n const response = Checkout.buildPaymentResponse(data)\n const rawStatus = response.rawStatus?.trim().toUpperCase()\n if (response.status !== 'UNKNOWN' || (rawStatus && rawStatus !== 'OK')) {\n this.dispatchResponse(response)\n }\n\n const error = Checkout.findValue(data, ['error'])\n const code = Checkout.asString(Checkout.findValue(data, ['code']))\n if (error || code === 'ERROR') {\n const err: PaymentError = {\n code: code ?? 'UNKNOWN',\n message: Checkout.asString(Checkout.findValue(data, ['message'])) ?? Checkout.asString(error) ?? 'An error occurred',\n }\n this.logger.error('Payment error from popup', err)\n this.emitter.emit('error', err)\n this.onErrorCallback?.(err)\n }\n\n if (data.action === 'CLOSE' || data.type === 'close') {\n this.close()\n }\n } catch {\n // Ignorer les messages non-JSON\n }\n }\n\n window.addEventListener('message', this.messageHandler)\n }\n}\n","/** Préfixe des messages de log */\nconst PREFIX = '[CinetPay Seamless]'\n\n/**\n * Logger interne du SDK Seamless.\n * Désactivé par défaut. Activable via `debug: true` dans la config.\n *\n * Tous les logs utilisent le préfixe `[CinetPay Seamless]` pour être\n * facilement filtrables dans la console du navigateur.\n */\nexport class Logger {\n private enabled: boolean\n\n constructor(enabled: boolean) {\n this.enabled = enabled\n }\n\n /** Log de debug — requêtes, réponses, événements */\n debug(message: string, data?: unknown): void {\n if (!this.enabled) return\n if (data !== undefined) {\n console.debug(`${PREFIX} ${message}`, data)\n } else {\n console.debug(`${PREFIX} ${message}`)\n }\n }\n\n /** Log d'avertissement — credentials exposés, statuts inattendus */\n warn(message: string, data?: unknown): void {\n if (!this.enabled) return\n if (data !== undefined) {\n console.warn(`${PREFIX} ${message}`, data)\n } else {\n console.warn(`${PREFIX} ${message}`)\n }\n }\n\n /** Log d'erreur — erreurs API, timeouts, postMessage invalides */\n error(message: string, data?: unknown): void {\n if (!this.enabled) return\n if (data !== undefined) {\n console.error(`${PREFIX} ${message}`, data)\n } else {\n console.error(`${PREFIX} ${message}`)\n }\n }\n}\n","import type { PaymentResponse, PaymentError } from './types'\n\n/**\n * Map des événements émis par le SDK Seamless.\n *\n * | Événement | Donnée | Quand |\n * |---|---|---|\n * | `ready` | — | Popup ouverte, passerelle prête |\n * | `payment.success` | `PaymentResponse` | Paiement accepté |\n * | `payment.failed` | `PaymentResponse` | Paiement refusé |\n * | `payment.pending` | `PaymentResponse` | En attente (PENDING, INITIATED, EXPIRED) |\n * | `close` | `{ status: string }` | Popup fermée, overlay retiré |\n * | `error` | `PaymentError` | Erreur technique |\n */\nexport interface EventMap {\n 'ready': void\n 'payment.success': PaymentResponse\n 'payment.failed': PaymentResponse\n 'payment.pending': PaymentResponse\n 'close': { status: string }\n 'error': PaymentError\n}\n\n/** Type des noms d'événements */\nexport type EventName = keyof EventMap\n\n/** Type d'un handler pour un événement donné */\ntype Handler<T> = T extends void ? () => void : (data: T) => void\n\n/**\n * Event emitter typé pour le SDK Seamless.\n *\n * Permet d'écouter les événements de paiement avec `on()` et `off()`,\n * style événementiel (`on('event', handler)`).\n *\n * @example\n * ```typescript\n * CinetPaySeamless.on('payment.success', (data) => {\n * console.log('Payé !', data.amount, data.currency)\n * })\n *\n * CinetPaySeamless.on('payment.failed', (data) => {\n * console.log('Refusé', data.transactionId)\n * })\n *\n * CinetPaySeamless.on('ready', () => {\n * console.log('Passerelle chargée')\n * })\n * ```\n */\nexport class EventEmitter {\n private listeners = new Map<string, Set<Function>>()\n\n /**\n * Enregistre un handler pour un événement.\n *\n * @param event - Nom de l'événement\n * @param handler - Fonction appelée quand l'événement est émis\n * @returns Fonction pour se désabonner (équivalent de `off(event, handler)`)\n *\n * @example\n * ```typescript\n * const unsubscribe = CinetPaySeamless.on('payment.success', (data) => { ... })\n * // Plus tard :\n * unsubscribe()\n * ```\n */\n on<E extends EventName>(event: E, handler: Handler<EventMap[E]>): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set())\n }\n this.listeners.get(event)!.add(handler)\n\n // Retourne une fonction de désabonnement\n return () => this.off(event, handler)\n }\n\n /**\n * Supprime un handler pour un événement.\n *\n * @param event - Nom de l'événement\n * @param handler - Référence du handler à supprimer\n */\n off<E extends EventName>(event: E, handler: Handler<EventMap[E]>): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n /**\n * Enregistre un handler qui ne sera appelé qu'une seule fois.\n *\n * @param event - Nom de l'événement\n * @param handler - Fonction appelée une seule fois\n *\n * @example\n * ```typescript\n * CinetPaySeamless.once('payment.success', (data) => {\n * // Appelé une seule fois\n * })\n * ```\n */\n once<E extends EventName>(event: E, handler: Handler<EventMap[E]>): void {\n const wrapper = ((...args: unknown[]) => {\n this.off(event, wrapper as Handler<EventMap[E]>)\n ;(handler as Function)(...args)\n }) as Handler<EventMap[E]>\n this.on(event, wrapper)\n }\n\n /**\n * Émet un événement — appelle tous les handlers enregistrés.\n * @internal\n */\n emit<E extends EventName>(event: E, ...args: EventMap[E] extends void ? [] : [EventMap[E]]): void {\n const handlers = this.listeners.get(event)\n if (!handlers) return\n for (const handler of handlers) {\n try {\n (handler as Function)(...args)\n } catch {\n // Ne pas bloquer les autres handlers si un throw\n }\n }\n }\n\n /**\n * Supprime tous les handlers pour tous les événements.\n * @internal\n */\n removeAll(): void {\n this.listeners.clear()\n }\n}\n","import { Checkout } from './checkout'\nimport type {\n SeamlessConfig,\n PaymentResponse,\n PaymentError,\n PaymentStatus,\n StatusCheckContext,\n SeamlessEnvironment,\n} from './types'\nimport { Logger } from './logger'\nimport { EventEmitter, type EventName, type EventMap } from './emitter'\n\nexport type {\n SeamlessConfig,\n PaymentResponse,\n PaymentError,\n PaymentStatus,\n StatusCheckContext,\n SeamlessEnvironment,\n}\nexport type { EventName, EventMap } from './emitter'\n\n/** @internal URLs de base de la passerelle de paiement sécurisée */\nconst SECURE_BASE_URLS: Record<SeamlessEnvironment, string> = {\n sandbox: 'https://secure.cinetpay.net',\n production: 'https://secure.cinetpay.co',\n}\n\n/** Récupère un callback en tolérant la casse pour les intégrations CDN/script tag. */\nfunction getCallback<T extends Function>(config: SeamlessConfig, names: string[]): T | undefined {\n const record = config as unknown as Record<string, unknown>\n\n for (const name of names) {\n const value = record[name]\n if (typeof value === 'function') return value as T\n }\n\n const lowerNames = new Set(names.map((name) => name.toLowerCase()))\n for (const [key, value] of Object.entries(record)) {\n if (lowerNames.has(key.toLowerCase()) && typeof value === 'function') {\n return value as T\n }\n }\n\n return undefined\n}\n\n/** Récupère une option en tolérant la casse pour les intégrations CDN/script tag. */\nfunction getOption<T>(config: SeamlessConfig, names: string[]): T | undefined {\n const record = config as unknown as Record<string, unknown>\n\n for (const name of names) {\n if (record[name] !== undefined) return record[name] as T\n }\n\n const lowerNames = new Set(names.map((name) => name.toLowerCase()))\n for (const [key, value] of Object.entries(record)) {\n if (lowerNames.has(key.toLowerCase())) return value as T\n }\n\n return undefined\n}\n\nfunction getPaymentToken(config: SeamlessConfig): string | undefined {\n return getOption<string>(config, ['paymentToken', 'payment_token'])\n}\n\nfunction getPaymentUrl(config: SeamlessConfig): string | undefined {\n return getOption<string>(config, ['paymentUrl', 'paymentURL', 'payment_url', 'checkoutUrl', 'checkout_url'])\n}\n\nfunction createStatusChecker(config: SeamlessConfig): (() => Promise<unknown>) | undefined {\n const context: StatusCheckContext = { paymentToken: getPaymentToken(config) ?? '' }\n const checkStatus = getCallback<(context: StatusCheckContext) => Promise<unknown>>(config, [\n 'checkStatus',\n 'checkPaymentStatus',\n 'checkTransactionStatus',\n ])\n\n if (checkStatus) {\n return () => checkStatus(context)\n }\n\n const statusUrl = getOption<SeamlessConfig['statusUrl']>(config, ['statusUrl', 'statusURL'])\n if (!statusUrl) return undefined\n\n return async () => {\n const url = typeof statusUrl === 'function' ? statusUrl(context) : statusUrl\n const response = await fetch(url, {\n method: 'GET',\n credentials: 'same-origin',\n headers: { Accept: 'application/json' },\n })\n\n if (!response.ok) {\n throw new Error(`Status check failed with HTTP ${response.status}`)\n }\n\n return response.json()\n }\n}\n\nfunction createPaymentUrl(config: SeamlessConfig): string {\n const explicitUrl = getPaymentUrl(config)\n if (explicitUrl) return explicitUrl\n\n const paymentToken = getPaymentToken(config)\n if (!paymentToken) {\n throw new Error('Invalid paymentToken format — expected alphanumeric string (10-128 chars)')\n }\n\n const environment = getOption<SeamlessEnvironment>(config, ['environment', 'env']) ?? 'sandbox'\n const checkoutBaseUrl =\n getOption<string>(config, ['checkoutBaseUrl', 'secureBaseUrl']) ??\n SECURE_BASE_URLS[environment] ??\n SECURE_BASE_URLS.sandbox\n\n return `${checkoutBaseUrl.replace(/\\/+$/, '')}/checkout/${paymentToken}`\n}\n\n/**\n * CinetPay Seamless — paiement inline via popup window.\n *\n * Affiche un overlay d'attente et ouvre la passerelle de paiement\n * CinetPay dans une popup. Le client reste sur votre page.\n *\n * Le `paymentToken` est obtenu côté serveur via l'API CinetPay :\n *\n * ```typescript\n * // Frontend\n * CinetPaySeamless.open({\n * paymentToken: 'abc123...',\n * onPaymentSuccess: (data) => console.log('Payé !', data.amount),\n * })\n * ```\n *\n * Ou avec des event listeners (style événementiel) :\n *\n * ```typescript\n * CinetPaySeamless.on('payment.success', (data) => { ... })\n * CinetPaySeamless.open({ paymentToken: 'abc123...' })\n * ```\n */\nexport const CinetPaySeamless = {\n /** Instance du checkout actuellement ouvert */\n _checkout: null as Checkout | null,\n\n /** Event emitter partagé */\n _emitter: new EventEmitter(),\n\n /**\n * Enregistre un listener d'événement (style événementiel).\n *\n * @param event - Nom de l'événement\n * @param handler - Fonction appelée quand l'événement est émis\n * @returns Fonction de désabonnement\n *\n * @example\n * ```typescript\n * const unsub = CinetPaySeamless.on('payment.success', (data) => {\n * console.log('Payé !', data.amount, data.currency)\n * })\n * unsub() // Se désabonner\n * ```\n */\n on<E extends EventName>(\n event: E,\n handler: EventMap[E] extends void ? () => void : (data: EventMap[E]) => void,\n ): () => void {\n return this._emitter.on(event, handler)\n },\n\n /**\n * Supprime un listener.\n */\n off<E extends EventName>(\n event: E,\n handler: EventMap[E] extends void ? () => void : (data: EventMap[E]) => void,\n ): void {\n this._emitter.off(event, handler)\n },\n\n /**\n * Enregistre un listener appelé une seule fois.\n */\n once<E extends EventName>(\n event: E,\n handler: EventMap[E] extends void ? () => void : (data: EventMap[E]) => void,\n ): void {\n this._emitter.once(event, handler)\n },\n\n /**\n * Ouvre le checkout CinetPay.\n *\n * Affiche un overlay d'attente et ouvre la page de paiement dans une popup.\n * La popup est centrée sur l'écran (500x700px).\n *\n * @param config - Configuration avec `paymentToken` et callbacks optionnels\n * @throws {Error} Si le `paymentToken` a un format invalide\n *\n * @example\n * ```typescript\n * CinetPaySeamless.open({\n * paymentToken: 'abc123def456...',\n * debug: true,\n * onPaymentSuccess: (data) => console.log('Payé !', data.amount),\n * onPaymentFailed: (data) => console.log('Refusé'),\n * onClose: ({ status }) => console.log('Fermé:', status),\n * })\n * ```\n */\n open(config: SeamlessConfig): void {\n this.close()\n\n const logger = new Logger(config.debug ?? false)\n logger.debug('CinetPaySeamless.open() called')\n\n // Validation du paymentToken quand le SDK doit reconstruire l'URL checkout.\n const paymentToken = getPaymentToken(config)\n if (paymentToken && !/^[a-zA-Z0-9_-]{10,128}$/.test(paymentToken)) {\n throw new Error('Invalid paymentToken format — expected alphanumeric string (10-128 chars)')\n }\n\n const paymentUrl = createPaymentUrl(config)\n\n this._checkout = new Checkout({\n logger,\n emitter: this._emitter,\n statusChecker: createStatusChecker(config),\n statusPollInterval: getOption<number>(config, ['statusPollInterval', 'statusCheckInterval']),\n onReady: getCallback(config, ['onReady']),\n onPaymentSuccess: getCallback(config, [\n 'onPaymentSuccess',\n 'onSuccess',\n 'onPaymentsuccess',\n 'onpaymentSuccess',\n 'onpaymentsuccess',\n ]),\n onPaymentFailed: getCallback(config, [\n 'onPaymentFailed',\n 'onPaymentFail',\n 'onPaymentFailure',\n 'onFailed',\n 'onPaymentfailed',\n 'onpaymentFailed',\n 'onpaymentfailed',\n ]),\n onPaymentPending: getCallback(config, ['onPaymentPending', 'onPending']),\n onClose: getCallback(config, ['onClose']),\n onError: getCallback(config, ['onError']),\n })\n\n this._checkout.open(paymentUrl)\n },\n\n /**\n * Ferme le checkout (popup + overlay).\n */\n close(): void {\n this._checkout?.close()\n this._checkout = null\n },\n}\n\n// Auto-attach to window for CDN/script tag usage\nif (typeof window !== 'undefined') {\n (window as unknown as Record<string, unknown>).CinetPaySeamless = CinetPaySeamless\n}\n"],"names":["STYLES","_Checkout","options","paymentUrl","_a","overlay","value","data","records","key","child","keys","record","parsed","rawStatus","apiCode","normalized","status","response","_b","_c","dispatchKey","isFinalStatus","styleEl","wrapper","waiting","spinner","title","msg","cancelBtn","left","top","err","reason","error","event","o","code","Checkout","PREFIX","Logger","enabled","message","EventEmitter","handler","args","handlers","SECURE_BASE_URLS","getCallback","config","names","name","lowerNames","getOption","getPaymentToken","getPaymentUrl","createStatusChecker","context","checkStatus","statusUrl","url","createPaymentUrl","explicitUrl","paymentToken","environment","CinetPaySeamless","logger"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- (function(c,h){typeof exports=="object"&&typeof module<"u"?h(exports):typeof define=="function"&&define.amd?define(["exports"],h):(c=typeof globalThis<"u"?globalThis:c||self,h(c.CinetPaySeamless={}))})(this,(function(c){"use strict";const h=`
1
+ (function(l,p){typeof exports=="object"&&typeof module<"u"?p(exports):typeof define=="function"&&define.amd?define(["exports"],p):(l=typeof globalThis<"u"?globalThis:l||self,p(l.CinetPaySeamless={}))})(this,(function(l){"use strict";const p=`
2
2
  .cp-seamless-overlay {
3
3
  position: fixed;
4
4
  inset: 0;
@@ -78,5 +78,5 @@
78
78
  color: #fff;
79
79
  }
80
80
 
81
- `,n=class n{constructor(t){this.overlay=null,this.popup=null,this.pollTimer=null,this.statusTimer=null,this.closeTimer=null,this.messageHandler=null,this.lastStatus="UNKNOWN",this.lastDispatchKey="",this.finalStatusDispatched=!1,this.statusCheckInFlight=!1,this.isClosing=!1,this.previousBodyOverflow="",this.logger=t.logger,this.emitter=t.emitter,this.onReadyCallback=t.onReady,this.onPaymentSuccessCallback=t.onPaymentSuccess,this.onPaymentFailedCallback=t.onPaymentFailed,this.onPaymentPendingCallback=t.onPaymentPending,this.onCloseCallback=t.onClose,this.onErrorCallback=t.onError,this.statusChecker=t.statusChecker,this.statusPollInterval=Math.max(1e3,t.statusPollInterval??3e3)}open(t){this.logger.debug("Opening checkout popup",{paymentUrl:t}),this.injectStyles(),this.createOverlay(),this.openPopup(t),this.popup&&(this.listenForMessages(),this.startPolling(),this.startStatusPolling(),requestAnimationFrame(()=>{var e;(e=this.overlay)==null||e.classList.add("cp-visible")}),this.previousBodyOverflow=document.body.style.overflow,document.body.style.overflow="hidden")}close(){if(!(this.closeTimer||this.isClosing)){if(!this.statusChecker||this.finalStatusDispatched){this.finishClose();return}this.isClosing=!0,this.checkStatus("close").finally(()=>{this.finishClose()})}}finishClose(){if(!this.closeTimer)if(this.stopPolling(),this.stopStatusPolling(),this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),this.popup&&!this.popup.closed&&this.popup.close(),this.popup=null,this.overlay){const t=this.overlay;this.overlay=null,t.classList.remove("cp-visible"),this.closeTimer=setTimeout(()=>{var e;t.remove(),this.closeTimer=null,this.isClosing=!1,document.querySelector(".cp-seamless-overlay")||(document.body.style.overflow=this.previousBodyOverflow),this.logger.debug("Checkout closed",{lastStatus:this.lastStatus}),this.emitter.emit("close",{status:this.lastStatus}),(e=this.onCloseCallback)==null||e.call(this,{status:this.lastStatus})},300)}else this.isClosing=!1}static isRecord(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}static childRecords(t){const e=[];for(const i of["details","transaction","payment","result","data"]){const s=t[i];n.isRecord(s)&&e.push(s)}return e.push(t),e}static findValue(t,e){for(const i of n.childRecords(t))for(const s of e)if(i[s]!==void 0&&i[s]!==null)return i[s]}static asString(t){if(t!=null)return String(t)}static asNumber(t){if(typeof t=="number")return Number.isFinite(t)?t:0;if(typeof t=="string"){const e=Number(t.replace(/\s/g,""));return Number.isFinite(e)?e:0}return 0}static asOptionalNumber(t){if(t!=null){if(typeof t=="number")return Number.isFinite(t)?t:void 0;if(typeof t=="string"){const e=Number(t.trim());return Number.isFinite(e)?e:void 0}}}static normalizeStatus(t,e){const i=t==null?void 0:t.trim().toUpperCase().replace(/[\s-]+/g,"_");if(i){if(["ACCEPTED","SUCCESS","SUCCEEDED","SUCCESSFUL","PAID","VALIDATED","APPROVED"].includes(i))return"ACCEPTED";if(["REFUSED","FAILED","FAIL","FAILURE","DENIED","DECLINED","REJECTED","CANCELED","CANCELLED","CANCEL","INSUFFICIENT_BALANCE"].includes(i))return"REFUSED";if(["PENDING","INITIATED","EXPIRED"].includes(i))return i;if(["WAITING","PROCESSING","IN_PROGRESS"].includes(i))return"PENDING"}switch(e){case 100:return"ACCEPTED";case 2010:case 2005:return"REFUSED";case 2001:return"INITIATED";case 2002:return"PENDING";case 2003:return"EXPIRED"}return"UNKNOWN"}static isFinalStatus(t){return t==="ACCEPTED"||t==="REFUSED"}static buildPaymentResponse(t){const e=n.asString(n.findValue(t,["status","transaction_status","trans_status","payment_status"])),i=n.asOptionalNumber(n.findValue(t,["code"])),s=n.normalizeStatus(e,i);return{amount:n.asNumber(n.findValue(t,["amount"])),currency:n.asString(n.findValue(t,["currency"]))??"",status:s,rawStatus:e,apiCode:i,paymentMethod:n.asString(n.findValue(t,["payment_method","paymentMethod"]))??"",description:n.asString(n.findValue(t,["description","designation","message"]))??"",metadata:n.asString(n.findValue(t,["metadata","custom"])),operatorId:n.asString(n.findValue(t,["operator_id","operatorId"])),paymentDate:n.asString(n.findValue(t,["payment_date","paymentDate"])),transactionId:n.asString(n.findValue(t,["transaction_id","transactionId","merchant_transaction_id"]))??""}}dispatchResponse(t){var s,r,o;const e=`${t.status}:${t.rawStatus??""}:${t.apiCode??""}`,i=n.isFinalStatus(t.status);if(!(i&&this.finalStatusDispatched)&&e!==this.lastDispatchKey)switch(this.lastDispatchKey=e,this.lastStatus=t.status,i&&(this.finalStatusDispatched=!0,this.stopStatusPolling()),this.logger.debug(`Payment response: ${t.status}`,{amount:t.amount,currency:t.currency,transactionId:t.transactionId,paymentMethod:t.paymentMethod}),t.status){case"ACCEPTED":this.logger.debug("Payment accepted"),this.emitter.emit("payment.success",t),(s=this.onPaymentSuccessCallback)==null||s.call(this,t);break;case"REFUSED":this.logger.warn("Payment refused"),this.emitter.emit("payment.failed",t),(r=this.onPaymentFailedCallback)==null||r.call(this,t);break;case"PENDING":case"INITIATED":case"EXPIRED":default:this.logger.debug(`Payment pending: ${t.status}`),this.emitter.emit("payment.pending",t),(o=this.onPaymentPendingCallback)==null||o.call(this,t);break}}injectStyles(){if(document.getElementById("cp-seamless-styles"))return;const t=document.createElement("style");t.id="cp-seamless-styles",t.textContent=h,document.head.appendChild(t)}createOverlay(){this.overlay=document.createElement("div"),this.overlay.className="cp-seamless-overlay";const t=document.createElement("div");t.className="cp-seamless-wrapper";const e=document.createElement("div");e.className="cp-seamless-waiting";const i=document.createElement("div");i.className="cp-seamless-spinner",e.appendChild(i);const s=document.createElement("p");s.className="cp-seamless-waiting-title",s.textContent="Paiement en cours...",e.appendChild(s);const r=document.createElement("p");r.className="cp-seamless-waiting-msg",r.textContent="Finalisez votre paiement dans la fenêtre CinetPay.",e.appendChild(r);const o=document.createElement("button");o.className="cp-seamless-cancel-btn",o.textContent="Annuler",o.addEventListener("click",()=>this.close()),e.appendChild(o),t.appendChild(e),this.overlay.appendChild(t),document.body.appendChild(this.overlay)}openPopup(t){var o,d;const s=Math.max(0,(screen.width-500)/2),r=Math.max(0,(screen.height-700)/2);if(this.popup=window.open(t,"CinetPayCheckout",`width=500,height=700,left=${s},top=${r},scrollbars=yes,resizable=yes`),!this.popup){this.logger.error("Popup blocked by browser");const m={code:"POPUP_BLOCKED",message:"La fenêtre de paiement a été bloquée par le navigateur. Autorisez les popups pour ce site."};this.emitter.emit("error",m),(o=this.onErrorCallback)==null||o.call(this,m),this.close();return}this.logger.debug("Popup opened"),this.emitter.emit("ready"),(d=this.onReadyCallback)==null||d.call(this)}startPolling(){this.pollTimer=setInterval(()=>{this.popup&&this.popup.closed&&(this.logger.debug("Popup closed by user or redirect"),this.stopPolling(),setTimeout(()=>{this.overlay&&this.close()},500))},500)}stopPolling(){this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=null)}startStatusPolling(){this.statusChecker&&(this.checkStatus("open"),this.statusTimer=setInterval(()=>{this.checkStatus("interval")},this.statusPollInterval))}stopStatusPolling(){this.statusTimer&&(clearInterval(this.statusTimer),this.statusTimer=null)}async checkStatus(t){var e;if(!(!this.statusChecker||this.statusCheckInFlight||this.finalStatusDispatched)){this.statusCheckInFlight=!0;try{this.logger.debug("Checking payment status",{reason:t});const i=await this.statusChecker();if(!n.isRecord(i))return;const s=n.buildPaymentResponse(i),r=(e=s.rawStatus)==null?void 0:e.trim().toUpperCase();(s.status!=="UNKNOWN"||r&&r!=="OK")&&this.dispatchResponse(s),n.isFinalStatus(s.status)&&this.finishClose()}catch(i){this.logger.warn("Payment status check failed",i)}finally{this.statusCheckInFlight=!1}}}listenForMessages(){this.messageHandler=t=>{var e,i;if(n.ALLOWED_ORIGINS.some(s=>t.origin===s))try{const s=typeof t.data=="string"?JSON.parse(t.data):t.data;if(!n.isRecord(s))return;const r=n.buildPaymentResponse(s),o=(e=r.rawStatus)==null?void 0:e.trim().toUpperCase();(r.status!=="UNKNOWN"||o&&o!=="OK")&&this.dispatchResponse(r);const d=n.findValue(s,["error"]),m=n.asString(n.findValue(s,["code"]));if(d||m==="ERROR"){const y={code:m??"UNKNOWN",message:n.asString(n.findValue(s,["message"]))??n.asString(d)??"An error occurred"};this.logger.error("Payment error from popup",y),this.emitter.emit("error",y),(i=this.onErrorCallback)==null||i.call(this,y)}(s.action==="CLOSE"||s.type==="close")&&this.close()}catch{}},window.addEventListener("message",this.messageHandler)}};n.ALLOWED_ORIGINS=["https://secure.cinetpay.net","https://secure.cinetpay.co","https://secure.cinetpay.com","https://checkout.cinetpay.net","https://checkout.cinetpay.co","https://checkout.cinetpay.com","https://api.cinetpay.net","https://api.cinetpay.co"];let f=n;const u="[CinetPay Seamless]";class C{constructor(t){this.enabled=t}debug(t,e){this.enabled&&(e!==void 0?console.debug(`${u} ${t}`,e):console.debug(`${u} ${t}`))}warn(t,e){this.enabled&&(e!==void 0?console.warn(`${u} ${t}`,e):console.warn(`${u} ${t}`))}error(t,e){this.enabled&&(e!==void 0?console.error(`${u} ${t}`,e):console.error(`${u} ${t}`))}}class P{constructor(){this.listeners=new Map}on(t,e){return this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e),()=>this.off(t,e)}off(t,e){var i;(i=this.listeners.get(t))==null||i.delete(e)}once(t,e){const i=((...s)=>{this.off(t,i),e(...s)});this.on(t,i)}emit(t,...e){const i=this.listeners.get(t);if(i)for(const s of i)try{s(...e)}catch{}}removeAll(){this.listeners.clear()}}const g={sandbox:"https://secure.cinetpay.net",production:"https://secure.cinetpay.co"};function l(a,t){const e=a;for(const s of t){const r=e[s];if(typeof r=="function")return r}const i=new Set(t.map(s=>s.toLowerCase()));for(const[s,r]of Object.entries(e))if(i.has(s.toLowerCase())&&typeof r=="function")return r}function p(a,t){const e=a;for(const s of t)if(e[s]!==void 0)return e[s];const i=new Set(t.map(s=>s.toLowerCase()));for(const[s,r]of Object.entries(e))if(i.has(s.toLowerCase()))return r}function E(a){const t={paymentToken:a.paymentToken},e=l(a,["checkStatus","checkPaymentStatus","checkTransactionStatus"]);if(e)return()=>e(t);const i=p(a,["statusUrl","statusURL"]);if(i)return async()=>{const s=typeof i=="function"?i(t):i,r=await fetch(s,{method:"GET",credentials:"same-origin",headers:{Accept:"application/json"}});if(!r.ok)throw new Error(`Status check failed with HTTP ${r.status}`);return r.json()}}function b(a){const t=p(a,["paymentUrl","checkoutUrl"]);if(t)return t;const e=p(a,["environment","env"])??"sandbox";return`${(p(a,["checkoutBaseUrl","secureBaseUrl"])??g[e]??g.sandbox).replace(/\/+$/,"")}/checkout/${a.paymentToken}`}const S={_checkout:null,_emitter:new P,on(a,t){return this._emitter.on(a,t)},off(a,t){this._emitter.off(a,t)},once(a,t){this._emitter.once(a,t)},open(a){this.close();const t=new C(a.debug??!1);if(t.debug("CinetPaySeamless.open() called"),!/^[a-zA-Z0-9_-]{10,128}$/.test(a.paymentToken))throw new Error("Invalid paymentToken format — expected alphanumeric string (10-128 chars)");const e=b(a);this._checkout=new f({logger:t,emitter:this._emitter,statusChecker:E(a),statusPollInterval:p(a,["statusPollInterval","statusCheckInterval"]),onReady:l(a,["onReady"]),onPaymentSuccess:l(a,["onPaymentSuccess","onSuccess","onPaymentsuccess","onpaymentSuccess","onpaymentsuccess"]),onPaymentFailed:l(a,["onPaymentFailed","onPaymentFail","onPaymentFailure","onFailed","onPaymentfailed","onpaymentFailed","onpaymentfailed"]),onPaymentPending:l(a,["onPaymentPending","onPending"]),onClose:l(a,["onClose"]),onError:l(a,["onError"])}),this._checkout.open(e)},close(){var a;(a=this._checkout)==null||a.close(),this._checkout=null}};typeof window<"u"&&(window.CinetPaySeamless=S),c.CinetPaySeamless=S,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})}));
81
+ `,i=class i{constructor(t){this.overlay=null,this.popup=null,this.pollTimer=null,this.statusTimer=null,this.closeTimer=null,this.messageHandler=null,this.lastStatus="UNKNOWN",this.lastDispatchKey="",this.finalStatusDispatched=!1,this.statusCheckInFlight=!1,this.isClosing=!1,this.previousBodyOverflow="",this.logger=t.logger,this.emitter=t.emitter,this.onReadyCallback=t.onReady,this.onPaymentSuccessCallback=t.onPaymentSuccess,this.onPaymentFailedCallback=t.onPaymentFailed,this.onPaymentPendingCallback=t.onPaymentPending,this.onCloseCallback=t.onClose,this.onErrorCallback=t.onError,this.statusChecker=t.statusChecker,this.statusPollInterval=Math.max(1e3,t.statusPollInterval??3e3)}open(t){this.logger.debug("Opening checkout popup",{paymentUrl:t}),this.injectStyles(),this.createOverlay(),this.openPopup(t),this.popup&&(this.listenForMessages(),this.startPolling(),this.startStatusPolling(),requestAnimationFrame(()=>{var e;(e=this.overlay)==null||e.classList.add("cp-visible")}),this.previousBodyOverflow=document.body.style.overflow,document.body.style.overflow="hidden")}close(){if(!(this.closeTimer||this.isClosing)){if(!this.statusChecker||this.finalStatusDispatched){this.finishClose();return}this.isClosing=!0,this.checkStatus("close").finally(()=>{this.finishClose()})}}finishClose(){if(!this.closeTimer)if(this.stopPolling(),this.stopStatusPolling(),this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),this.popup&&!this.popup.closed&&this.popup.close(),this.popup=null,this.overlay){const t=this.overlay;this.overlay=null,t.classList.remove("cp-visible"),this.closeTimer=setTimeout(()=>{var e;t.remove(),this.closeTimer=null,this.isClosing=!1,document.querySelector(".cp-seamless-overlay")||(document.body.style.overflow=this.previousBodyOverflow),this.logger.debug("Checkout closed",{lastStatus:this.lastStatus}),this.emitter.emit("close",{status:this.lastStatus}),(e=this.onCloseCallback)==null||e.call(this,{status:this.lastStatus})},300)}else this.isClosing=!1}static isRecord(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}static childRecords(t){const e=[];for(const s of["details","transaction","payment","result","data"]){const n=t[s];i.isRecord(n)&&e.push(n)}return e.push(t),e}static findValue(t,e){for(const s of i.childRecords(t))for(const n of e)if(s[n]!==void 0&&s[n]!==null)return s[n]}static asString(t){if(t!=null)return String(t)}static asNumber(t){if(typeof t=="number")return Number.isFinite(t)?t:0;if(typeof t=="string"){const e=Number(t.replace(/\s/g,""));return Number.isFinite(e)?e:0}return 0}static asOptionalNumber(t){if(t!=null){if(typeof t=="number")return Number.isFinite(t)?t:void 0;if(typeof t=="string"){const e=Number(t.trim());return Number.isFinite(e)?e:void 0}}}static normalizeStatus(t,e){const s=t==null?void 0:t.trim().toUpperCase().replace(/[\s-]+/g,"_");if(s){if(["ACCEPTED","SUCCESS","SUCCEEDED","SUCCESSFUL","PAID","VALIDATED","APPROVED"].includes(s))return"ACCEPTED";if(["REFUSED","FAILED","FAIL","FAILURE","DENIED","DECLINED","REJECTED","CANCELED","CANCELLED","CANCEL","INSUFFICIENT_BALANCE"].includes(s))return"REFUSED";if(["PENDING","INITIATED","EXPIRED"].includes(s))return s;if(["WAITING","PROCESSING","IN_PROGRESS"].includes(s))return"PENDING"}switch(e){case 100:return"ACCEPTED";case 2010:case 2005:return"REFUSED";case 2001:return"INITIATED";case 2002:return"PENDING";case 2003:return"EXPIRED"}return"UNKNOWN"}static isFinalStatus(t){return t==="ACCEPTED"||t==="REFUSED"}static buildPaymentResponse(t){const e=i.asString(i.findValue(t,["status","transaction_status","trans_status","payment_status"])),s=i.asOptionalNumber(i.findValue(t,["code"])),n=i.normalizeStatus(e,s);return{amount:i.asNumber(i.findValue(t,["amount"])),currency:i.asString(i.findValue(t,["currency"]))??"",status:n,rawStatus:e,apiCode:s,paymentMethod:i.asString(i.findValue(t,["payment_method","paymentMethod"]))??"",description:i.asString(i.findValue(t,["description","designation","message"]))??"",metadata:i.asString(i.findValue(t,["metadata","custom"])),operatorId:i.asString(i.findValue(t,["operator_id","operatorId"])),paymentDate:i.asString(i.findValue(t,["payment_date","paymentDate"])),transactionId:i.asString(i.findValue(t,["transaction_id","transactionId","merchant_transaction_id"]))??""}}dispatchResponse(t){var n,r,o;const e=`${t.status}:${t.rawStatus??""}:${t.apiCode??""}`,s=i.isFinalStatus(t.status);if(!(s&&this.finalStatusDispatched)&&e!==this.lastDispatchKey)switch(this.lastDispatchKey=e,this.lastStatus=t.status,s&&(this.finalStatusDispatched=!0,this.stopStatusPolling()),this.logger.debug(`Payment response: ${t.status}`,{amount:t.amount,currency:t.currency,transactionId:t.transactionId,paymentMethod:t.paymentMethod}),t.status){case"ACCEPTED":this.logger.debug("Payment accepted"),this.emitter.emit("payment.success",t),(n=this.onPaymentSuccessCallback)==null||n.call(this,t);break;case"REFUSED":this.logger.warn("Payment refused"),this.emitter.emit("payment.failed",t),(r=this.onPaymentFailedCallback)==null||r.call(this,t);break;case"PENDING":case"INITIATED":case"EXPIRED":default:this.logger.debug(`Payment pending: ${t.status}`),this.emitter.emit("payment.pending",t),(o=this.onPaymentPendingCallback)==null||o.call(this,t);break}}injectStyles(){if(document.getElementById("cp-seamless-styles"))return;const t=document.createElement("style");t.id="cp-seamless-styles",t.textContent=p,document.head.appendChild(t)}createOverlay(){this.overlay=document.createElement("div"),this.overlay.className="cp-seamless-overlay";const t=document.createElement("div");t.className="cp-seamless-wrapper";const e=document.createElement("div");e.className="cp-seamless-waiting";const s=document.createElement("div");s.className="cp-seamless-spinner",e.appendChild(s);const n=document.createElement("p");n.className="cp-seamless-waiting-title",n.textContent="Paiement en cours...",e.appendChild(n);const r=document.createElement("p");r.className="cp-seamless-waiting-msg",r.textContent="Finalisez votre paiement dans la fenêtre CinetPay.",e.appendChild(r);const o=document.createElement("button");o.className="cp-seamless-cancel-btn",o.textContent="Annuler",o.addEventListener("click",()=>this.close()),e.appendChild(o),t.appendChild(e),this.overlay.appendChild(t),document.body.appendChild(this.overlay)}openPopup(t){var o,d;const n=Math.max(0,(screen.width-500)/2),r=Math.max(0,(screen.height-700)/2);if(this.popup=window.open(t,"CinetPayCheckout",`width=500,height=700,left=${n},top=${r},scrollbars=yes,resizable=yes`),!this.popup){this.logger.error("Popup blocked by browser");const m={code:"POPUP_BLOCKED",message:"La fenêtre de paiement a été bloquée par le navigateur. Autorisez les popups pour ce site."};this.emitter.emit("error",m),(o=this.onErrorCallback)==null||o.call(this,m),this.close();return}this.logger.debug("Popup opened"),this.emitter.emit("ready"),(d=this.onReadyCallback)==null||d.call(this)}startPolling(){this.pollTimer=setInterval(()=>{this.popup&&this.popup.closed&&(this.logger.debug("Popup closed by user or redirect"),this.stopPolling(),setTimeout(()=>{this.overlay&&this.close()},500))},500)}stopPolling(){this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=null)}startStatusPolling(){this.statusChecker&&(this.checkStatus("open"),this.statusTimer=setInterval(()=>{this.checkStatus("interval")},this.statusPollInterval))}stopStatusPolling(){this.statusTimer&&(clearInterval(this.statusTimer),this.statusTimer=null)}async checkStatus(t){var e;if(!(!this.statusChecker||this.statusCheckInFlight||this.finalStatusDispatched)){this.statusCheckInFlight=!0;try{this.logger.debug("Checking payment status",{reason:t});const s=await this.statusChecker();if(!i.isRecord(s))return;const n=i.buildPaymentResponse(s),r=(e=n.rawStatus)==null?void 0:e.trim().toUpperCase();(n.status!=="UNKNOWN"||r&&r!=="OK")&&this.dispatchResponse(n),i.isFinalStatus(n.status)&&this.finishClose()}catch(s){this.logger.warn("Payment status check failed",s)}finally{this.statusCheckInFlight=!1}}}listenForMessages(){this.messageHandler=t=>{var e,s;if(i.ALLOWED_ORIGINS.some(n=>t.origin===n))try{const n=typeof t.data=="string"?JSON.parse(t.data):t.data;if(!i.isRecord(n))return;const r=i.buildPaymentResponse(n),o=(e=r.rawStatus)==null?void 0:e.trim().toUpperCase();(r.status!=="UNKNOWN"||o&&o!=="OK")&&this.dispatchResponse(r);const d=i.findValue(n,["error"]),m=i.asString(i.findValue(n,["code"]));if(d||m==="ERROR"){const g={code:m??"UNKNOWN",message:i.asString(i.findValue(n,["message"]))??i.asString(d)??"An error occurred"};this.logger.error("Payment error from popup",g),this.emitter.emit("error",g),(s=this.onErrorCallback)==null||s.call(this,g)}(n.action==="CLOSE"||n.type==="close")&&this.close()}catch{}},window.addEventListener("message",this.messageHandler)}};i.ALLOWED_ORIGINS=["https://secure.cinetpay.net","https://secure.cinetpay.co","https://secure.cinetpay.com","https://checkout.cinetpay.net","https://checkout.cinetpay.co","https://checkout.cinetpay.com","https://api.cinetpay.net","https://api.cinetpay.co"];let f=i;const u="[CinetPay Seamless]";class C{constructor(t){this.enabled=t}debug(t,e){this.enabled&&(e!==void 0?console.debug(`${u} ${t}`,e):console.debug(`${u} ${t}`))}warn(t,e){this.enabled&&(e!==void 0?console.warn(`${u} ${t}`,e):console.warn(`${u} ${t}`))}error(t,e){this.enabled&&(e!==void 0?console.error(`${u} ${t}`,e):console.error(`${u} ${t}`))}}class E{constructor(){this.listeners=new Map}on(t,e){return this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e),()=>this.off(t,e)}off(t,e){var s;(s=this.listeners.get(t))==null||s.delete(e)}once(t,e){const s=((...n)=>{this.off(t,s),e(...n)});this.on(t,s)}emit(t,...e){const s=this.listeners.get(t);if(s)for(const n of s)try{n(...e)}catch{}}removeAll(){this.listeners.clear()}}const S={sandbox:"https://secure.cinetpay.net",production:"https://secure.cinetpay.co"};function c(a,t){const e=a;for(const n of t){const r=e[n];if(typeof r=="function")return r}const s=new Set(t.map(n=>n.toLowerCase()));for(const[n,r]of Object.entries(e))if(s.has(n.toLowerCase())&&typeof r=="function")return r}function h(a,t){const e=a;for(const n of t)if(e[n]!==void 0)return e[n];const s=new Set(t.map(n=>n.toLowerCase()));for(const[n,r]of Object.entries(e))if(s.has(n.toLowerCase()))return r}function y(a){return h(a,["paymentToken","payment_token"])}function b(a){return h(a,["paymentUrl","paymentURL","payment_url","checkoutUrl","checkout_url"])}function k(a){const t={paymentToken:y(a)??""},e=c(a,["checkStatus","checkPaymentStatus","checkTransactionStatus"]);if(e)return()=>e(t);const s=h(a,["statusUrl","statusURL"]);if(s)return async()=>{const n=typeof s=="function"?s(t):s,r=await fetch(n,{method:"GET",credentials:"same-origin",headers:{Accept:"application/json"}});if(!r.ok)throw new Error(`Status check failed with HTTP ${r.status}`);return r.json()}}function w(a){const t=b(a);if(t)return t;const e=y(a);if(!e)throw new Error("Invalid paymentToken format — expected alphanumeric string (10-128 chars)");const s=h(a,["environment","env"])??"sandbox";return`${(h(a,["checkoutBaseUrl","secureBaseUrl"])??S[s]??S.sandbox).replace(/\/+$/,"")}/checkout/${e}`}const P={_checkout:null,_emitter:new E,on(a,t){return this._emitter.on(a,t)},off(a,t){this._emitter.off(a,t)},once(a,t){this._emitter.once(a,t)},open(a){this.close();const t=new C(a.debug??!1);t.debug("CinetPaySeamless.open() called");const e=y(a);if(e&&!/^[a-zA-Z0-9_-]{10,128}$/.test(e))throw new Error("Invalid paymentToken format — expected alphanumeric string (10-128 chars)");const s=w(a);this._checkout=new f({logger:t,emitter:this._emitter,statusChecker:k(a),statusPollInterval:h(a,["statusPollInterval","statusCheckInterval"]),onReady:c(a,["onReady"]),onPaymentSuccess:c(a,["onPaymentSuccess","onSuccess","onPaymentsuccess","onpaymentSuccess","onpaymentsuccess"]),onPaymentFailed:c(a,["onPaymentFailed","onPaymentFail","onPaymentFailure","onFailed","onPaymentfailed","onpaymentFailed","onpaymentfailed"]),onPaymentPending:c(a,["onPaymentPending","onPending"]),onClose:c(a,["onClose"]),onError:c(a,["onError"])}),this._checkout.open(s)},close(){var a;(a=this._checkout)==null||a.close(),this._checkout=null}};typeof window<"u"&&(window.CinetPaySeamless=P),l.CinetPaySeamless=P,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})}));
82
82
  //# sourceMappingURL=cinetpay-seamless.umd.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"cinetpay-seamless.umd.cjs","sources":["../src/styles.ts","../src/checkout.ts","../src/logger.ts","../src/emitter.ts","../src/index.ts"],"sourcesContent":["/**\n * Styles CSS du checkout CinetPay Seamless (mode popup).\n */\nexport const STYLES = `\n.cp-seamless-overlay {\n position: fixed;\n inset: 0;\n z-index: 999999;\n background: rgba(0, 0, 0, 0.7);\n backdrop-filter: blur(6px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n transition: opacity 0.3s ease;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n.cp-seamless-overlay.cp-visible {\n opacity: 1;\n}\n\n.cp-seamless-wrapper {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Waiting screen (pendant que la popup est ouverte) */\n.cp-seamless-waiting {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 20px;\n text-align: center;\n padding: 40px;\n}\n\n.cp-seamless-waiting-title {\n color: #fff;\n font-size: 22px;\n font-weight: 600;\n margin: 0;\n}\n\n.cp-seamless-waiting-msg {\n color: rgba(255, 255, 255, 0.7);\n font-size: 15px;\n margin: 0;\n max-width: 320px;\n line-height: 1.5;\n}\n\n.cp-seamless-spinner {\n width: 48px;\n height: 48px;\n border: 3px solid rgba(255, 255, 255, 0.2);\n border-top-color: #e8530e;\n border-radius: 50%;\n animation: cp-spin 0.8s linear infinite;\n}\n\n@keyframes cp-spin {\n to { transform: rotate(360deg); }\n}\n\n.cp-seamless-cancel-btn {\n margin-top: 12px;\n padding: 10px 28px;\n background: rgba(255, 255, 255, 0.12);\n color: rgba(255, 255, 255, 0.8);\n border: 1px solid rgba(255, 255, 255, 0.2);\n border-radius: 8px;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.cp-seamless-cancel-btn:hover {\n background: rgba(255, 255, 255, 0.2);\n color: #fff;\n}\n\n`\n","import { STYLES } from './styles'\nimport type { PaymentResponse, PaymentError, PaymentStatus } from './types'\nimport { Logger } from './logger'\nimport { EventEmitter } from './emitter'\n\ntype StatusChecker = () => Promise<unknown>\n\n/** @internal Options du constructeur Checkout */\nexport interface CheckoutOptions {\n onReady?: () => void\n onPaymentSuccess?: (data: PaymentResponse) => void\n onPaymentFailed?: (data: PaymentResponse) => void\n onPaymentPending?: (data: PaymentResponse) => void\n onClose?: (data: { status: string }) => void\n onError?: (error: PaymentError) => void\n statusChecker?: StatusChecker\n statusPollInterval?: number\n logger: Logger\n emitter: EventEmitter\n}\n\n/** @internal Intervalle de polling pour vérifier si la popup est fermée */\nconst POPUP_POLL_INTERVAL = 500\n/** @internal Intervalle par défaut pour vérifier le statut via le backend marchand */\nconst STATUS_POLL_INTERVAL = 3000\n/** @internal Évite un polling trop agressif depuis le navigateur */\nconst MIN_STATUS_POLL_INTERVAL = 1000\n\n/**\n * Gère le checkout CinetPay via une popup window + overlay.\n *\n * Flow :\n * 1. Affiche un overlay sombre avec un message d'attente\n * 2. Ouvre la page de checkout dans une popup (window.open)\n * 3. Poll la popup pour détecter sa fermeture\n * 4. Écoute les messages postMessage de la popup\n * 5. Ferme l'overlay et dispatche les callbacks\n *\n * @internal Utilisé par {@link CinetPaySeamless}. Ne pas instancier directement.\n */\nexport class Checkout {\n private overlay: HTMLDivElement | null = null\n private popup: Window | null = null\n private pollTimer: ReturnType<typeof setInterval> | null = null\n private statusTimer: ReturnType<typeof setInterval> | null = null\n private closeTimer: ReturnType<typeof setTimeout> | null = null\n private messageHandler: ((event: MessageEvent) => void) | null = null\n private lastStatus = 'UNKNOWN'\n private lastDispatchKey = ''\n private finalStatusDispatched = false\n private statusCheckInFlight = false\n private isClosing = false\n private previousBodyOverflow = ''\n\n private onReadyCallback?: () => void\n private onPaymentSuccessCallback?: (data: PaymentResponse) => void\n private onPaymentFailedCallback?: (data: PaymentResponse) => void\n private onPaymentPendingCallback?: (data: PaymentResponse) => void\n private onCloseCallback?: (data: { status: string }) => void\n private onErrorCallback?: (error: PaymentError) => void\n private statusChecker?: StatusChecker\n private statusPollInterval: number\n private logger: Logger\n private emitter: EventEmitter\n\n constructor(options: CheckoutOptions) {\n this.logger = options.logger\n this.emitter = options.emitter\n this.onReadyCallback = options.onReady\n this.onPaymentSuccessCallback = options.onPaymentSuccess\n this.onPaymentFailedCallback = options.onPaymentFailed\n this.onPaymentPendingCallback = options.onPaymentPending\n this.onCloseCallback = options.onClose\n this.onErrorCallback = options.onError\n this.statusChecker = options.statusChecker\n this.statusPollInterval = Math.max(\n MIN_STATUS_POLL_INTERVAL,\n options.statusPollInterval ?? STATUS_POLL_INTERVAL,\n )\n }\n\n /**\n * Ouvre la popup de checkout et affiche l'overlay d'attente.\n *\n * @param paymentUrl - URL complète de la page de checkout CinetPay\n */\n open(paymentUrl: string): void {\n this.logger.debug('Opening checkout popup', { paymentUrl })\n this.injectStyles()\n this.createOverlay()\n this.openPopup(paymentUrl)\n if (!this.popup) return\n\n this.listenForMessages()\n this.startPolling()\n this.startStatusPolling()\n\n requestAnimationFrame(() => {\n this.overlay?.classList.add('cp-visible')\n })\n\n this.previousBodyOverflow = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n }\n\n /**\n * Ferme la popup et l'overlay.\n */\n close(): void {\n if (this.closeTimer || this.isClosing) return\n\n if (!this.statusChecker || this.finalStatusDispatched) {\n this.finishClose()\n return\n }\n\n this.isClosing = true\n\n void this.checkStatus('close').finally(() => {\n this.finishClose()\n })\n }\n\n private finishClose(): void {\n if (this.closeTimer) return\n this.stopPolling()\n this.stopStatusPolling()\n\n if (this.messageHandler) {\n window.removeEventListener('message', this.messageHandler)\n this.messageHandler = null\n }\n\n if (this.popup && !this.popup.closed) {\n this.popup.close()\n }\n this.popup = null\n\n if (this.overlay) {\n const overlay = this.overlay\n this.overlay = null\n overlay.classList.remove('cp-visible')\n this.closeTimer = setTimeout(() => {\n overlay.remove()\n this.closeTimer = null\n this.isClosing = false\n\n if (!document.querySelector('.cp-seamless-overlay')) {\n document.body.style.overflow = this.previousBodyOverflow\n }\n\n this.logger.debug('Checkout closed', { lastStatus: this.lastStatus })\n this.emitter.emit('close', { status: this.lastStatus })\n this.onCloseCallback?.({ status: this.lastStatus })\n }, 300)\n } else {\n this.isClosing = false\n }\n }\n\n private static isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n }\n\n private static childRecords(data: Record<string, unknown>): Record<string, unknown>[] {\n const records: Record<string, unknown>[] = []\n for (const key of ['details', 'transaction', 'payment', 'result', 'data']) {\n const child = data[key]\n if (Checkout.isRecord(child)) records.push(child)\n }\n records.push(data)\n return records\n }\n\n private static findValue(data: Record<string, unknown>, keys: string[]): unknown {\n for (const record of Checkout.childRecords(data)) {\n for (const key of keys) {\n if (record[key] !== undefined && record[key] !== null) return record[key]\n }\n }\n return undefined\n }\n\n private static asString(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined\n return String(value)\n }\n\n private static asNumber(value: unknown): number {\n if (typeof value === 'number') return Number.isFinite(value) ? value : 0\n if (typeof value === 'string') {\n const parsed = Number(value.replace(/\\s/g, ''))\n return Number.isFinite(parsed) ? parsed : 0\n }\n return 0\n }\n\n private static asOptionalNumber(value: unknown): number | undefined {\n if (value === undefined || value === null) return undefined\n if (typeof value === 'number') return Number.isFinite(value) ? value : undefined\n if (typeof value === 'string') {\n const parsed = Number(value.trim())\n return Number.isFinite(parsed) ? parsed : undefined\n }\n return undefined\n }\n\n private static normalizeStatus(rawStatus?: string, apiCode?: number): PaymentStatus {\n const normalized = rawStatus?.trim().toUpperCase().replace(/[\\s-]+/g, '_')\n\n if (normalized) {\n if (['ACCEPTED', 'SUCCESS', 'SUCCEEDED', 'SUCCESSFUL', 'PAID', 'VALIDATED', 'APPROVED'].includes(normalized)) {\n return 'ACCEPTED'\n }\n if ([\n 'REFUSED',\n 'FAILED',\n 'FAIL',\n 'FAILURE',\n 'DENIED',\n 'DECLINED',\n 'REJECTED',\n 'CANCELED',\n 'CANCELLED',\n 'CANCEL',\n 'INSUFFICIENT_BALANCE',\n ].includes(normalized)) {\n return 'REFUSED'\n }\n if (['PENDING', 'INITIATED', 'EXPIRED'].includes(normalized)) {\n return normalized as PaymentStatus\n }\n if (['WAITING', 'PROCESSING', 'IN_PROGRESS'].includes(normalized)) {\n return 'PENDING'\n }\n }\n\n switch (apiCode) {\n case 100:\n return 'ACCEPTED'\n case 2010:\n case 2005:\n return 'REFUSED'\n case 2001:\n return 'INITIATED'\n case 2002:\n return 'PENDING'\n case 2003:\n return 'EXPIRED'\n }\n\n return 'UNKNOWN'\n }\n\n private static isFinalStatus(status: PaymentStatus): boolean {\n return status === 'ACCEPTED' || status === 'REFUSED'\n }\n\n private static buildPaymentResponse(data: Record<string, unknown>): PaymentResponse {\n const rawStatus = Checkout.asString(Checkout.findValue(data, [\n 'status',\n 'transaction_status',\n 'trans_status',\n 'payment_status',\n ]))\n const apiCode = Checkout.asOptionalNumber(Checkout.findValue(data, ['code']))\n const status = Checkout.normalizeStatus(rawStatus, apiCode)\n\n return {\n amount: Checkout.asNumber(Checkout.findValue(data, ['amount'])),\n currency: Checkout.asString(Checkout.findValue(data, ['currency'])) ?? '',\n status,\n rawStatus,\n apiCode,\n paymentMethod: Checkout.asString(Checkout.findValue(data, ['payment_method', 'paymentMethod'])) ?? '',\n description: Checkout.asString(Checkout.findValue(data, ['description', 'designation', 'message'])) ?? '',\n metadata: Checkout.asString(Checkout.findValue(data, ['metadata', 'custom'])),\n operatorId: Checkout.asString(Checkout.findValue(data, ['operator_id', 'operatorId'])),\n paymentDate: Checkout.asString(Checkout.findValue(data, ['payment_date', 'paymentDate'])),\n transactionId: Checkout.asString(Checkout.findValue(data, ['transaction_id', 'transactionId', 'merchant_transaction_id'])) ?? '',\n }\n }\n\n /** Dispatche la réponse vers le bon callback selon le statut. */\n private dispatchResponse(response: PaymentResponse): void {\n const dispatchKey = `${response.status}:${response.rawStatus ?? ''}:${response.apiCode ?? ''}`\n const isFinalStatus = Checkout.isFinalStatus(response.status)\n\n if (isFinalStatus && this.finalStatusDispatched) return\n if (dispatchKey === this.lastDispatchKey) return\n\n this.lastDispatchKey = dispatchKey\n this.lastStatus = response.status\n if (isFinalStatus) {\n this.finalStatusDispatched = true\n this.stopStatusPolling()\n }\n\n this.logger.debug(`Payment response: ${response.status}`, {\n amount: response.amount,\n currency: response.currency,\n transactionId: response.transactionId,\n paymentMethod: response.paymentMethod,\n })\n\n switch (response.status) {\n case 'ACCEPTED':\n this.logger.debug('Payment accepted')\n this.emitter.emit('payment.success', response)\n this.onPaymentSuccessCallback?.(response)\n break\n case 'REFUSED':\n this.logger.warn('Payment refused')\n this.emitter.emit('payment.failed', response)\n this.onPaymentFailedCallback?.(response)\n break\n case 'PENDING':\n case 'INITIATED':\n case 'EXPIRED':\n default:\n this.logger.debug(`Payment pending: ${response.status}`)\n this.emitter.emit('payment.pending', response)\n this.onPaymentPendingCallback?.(response)\n break\n }\n }\n\n private injectStyles(): void {\n if (document.getElementById('cp-seamless-styles')) return\n const styleEl = document.createElement('style')\n styleEl.id = 'cp-seamless-styles'\n styleEl.textContent = STYLES\n document.head.appendChild(styleEl)\n }\n\n private createOverlay(): void {\n this.overlay = document.createElement('div')\n this.overlay.className = 'cp-seamless-overlay'\n\n const wrapper = document.createElement('div')\n wrapper.className = 'cp-seamless-wrapper'\n\n // Spinner + message\n const waiting = document.createElement('div')\n waiting.className = 'cp-seamless-waiting'\n\n const spinner = document.createElement('div')\n spinner.className = 'cp-seamless-spinner'\n waiting.appendChild(spinner)\n\n const title = document.createElement('p')\n title.className = 'cp-seamless-waiting-title'\n title.textContent = 'Paiement en cours...'\n waiting.appendChild(title)\n\n const msg = document.createElement('p')\n msg.className = 'cp-seamless-waiting-msg'\n msg.textContent = 'Finalisez votre paiement dans la fenêtre CinetPay.'\n waiting.appendChild(msg)\n\n // Bouton fermer\n const cancelBtn = document.createElement('button')\n cancelBtn.className = 'cp-seamless-cancel-btn'\n cancelBtn.textContent = 'Annuler'\n cancelBtn.addEventListener('click', () => this.close())\n waiting.appendChild(cancelBtn)\n\n wrapper.appendChild(waiting)\n this.overlay.appendChild(wrapper)\n document.body.appendChild(this.overlay)\n }\n\n /**\n * Ouvre la popup centrée sur l'écran.\n */\n private openPopup(paymentUrl: string): void {\n const width = 500\n const height = 700\n const left = Math.max(0, (screen.width - width) / 2)\n const top = Math.max(0, (screen.height - height) / 2)\n\n this.popup = window.open(\n paymentUrl,\n 'CinetPayCheckout',\n `width=${width},height=${height},left=${left},top=${top},scrollbars=yes,resizable=yes`,\n )\n\n if (!this.popup) {\n this.logger.error('Popup blocked by browser')\n const err: PaymentError = {\n code: 'POPUP_BLOCKED',\n message: 'La fenêtre de paiement a été bloquée par le navigateur. Autorisez les popups pour ce site.',\n }\n this.emitter.emit('error', err)\n this.onErrorCallback?.(err)\n this.close()\n return\n }\n\n this.logger.debug('Popup opened')\n this.emitter.emit('ready')\n this.onReadyCallback?.()\n }\n\n /**\n * Poll toutes les 500ms pour détecter si la popup a été fermée\n * (par l'utilisateur ou après redirection).\n */\n private startPolling(): void {\n this.pollTimer = setInterval(() => {\n if (this.popup && this.popup.closed) {\n this.logger.debug('Popup closed by user or redirect')\n this.stopPolling()\n\n // Laisser un court délai pour que le postMessage arrive avant le close\n setTimeout(() => {\n if (this.overlay) {\n this.close()\n }\n }, 500)\n }\n }, POPUP_POLL_INTERVAL)\n }\n\n private stopPolling(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer)\n this.pollTimer = null\n }\n }\n\n private startStatusPolling(): void {\n if (!this.statusChecker) return\n\n void this.checkStatus('open')\n\n this.statusTimer = setInterval(() => {\n void this.checkStatus('interval')\n }, this.statusPollInterval)\n }\n\n private stopStatusPolling(): void {\n if (this.statusTimer) {\n clearInterval(this.statusTimer)\n this.statusTimer = null\n }\n }\n\n private async checkStatus(reason: string): Promise<void> {\n if (!this.statusChecker || this.statusCheckInFlight || this.finalStatusDispatched) return\n\n this.statusCheckInFlight = true\n try {\n this.logger.debug('Checking payment status', { reason })\n const data = await this.statusChecker()\n if (!Checkout.isRecord(data)) return\n\n const response = Checkout.buildPaymentResponse(data)\n const rawStatus = response.rawStatus?.trim().toUpperCase()\n if (response.status !== 'UNKNOWN' || (rawStatus && rawStatus !== 'OK')) {\n this.dispatchResponse(response)\n }\n\n if (Checkout.isFinalStatus(response.status)) {\n this.finishClose()\n }\n } catch (error) {\n this.logger.warn('Payment status check failed', error)\n } finally {\n this.statusCheckInFlight = false\n }\n }\n\n /** Origines autorisées pour les messages postMessage */\n private static readonly ALLOWED_ORIGINS = [\n 'https://secure.cinetpay.net',\n 'https://secure.cinetpay.co',\n 'https://secure.cinetpay.com',\n 'https://checkout.cinetpay.net',\n 'https://checkout.cinetpay.co',\n 'https://checkout.cinetpay.com',\n 'https://api.cinetpay.net',\n 'https://api.cinetpay.co',\n ]\n\n /** Écoute les messages postMessage de la popup CinetPay. */\n private listenForMessages(): void {\n this.messageHandler = (event: MessageEvent) => {\n if (!Checkout.ALLOWED_ORIGINS.some((o) => event.origin === o)) {\n return\n }\n\n try {\n const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data\n if (!Checkout.isRecord(data)) return\n\n const response = Checkout.buildPaymentResponse(data)\n const rawStatus = response.rawStatus?.trim().toUpperCase()\n if (response.status !== 'UNKNOWN' || (rawStatus && rawStatus !== 'OK')) {\n this.dispatchResponse(response)\n }\n\n const error = Checkout.findValue(data, ['error'])\n const code = Checkout.asString(Checkout.findValue(data, ['code']))\n if (error || code === 'ERROR') {\n const err: PaymentError = {\n code: code ?? 'UNKNOWN',\n message: Checkout.asString(Checkout.findValue(data, ['message'])) ?? Checkout.asString(error) ?? 'An error occurred',\n }\n this.logger.error('Payment error from popup', err)\n this.emitter.emit('error', err)\n this.onErrorCallback?.(err)\n }\n\n if (data.action === 'CLOSE' || data.type === 'close') {\n this.close()\n }\n } catch {\n // Ignorer les messages non-JSON\n }\n }\n\n window.addEventListener('message', this.messageHandler)\n }\n}\n","/** Préfixe des messages de log */\nconst PREFIX = '[CinetPay Seamless]'\n\n/**\n * Logger interne du SDK Seamless.\n * Désactivé par défaut. Activable via `debug: true` dans la config.\n *\n * Tous les logs utilisent le préfixe `[CinetPay Seamless]` pour être\n * facilement filtrables dans la console du navigateur.\n */\nexport class Logger {\n private enabled: boolean\n\n constructor(enabled: boolean) {\n this.enabled = enabled\n }\n\n /** Log de debug — requêtes, réponses, événements */\n debug(message: string, data?: unknown): void {\n if (!this.enabled) return\n if (data !== undefined) {\n console.debug(`${PREFIX} ${message}`, data)\n } else {\n console.debug(`${PREFIX} ${message}`)\n }\n }\n\n /** Log d'avertissement — credentials exposés, statuts inattendus */\n warn(message: string, data?: unknown): void {\n if (!this.enabled) return\n if (data !== undefined) {\n console.warn(`${PREFIX} ${message}`, data)\n } else {\n console.warn(`${PREFIX} ${message}`)\n }\n }\n\n /** Log d'erreur — erreurs API, timeouts, postMessage invalides */\n error(message: string, data?: unknown): void {\n if (!this.enabled) return\n if (data !== undefined) {\n console.error(`${PREFIX} ${message}`, data)\n } else {\n console.error(`${PREFIX} ${message}`)\n }\n }\n}\n","import type { PaymentResponse, PaymentError } from './types'\n\n/**\n * Map des événements émis par le SDK Seamless.\n *\n * | Événement | Donnée | Quand |\n * |---|---|---|\n * | `ready` | — | Popup ouverte, passerelle prête |\n * | `payment.success` | `PaymentResponse` | Paiement accepté |\n * | `payment.failed` | `PaymentResponse` | Paiement refusé |\n * | `payment.pending` | `PaymentResponse` | En attente (PENDING, INITIATED, EXPIRED) |\n * | `close` | `{ status: string }` | Popup fermée, overlay retiré |\n * | `error` | `PaymentError` | Erreur technique |\n */\nexport interface EventMap {\n 'ready': void\n 'payment.success': PaymentResponse\n 'payment.failed': PaymentResponse\n 'payment.pending': PaymentResponse\n 'close': { status: string }\n 'error': PaymentError\n}\n\n/** Type des noms d'événements */\nexport type EventName = keyof EventMap\n\n/** Type d'un handler pour un événement donné */\ntype Handler<T> = T extends void ? () => void : (data: T) => void\n\n/**\n * Event emitter typé pour le SDK Seamless.\n *\n * Permet d'écouter les événements de paiement avec `on()` et `off()`,\n * style événementiel (`on('event', handler)`).\n *\n * @example\n * ```typescript\n * CinetPaySeamless.on('payment.success', (data) => {\n * console.log('Payé !', data.amount, data.currency)\n * })\n *\n * CinetPaySeamless.on('payment.failed', (data) => {\n * console.log('Refusé', data.transactionId)\n * })\n *\n * CinetPaySeamless.on('ready', () => {\n * console.log('Passerelle chargée')\n * })\n * ```\n */\nexport class EventEmitter {\n private listeners = new Map<string, Set<Function>>()\n\n /**\n * Enregistre un handler pour un événement.\n *\n * @param event - Nom de l'événement\n * @param handler - Fonction appelée quand l'événement est émis\n * @returns Fonction pour se désabonner (équivalent de `off(event, handler)`)\n *\n * @example\n * ```typescript\n * const unsubscribe = CinetPaySeamless.on('payment.success', (data) => { ... })\n * // Plus tard :\n * unsubscribe()\n * ```\n */\n on<E extends EventName>(event: E, handler: Handler<EventMap[E]>): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set())\n }\n this.listeners.get(event)!.add(handler)\n\n // Retourne une fonction de désabonnement\n return () => this.off(event, handler)\n }\n\n /**\n * Supprime un handler pour un événement.\n *\n * @param event - Nom de l'événement\n * @param handler - Référence du handler à supprimer\n */\n off<E extends EventName>(event: E, handler: Handler<EventMap[E]>): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n /**\n * Enregistre un handler qui ne sera appelé qu'une seule fois.\n *\n * @param event - Nom de l'événement\n * @param handler - Fonction appelée une seule fois\n *\n * @example\n * ```typescript\n * CinetPaySeamless.once('payment.success', (data) => {\n * // Appelé une seule fois\n * })\n * ```\n */\n once<E extends EventName>(event: E, handler: Handler<EventMap[E]>): void {\n const wrapper = ((...args: unknown[]) => {\n this.off(event, wrapper as Handler<EventMap[E]>)\n ;(handler as Function)(...args)\n }) as Handler<EventMap[E]>\n this.on(event, wrapper)\n }\n\n /**\n * Émet un événement — appelle tous les handlers enregistrés.\n * @internal\n */\n emit<E extends EventName>(event: E, ...args: EventMap[E] extends void ? [] : [EventMap[E]]): void {\n const handlers = this.listeners.get(event)\n if (!handlers) return\n for (const handler of handlers) {\n try {\n (handler as Function)(...args)\n } catch {\n // Ne pas bloquer les autres handlers si un throw\n }\n }\n }\n\n /**\n * Supprime tous les handlers pour tous les événements.\n * @internal\n */\n removeAll(): void {\n this.listeners.clear()\n }\n}\n","import { Checkout } from './checkout'\nimport type {\n SeamlessConfig,\n PaymentResponse,\n PaymentError,\n PaymentStatus,\n StatusCheckContext,\n SeamlessEnvironment,\n} from './types'\nimport { Logger } from './logger'\nimport { EventEmitter, type EventName, type EventMap } from './emitter'\n\nexport type {\n SeamlessConfig,\n PaymentResponse,\n PaymentError,\n PaymentStatus,\n StatusCheckContext,\n SeamlessEnvironment,\n}\nexport type { EventName, EventMap } from './emitter'\n\n/** @internal URLs de base de la passerelle de paiement sécurisée */\nconst SECURE_BASE_URLS: Record<SeamlessEnvironment, string> = {\n sandbox: 'https://secure.cinetpay.net',\n production: 'https://secure.cinetpay.co',\n}\n\n/** Récupère un callback en tolérant la casse pour les intégrations CDN/script tag. */\nfunction getCallback<T extends Function>(config: SeamlessConfig, names: string[]): T | undefined {\n const record = config as unknown as Record<string, unknown>\n\n for (const name of names) {\n const value = record[name]\n if (typeof value === 'function') return value as T\n }\n\n const lowerNames = new Set(names.map((name) => name.toLowerCase()))\n for (const [key, value] of Object.entries(record)) {\n if (lowerNames.has(key.toLowerCase()) && typeof value === 'function') {\n return value as T\n }\n }\n\n return undefined\n}\n\n/** Récupère une option en tolérant la casse pour les intégrations CDN/script tag. */\nfunction getOption<T>(config: SeamlessConfig, names: string[]): T | undefined {\n const record = config as unknown as Record<string, unknown>\n\n for (const name of names) {\n if (record[name] !== undefined) return record[name] as T\n }\n\n const lowerNames = new Set(names.map((name) => name.toLowerCase()))\n for (const [key, value] of Object.entries(record)) {\n if (lowerNames.has(key.toLowerCase())) return value as T\n }\n\n return undefined\n}\n\nfunction createStatusChecker(config: SeamlessConfig): (() => Promise<unknown>) | undefined {\n const context: StatusCheckContext = { paymentToken: config.paymentToken }\n const checkStatus = getCallback<(context: StatusCheckContext) => Promise<unknown>>(config, [\n 'checkStatus',\n 'checkPaymentStatus',\n 'checkTransactionStatus',\n ])\n\n if (checkStatus) {\n return () => checkStatus(context)\n }\n\n const statusUrl = getOption<SeamlessConfig['statusUrl']>(config, ['statusUrl', 'statusURL'])\n if (!statusUrl) return undefined\n\n return async () => {\n const url = typeof statusUrl === 'function' ? statusUrl(context) : statusUrl\n const response = await fetch(url, {\n method: 'GET',\n credentials: 'same-origin',\n headers: { Accept: 'application/json' },\n })\n\n if (!response.ok) {\n throw new Error(`Status check failed with HTTP ${response.status}`)\n }\n\n return response.json()\n }\n}\n\nfunction createPaymentUrl(config: SeamlessConfig): string {\n const explicitUrl = getOption<string>(config, ['paymentUrl', 'checkoutUrl'])\n if (explicitUrl) return explicitUrl\n\n const environment = getOption<SeamlessEnvironment>(config, ['environment', 'env']) ?? 'sandbox'\n const checkoutBaseUrl =\n getOption<string>(config, ['checkoutBaseUrl', 'secureBaseUrl']) ??\n SECURE_BASE_URLS[environment] ??\n SECURE_BASE_URLS.sandbox\n\n return `${checkoutBaseUrl.replace(/\\/+$/, '')}/checkout/${config.paymentToken}`\n}\n\n/**\n * CinetPay Seamless — paiement inline via popup window.\n *\n * Affiche un overlay d'attente et ouvre la passerelle de paiement\n * CinetPay dans une popup. Le client reste sur votre page.\n *\n * Le `paymentToken` est obtenu côté serveur via l'API CinetPay :\n *\n * ```typescript\n * // Frontend\n * CinetPaySeamless.open({\n * paymentToken: 'abc123...',\n * onPaymentSuccess: (data) => console.log('Payé !', data.amount),\n * })\n * ```\n *\n * Ou avec des event listeners (style événementiel) :\n *\n * ```typescript\n * CinetPaySeamless.on('payment.success', (data) => { ... })\n * CinetPaySeamless.open({ paymentToken: 'abc123...' })\n * ```\n */\nexport const CinetPaySeamless = {\n /** Instance du checkout actuellement ouvert */\n _checkout: null as Checkout | null,\n\n /** Event emitter partagé */\n _emitter: new EventEmitter(),\n\n /**\n * Enregistre un listener d'événement (style événementiel).\n *\n * @param event - Nom de l'événement\n * @param handler - Fonction appelée quand l'événement est émis\n * @returns Fonction de désabonnement\n *\n * @example\n * ```typescript\n * const unsub = CinetPaySeamless.on('payment.success', (data) => {\n * console.log('Payé !', data.amount, data.currency)\n * })\n * unsub() // Se désabonner\n * ```\n */\n on<E extends EventName>(\n event: E,\n handler: EventMap[E] extends void ? () => void : (data: EventMap[E]) => void,\n ): () => void {\n return this._emitter.on(event, handler)\n },\n\n /**\n * Supprime un listener.\n */\n off<E extends EventName>(\n event: E,\n handler: EventMap[E] extends void ? () => void : (data: EventMap[E]) => void,\n ): void {\n this._emitter.off(event, handler)\n },\n\n /**\n * Enregistre un listener appelé une seule fois.\n */\n once<E extends EventName>(\n event: E,\n handler: EventMap[E] extends void ? () => void : (data: EventMap[E]) => void,\n ): void {\n this._emitter.once(event, handler)\n },\n\n /**\n * Ouvre le checkout CinetPay.\n *\n * Affiche un overlay d'attente et ouvre la page de paiement dans une popup.\n * La popup est centrée sur l'écran (500x700px).\n *\n * @param config - Configuration avec `paymentToken` et callbacks optionnels\n * @throws {Error} Si le `paymentToken` a un format invalide\n *\n * @example\n * ```typescript\n * CinetPaySeamless.open({\n * paymentToken: 'abc123def456...',\n * debug: true,\n * onPaymentSuccess: (data) => console.log('Payé !', data.amount),\n * onPaymentFailed: (data) => console.log('Refusé'),\n * onClose: ({ status }) => console.log('Fermé:', status),\n * })\n * ```\n */\n open(config: SeamlessConfig): void {\n this.close()\n\n const logger = new Logger(config.debug ?? false)\n logger.debug('CinetPaySeamless.open() called')\n\n // Validation du paymentToken\n if (!/^[a-zA-Z0-9_-]{10,128}$/.test(config.paymentToken)) {\n throw new Error('Invalid paymentToken format — expected alphanumeric string (10-128 chars)')\n }\n\n const paymentUrl = createPaymentUrl(config)\n\n this._checkout = new Checkout({\n logger,\n emitter: this._emitter,\n statusChecker: createStatusChecker(config),\n statusPollInterval: getOption<number>(config, ['statusPollInterval', 'statusCheckInterval']),\n onReady: getCallback(config, ['onReady']),\n onPaymentSuccess: getCallback(config, [\n 'onPaymentSuccess',\n 'onSuccess',\n 'onPaymentsuccess',\n 'onpaymentSuccess',\n 'onpaymentsuccess',\n ]),\n onPaymentFailed: getCallback(config, [\n 'onPaymentFailed',\n 'onPaymentFail',\n 'onPaymentFailure',\n 'onFailed',\n 'onPaymentfailed',\n 'onpaymentFailed',\n 'onpaymentfailed',\n ]),\n onPaymentPending: getCallback(config, ['onPaymentPending', 'onPending']),\n onClose: getCallback(config, ['onClose']),\n onError: getCallback(config, ['onError']),\n })\n\n this._checkout.open(paymentUrl)\n },\n\n /**\n * Ferme le checkout (popup + overlay).\n */\n close(): void {\n this._checkout?.close()\n this._checkout = null\n },\n}\n\n// Auto-attach to window for CDN/script tag usage\nif (typeof window !== 'undefined') {\n (window as unknown as Record<string, unknown>).CinetPaySeamless = CinetPaySeamless\n}\n"],"names":["STYLES","_Checkout","options","paymentUrl","_a","overlay","value","data","records","key","child","keys","record","parsed","rawStatus","apiCode","normalized","status","response","dispatchKey","isFinalStatus","_b","_c","styleEl","wrapper","waiting","spinner","title","msg","cancelBtn","left","top","err","reason","error","event","o","code","Checkout","PREFIX","Logger","enabled","message","EventEmitter","handler","args","handlers","SECURE_BASE_URLS","getCallback","config","names","name","lowerNames","getOption","createStatusChecker","context","checkStatus","statusUrl","url","createPaymentUrl","explicitUrl","environment","CinetPaySeamless","logger"],"mappings":"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"}
1
+ {"version":3,"file":"cinetpay-seamless.umd.cjs","sources":["../src/styles.ts","../src/checkout.ts","../src/logger.ts","../src/emitter.ts","../src/index.ts"],"sourcesContent":["/**\n * Styles CSS du checkout CinetPay Seamless (mode popup).\n */\nexport const STYLES = `\n.cp-seamless-overlay {\n position: fixed;\n inset: 0;\n z-index: 999999;\n background: rgba(0, 0, 0, 0.7);\n backdrop-filter: blur(6px);\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n transition: opacity 0.3s ease;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n.cp-seamless-overlay.cp-visible {\n opacity: 1;\n}\n\n.cp-seamless-wrapper {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Waiting screen (pendant que la popup est ouverte) */\n.cp-seamless-waiting {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 20px;\n text-align: center;\n padding: 40px;\n}\n\n.cp-seamless-waiting-title {\n color: #fff;\n font-size: 22px;\n font-weight: 600;\n margin: 0;\n}\n\n.cp-seamless-waiting-msg {\n color: rgba(255, 255, 255, 0.7);\n font-size: 15px;\n margin: 0;\n max-width: 320px;\n line-height: 1.5;\n}\n\n.cp-seamless-spinner {\n width: 48px;\n height: 48px;\n border: 3px solid rgba(255, 255, 255, 0.2);\n border-top-color: #e8530e;\n border-radius: 50%;\n animation: cp-spin 0.8s linear infinite;\n}\n\n@keyframes cp-spin {\n to { transform: rotate(360deg); }\n}\n\n.cp-seamless-cancel-btn {\n margin-top: 12px;\n padding: 10px 28px;\n background: rgba(255, 255, 255, 0.12);\n color: rgba(255, 255, 255, 0.8);\n border: 1px solid rgba(255, 255, 255, 0.2);\n border-radius: 8px;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.cp-seamless-cancel-btn:hover {\n background: rgba(255, 255, 255, 0.2);\n color: #fff;\n}\n\n`\n","import { STYLES } from './styles'\nimport type { PaymentResponse, PaymentError, PaymentStatus } from './types'\nimport { Logger } from './logger'\nimport { EventEmitter } from './emitter'\n\ntype StatusChecker = () => Promise<unknown>\n\n/** @internal Options du constructeur Checkout */\nexport interface CheckoutOptions {\n onReady?: () => void\n onPaymentSuccess?: (data: PaymentResponse) => void\n onPaymentFailed?: (data: PaymentResponse) => void\n onPaymentPending?: (data: PaymentResponse) => void\n onClose?: (data: { status: string }) => void\n onError?: (error: PaymentError) => void\n statusChecker?: StatusChecker\n statusPollInterval?: number\n logger: Logger\n emitter: EventEmitter\n}\n\n/** @internal Intervalle de polling pour vérifier si la popup est fermée */\nconst POPUP_POLL_INTERVAL = 500\n/** @internal Intervalle par défaut pour vérifier le statut via le backend marchand */\nconst STATUS_POLL_INTERVAL = 3000\n/** @internal Évite un polling trop agressif depuis le navigateur */\nconst MIN_STATUS_POLL_INTERVAL = 1000\n\n/**\n * Gère le checkout CinetPay via une popup window + overlay.\n *\n * Flow :\n * 1. Affiche un overlay sombre avec un message d'attente\n * 2. Ouvre la page de checkout dans une popup (window.open)\n * 3. Poll la popup pour détecter sa fermeture\n * 4. Écoute les messages postMessage de la popup\n * 5. Ferme l'overlay et dispatche les callbacks\n *\n * @internal Utilisé par {@link CinetPaySeamless}. Ne pas instancier directement.\n */\nexport class Checkout {\n private overlay: HTMLDivElement | null = null\n private popup: Window | null = null\n private pollTimer: ReturnType<typeof setInterval> | null = null\n private statusTimer: ReturnType<typeof setInterval> | null = null\n private closeTimer: ReturnType<typeof setTimeout> | null = null\n private messageHandler: ((event: MessageEvent) => void) | null = null\n private lastStatus = 'UNKNOWN'\n private lastDispatchKey = ''\n private finalStatusDispatched = false\n private statusCheckInFlight = false\n private isClosing = false\n private previousBodyOverflow = ''\n\n private onReadyCallback?: () => void\n private onPaymentSuccessCallback?: (data: PaymentResponse) => void\n private onPaymentFailedCallback?: (data: PaymentResponse) => void\n private onPaymentPendingCallback?: (data: PaymentResponse) => void\n private onCloseCallback?: (data: { status: string }) => void\n private onErrorCallback?: (error: PaymentError) => void\n private statusChecker?: StatusChecker\n private statusPollInterval: number\n private logger: Logger\n private emitter: EventEmitter\n\n constructor(options: CheckoutOptions) {\n this.logger = options.logger\n this.emitter = options.emitter\n this.onReadyCallback = options.onReady\n this.onPaymentSuccessCallback = options.onPaymentSuccess\n this.onPaymentFailedCallback = options.onPaymentFailed\n this.onPaymentPendingCallback = options.onPaymentPending\n this.onCloseCallback = options.onClose\n this.onErrorCallback = options.onError\n this.statusChecker = options.statusChecker\n this.statusPollInterval = Math.max(\n MIN_STATUS_POLL_INTERVAL,\n options.statusPollInterval ?? STATUS_POLL_INTERVAL,\n )\n }\n\n /**\n * Ouvre la popup de checkout et affiche l'overlay d'attente.\n *\n * @param paymentUrl - URL complète de la page de checkout CinetPay\n */\n open(paymentUrl: string): void {\n this.logger.debug('Opening checkout popup', { paymentUrl })\n this.injectStyles()\n this.createOverlay()\n this.openPopup(paymentUrl)\n if (!this.popup) return\n\n this.listenForMessages()\n this.startPolling()\n this.startStatusPolling()\n\n requestAnimationFrame(() => {\n this.overlay?.classList.add('cp-visible')\n })\n\n this.previousBodyOverflow = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n }\n\n /**\n * Ferme la popup et l'overlay.\n */\n close(): void {\n if (this.closeTimer || this.isClosing) return\n\n if (!this.statusChecker || this.finalStatusDispatched) {\n this.finishClose()\n return\n }\n\n this.isClosing = true\n\n void this.checkStatus('close').finally(() => {\n this.finishClose()\n })\n }\n\n private finishClose(): void {\n if (this.closeTimer) return\n this.stopPolling()\n this.stopStatusPolling()\n\n if (this.messageHandler) {\n window.removeEventListener('message', this.messageHandler)\n this.messageHandler = null\n }\n\n if (this.popup && !this.popup.closed) {\n this.popup.close()\n }\n this.popup = null\n\n if (this.overlay) {\n const overlay = this.overlay\n this.overlay = null\n overlay.classList.remove('cp-visible')\n this.closeTimer = setTimeout(() => {\n overlay.remove()\n this.closeTimer = null\n this.isClosing = false\n\n if (!document.querySelector('.cp-seamless-overlay')) {\n document.body.style.overflow = this.previousBodyOverflow\n }\n\n this.logger.debug('Checkout closed', { lastStatus: this.lastStatus })\n this.emitter.emit('close', { status: this.lastStatus })\n this.onCloseCallback?.({ status: this.lastStatus })\n }, 300)\n } else {\n this.isClosing = false\n }\n }\n\n private static isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n }\n\n private static childRecords(data: Record<string, unknown>): Record<string, unknown>[] {\n const records: Record<string, unknown>[] = []\n for (const key of ['details', 'transaction', 'payment', 'result', 'data']) {\n const child = data[key]\n if (Checkout.isRecord(child)) records.push(child)\n }\n records.push(data)\n return records\n }\n\n private static findValue(data: Record<string, unknown>, keys: string[]): unknown {\n for (const record of Checkout.childRecords(data)) {\n for (const key of keys) {\n if (record[key] !== undefined && record[key] !== null) return record[key]\n }\n }\n return undefined\n }\n\n private static asString(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined\n return String(value)\n }\n\n private static asNumber(value: unknown): number {\n if (typeof value === 'number') return Number.isFinite(value) ? value : 0\n if (typeof value === 'string') {\n const parsed = Number(value.replace(/\\s/g, ''))\n return Number.isFinite(parsed) ? parsed : 0\n }\n return 0\n }\n\n private static asOptionalNumber(value: unknown): number | undefined {\n if (value === undefined || value === null) return undefined\n if (typeof value === 'number') return Number.isFinite(value) ? value : undefined\n if (typeof value === 'string') {\n const parsed = Number(value.trim())\n return Number.isFinite(parsed) ? parsed : undefined\n }\n return undefined\n }\n\n private static normalizeStatus(rawStatus?: string, apiCode?: number): PaymentStatus {\n const normalized = rawStatus?.trim().toUpperCase().replace(/[\\s-]+/g, '_')\n\n if (normalized) {\n if (['ACCEPTED', 'SUCCESS', 'SUCCEEDED', 'SUCCESSFUL', 'PAID', 'VALIDATED', 'APPROVED'].includes(normalized)) {\n return 'ACCEPTED'\n }\n if ([\n 'REFUSED',\n 'FAILED',\n 'FAIL',\n 'FAILURE',\n 'DENIED',\n 'DECLINED',\n 'REJECTED',\n 'CANCELED',\n 'CANCELLED',\n 'CANCEL',\n 'INSUFFICIENT_BALANCE',\n ].includes(normalized)) {\n return 'REFUSED'\n }\n if (['PENDING', 'INITIATED', 'EXPIRED'].includes(normalized)) {\n return normalized as PaymentStatus\n }\n if (['WAITING', 'PROCESSING', 'IN_PROGRESS'].includes(normalized)) {\n return 'PENDING'\n }\n }\n\n switch (apiCode) {\n case 100:\n return 'ACCEPTED'\n case 2010:\n case 2005:\n return 'REFUSED'\n case 2001:\n return 'INITIATED'\n case 2002:\n return 'PENDING'\n case 2003:\n return 'EXPIRED'\n }\n\n return 'UNKNOWN'\n }\n\n private static isFinalStatus(status: PaymentStatus): boolean {\n return status === 'ACCEPTED' || status === 'REFUSED'\n }\n\n private static buildPaymentResponse(data: Record<string, unknown>): PaymentResponse {\n const rawStatus = Checkout.asString(Checkout.findValue(data, [\n 'status',\n 'transaction_status',\n 'trans_status',\n 'payment_status',\n ]))\n const apiCode = Checkout.asOptionalNumber(Checkout.findValue(data, ['code']))\n const status = Checkout.normalizeStatus(rawStatus, apiCode)\n\n return {\n amount: Checkout.asNumber(Checkout.findValue(data, ['amount'])),\n currency: Checkout.asString(Checkout.findValue(data, ['currency'])) ?? '',\n status,\n rawStatus,\n apiCode,\n paymentMethod: Checkout.asString(Checkout.findValue(data, ['payment_method', 'paymentMethod'])) ?? '',\n description: Checkout.asString(Checkout.findValue(data, ['description', 'designation', 'message'])) ?? '',\n metadata: Checkout.asString(Checkout.findValue(data, ['metadata', 'custom'])),\n operatorId: Checkout.asString(Checkout.findValue(data, ['operator_id', 'operatorId'])),\n paymentDate: Checkout.asString(Checkout.findValue(data, ['payment_date', 'paymentDate'])),\n transactionId: Checkout.asString(Checkout.findValue(data, ['transaction_id', 'transactionId', 'merchant_transaction_id'])) ?? '',\n }\n }\n\n /** Dispatche la réponse vers le bon callback selon le statut. */\n private dispatchResponse(response: PaymentResponse): void {\n const dispatchKey = `${response.status}:${response.rawStatus ?? ''}:${response.apiCode ?? ''}`\n const isFinalStatus = Checkout.isFinalStatus(response.status)\n\n if (isFinalStatus && this.finalStatusDispatched) return\n if (dispatchKey === this.lastDispatchKey) return\n\n this.lastDispatchKey = dispatchKey\n this.lastStatus = response.status\n if (isFinalStatus) {\n this.finalStatusDispatched = true\n this.stopStatusPolling()\n }\n\n this.logger.debug(`Payment response: ${response.status}`, {\n amount: response.amount,\n currency: response.currency,\n transactionId: response.transactionId,\n paymentMethod: response.paymentMethod,\n })\n\n switch (response.status) {\n case 'ACCEPTED':\n this.logger.debug('Payment accepted')\n this.emitter.emit('payment.success', response)\n this.onPaymentSuccessCallback?.(response)\n break\n case 'REFUSED':\n this.logger.warn('Payment refused')\n this.emitter.emit('payment.failed', response)\n this.onPaymentFailedCallback?.(response)\n break\n case 'PENDING':\n case 'INITIATED':\n case 'EXPIRED':\n default:\n this.logger.debug(`Payment pending: ${response.status}`)\n this.emitter.emit('payment.pending', response)\n this.onPaymentPendingCallback?.(response)\n break\n }\n }\n\n private injectStyles(): void {\n if (document.getElementById('cp-seamless-styles')) return\n const styleEl = document.createElement('style')\n styleEl.id = 'cp-seamless-styles'\n styleEl.textContent = STYLES\n document.head.appendChild(styleEl)\n }\n\n private createOverlay(): void {\n this.overlay = document.createElement('div')\n this.overlay.className = 'cp-seamless-overlay'\n\n const wrapper = document.createElement('div')\n wrapper.className = 'cp-seamless-wrapper'\n\n // Spinner + message\n const waiting = document.createElement('div')\n waiting.className = 'cp-seamless-waiting'\n\n const spinner = document.createElement('div')\n spinner.className = 'cp-seamless-spinner'\n waiting.appendChild(spinner)\n\n const title = document.createElement('p')\n title.className = 'cp-seamless-waiting-title'\n title.textContent = 'Paiement en cours...'\n waiting.appendChild(title)\n\n const msg = document.createElement('p')\n msg.className = 'cp-seamless-waiting-msg'\n msg.textContent = 'Finalisez votre paiement dans la fenêtre CinetPay.'\n waiting.appendChild(msg)\n\n // Bouton fermer\n const cancelBtn = document.createElement('button')\n cancelBtn.className = 'cp-seamless-cancel-btn'\n cancelBtn.textContent = 'Annuler'\n cancelBtn.addEventListener('click', () => this.close())\n waiting.appendChild(cancelBtn)\n\n wrapper.appendChild(waiting)\n this.overlay.appendChild(wrapper)\n document.body.appendChild(this.overlay)\n }\n\n /**\n * Ouvre la popup centrée sur l'écran.\n */\n private openPopup(paymentUrl: string): void {\n const width = 500\n const height = 700\n const left = Math.max(0, (screen.width - width) / 2)\n const top = Math.max(0, (screen.height - height) / 2)\n\n this.popup = window.open(\n paymentUrl,\n 'CinetPayCheckout',\n `width=${width},height=${height},left=${left},top=${top},scrollbars=yes,resizable=yes`,\n )\n\n if (!this.popup) {\n this.logger.error('Popup blocked by browser')\n const err: PaymentError = {\n code: 'POPUP_BLOCKED',\n message: 'La fenêtre de paiement a été bloquée par le navigateur. Autorisez les popups pour ce site.',\n }\n this.emitter.emit('error', err)\n this.onErrorCallback?.(err)\n this.close()\n return\n }\n\n this.logger.debug('Popup opened')\n this.emitter.emit('ready')\n this.onReadyCallback?.()\n }\n\n /**\n * Poll toutes les 500ms pour détecter si la popup a été fermée\n * (par l'utilisateur ou après redirection).\n */\n private startPolling(): void {\n this.pollTimer = setInterval(() => {\n if (this.popup && this.popup.closed) {\n this.logger.debug('Popup closed by user or redirect')\n this.stopPolling()\n\n // Laisser un court délai pour que le postMessage arrive avant le close\n setTimeout(() => {\n if (this.overlay) {\n this.close()\n }\n }, 500)\n }\n }, POPUP_POLL_INTERVAL)\n }\n\n private stopPolling(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer)\n this.pollTimer = null\n }\n }\n\n private startStatusPolling(): void {\n if (!this.statusChecker) return\n\n void this.checkStatus('open')\n\n this.statusTimer = setInterval(() => {\n void this.checkStatus('interval')\n }, this.statusPollInterval)\n }\n\n private stopStatusPolling(): void {\n if (this.statusTimer) {\n clearInterval(this.statusTimer)\n this.statusTimer = null\n }\n }\n\n private async checkStatus(reason: string): Promise<void> {\n if (!this.statusChecker || this.statusCheckInFlight || this.finalStatusDispatched) return\n\n this.statusCheckInFlight = true\n try {\n this.logger.debug('Checking payment status', { reason })\n const data = await this.statusChecker()\n if (!Checkout.isRecord(data)) return\n\n const response = Checkout.buildPaymentResponse(data)\n const rawStatus = response.rawStatus?.trim().toUpperCase()\n if (response.status !== 'UNKNOWN' || (rawStatus && rawStatus !== 'OK')) {\n this.dispatchResponse(response)\n }\n\n if (Checkout.isFinalStatus(response.status)) {\n this.finishClose()\n }\n } catch (error) {\n this.logger.warn('Payment status check failed', error)\n } finally {\n this.statusCheckInFlight = false\n }\n }\n\n /** Origines autorisées pour les messages postMessage */\n private static readonly ALLOWED_ORIGINS = [\n 'https://secure.cinetpay.net',\n 'https://secure.cinetpay.co',\n 'https://secure.cinetpay.com',\n 'https://checkout.cinetpay.net',\n 'https://checkout.cinetpay.co',\n 'https://checkout.cinetpay.com',\n 'https://api.cinetpay.net',\n 'https://api.cinetpay.co',\n ]\n\n /** Écoute les messages postMessage de la popup CinetPay. */\n private listenForMessages(): void {\n this.messageHandler = (event: MessageEvent) => {\n if (!Checkout.ALLOWED_ORIGINS.some((o) => event.origin === o)) {\n return\n }\n\n try {\n const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data\n if (!Checkout.isRecord(data)) return\n\n const response = Checkout.buildPaymentResponse(data)\n const rawStatus = response.rawStatus?.trim().toUpperCase()\n if (response.status !== 'UNKNOWN' || (rawStatus && rawStatus !== 'OK')) {\n this.dispatchResponse(response)\n }\n\n const error = Checkout.findValue(data, ['error'])\n const code = Checkout.asString(Checkout.findValue(data, ['code']))\n if (error || code === 'ERROR') {\n const err: PaymentError = {\n code: code ?? 'UNKNOWN',\n message: Checkout.asString(Checkout.findValue(data, ['message'])) ?? Checkout.asString(error) ?? 'An error occurred',\n }\n this.logger.error('Payment error from popup', err)\n this.emitter.emit('error', err)\n this.onErrorCallback?.(err)\n }\n\n if (data.action === 'CLOSE' || data.type === 'close') {\n this.close()\n }\n } catch {\n // Ignorer les messages non-JSON\n }\n }\n\n window.addEventListener('message', this.messageHandler)\n }\n}\n","/** Préfixe des messages de log */\nconst PREFIX = '[CinetPay Seamless]'\n\n/**\n * Logger interne du SDK Seamless.\n * Désactivé par défaut. Activable via `debug: true` dans la config.\n *\n * Tous les logs utilisent le préfixe `[CinetPay Seamless]` pour être\n * facilement filtrables dans la console du navigateur.\n */\nexport class Logger {\n private enabled: boolean\n\n constructor(enabled: boolean) {\n this.enabled = enabled\n }\n\n /** Log de debug — requêtes, réponses, événements */\n debug(message: string, data?: unknown): void {\n if (!this.enabled) return\n if (data !== undefined) {\n console.debug(`${PREFIX} ${message}`, data)\n } else {\n console.debug(`${PREFIX} ${message}`)\n }\n }\n\n /** Log d'avertissement — credentials exposés, statuts inattendus */\n warn(message: string, data?: unknown): void {\n if (!this.enabled) return\n if (data !== undefined) {\n console.warn(`${PREFIX} ${message}`, data)\n } else {\n console.warn(`${PREFIX} ${message}`)\n }\n }\n\n /** Log d'erreur — erreurs API, timeouts, postMessage invalides */\n error(message: string, data?: unknown): void {\n if (!this.enabled) return\n if (data !== undefined) {\n console.error(`${PREFIX} ${message}`, data)\n } else {\n console.error(`${PREFIX} ${message}`)\n }\n }\n}\n","import type { PaymentResponse, PaymentError } from './types'\n\n/**\n * Map des événements émis par le SDK Seamless.\n *\n * | Événement | Donnée | Quand |\n * |---|---|---|\n * | `ready` | — | Popup ouverte, passerelle prête |\n * | `payment.success` | `PaymentResponse` | Paiement accepté |\n * | `payment.failed` | `PaymentResponse` | Paiement refusé |\n * | `payment.pending` | `PaymentResponse` | En attente (PENDING, INITIATED, EXPIRED) |\n * | `close` | `{ status: string }` | Popup fermée, overlay retiré |\n * | `error` | `PaymentError` | Erreur technique |\n */\nexport interface EventMap {\n 'ready': void\n 'payment.success': PaymentResponse\n 'payment.failed': PaymentResponse\n 'payment.pending': PaymentResponse\n 'close': { status: string }\n 'error': PaymentError\n}\n\n/** Type des noms d'événements */\nexport type EventName = keyof EventMap\n\n/** Type d'un handler pour un événement donné */\ntype Handler<T> = T extends void ? () => void : (data: T) => void\n\n/**\n * Event emitter typé pour le SDK Seamless.\n *\n * Permet d'écouter les événements de paiement avec `on()` et `off()`,\n * style événementiel (`on('event', handler)`).\n *\n * @example\n * ```typescript\n * CinetPaySeamless.on('payment.success', (data) => {\n * console.log('Payé !', data.amount, data.currency)\n * })\n *\n * CinetPaySeamless.on('payment.failed', (data) => {\n * console.log('Refusé', data.transactionId)\n * })\n *\n * CinetPaySeamless.on('ready', () => {\n * console.log('Passerelle chargée')\n * })\n * ```\n */\nexport class EventEmitter {\n private listeners = new Map<string, Set<Function>>()\n\n /**\n * Enregistre un handler pour un événement.\n *\n * @param event - Nom de l'événement\n * @param handler - Fonction appelée quand l'événement est émis\n * @returns Fonction pour se désabonner (équivalent de `off(event, handler)`)\n *\n * @example\n * ```typescript\n * const unsubscribe = CinetPaySeamless.on('payment.success', (data) => { ... })\n * // Plus tard :\n * unsubscribe()\n * ```\n */\n on<E extends EventName>(event: E, handler: Handler<EventMap[E]>): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set())\n }\n this.listeners.get(event)!.add(handler)\n\n // Retourne une fonction de désabonnement\n return () => this.off(event, handler)\n }\n\n /**\n * Supprime un handler pour un événement.\n *\n * @param event - Nom de l'événement\n * @param handler - Référence du handler à supprimer\n */\n off<E extends EventName>(event: E, handler: Handler<EventMap[E]>): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n /**\n * Enregistre un handler qui ne sera appelé qu'une seule fois.\n *\n * @param event - Nom de l'événement\n * @param handler - Fonction appelée une seule fois\n *\n * @example\n * ```typescript\n * CinetPaySeamless.once('payment.success', (data) => {\n * // Appelé une seule fois\n * })\n * ```\n */\n once<E extends EventName>(event: E, handler: Handler<EventMap[E]>): void {\n const wrapper = ((...args: unknown[]) => {\n this.off(event, wrapper as Handler<EventMap[E]>)\n ;(handler as Function)(...args)\n }) as Handler<EventMap[E]>\n this.on(event, wrapper)\n }\n\n /**\n * Émet un événement — appelle tous les handlers enregistrés.\n * @internal\n */\n emit<E extends EventName>(event: E, ...args: EventMap[E] extends void ? [] : [EventMap[E]]): void {\n const handlers = this.listeners.get(event)\n if (!handlers) return\n for (const handler of handlers) {\n try {\n (handler as Function)(...args)\n } catch {\n // Ne pas bloquer les autres handlers si un throw\n }\n }\n }\n\n /**\n * Supprime tous les handlers pour tous les événements.\n * @internal\n */\n removeAll(): void {\n this.listeners.clear()\n }\n}\n","import { Checkout } from './checkout'\nimport type {\n SeamlessConfig,\n PaymentResponse,\n PaymentError,\n PaymentStatus,\n StatusCheckContext,\n SeamlessEnvironment,\n} from './types'\nimport { Logger } from './logger'\nimport { EventEmitter, type EventName, type EventMap } from './emitter'\n\nexport type {\n SeamlessConfig,\n PaymentResponse,\n PaymentError,\n PaymentStatus,\n StatusCheckContext,\n SeamlessEnvironment,\n}\nexport type { EventName, EventMap } from './emitter'\n\n/** @internal URLs de base de la passerelle de paiement sécurisée */\nconst SECURE_BASE_URLS: Record<SeamlessEnvironment, string> = {\n sandbox: 'https://secure.cinetpay.net',\n production: 'https://secure.cinetpay.co',\n}\n\n/** Récupère un callback en tolérant la casse pour les intégrations CDN/script tag. */\nfunction getCallback<T extends Function>(config: SeamlessConfig, names: string[]): T | undefined {\n const record = config as unknown as Record<string, unknown>\n\n for (const name of names) {\n const value = record[name]\n if (typeof value === 'function') return value as T\n }\n\n const lowerNames = new Set(names.map((name) => name.toLowerCase()))\n for (const [key, value] of Object.entries(record)) {\n if (lowerNames.has(key.toLowerCase()) && typeof value === 'function') {\n return value as T\n }\n }\n\n return undefined\n}\n\n/** Récupère une option en tolérant la casse pour les intégrations CDN/script tag. */\nfunction getOption<T>(config: SeamlessConfig, names: string[]): T | undefined {\n const record = config as unknown as Record<string, unknown>\n\n for (const name of names) {\n if (record[name] !== undefined) return record[name] as T\n }\n\n const lowerNames = new Set(names.map((name) => name.toLowerCase()))\n for (const [key, value] of Object.entries(record)) {\n if (lowerNames.has(key.toLowerCase())) return value as T\n }\n\n return undefined\n}\n\nfunction getPaymentToken(config: SeamlessConfig): string | undefined {\n return getOption<string>(config, ['paymentToken', 'payment_token'])\n}\n\nfunction getPaymentUrl(config: SeamlessConfig): string | undefined {\n return getOption<string>(config, ['paymentUrl', 'paymentURL', 'payment_url', 'checkoutUrl', 'checkout_url'])\n}\n\nfunction createStatusChecker(config: SeamlessConfig): (() => Promise<unknown>) | undefined {\n const context: StatusCheckContext = { paymentToken: getPaymentToken(config) ?? '' }\n const checkStatus = getCallback<(context: StatusCheckContext) => Promise<unknown>>(config, [\n 'checkStatus',\n 'checkPaymentStatus',\n 'checkTransactionStatus',\n ])\n\n if (checkStatus) {\n return () => checkStatus(context)\n }\n\n const statusUrl = getOption<SeamlessConfig['statusUrl']>(config, ['statusUrl', 'statusURL'])\n if (!statusUrl) return undefined\n\n return async () => {\n const url = typeof statusUrl === 'function' ? statusUrl(context) : statusUrl\n const response = await fetch(url, {\n method: 'GET',\n credentials: 'same-origin',\n headers: { Accept: 'application/json' },\n })\n\n if (!response.ok) {\n throw new Error(`Status check failed with HTTP ${response.status}`)\n }\n\n return response.json()\n }\n}\n\nfunction createPaymentUrl(config: SeamlessConfig): string {\n const explicitUrl = getPaymentUrl(config)\n if (explicitUrl) return explicitUrl\n\n const paymentToken = getPaymentToken(config)\n if (!paymentToken) {\n throw new Error('Invalid paymentToken format — expected alphanumeric string (10-128 chars)')\n }\n\n const environment = getOption<SeamlessEnvironment>(config, ['environment', 'env']) ?? 'sandbox'\n const checkoutBaseUrl =\n getOption<string>(config, ['checkoutBaseUrl', 'secureBaseUrl']) ??\n SECURE_BASE_URLS[environment] ??\n SECURE_BASE_URLS.sandbox\n\n return `${checkoutBaseUrl.replace(/\\/+$/, '')}/checkout/${paymentToken}`\n}\n\n/**\n * CinetPay Seamless — paiement inline via popup window.\n *\n * Affiche un overlay d'attente et ouvre la passerelle de paiement\n * CinetPay dans une popup. Le client reste sur votre page.\n *\n * Le `paymentToken` est obtenu côté serveur via l'API CinetPay :\n *\n * ```typescript\n * // Frontend\n * CinetPaySeamless.open({\n * paymentToken: 'abc123...',\n * onPaymentSuccess: (data) => console.log('Payé !', data.amount),\n * })\n * ```\n *\n * Ou avec des event listeners (style événementiel) :\n *\n * ```typescript\n * CinetPaySeamless.on('payment.success', (data) => { ... })\n * CinetPaySeamless.open({ paymentToken: 'abc123...' })\n * ```\n */\nexport const CinetPaySeamless = {\n /** Instance du checkout actuellement ouvert */\n _checkout: null as Checkout | null,\n\n /** Event emitter partagé */\n _emitter: new EventEmitter(),\n\n /**\n * Enregistre un listener d'événement (style événementiel).\n *\n * @param event - Nom de l'événement\n * @param handler - Fonction appelée quand l'événement est émis\n * @returns Fonction de désabonnement\n *\n * @example\n * ```typescript\n * const unsub = CinetPaySeamless.on('payment.success', (data) => {\n * console.log('Payé !', data.amount, data.currency)\n * })\n * unsub() // Se désabonner\n * ```\n */\n on<E extends EventName>(\n event: E,\n handler: EventMap[E] extends void ? () => void : (data: EventMap[E]) => void,\n ): () => void {\n return this._emitter.on(event, handler)\n },\n\n /**\n * Supprime un listener.\n */\n off<E extends EventName>(\n event: E,\n handler: EventMap[E] extends void ? () => void : (data: EventMap[E]) => void,\n ): void {\n this._emitter.off(event, handler)\n },\n\n /**\n * Enregistre un listener appelé une seule fois.\n */\n once<E extends EventName>(\n event: E,\n handler: EventMap[E] extends void ? () => void : (data: EventMap[E]) => void,\n ): void {\n this._emitter.once(event, handler)\n },\n\n /**\n * Ouvre le checkout CinetPay.\n *\n * Affiche un overlay d'attente et ouvre la page de paiement dans une popup.\n * La popup est centrée sur l'écran (500x700px).\n *\n * @param config - Configuration avec `paymentToken` et callbacks optionnels\n * @throws {Error} Si le `paymentToken` a un format invalide\n *\n * @example\n * ```typescript\n * CinetPaySeamless.open({\n * paymentToken: 'abc123def456...',\n * debug: true,\n * onPaymentSuccess: (data) => console.log('Payé !', data.amount),\n * onPaymentFailed: (data) => console.log('Refusé'),\n * onClose: ({ status }) => console.log('Fermé:', status),\n * })\n * ```\n */\n open(config: SeamlessConfig): void {\n this.close()\n\n const logger = new Logger(config.debug ?? false)\n logger.debug('CinetPaySeamless.open() called')\n\n // Validation du paymentToken quand le SDK doit reconstruire l'URL checkout.\n const paymentToken = getPaymentToken(config)\n if (paymentToken && !/^[a-zA-Z0-9_-]{10,128}$/.test(paymentToken)) {\n throw new Error('Invalid paymentToken format — expected alphanumeric string (10-128 chars)')\n }\n\n const paymentUrl = createPaymentUrl(config)\n\n this._checkout = new Checkout({\n logger,\n emitter: this._emitter,\n statusChecker: createStatusChecker(config),\n statusPollInterval: getOption<number>(config, ['statusPollInterval', 'statusCheckInterval']),\n onReady: getCallback(config, ['onReady']),\n onPaymentSuccess: getCallback(config, [\n 'onPaymentSuccess',\n 'onSuccess',\n 'onPaymentsuccess',\n 'onpaymentSuccess',\n 'onpaymentsuccess',\n ]),\n onPaymentFailed: getCallback(config, [\n 'onPaymentFailed',\n 'onPaymentFail',\n 'onPaymentFailure',\n 'onFailed',\n 'onPaymentfailed',\n 'onpaymentFailed',\n 'onpaymentfailed',\n ]),\n onPaymentPending: getCallback(config, ['onPaymentPending', 'onPending']),\n onClose: getCallback(config, ['onClose']),\n onError: getCallback(config, ['onError']),\n })\n\n this._checkout.open(paymentUrl)\n },\n\n /**\n * Ferme le checkout (popup + overlay).\n */\n close(): void {\n this._checkout?.close()\n this._checkout = null\n },\n}\n\n// Auto-attach to window for CDN/script tag usage\nif (typeof window !== 'undefined') {\n (window as unknown as Record<string, unknown>).CinetPaySeamless = CinetPaySeamless\n}\n"],"names":["STYLES","_Checkout","options","paymentUrl","_a","overlay","value","data","records","key","child","keys","record","parsed","rawStatus","apiCode","normalized","status","response","dispatchKey","isFinalStatus","_b","_c","styleEl","wrapper","waiting","spinner","title","msg","cancelBtn","left","top","err","reason","error","event","o","code","Checkout","PREFIX","Logger","enabled","message","EventEmitter","handler","args","handlers","SECURE_BASE_URLS","getCallback","config","names","name","lowerNames","getOption","getPaymentToken","getPaymentUrl","createStatusChecker","context","checkStatus","statusUrl","url","createPaymentUrl","explicitUrl","paymentToken","environment","CinetPaySeamless","logger"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,YAAY,EAAE,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEvE,YAAY,EACV,cAAc,EACd,eAAe,EACf,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,mBAAmB,GACpB,CAAA;AACD,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAuFpD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,gBAAgB;IAC3B,+CAA+C;eAC5B,QAAQ,GAAG,IAAI;IAElC,4BAA4B;;IAG5B;;;;;;;;;;;;;;OAcG;OACA,CAAC,SAAS,SAAS,SACb,CAAC,WACC,QAAQ,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAC3E,MAAM,IAAI;IAIb;;OAEG;QACC,CAAC,SAAS,SAAS,SACd,CAAC,WACC,QAAQ,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAC3E,IAAI;IAIP;;OAEG;SACE,CAAC,SAAS,SAAS,SACf,CAAC,WACC,QAAQ,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAC3E,IAAI;IAIP;;;;;;;;;;;;;;;;;;;OAmBG;iBACU,cAAc,GAAG,IAAI;IA2ClC;;OAEG;aACM,IAAI;CAId,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,YAAY,EAAE,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEvE,YAAY,EACV,cAAc,EACd,eAAe,EACf,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,mBAAmB,GACpB,CAAA;AACD,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAoGpD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,gBAAgB;IAC3B,+CAA+C;eAC5B,QAAQ,GAAG,IAAI;IAElC,4BAA4B;;IAG5B;;;;;;;;;;;;;;OAcG;OACA,CAAC,SAAS,SAAS,SACb,CAAC,WACC,QAAQ,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAC3E,MAAM,IAAI;IAIb;;OAEG;QACC,CAAC,SAAS,SAAS,SACd,CAAC,WACC,QAAQ,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAC3E,IAAI;IAIP;;OAEG;SACE,CAAC,SAAS,SAAS,SACf,CAAC,WACC,QAAQ,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAC3E,IAAI;IAIP;;;;;;;;;;;;;;;;;;;OAmBG;iBACU,cAAc,GAAG,IAAI;IA4ClC;;OAEG;aACM,IAAI;CAId,CAAA"}
package/dist/types.d.ts CHANGED
@@ -15,7 +15,11 @@
15
15
  */
16
16
  export interface SeamlessConfig {
17
17
  /** Token de paiement obtenu côté serveur via l'API CinetPay `POST /v1/payment` */
18
- paymentToken: string;
18
+ paymentToken?: string;
19
+ /**
20
+ * @deprecated Utilisez `paymentToken`. Alias du champ brut CinetPay.
21
+ */
22
+ payment_token?: string;
19
23
  /**
20
24
  * Environnement CinetPay utilisé pour construire l'URL checkout quand
21
25
  * `paymentUrl` n'est pas fourni.
@@ -29,6 +33,10 @@ export interface SeamlessConfig {
29
33
  * l'URL à partir du `paymentToken`.
30
34
  */
31
35
  paymentUrl?: string;
36
+ /**
37
+ * @deprecated Utilisez `paymentUrl`. Alias du champ brut CinetPay.
38
+ */
39
+ payment_url?: string;
32
40
  /**
33
41
  * @deprecated Utilisez `paymentUrl`.
34
42
  */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cinetpay-seamless",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "CinetPay Seamless — inline payment modal for web applications. No redirect, no iframe. Works with any framework.",
5
5
  "type": "module",
6
6
  "main": "./dist/cinetpay-seamless.umd.cjs",