English
Spanish
French
0
Notifications
0 Non lues
Aucune notification
Voir toutes
Aucune nouvelle notification
Raccourcis
Tableau de bord
Profil
Paramètres
Voir toutes les apps
Utilisateur
Utilisateur
Profil
Messages
25
Paramètres
Solde
$47.12
Support
Se déconnecter
Dashboard
Dashboard
Éditer test/payment_form.php
Vous devez être connecté.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Test Paiement avec OTP (Bouton Loading + Erreurs Robustes)</title> <style> body { font-family: Arial, sans-serif; max-width: 800px; margin: 20px auto; padding: 20px; } .form-group { margin-bottom: 15px; } label { display: block; margin-bottom: 5px; } input, select { width: 100%; padding: 8px; margin-bottom: 10px; border: 1px solid #ddd; border-radius: 4px; } button { background: #4CAF50; color: white; padding: 10px 15px; border: none; border-radius: 4px; cursor: pointer; margin-right: 10px; } button:hover { background: #45a049; } .payment-section { display: none; margin-top: 15px; padding: 15px; border: 1px solid #ddd; border-radius: 4px; } .error { color: red; margin-top: 5px; } /* === Modale OTP (simple) === */ .modal-backdrop { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.4); z-index: 9998; } .modal { display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 300px; background: #fff; border-radius: 8px; padding: 20px; z-index: 9999; } .modal h3 { margin-top: 0; } .modal-close { float: right; cursor: pointer; color: #999; } .modal-close:hover { color: #333; } /* === Logs JSON === */ #logOutput { margin-top: 20px; background: #f9f9f9; border: 1px solid #ccc; padding: 10px; min-height: 100px; max-height: 300px; overflow-y: auto; font-family: monospace; } </style> </head> <body> <h2>Formulaire de Paiement1</h2> <!-- Montant --> <div class="form-group"> <label for="amount">Montant (USD)</label> <input type="number" id="amount" name="amount" required min="1" step="0.01" value="1"> </div> <!-- Sélection du mode de paiement --> <div class="form-group"> <label for="payment_mode">Mode de paiement</label> <select id="payment_mode" name="mode" required> <option value="">Sélectionnez un mode de paiement</option> <option value="illico">Illico Cash</option> <option value="flexpay">FlexPay</option> <option value="mastercard">MasterCard/Visa</option> </select> </div> <!-- Section Illico --> <div id="illico_section" class="payment-section"> <div class="form-group"> <label for="illico_phone">Numéro de téléphone</label> <input type="tel" id="illico_phone" name="phone" placeholder="Ex: 243990000000"> </div> </div> <!-- Section FlexPay --> <div id="flexpay_section" class="payment-section"> <div class="form-group"> <label for="flexpay_phone">Numéro de téléphone</label> <input type="tel" id="flexpay_phone" name="phone" placeholder="Ex: 243990000000"> </div> </div> <!-- Section Carte Bancaire --> <div id="card_section" class="payment-section"> <div class="form-group"> <label for="card_number">Numéro de carte</label> <input type="text" id="card_number" name="card_number" placeholder="1234 5678 9012 3456"> </div> <div class="form-group"> <label for="exp_month">Mois d'expiration</label> <input type="number" id="exp_month" name="exp_month" min="1" max="12" placeholder="MM"> </div> <div class="form-group"> <label for="exp_year">Année d'expiration</label> <input type="number" id="exp_year" name="exp_year" min="2024" max="2099" placeholder="YYYY"> </div> <div class="form-group"> <label for="cvv">CVV</label> <input type="number" id="cvv" name="cvv" placeholder="123"> </div> </div> <!-- Bouton Payer --> <button type="button" id="btnPay">Payer</button> <!-- Zone d'affichage des messages --> <div id="response" class="error"></div> <!-- === Modale OTP === --> <div class="modal-backdrop" id="otpBackdrop"></div> <div class="modal" id="otpModal"> <span class="modal-close" onclick="closeOtpModal()">×</span> <h3>Entrez le Code OTP</h3> <p>Veuillez saisir le code reçu sur votre téléphone :</p> <input type="text" id="otpInput" placeholder="Ex: 123456" style="width: 100%; margin-bottom: 10px;" /> <button type="button" id="btnConfirmOTP">Confirmer OTP</button> </div> <!-- === LOGS JSON Bruts === --> <h3>Log de la dernière réponse JSON</h3> <div id="logOutput"></div> <script> // Pour stocker la référence Illico let illicoRef = null; // ---------------------------- // 1) GESTION DU MODE PAIEMENT // ---------------------------- document.getElementById('payment_mode').addEventListener('change', () => { document.querySelectorAll('.payment-section').forEach(sec => { sec.style.display = 'none'; }); switch (document.getElementById('payment_mode').value) { case 'illico': document.getElementById('illico_section').style.display = 'block'; break; case 'flexpay': document.getElementById('flexpay_section').style.display = 'block'; break; case 'mastercard': document.getElementById('card_section').style.display = 'block'; break; } }); // ---------------------------- // 2) BOUTON LOADING MANAGER // ---------------------------- /** Désactive le bouton et change son texte => “Chargement...” */ function showButtonLoading(btn) { btn.disabled = true; btn.dataset.originalText = btn.textContent; btn.textContent = "Chargement..."; } /** Restaure l’état et le texte du bouton */ function hideButtonLoading(btn) { btn.disabled = false; if (btn.dataset.originalText) { btn.textContent = btn.dataset.originalText; } } // ---------------------------- // 3) LANCER LE PAIEMENT // ---------------------------- document.getElementById('btnPay').addEventListener('click', function() { const payBtn = this; showButtonLoading(payBtn); const mode = document.getElementById('payment_mode').value; const amount = document.getElementById('amount').value; if (!mode || !amount) { hideButtonLoading(payBtn); displayMessage("Veuillez remplir tous les champs requis.", "red"); return; } // Construire FormData const fd = new FormData(); fd.append('mode', mode); fd.append('amount', amount); switch(mode) { case 'illico': fd.append('phone', document.getElementById('illico_phone').value); break; case 'flexpay': fd.append('phone', document.getElementById('flexpay_phone').value); break; case 'mastercard': fd.append('card_number', document.getElementById('card_number').value); fd.append('exp_month', document.getElementById('exp_month').value); fd.append('exp_year', document.getElementById('exp_year').value); fd.append('cvv', document.getElementById('cvv').value); break; } // ====== APPEL FETCH ====== fetch('/paiement_normal/payment/process', { method: 'POST', headers: { 'Accept': 'application/json' }, body: fd }) .then(resp => { // Vérification code HTTP if (!resp.ok) { return resp.text().then(txt => { console.warn("Réponse brute (text) => ", txt); throw new Error(`HTTP Error ${resp.status} : ${txt}`); }); } // Tenter un parse JSON return resp.json(); }) .then(data => { hideButtonLoading(payBtn); // Log logResponse(data); // Vérification qu’on a un champ status if (typeof data.status === 'undefined') { throw new Error("JSON invalide, champ 'status' manquant."); } if (data.status) { displayMessage(data.message || "Paiement initié avec succès.", "green"); // Cas Illico => on ouvre la modale OTP if (mode === 'illico') { illicoRef = data.illico_data?.referencenumber || null; showOtpModal(); } } else { displayMessage(data.message || "Erreur paiement", "red"); } }) .catch(err => { console.error("ERREUR fetch:", err); hideButtonLoading(payBtn); displayMessage("Une erreur est survenue : " + err.message, "red"); }); }); // ---------------------------- // 4) CONFIRMER L'OTP // ---------------------------- document.getElementById('btnConfirmOTP').addEventListener('click', function() { const otpBtn = this; showButtonLoading(otpBtn); const otpVal = document.getElementById('otpInput').value; if (!otpVal) { hideButtonLoading(otpBtn); alert("Veuillez saisir l'OTP."); return; } if (!illicoRef) { hideButtonLoading(otpBtn); alert("Référence Illico introuvable. Avez-vous initié le paiement ?"); return; } const fd = new FormData(); fd.append('ref', illicoRef); fd.append('otpmsg', otpVal); fetch('/paiement_normal/payment/confirmOtpIllico', { method: 'POST', headers: { 'Accept': 'application/json' }, body: fd }) .then(resp => { if (!resp.ok) { return resp.text().then(txt => { console.warn("Réponse brute (text):", txt); throw new Error("HTTP Error " + resp.status + " => " + txt); }); } return resp.json(); }) .then(data => { hideButtonLoading(otpBtn); logResponse(data); // Vérification if (typeof data.status === 'undefined') { throw new Error("JSON invalide, champ 'status' manquant."); } if (data.status) { alert("OTP confirmé : " + (data.message || "OK")); closeOtpModal(); } else { alert("Erreur OTP : " + (data.message || "")); } }) .catch(err => { hideButtonLoading(otpBtn); alert("Erreur AJAX : " + err.message); }); }); // ---------------------------- // 5) GESTION MODALE // ---------------------------- function showOtpModal() { document.getElementById('otpModal').style.display = 'block'; document.getElementById('otpBackdrop').style.display = 'block'; } function closeOtpModal() { document.getElementById('otpModal').style.display = 'none'; document.getElementById('otpBackdrop').style.display = 'none'; } // ---------------------------- // 6) OUTILS D’AFFICHAGE // ---------------------------- function displayMessage(msg, color) { const resp = document.getElementById('response'); resp.textContent = msg; resp.style.color = color || 'red'; } function logResponse(jsonData) { console.log("Réponse JSON:", jsonData); document.getElementById('logOutput').textContent = JSON.stringify(jsonData, null, 2); } </script> </body> </html>
Annuler
Enregistrer
Switcher
Theme Styles
Theme Colors
Theme Color Mode:
Light
Dark
Menu Colors: