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 +41 -8
- package/dist/cinetpay-seamless.js +133 -122
- package/dist/cinetpay-seamless.js.map +1 -1
- package/dist/cinetpay-seamless.umd.cjs +2 -2
- package/dist/cinetpay-seamless.umd.cjs.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/types.d.ts +9 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
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.
|
|
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é
|
|
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.
|
|
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.
|
|
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/
|
|
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
|
|
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
|
|
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
|
|
131
|
-
const
|
|
132
|
-
|
|
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
|
|
138
|
-
for (const
|
|
139
|
-
if (
|
|
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
|
|
164
|
-
if (
|
|
165
|
-
if (["ACCEPTED", "SUCCESS", "SUCCEEDED", "SUCCESSFUL", "PAID", "VALIDATED", "APPROVED"].includes(
|
|
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(
|
|
179
|
+
].includes(s))
|
|
180
180
|
return "REFUSED";
|
|
181
|
-
if (["PENDING", "INITIATED", "EXPIRED"].includes(
|
|
182
|
-
return
|
|
183
|
-
if (["WAITING", "PROCESSING", "IN_PROGRESS"].includes(
|
|
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 =
|
|
205
|
+
const e = a.asString(a.findValue(t, [
|
|
206
206
|
"status",
|
|
207
207
|
"transaction_status",
|
|
208
208
|
"trans_status",
|
|
209
209
|
"payment_status"
|
|
210
|
-
])),
|
|
210
|
+
])), s = a.asOptionalNumber(a.findValue(t, ["code"])), n = a.normalizeStatus(e, s);
|
|
211
211
|
return {
|
|
212
|
-
amount:
|
|
213
|
-
currency:
|
|
214
|
-
status:
|
|
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:
|
|
217
|
-
paymentMethod:
|
|
218
|
-
description:
|
|
219
|
-
metadata:
|
|
220
|
-
operatorId:
|
|
221
|
-
paymentDate:
|
|
222
|
-
transactionId:
|
|
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
|
|
228
|
-
const e = `${t.status}:${t.rawStatus ?? ""}:${t.apiCode ?? ""}`,
|
|
229
|
-
if (!(
|
|
230
|
-
switch (this.lastDispatchKey = e, this.lastStatus = 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), (
|
|
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 =
|
|
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
|
|
262
|
-
|
|
263
|
-
const
|
|
264
|
-
|
|
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,
|
|
275
|
-
const
|
|
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=${
|
|
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
|
|
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",
|
|
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"), (
|
|
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
|
|
320
|
-
if (!
|
|
321
|
-
const
|
|
322
|
-
(
|
|
323
|
-
} catch (
|
|
324
|
-
this.logger.warn("Payment status check failed",
|
|
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,
|
|
334
|
-
if (
|
|
333
|
+
var e, s;
|
|
334
|
+
if (a.ALLOWED_ORIGINS.some((n) => t.origin === n))
|
|
335
335
|
try {
|
|
336
|
-
const
|
|
337
|
-
if (!
|
|
338
|
-
const r =
|
|
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
|
|
341
|
-
if (
|
|
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:
|
|
344
|
-
message:
|
|
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), (
|
|
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
|
-
(
|
|
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
|
-
|
|
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 =
|
|
364
|
+
let m = a;
|
|
365
365
|
const l = "[CinetPay Seamless]";
|
|
366
|
-
class
|
|
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
|
|
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
|
|
412
|
-
(
|
|
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
|
|
429
|
-
this.off(t,
|
|
428
|
+
const s = ((...n) => {
|
|
429
|
+
this.off(t, s), e(...n);
|
|
430
430
|
});
|
|
431
|
-
this.on(t,
|
|
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
|
|
439
|
-
if (
|
|
440
|
-
for (const
|
|
438
|
+
const s = this.listeners.get(t);
|
|
439
|
+
if (s)
|
|
440
|
+
for (const n of s)
|
|
441
441
|
try {
|
|
442
|
-
|
|
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
|
|
454
|
+
const y = {
|
|
455
455
|
sandbox: "https://secure.cinetpay.net",
|
|
456
456
|
production: "https://secure.cinetpay.co"
|
|
457
457
|
};
|
|
458
|
-
function c(
|
|
459
|
-
const e =
|
|
460
|
-
for (const
|
|
461
|
-
const r = e[
|
|
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
|
|
465
|
-
for (const [
|
|
466
|
-
if (
|
|
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
|
|
470
|
-
const e =
|
|
471
|
-
for (const
|
|
472
|
-
if (e[
|
|
473
|
-
const
|
|
474
|
-
for (const [
|
|
475
|
-
if (
|
|
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
|
|
478
|
-
|
|
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
|
|
486
|
-
if (
|
|
491
|
+
const s = u(i, ["statusUrl", "statusURL"]);
|
|
492
|
+
if (s)
|
|
487
493
|
return async () => {
|
|
488
|
-
const
|
|
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
|
|
499
|
-
const t =
|
|
504
|
+
function b(i) {
|
|
505
|
+
const t = E(i);
|
|
500
506
|
if (t) return t;
|
|
501
|
-
const e =
|
|
502
|
-
|
|
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
|
|
513
|
+
const k = {
|
|
505
514
|
/** Instance du checkout actuellement ouvert */
|
|
506
515
|
_checkout: null,
|
|
507
516
|
/** Event emitter partagé */
|
|
508
|
-
_emitter: new
|
|
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(
|
|
525
|
-
return this._emitter.on(
|
|
533
|
+
on(i, t) {
|
|
534
|
+
return this._emitter.on(i, t);
|
|
526
535
|
},
|
|
527
536
|
/**
|
|
528
537
|
* Supprime un listener.
|
|
529
538
|
*/
|
|
530
|
-
off(
|
|
531
|
-
this._emitter.off(
|
|
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(
|
|
537
|
-
this._emitter.once(
|
|
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(
|
|
568
|
+
open(i) {
|
|
560
569
|
this.close();
|
|
561
|
-
const t = new
|
|
562
|
-
|
|
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
|
|
575
|
+
const s = b(i);
|
|
565
576
|
this._checkout = new m({
|
|
566
577
|
logger: t,
|
|
567
578
|
emitter: this._emitter,
|
|
568
|
-
statusChecker:
|
|
569
|
-
statusPollInterval:
|
|
570
|
-
onReady: c(
|
|
571
|
-
onPaymentSuccess: c(
|
|
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(
|
|
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(
|
|
588
|
-
onClose: c(
|
|
589
|
-
onError: c(
|
|
590
|
-
}), this._checkout.open(
|
|
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
|
|
597
|
-
(
|
|
607
|
+
var i;
|
|
608
|
+
(i = this._checkout) == null || i.close(), this._checkout = null;
|
|
598
609
|
}
|
|
599
610
|
};
|
|
600
|
-
typeof window < "u" && (window.CinetPaySeamless =
|
|
611
|
+
typeof window < "u" && (window.CinetPaySeamless = k);
|
|
601
612
|
export {
|
|
602
|
-
|
|
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(
|
|
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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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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
|
|
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
|
*/
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,YAAY,EAAE,MAAM,CAAA;
|
|
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.
|
|
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",
|