sunuid-sdk 1.0.51 → 1.0.53
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 +429 -193
- package/dist/sunuid-sdk.esm.js +5 -5
- package/dist/sunuid-sdk.esm.js.map +1 -1
- package/dist/sunuid-sdk.js +5 -5
- package/dist/sunuid-sdk.js.map +1 -1
- package/dist/sunuid-sdk.min.js +1 -1
- package/dist/sunuid-sdk.min.js.map +1 -1
- package/docs/INTEGRATION_GUIDE.md +334 -0
- package/docs/SECURITY_GUIDE.md +369 -0
- package/examples/.htaccess.example +190 -0
- package/examples/README.md +192 -0
- package/examples/auto-code.js +234 -0
- package/examples/auto-integration.html +337 -0
- package/examples/callback-example.html +232 -0
- package/examples/config-example.js +41 -0
- package/examples/demo.html +323 -0
- package/examples/env.example +83 -0
- package/examples/minimal-code.js +147 -0
- package/examples/minimal-integration.html +157 -0
- package/examples/no-loop-example.html +250 -0
- package/examples/partner-name-config.js +123 -0
- package/examples/production-config.js +60 -0
- package/examples/secure-init.php +154 -0
- package/examples/secure-integration-example.js +186 -0
- package/examples/secure-integration.html +410 -0
- package/examples/simple-kyc.html +95 -0
- package/examples/simple-login.html +96 -0
- package/examples/test-partner-name.html +251 -0
- package/examples/test-production.html +200 -0
- package/examples/universal-kyc.html +199 -0
- package/examples/universal-login.html +148 -0
- package/package.json +24 -10
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="fr">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Intégration Auto SunuID SDK</title>
|
|
7
|
+
|
|
8
|
+
<!-- Socket.IO (requis) -->
|
|
9
|
+
<script src="https://cdn.socket.io/4.7.4/socket.io.min.js"></script>
|
|
10
|
+
|
|
11
|
+
<!-- SunuID SDK -->
|
|
12
|
+
<script src="https://unpkg.com/sunuid-sdk@1.0.34/dist/sunuid-sdk.min.js"></script>
|
|
13
|
+
|
|
14
|
+
<style>
|
|
15
|
+
body {
|
|
16
|
+
font-family: Arial, sans-serif;
|
|
17
|
+
max-width: 600px;
|
|
18
|
+
margin: 50px auto;
|
|
19
|
+
padding: 20px;
|
|
20
|
+
text-align: center;
|
|
21
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
22
|
+
min-height: 100vh;
|
|
23
|
+
color: white;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.container {
|
|
27
|
+
background: rgba(255, 255, 255, 0.1);
|
|
28
|
+
backdrop-filter: blur(10px);
|
|
29
|
+
border-radius: 20px;
|
|
30
|
+
padding: 30px;
|
|
31
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.qr-container {
|
|
35
|
+
margin: 30px 0;
|
|
36
|
+
padding: 20px;
|
|
37
|
+
border: 2px dashed rgba(255, 255, 255, 0.3);
|
|
38
|
+
border-radius: 15px;
|
|
39
|
+
min-height: 300px;
|
|
40
|
+
display: flex;
|
|
41
|
+
align-items: center;
|
|
42
|
+
justify-content: center;
|
|
43
|
+
background: rgba(255, 255, 255, 0.05);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.qr-container img {
|
|
47
|
+
max-width: 250px;
|
|
48
|
+
border: 3px solid rgba(255, 255, 255, 0.2);
|
|
49
|
+
border-radius: 10px;
|
|
50
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.status {
|
|
54
|
+
margin: 20px 0;
|
|
55
|
+
padding: 15px;
|
|
56
|
+
border-radius: 10px;
|
|
57
|
+
font-weight: bold;
|
|
58
|
+
font-size: 16px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.status.loading {
|
|
62
|
+
background: rgba(255, 193, 7, 0.2);
|
|
63
|
+
color: #ffc107;
|
|
64
|
+
border: 1px solid rgba(255, 193, 7, 0.3);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.status.success {
|
|
68
|
+
background: rgba(40, 167, 69, 0.2);
|
|
69
|
+
color: #28a745;
|
|
70
|
+
border: 1px solid rgba(40, 167, 69, 0.3);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.status.error {
|
|
74
|
+
background: rgba(220, 53, 69, 0.2);
|
|
75
|
+
color: #dc3545;
|
|
76
|
+
border: 1px solid rgba(220, 53, 69, 0.3);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.loading-spinner {
|
|
80
|
+
display: inline-block;
|
|
81
|
+
width: 20px;
|
|
82
|
+
height: 20px;
|
|
83
|
+
border: 3px solid rgba(255, 255, 255, 0.3);
|
|
84
|
+
border-radius: 50%;
|
|
85
|
+
border-top-color: #fff;
|
|
86
|
+
animation: spin 1s ease-in-out infinite;
|
|
87
|
+
margin-right: 10px;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@keyframes spin {
|
|
91
|
+
to { transform: rotate(360deg); }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.info {
|
|
95
|
+
margin-top: 20px;
|
|
96
|
+
font-size: 14px;
|
|
97
|
+
opacity: 0.8;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.retry-btn {
|
|
101
|
+
background: rgba(255, 255, 255, 0.2);
|
|
102
|
+
color: white;
|
|
103
|
+
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
104
|
+
padding: 10px 20px;
|
|
105
|
+
border-radius: 25px;
|
|
106
|
+
cursor: pointer;
|
|
107
|
+
font-size: 14px;
|
|
108
|
+
margin-top: 15px;
|
|
109
|
+
transition: all 0.3s ease;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.retry-btn:hover {
|
|
113
|
+
background: rgba(255, 255, 255, 0.3);
|
|
114
|
+
transform: translateY(-2px);
|
|
115
|
+
}
|
|
116
|
+
</style>
|
|
117
|
+
</head>
|
|
118
|
+
<body>
|
|
119
|
+
<div class="container">
|
|
120
|
+
<h1>🔐 Authentification SunuID</h1>
|
|
121
|
+
<p>Initialisation et génération automatique du QR code</p>
|
|
122
|
+
|
|
123
|
+
<div id="status" class="status loading">
|
|
124
|
+
<span class="loading-spinner"></span>
|
|
125
|
+
Initialisation automatique en cours...
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
<div id="qr-container" class="qr-container">
|
|
129
|
+
<p>Chargement...</p>
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
<div class="info">
|
|
133
|
+
<p>📱 Scannez le QR code avec l'application SunuID</p>
|
|
134
|
+
<p>🔄 Le QR code se génère automatiquement</p>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
<script>
|
|
139
|
+
// Configuration automatique
|
|
140
|
+
const config = {
|
|
141
|
+
clientId: '1754166754_221A57B46843D755',
|
|
142
|
+
secretId: '56d40fe70507228b27f2640ae65894177c2fedbf246e2b30978fde1fc43953c5',
|
|
143
|
+
type: 2, // 2 = Authentification
|
|
144
|
+
autoRefresh: false, // Désactivé pour éviter les appels répétitifs
|
|
145
|
+
// Désactiver l'initialisation automatique dans le constructeur
|
|
146
|
+
autoInit: false,
|
|
147
|
+
// Callbacks automatiques
|
|
148
|
+
onSuccess: (data) => {
|
|
149
|
+
console.log('🎉 Authentification réussie:', data);
|
|
150
|
+
updateStatus('✅ Authentification réussie !', 'success');
|
|
151
|
+
},
|
|
152
|
+
onError: (error) => {
|
|
153
|
+
console.error('💥 Erreur:', error);
|
|
154
|
+
updateStatus(`❌ Erreur: ${error.message}`, 'error');
|
|
155
|
+
showRetryButton();
|
|
156
|
+
},
|
|
157
|
+
onStatusUpdate: (status) => {
|
|
158
|
+
console.log('📊 Statut mis à jour:', status);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
let sunuid = null;
|
|
163
|
+
|
|
164
|
+
function updateStatus(message, type = 'loading') {
|
|
165
|
+
const statusDiv = document.getElementById('status');
|
|
166
|
+
if (!statusDiv) {
|
|
167
|
+
console.warn('⚠️ Élément status non trouvé, création d\'un élément temporaire');
|
|
168
|
+
const tempStatus = document.createElement('div');
|
|
169
|
+
tempStatus.id = 'status';
|
|
170
|
+
tempStatus.className = `status ${type}`;
|
|
171
|
+
document.body.appendChild(tempStatus);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const spinner = type === 'loading' ? '<span class="loading-spinner"></span>' : '';
|
|
176
|
+
statusDiv.innerHTML = spinner + message;
|
|
177
|
+
statusDiv.className = `status ${type}`;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function showRetryButton() {
|
|
181
|
+
const container = document.querySelector('.container');
|
|
182
|
+
if (!container) {
|
|
183
|
+
console.warn('⚠️ Container non trouvé, ajout du bouton au body');
|
|
184
|
+
const retryBtn = document.createElement('button');
|
|
185
|
+
retryBtn.className = 'retry-btn';
|
|
186
|
+
retryBtn.textContent = '🔄 Réessayer';
|
|
187
|
+
retryBtn.onclick = initAutoSunuID;
|
|
188
|
+
document.body.appendChild(retryBtn);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Vérifier si le bouton existe déjà
|
|
193
|
+
const existingBtn = container.querySelector('.retry-btn');
|
|
194
|
+
if (existingBtn) {
|
|
195
|
+
return; // Le bouton existe déjà
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const retryBtn = document.createElement('button');
|
|
199
|
+
retryBtn.className = 'retry-btn';
|
|
200
|
+
retryBtn.textContent = '🔄 Réessayer';
|
|
201
|
+
retryBtn.onclick = initAutoSunuID;
|
|
202
|
+
container.appendChild(retryBtn);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async function initAutoSunuID() {
|
|
206
|
+
try {
|
|
207
|
+
// Vérifier que les éléments nécessaires sont présents
|
|
208
|
+
const qrContainer = document.getElementById('qr-container');
|
|
209
|
+
if (!qrContainer) {
|
|
210
|
+
console.error('❌ Élément qr-container non trouvé');
|
|
211
|
+
throw new Error('Conteneur QR non trouvé dans le DOM');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
updateStatus('🔄 Initialisation du SDK...', 'loading');
|
|
215
|
+
|
|
216
|
+
// Vérifier que SunuID est disponible
|
|
217
|
+
if (typeof SunuID === 'undefined') {
|
|
218
|
+
throw new Error('SDK SunuID non chargé. Vérifiez que les scripts sont inclus.');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Créer l'instance SDK
|
|
222
|
+
sunuid = new SunuID(config);
|
|
223
|
+
|
|
224
|
+
// Initialiser automatiquement
|
|
225
|
+
await sunuid.init();
|
|
226
|
+
|
|
227
|
+
// Attendre que le WebSocket soit connecté
|
|
228
|
+
updateStatus('🔄 Connexion WebSocket...', 'loading');
|
|
229
|
+
|
|
230
|
+
// Attendre jusqu'à 10 secondes que le socket soit connecté
|
|
231
|
+
let attempts = 0;
|
|
232
|
+
const maxAttempts = 20; // 20 tentatives * 500ms = 10 secondes
|
|
233
|
+
|
|
234
|
+
while (attempts < maxAttempts) {
|
|
235
|
+
if (sunuid.socket && sunuid.socket.connected && sunuid.socket.id) {
|
|
236
|
+
console.log('✅ WebSocket connecté avec ID:', sunuid.socket.id);
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
241
|
+
attempts++;
|
|
242
|
+
console.log(`🔄 Tentative ${attempts}/${maxAttempts} - Attente WebSocket...`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (!sunuid.socket || !sunuid.socket.connected || !sunuid.socket.id) {
|
|
246
|
+
throw new Error('WebSocket non connecté après 10 secondes');
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
updateStatus('🔄 Génération du QR code...', 'loading');
|
|
250
|
+
|
|
251
|
+
// Générer le QR code automatiquement
|
|
252
|
+
const result = await sunuid.generateQR('qr-container');
|
|
253
|
+
|
|
254
|
+
updateStatus('✅ QR code généré avec succès !', 'success');
|
|
255
|
+
|
|
256
|
+
console.log('✅ QR Code généré automatiquement:', result);
|
|
257
|
+
|
|
258
|
+
// Écouter les événements WebSocket
|
|
259
|
+
if (sunuid.socket) {
|
|
260
|
+
sunuid.socket.on('qr_scanned', (data) => {
|
|
261
|
+
console.log('📱 QR code scanné:', data);
|
|
262
|
+
updateStatus('📱 QR code scanné - Authentification en cours...', 'loading');
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
sunuid.socket.on('auth_success', (data) => {
|
|
266
|
+
console.log('🎉 Authentification réussie:', data);
|
|
267
|
+
updateStatus('🎉 Authentification réussie !', 'success');
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
sunuid.socket.on('auth_error', (data) => {
|
|
271
|
+
console.error('❌ Erreur d\'authentification:', data);
|
|
272
|
+
updateStatus('❌ Erreur d\'authentification', 'error');
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
} catch (error) {
|
|
277
|
+
console.error('❌ Erreur lors de l\'initialisation automatique:', error);
|
|
278
|
+
updateStatus(`❌ Erreur: ${error.message}`, 'error');
|
|
279
|
+
showRetryButton();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Initialisation automatique au chargement de la page
|
|
284
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
285
|
+
console.log('🚀 Démarrage de l\'initialisation automatique...');
|
|
286
|
+
|
|
287
|
+
// Vérifier que tous les éléments nécessaires sont présents
|
|
288
|
+
const requiredElements = ['status', 'qr-container'];
|
|
289
|
+
const missingElements = requiredElements.filter(id => !document.getElementById(id));
|
|
290
|
+
|
|
291
|
+
if (missingElements.length > 0) {
|
|
292
|
+
console.error('❌ Éléments manquants:', missingElements);
|
|
293
|
+
console.log('🔧 Création des éléments manquants...');
|
|
294
|
+
|
|
295
|
+
// Créer les éléments manquants
|
|
296
|
+
missingElements.forEach(id => {
|
|
297
|
+
const element = document.createElement('div');
|
|
298
|
+
element.id = id;
|
|
299
|
+
if (id === 'status') {
|
|
300
|
+
element.className = 'status loading';
|
|
301
|
+
element.innerHTML = '<span class="loading-spinner"></span>Initialisation...';
|
|
302
|
+
} else if (id === 'qr-container') {
|
|
303
|
+
element.className = 'qr-container';
|
|
304
|
+
element.innerHTML = '<p>Chargement...</p>';
|
|
305
|
+
}
|
|
306
|
+
document.body.appendChild(element);
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Attendre un peu que tout soit chargé
|
|
311
|
+
setTimeout(() => {
|
|
312
|
+
initAutoSunuID();
|
|
313
|
+
}, 500);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
// Gestion des erreurs globales
|
|
317
|
+
window.addEventListener('error', function(event) {
|
|
318
|
+
console.error('❌ Erreur globale:', event.error);
|
|
319
|
+
try {
|
|
320
|
+
updateStatus('❌ Erreur inattendue', 'error');
|
|
321
|
+
} catch (updateError) {
|
|
322
|
+
console.error('❌ Impossible de mettre à jour le statut:', updateError);
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
// Gestion des promesses rejetées
|
|
327
|
+
window.addEventListener('unhandledrejection', function(event) {
|
|
328
|
+
console.error('❌ Promesse rejetée:', event.reason);
|
|
329
|
+
try {
|
|
330
|
+
updateStatus('❌ Erreur de promesse', 'error');
|
|
331
|
+
} catch (updateError) {
|
|
332
|
+
console.error('❌ Impossible de mettre à jour le statut:', updateError);
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
</script>
|
|
336
|
+
</body>
|
|
337
|
+
</html>
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="fr">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>SunuID Callback Example</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
font-family: Arial, sans-serif;
|
|
10
|
+
max-width: 800px;
|
|
11
|
+
margin: 0 auto;
|
|
12
|
+
padding: 20px;
|
|
13
|
+
background: #f5f5f5;
|
|
14
|
+
}
|
|
15
|
+
.container {
|
|
16
|
+
background: white;
|
|
17
|
+
padding: 30px;
|
|
18
|
+
border-radius: 10px;
|
|
19
|
+
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
20
|
+
}
|
|
21
|
+
.status {
|
|
22
|
+
padding: 15px;
|
|
23
|
+
border-radius: 5px;
|
|
24
|
+
margin: 10px 0;
|
|
25
|
+
}
|
|
26
|
+
.success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
|
|
27
|
+
.error { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
|
|
28
|
+
.info { background: #d1ecf1; color: #0c5460; border: 1px solid #bee5eb; }
|
|
29
|
+
.qr-container {
|
|
30
|
+
text-align: center;
|
|
31
|
+
margin: 20px 0;
|
|
32
|
+
padding: 20px;
|
|
33
|
+
border: 2px dashed #ccc;
|
|
34
|
+
border-radius: 10px;
|
|
35
|
+
}
|
|
36
|
+
.callback-data {
|
|
37
|
+
background: #f8f9fa;
|
|
38
|
+
padding: 15px;
|
|
39
|
+
border-radius: 5px;
|
|
40
|
+
font-family: monospace;
|
|
41
|
+
white-space: pre-wrap;
|
|
42
|
+
margin: 10px 0;
|
|
43
|
+
}
|
|
44
|
+
button {
|
|
45
|
+
background: #007bff;
|
|
46
|
+
color: white;
|
|
47
|
+
border: none;
|
|
48
|
+
padding: 10px 20px;
|
|
49
|
+
border-radius: 5px;
|
|
50
|
+
cursor: pointer;
|
|
51
|
+
margin: 5px;
|
|
52
|
+
}
|
|
53
|
+
button:hover { background: #0056b3; }
|
|
54
|
+
.hidden { display: none; }
|
|
55
|
+
</style>
|
|
56
|
+
</head>
|
|
57
|
+
<body>
|
|
58
|
+
<div class="container">
|
|
59
|
+
<h1>🔐 SunuID Callback Example</h1>
|
|
60
|
+
|
|
61
|
+
<div id="status" class="status info">
|
|
62
|
+
Initialisation en cours...
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div id="qr-section" class="hidden">
|
|
66
|
+
<h2>📱 Scannez le QR Code</h2>
|
|
67
|
+
<div id="qr-area" class="qr-container">
|
|
68
|
+
<!-- Le QR code sera affiché ici -->
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<div id="callback-section" class="hidden">
|
|
73
|
+
<h2>✅ Authentification Réussie</h2>
|
|
74
|
+
<div id="callback-data" class="callback-data">
|
|
75
|
+
<!-- Les données du callback seront affichées ici -->
|
|
76
|
+
</div>
|
|
77
|
+
<button onclick="window.location.href='/dashboard'">Aller au Dashboard</button>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<div id="error-section" class="hidden">
|
|
81
|
+
<h2>❌ Erreur d'Authentification</h2>
|
|
82
|
+
<div id="error-data" class="callback-data">
|
|
83
|
+
<!-- Les erreurs seront affichées ici -->
|
|
84
|
+
</div>
|
|
85
|
+
<button onclick="location.reload()">Réessayer</button>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<!-- Socket.IO -->
|
|
90
|
+
<script src="https://cdn.socket.io/4.7.2/socket.io.min.js"></script>
|
|
91
|
+
|
|
92
|
+
<!-- SunuID SDK -->
|
|
93
|
+
<script src="../../dist/sunuid-sdk.min.js"></script>
|
|
94
|
+
|
|
95
|
+
<script>
|
|
96
|
+
// Configuration du SDK avec gestion des callbacks
|
|
97
|
+
const config = {
|
|
98
|
+
apiUrl: 'https://api.sunuid.fayma.sn',
|
|
99
|
+
clientId: '1754166754_221A57B46843D755',
|
|
100
|
+
secretId: '56d40fe70507228b27f2640ae65894177c2fedbf246e2b30978fde1fc43953c5',
|
|
101
|
+
type: 2, // AUTH
|
|
102
|
+
theme: 'light',
|
|
103
|
+
language: 'fr',
|
|
104
|
+
|
|
105
|
+
// Configuration des callbacks
|
|
106
|
+
redirectAfterSuccess: '/dashboard?user={user_id}&session={session_id}',
|
|
107
|
+
verifySignature: false, // Désactivé pour l'exemple
|
|
108
|
+
tokenMaxAge: 300, // 5 minutes
|
|
109
|
+
|
|
110
|
+
// Callbacks d'authentification
|
|
111
|
+
onAuthenticationSuccess: function(userData, callbackData) {
|
|
112
|
+
console.log('🎉 Authentification réussie:', userData);
|
|
113
|
+
showSuccess(userData, callbackData);
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
onAuthenticationError: function(error, callbackData) {
|
|
117
|
+
console.error('❌ Erreur d\'authentification:', error);
|
|
118
|
+
showError(error, callbackData);
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
// Callbacks WebSocket
|
|
122
|
+
onStatusUpdate: function(status) {
|
|
123
|
+
updateStatus('Statut: ' + status, 'info');
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
onSuccess: function(data) {
|
|
127
|
+
updateStatus('Succès: ' + JSON.stringify(data), 'success');
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
onError: function(error) {
|
|
131
|
+
updateStatus('Erreur: ' + error.message, 'error');
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Initialiser le SDK
|
|
136
|
+
let sunuid;
|
|
137
|
+
|
|
138
|
+
async function initSDK() {
|
|
139
|
+
try {
|
|
140
|
+
sunuid = new SunuID(config);
|
|
141
|
+
await sunuid.init();
|
|
142
|
+
|
|
143
|
+
// Vérifier si on est sur une page de callback
|
|
144
|
+
if (window.location.search.includes('token=')) {
|
|
145
|
+
updateStatus('Callback détecté, traitement en cours...', 'info');
|
|
146
|
+
return; // Le callback sera traité automatiquement
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Sinon, afficher le QR code
|
|
150
|
+
showQRCode();
|
|
151
|
+
|
|
152
|
+
} catch (error) {
|
|
153
|
+
updateStatus('Erreur d\'initialisation: ' + error.message, 'error');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function showQRCode() {
|
|
158
|
+
document.getElementById('qr-section').classList.remove('hidden');
|
|
159
|
+
updateStatus('QR Code généré, scannez-le avec l\'app SunuID', 'info');
|
|
160
|
+
|
|
161
|
+
// Générer le QR code
|
|
162
|
+
sunuid.generateQR('qr-area').then(result => {
|
|
163
|
+
console.log('QR Code généré:', result);
|
|
164
|
+
}).catch(error => {
|
|
165
|
+
updateStatus('Erreur génération QR: ' + error.message, 'error');
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function showSuccess(userData, callbackData) {
|
|
170
|
+
document.getElementById('qr-section').classList.add('hidden');
|
|
171
|
+
document.getElementById('callback-section').classList.remove('hidden');
|
|
172
|
+
|
|
173
|
+
const dataDisplay = `
|
|
174
|
+
🔐 Authentification Réussie
|
|
175
|
+
|
|
176
|
+
👤 Utilisateur: ${userData.user_id}
|
|
177
|
+
🆔 Session: ${userData.session_id}
|
|
178
|
+
🏢 Partenaire: ${userData.partner_id}
|
|
179
|
+
📋 Type: ${getTypeName(userData.type)}
|
|
180
|
+
⏰ Créé: ${new Date(userData.iat * 1000).toLocaleString()}
|
|
181
|
+
⏰ Expire: ${new Date(userData.exp * 1000).toLocaleString()}
|
|
182
|
+
|
|
183
|
+
📋 Données Callback:
|
|
184
|
+
${JSON.stringify(callbackData, null, 2)}
|
|
185
|
+
`;
|
|
186
|
+
|
|
187
|
+
document.getElementById('callback-data').textContent = dataDisplay;
|
|
188
|
+
updateStatus('✅ Authentification réussie !', 'success');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function showError(error, callbackData) {
|
|
192
|
+
document.getElementById('qr-section').classList.add('hidden');
|
|
193
|
+
document.getElementById('error-section').classList.remove('hidden');
|
|
194
|
+
|
|
195
|
+
const errorDisplay = `
|
|
196
|
+
❌ Erreur d'Authentification
|
|
197
|
+
|
|
198
|
+
🚨 Erreur: ${error.message}
|
|
199
|
+
📋 Type: ${error.name}
|
|
200
|
+
⏰ Timestamp: ${new Date().toLocaleString()}
|
|
201
|
+
|
|
202
|
+
📋 Données Callback:
|
|
203
|
+
${JSON.stringify(callbackData, null, 2)}
|
|
204
|
+
`;
|
|
205
|
+
|
|
206
|
+
document.getElementById('error-data').textContent = errorDisplay;
|
|
207
|
+
updateStatus('❌ Erreur d\'authentification', 'error');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function updateStatus(message, type) {
|
|
211
|
+
const statusEl = document.getElementById('status');
|
|
212
|
+
statusEl.textContent = message;
|
|
213
|
+
statusEl.className = `status ${type}`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function getTypeName(type) {
|
|
217
|
+
const types = {
|
|
218
|
+
1: 'KYC',
|
|
219
|
+
2: 'AUTH',
|
|
220
|
+
3: 'SIGNATURE'
|
|
221
|
+
};
|
|
222
|
+
return types[type] || 'INCONNU';
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Initialiser au chargement de la page
|
|
226
|
+
document.addEventListener('DOMContentLoaded', initSDK);
|
|
227
|
+
|
|
228
|
+
// Exposer globalement pour debug
|
|
229
|
+
window.sunuid = sunuid;
|
|
230
|
+
</script>
|
|
231
|
+
</body>
|
|
232
|
+
</html>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// 🌍 Configuration SunuID - Exemple Ultra-Simple
|
|
2
|
+
// Copiez ce fichier et remplacez les valeurs par les vôtres !
|
|
3
|
+
|
|
4
|
+
const sunuidConfig = {
|
|
5
|
+
// 🔑 Vos credentials (obtenez-les sur https://sunuid.sn/register)
|
|
6
|
+
client_id: 'VOTRE_CLIENT_ID', // ← Remplacez par votre CLIENT_ID
|
|
7
|
+
secret_id: 'VOTRE_SECRET_ID', // ← Remplacez par votre SECRET_ID
|
|
8
|
+
|
|
9
|
+
// 🎯 Type de service
|
|
10
|
+
type: 2, // ← 1=KYC, 2=AUTH, 3=Signature
|
|
11
|
+
|
|
12
|
+
// 🏢 Nom de votre entreprise
|
|
13
|
+
partner_name: 'Votre Entreprise', // ← Remplacez par votre nom
|
|
14
|
+
|
|
15
|
+
// 🔧 Options avancées (optionnel)
|
|
16
|
+
options: {
|
|
17
|
+
// URL de redirection après connexion
|
|
18
|
+
redirect_url: 'https://votre-site.com/dashboard',
|
|
19
|
+
|
|
20
|
+
// Pour KYC uniquement
|
|
21
|
+
kyc_type: 'full', // 'basic' ou 'full'
|
|
22
|
+
required_fields: ['identity', 'address', 'phone'],
|
|
23
|
+
|
|
24
|
+
// Personnalisation
|
|
25
|
+
qr_size: 300, // Taille du QR code
|
|
26
|
+
logo_url: 'https://votre-site.com/logo.png', // Votre logo
|
|
27
|
+
theme: 'default' // 'default', 'dark', 'custom'
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// 📝 Comment utiliser :
|
|
32
|
+
// 1. Remplacez les valeurs ci-dessus
|
|
33
|
+
// 2. Sauvegardez en config.js
|
|
34
|
+
// 3. Incluez dans votre HTML :
|
|
35
|
+
// <script src="config.js"></script>
|
|
36
|
+
// <script>
|
|
37
|
+
// const sunuid = new SunuID(sunuidConfig);
|
|
38
|
+
// sunuid.init();
|
|
39
|
+
// </script>
|
|
40
|
+
|
|
41
|
+
// 🎉 C'est tout ! Votre configuration est prête !
|