cinetpay-seamless 0.1.3 → 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.2/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,8 +44,8 @@ npm install cinetpay-seamless
44
44
  ```typescript
45
45
  import { CinetPaySeamless } from 'cinetpay-seamless'
46
46
 
47
- // 1. Obtenir le paymentToken depuis votre backend
48
- const { paymentToken } = await fetch('/api/pay', {
47
+ // 1. Obtenir le paymentToken et, idéalement, paymentUrl depuis votre backend
48
+ const { paymentToken, paymentUrl } = await fetch('/api/pay', {
49
49
  method: 'POST',
50
50
  headers: { 'Content-Type': 'application/json' },
51
51
  body: JSON.stringify({ amount: 5000, orderId: 'ORDER-001' }),
@@ -54,6 +54,7 @@ const { paymentToken } = await fetch('/api/pay', {
54
54
  // 2. Ouvrir la popup
55
55
  CinetPaySeamless.open({
56
56
  paymentToken,
57
+ paymentUrl, // recommandé en production: URL CinetPay exacte renvoyée par l'API
57
58
  onPaymentSuccess: (data) => {
58
59
  console.log('Paiement réussi !', data.amount, data.currency)
59
60
  },
@@ -68,7 +69,7 @@ CinetPaySeamless.open({
68
69
  ```html
69
70
  <button id="pay-btn">Payer 5 000 XOF</button>
70
71
 
71
- <script src="https://unpkg.com/cinetpay-seamless@0.1.2/dist/cinetpay-seamless.umd.cjs"></script>
72
+ <script src="https://unpkg.com/cinetpay-seamless@0.1.5/dist/cinetpay-seamless.umd.cjs"></script>
72
73
  <script>
73
74
  document.getElementById('pay-btn').addEventListener('click', function() {
74
75
  // Appeler votre backend pour obtenir le paymentToken
@@ -81,6 +82,7 @@ CinetPaySeamless.open({
81
82
  .then(function(data) {
82
83
  CinetPaySeamless.open({
83
84
  paymentToken: data.paymentToken,
85
+ paymentUrl: data.paymentUrl,
84
86
  onPaymentSuccess: function(result) {
85
87
  alert('Merci ! ' + result.amount + ' ' + result.currency)
86
88
  },
@@ -152,6 +154,9 @@ Ouvre la popup de paiement CinetPay.
152
154
  | Option | Type | Default | Description |
153
155
  |---|---|---|---|
154
156
  | `paymentToken` | `string` | **requis** | Token obtenu via votre backend (`POST /v1/payment`) |
157
+ | `environment` | `'sandbox' \| 'production'` | `'sandbox'` | Environnement utilisé si `paymentUrl` n'est pas fourni |
158
+ | `paymentUrl` | `string` | - | URL complète renvoyée par CinetPay, prioritaire sur `environment` |
159
+ | `checkoutBaseUrl` | `string` | selon `environment` | Host checkout personnalisé |
155
160
  | `statusUrl` | `string \| (ctx) => string` | - | Endpoint de votre backend pour vérifier le statut canonique |
156
161
  | `checkStatus` | `(ctx) => Promise<object>` | - | Fonction personnalisée de vérification statut |
157
162
  | `statusPollInterval` | `number` | `3000` | Intervalle de vérification statut en ms |
@@ -163,6 +168,39 @@ Ouvre la popup de paiement CinetPay.
163
168
  | `onClose` | `({ status }) => void` | - | Modal fermé |
164
169
  | `onError` | `(error) => void` | - | Erreur technique |
165
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
+
166
204
  ### `CinetPaySeamless.on(event, handler)`
167
205
 
168
206
  | Événement | Donnée | Description |
@@ -289,7 +327,10 @@ app.post('/api/pay', async (req, res) => {
289
327
  channel: 'PUSH',
290
328
  }, 'CI')
291
329
 
292
- res.json({ paymentToken: payment.paymentToken })
330
+ res.json({
331
+ paymentToken: payment.paymentToken ?? payment.payment_token,
332
+ paymentUrl: payment.paymentUrl ?? payment.payment_url,
333
+ })
293
334
  })
294
335
  ```
295
336
 
@@ -310,9 +351,9 @@ async function pay(amount: number) {
310
351
  phone: '+2250707000000',
311
352
  }),
312
353
  })
313
- const { paymentToken } = await res.json()
354
+ const { paymentToken, paymentUrl } = await res.json()
314
355
 
315
- CinetPaySeamless.open({ paymentToken, debug: true })
356
+ CinetPaySeamless.open({ paymentToken, paymentUrl, debug: true })
316
357
  }
317
358
  ```
318
359
 
@@ -536,7 +577,7 @@ async function pay() {
536
577
  <meta charset="UTF-8">
537
578
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
538
579
  <title>Paiement</title>
539
- <script src="https://unpkg.com/cinetpay-seamless@0.1.2/dist/cinetpay-seamless.umd.cjs"></script>
580
+ <script src="https://unpkg.com/cinetpay-seamless@0.1.5/dist/cinetpay-seamless.umd.cjs"></script>
540
581
  </head>
541
582
  <body>
542
583
  <form id="payment-form">
@@ -637,7 +678,7 @@ CinetPaySeamless.open({ paymentToken: 'abc...', debug: true })
637
678
 
638
679
  ```
639
680
  [CinetPay Seamless] CinetPaySeamless.open() called
640
- [CinetPay Seamless] Opening popup { paymentUrl: 'https://secure.cinetpay.net/checkout/abc...' }
681
+ [CinetPay Seamless] Opening popup { paymentUrl: 'https://secure.cinetpay.co/payment/abc...' }
641
682
  [CinetPay Seamless] Iframe loaded — checkout ready
642
683
  [CinetPay Seamless] Payment response: ACCEPTED { amount: 5000, currency: 'XOF', ... }
643
684
  [CinetPay Seamless] Payment accepted
@@ -665,8 +706,8 @@ Commiter le .env dans git Ajouter .env dans .gitignore
665
706
 
666
707
  | Préfixe de clé | Environnement | Usage |
667
708
  |---|---|---|
668
- | `sk_test_...` | Sandbox (`api.cinetpay.net`) | Développement et tests |
669
- | `sk_live_...` | Production (`api.cinetpay.co`) | Transactions réelles |
709
+ | `sk_test_...` | Sandbox API `api.cinetpay.net`, checkout `secure.cinetpay.net` | Développement et tests |
710
+ | `sk_live_...` | Production API `api.cinetpay.co`, checkout `secure.cinetpay.co` | Transactions réelles |
670
711
 
671
712
  **Règles importantes :**
672
713
  - Ne **jamais** utiliser des clés `sk_live_` en développement
@@ -1 +1 @@
1
- {"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../src/checkout.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../src/checkout.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- const f = `
1
+ const g = `
2
2
  .cp-seamless-overlay {
3
3
  position: fixed;
4
4
  inset: 0;
@@ -79,7 +79,7 @@ const f = `
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 = f, 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,55 +330,57 @@ 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
+ "https://secure.cinetpay.co",
356
357
  "https://secure.cinetpay.com",
357
358
  "https://checkout.cinetpay.net",
359
+ "https://checkout.cinetpay.co",
358
360
  "https://checkout.cinetpay.com",
359
361
  "https://api.cinetpay.net",
360
362
  "https://api.cinetpay.co"
361
363
  ];
362
- let p = n;
363
- const c = "[CinetPay Seamless]";
364
- class y {
364
+ let m = a;
365
+ const l = "[CinetPay Seamless]";
366
+ class S {
365
367
  constructor(t) {
366
368
  this.enabled = t;
367
369
  }
368
370
  /** Log de debug — requêtes, réponses, événements */
369
371
  debug(t, e) {
370
- this.enabled && (e !== void 0 ? console.debug(`${c} ${t}`, e) : console.debug(`${c} ${t}`));
372
+ this.enabled && (e !== void 0 ? console.debug(`${l} ${t}`, e) : console.debug(`${l} ${t}`));
371
373
  }
372
374
  /** Log d'avertissement — credentials exposés, statuts inattendus */
373
375
  warn(t, e) {
374
- this.enabled && (e !== void 0 ? console.warn(`${c} ${t}`, e) : console.warn(`${c} ${t}`));
376
+ this.enabled && (e !== void 0 ? console.warn(`${l} ${t}`, e) : console.warn(`${l} ${t}`));
375
377
  }
376
378
  /** Log d'erreur — erreurs API, timeouts, postMessage invalides */
377
379
  error(t, e) {
378
- this.enabled && (e !== void 0 ? console.error(`${c} ${t}`, e) : console.error(`${c} ${t}`));
380
+ this.enabled && (e !== void 0 ? console.error(`${l} ${t}`, e) : console.error(`${l} ${t}`));
379
381
  }
380
382
  }
381
- class g {
383
+ class C {
382
384
  constructor() {
383
385
  this.listeners = /* @__PURE__ */ new Map();
384
386
  }
@@ -406,8 +408,8 @@ class g {
406
408
  * @param handler - Référence du handler à supprimer
407
409
  */
408
410
  off(t, e) {
409
- var i;
410
- (i = this.listeners.get(t)) == null || i.delete(e);
411
+ var s;
412
+ (s = this.listeners.get(t)) == null || s.delete(e);
411
413
  }
412
414
  /**
413
415
  * Enregistre un handler qui ne sera appelé qu'une seule fois.
@@ -423,21 +425,21 @@ class g {
423
425
  * ```
424
426
  */
425
427
  once(t, e) {
426
- const i = ((...s) => {
427
- this.off(t, i), e(...s);
428
+ const s = ((...n) => {
429
+ this.off(t, s), e(...n);
428
430
  });
429
- this.on(t, i);
431
+ this.on(t, s);
430
432
  }
431
433
  /**
432
434
  * Émet un événement — appelle tous les handlers enregistrés.
433
435
  * @internal
434
436
  */
435
437
  emit(t, ...e) {
436
- const i = this.listeners.get(t);
437
- if (i)
438
- for (const s of i)
438
+ const s = this.listeners.get(t);
439
+ if (s)
440
+ for (const n of s)
439
441
  try {
440
- s(...e);
442
+ n(...e);
441
443
  } catch {
442
444
  }
443
445
  }
@@ -449,38 +451,47 @@ class g {
449
451
  this.listeners.clear();
450
452
  }
451
453
  }
452
- const C = "https://secure.cinetpay.net";
453
- function l(a, t) {
454
- const e = a;
455
- for (const s of t) {
456
- const r = e[s];
454
+ const y = {
455
+ sandbox: "https://secure.cinetpay.net",
456
+ production: "https://secure.cinetpay.co"
457
+ };
458
+ function c(i, t) {
459
+ const e = i;
460
+ for (const n of t) {
461
+ const r = e[n];
457
462
  if (typeof r == "function") return r;
458
463
  }
459
- const i = new Set(t.map((s) => s.toLowerCase()));
460
- for (const [s, r] of Object.entries(e))
461
- 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")
462
467
  return r;
463
468
  }
464
- function m(a, t) {
465
- const e = a;
466
- for (const s of t)
467
- if (e[s] !== void 0) return e[s];
468
- const i = new Set(t.map((s) => s.toLowerCase()));
469
- for (const [s, r] of Object.entries(e))
470
- 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
+ }
477
+ function f(i) {
478
+ return u(i, ["paymentToken", "payment_token"]);
471
479
  }
472
- function S(a) {
473
- const t = { paymentToken: a.paymentToken }, e = l(a, [
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, [
474
485
  "checkStatus",
475
486
  "checkPaymentStatus",
476
487
  "checkTransactionStatus"
477
488
  ]);
478
489
  if (e)
479
490
  return () => e(t);
480
- const i = m(a, ["statusUrl", "statusURL"]);
481
- if (i)
491
+ const s = u(i, ["statusUrl", "statusURL"]);
492
+ if (s)
482
493
  return async () => {
483
- 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, {
484
495
  method: "GET",
485
496
  credentials: "same-origin",
486
497
  headers: { Accept: "application/json" }
@@ -490,11 +501,20 @@ function S(a) {
490
501
  return r.json();
491
502
  };
492
503
  }
493
- const E = {
504
+ function b(i) {
505
+ const t = E(i);
506
+ if (t) return t;
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}`;
512
+ }
513
+ const k = {
494
514
  /** Instance du checkout actuellement ouvert */
495
515
  _checkout: null,
496
516
  /** Event emitter partagé */
497
- _emitter: new g(),
517
+ _emitter: new C(),
498
518
  /**
499
519
  * Enregistre un listener d'événement (style événementiel).
500
520
  *
@@ -510,20 +530,20 @@ const E = {
510
530
  * unsub() // Se désabonner
511
531
  * ```
512
532
  */
513
- on(a, t) {
514
- return this._emitter.on(a, t);
533
+ on(i, t) {
534
+ return this._emitter.on(i, t);
515
535
  },
516
536
  /**
517
537
  * Supprime un listener.
518
538
  */
519
- off(a, t) {
520
- this._emitter.off(a, t);
539
+ off(i, t) {
540
+ this._emitter.off(i, t);
521
541
  },
522
542
  /**
523
543
  * Enregistre un listener appelé une seule fois.
524
544
  */
525
- once(a, t) {
526
- this._emitter.once(a, t);
545
+ once(i, t) {
546
+ this._emitter.once(i, t);
527
547
  },
528
548
  /**
529
549
  * Ouvre le checkout CinetPay.
@@ -545,26 +565,28 @@ const E = {
545
565
  * })
546
566
  * ```
547
567
  */
548
- open(a) {
568
+ open(i) {
549
569
  this.close();
550
- const t = new y(a.debug ?? !1);
551
- 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))
552
574
  throw new Error("Invalid paymentToken format — expected alphanumeric string (10-128 chars)");
553
- const e = `${C}/checkout/${a.paymentToken}`;
554
- this._checkout = new p({
575
+ const s = b(i);
576
+ this._checkout = new m({
555
577
  logger: t,
556
578
  emitter: this._emitter,
557
- statusChecker: S(a),
558
- statusPollInterval: m(a, ["statusPollInterval", "statusCheckInterval"]),
559
- onReady: l(a, ["onReady"]),
560
- onPaymentSuccess: l(a, [
579
+ statusChecker: P(i),
580
+ statusPollInterval: u(i, ["statusPollInterval", "statusCheckInterval"]),
581
+ onReady: c(i, ["onReady"]),
582
+ onPaymentSuccess: c(i, [
561
583
  "onPaymentSuccess",
562
584
  "onSuccess",
563
585
  "onPaymentsuccess",
564
586
  "onpaymentSuccess",
565
587
  "onpaymentsuccess"
566
588
  ]),
567
- onPaymentFailed: l(a, [
589
+ onPaymentFailed: c(i, [
568
590
  "onPaymentFailed",
569
591
  "onPaymentFail",
570
592
  "onPaymentFailure",
@@ -573,21 +595,21 @@ const E = {
573
595
  "onpaymentFailed",
574
596
  "onpaymentfailed"
575
597
  ]),
576
- onPaymentPending: l(a, ["onPaymentPending", "onPending"]),
577
- onClose: l(a, ["onClose"]),
578
- onError: l(a, ["onError"])
579
- }), 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);
580
602
  },
581
603
  /**
582
604
  * Ferme le checkout (popup + overlay).
583
605
  */
584
606
  close() {
585
- var a;
586
- (a = this._checkout) == null || a.close(), this._checkout = null;
607
+ var i;
608
+ (i = this._checkout) == null || i.close(), this._checkout = null;
587
609
  }
588
610
  };
589
- typeof window < "u" && (window.CinetPaySeamless = E);
611
+ typeof window < "u" && (window.CinetPaySeamless = k);
590
612
  export {
591
- E as CinetPaySeamless
613
+ k as CinetPaySeamless
592
614
  };
593
615
  //# sourceMappingURL=cinetpay-seamless.js.map