435 Avenue du Pylône
06600 Antibes
07 63 86 87 10

435 Avenue du Pylône - 06600 Antibes

Venez tenter l’aventure Warrior Paintball Antibes

Équipement Complet

6 terrains plats en plein air

Différents modes de jeux

Sensations fortes

Warrior Paintball Antibes

Vous serez encadrés par des professionnels compétents et qualifiés qui s’occuperont de vous et de l’élaboration de scénarios originaux.

Sécurité optimale

À partir de 7 ans

Espace détente

Des prix attractifs

Tarifs

Une session paintball en famille ou entre amis, un anniversaire à fêter ou événement Team Building ? Nous sommes ouverts pour toute demande particulière et nous pouvons élaborer vos événements sur mesure avec des thèmes spécifiques.
hp-section1-1

Fun & Amis

Entre amis ou en famille, rien de mieux qu’une activité plein air où tout le monde peut s’amuser. Nous avons des lanceurs et des équipements adaptés pour tout âge et niveau à partir de 7 ans

hp-section1-2

Les Anniversaires

Vous souhaitez faire une surprise exceptionnelle pour un anniversaire ? Venez chez Warrior Paintball Antibes ! Nous proposons des formules avec boissons, bonbons, gâteaux,...

hp-section1-3

Enterrement de vie de garçon ou de jeune fille

Venez passer un EVG ou EVJF inoubliable entre amis grâce au scénario « chasse au lapin ». De la joie et de la bonne humeur garantie !

hp-section1-4

Team building entreprises

Vous recherchez une activité alliant entraide, communication, esprit d’équipe et défoulement ? Le Paintball est l’activité qu'il vous faut !

hp-section1-5

Écoles, BDE & WEI

L'Esprit d'équipe avant tout ! Le Paintball est un excellent moyen d’optimiser la socialisation et favoriser la solidarité entre les élèves.

hp-section1-6

Joueurs équipés

Que vous soyez joueur débutant ou confirmé, nous vous proposons l’accès aux différents terrains de Warrior Paintball à des tarifs préférentiels...

Vous recherchez une activité sportive et originale ?

Le paintball est fait pour vous !

Jamais joué au paintball ?

N’ayez crainte, avec Warrior Paintball Antibes, c’est simple et accessible à tous à partir de sept ans.
Nos équipes vous proposent différents scénarios de jeu adaptés à vos envies et au nombre de joueurs.
Parfait pour développer la cohésion d’équipe, l’échange et pour vous amuser en toute sécurité.
Des sensations fortes, de l’action et du rire garanti !

Avis & Commentaires

Chez Warrior Paintball Antibes, nous prenons très à cœur les appréciations de nos joueurs.
Nous souhaitons en permanence développer le confort, l’accueil et les styles de jeux !

Emilie Hobeich
Emilie Hobeich
16/03/2026
Anthony Gastien
Anthony Gastien
15/03/2026
Pauline Cazals
Pauline Cazals
09/03/2026
Maxime DUPANLOUP
Maxime DUPANLOUP
08/03/2026
Constant DELLAMONICA
Constant DELLAMONICA
08/03/2026
Chaden Mawazini
Chaden Mawazini
08/03/2026
Nicolas Marro
Nicolas Marro
08/03/2026
Mat Mat
Mat Mat
08/03/2026
Michaël AOUIZERATE
Michaël AOUIZERATE
21/02/2026

Réservez votre partie de paintball
directement en ligne

Tous nos packs incluent l’équipement complet pour jouer en toute sécurité et vous donne l’accès à nos 6 terrains.
La durée dépend du pack choisi et de la cadence de tir des joueurs.

Sélectionnez une date et choisissez un horaire qui vous convient :

Contacter Warrior PaintBall Antibes

En soumettant ce formulaire vous acceptez que WarriorPaintBall Antibes, en sa qualité de responsable de traitement, collecte vos données afin de pouvoir répondre à votre message. Pour connaitre et exercer vos droits , notamment de retrait de votre consentement à l’utilisation de données collectées par ce formulaire, veuillez consulter notre politique  de  confidentialité

Vous avez désormais la possibilité de vos restaurez sur place. Si toutefois vous êtes un groupe nous vous recommandons de nous le mentionner dans la réservation afin de faciliter la préparation pour le jour J. Il est toujours possible de ramener votre propre picnic.

Les packs avec gâteaux incluent bonbons et boissons.
Nous nous occuperons des assiettes, couverts et serviettes que si nous gérons le gâteau et des gobelets que si nous gérons les boissons.
Vous pouvez emporter des éléments supplémentaires ou de la décoration sans aucun problème.

Nous vous conseillons de rajouter des options pour rendre l’activité encore plus immersive.
Les fumigènes sont exceptionnels pour les parties comme la capture du drapeau ou la prise de position.

Pour les groupes de + de 10 personnes ou + de 20 personnes vous bénéficiez de billes offertes ou de réductions.
D’avril à Octobre découvrez le pack combo Paintball et Ninja Warrior Antibes.

Nous sélectionnons toujours le type de lanceur en fonction de l’âge du plus jeune joueur du groupe.

Vous souhaitez jouer au paintball ou organiser un événement particulier ?
Sélectionnez un évènement …

Traitement en cours...

Veuillez patienter nous interrogeons votre banque

Paiement non abouti

Détails de l'erreur : Chargement...

Informations incomplètes

Sélectionnez un Pack

Pour voir les options

Sélectionnez un lanceur

Pour voir les tarifs

Sélectionnez un évènement

Pour voir les lanceurs

Offrez l'Aventure
Bon Cadeau
Warrior Paintball

À la recherche du cadeau parfait ?

Surprenez vos proches avec une séance de paintball, chargée d’adrénaline et de stratégie !
Idéal pour les anniversaires, les occasions spéciales ou juste pour le plaisir.

Un moment inoubliable garanti !

Bon cadeau validé

Félicitations ! Votre bon cadeau a été créé avec succès.
Nous avons envoyé une copie du bon à votre adresse email ainsi qu’à celle du bénéficiaire. Le bon peut être utilisé selon les préférences du destinataire.

Nous sommes impatients d’accueillir le bénéficiaire et restons à votre disposition pour toute question ou information complémentaire.
N’hésitez pas à nous contacter.

[pdfjs-viewer url="https://www.warriorpaintball.fr/wp-content/uploads/2022/08/Anniversaire-Paintball.pdf?ver=1715153916"]
[pdfjs-viewer url="https://www.warriorpaintball.fr/wp-content/uploads/2022/08/Anniversaire-Paintball.pdf?ver=1715153916"]
[pdfjs-viewer url="https://www.warriorpaintball.fr/wp-content/uploads/2022/08/Anniversaire-Paintball.pdf?ver=1715153916"]

Lanceur

INCLUS

Billes

INCLUS

Masque

INCLUS

Plastron

INCLUS

Combinaison

INCLUS

Gants

OPTION

Protège cou

OPTION

Fumigène

OPTION

Nourriture et boissons

OPTION

Espace de réception

À DISPOSITION

gotcha

De 7 à 9 ans

Le Gotcha est le plus simple et le plus adapté aux jeunes joueurs de paintball. Plus lent à utiliser car il doit être manuellement recharger il s’apparente à un fusil à pompe et sûr pour les enfants de 7 ans et plus.
Ergonomie
Puissance
Cadence

Précision

De 10 à 17 ans

Ce lanceur semi-automatique de calibre .50 est une excellente option pour les débutants et les adolescents. Son mécanisme permet une fluidité de tir et une stabilité sans pareil. Léger et équilibré, le Précision est l’allié des joueurs recherchant la perfection sur le terrain.
Ergonomie
Puissance
Cadence

BT4 Combat

À partir de 15 ans

Le Lanceur Combat est le compagnon idéal pour les amateurs d’action qui cherchent un équipement fiable et puissant. Le BT4 est le tank du paintball, conçu pour ceux qui aiment être en première ligne. Robuste et fiable, il peut résister aux conditions les plus difficiles
Ergonomie
Puissance
Cadence

Emek

À partir de 16 ans

L’Emek est une combinaison parfaite adaptée à tous les styles de jeu grâce à son système de tir pneumatique offrant une précision et une cadence de tir incroyablement efficaces et extrêmement fiables.
Ergonomie
Puissance
Cadence
logo noir warrior paintball antibes

ANGIE
435  avenue du Pylône
06600 ANTIBES

Quantité

Description

PU HT

Montant HT

Fumigène(s)

Déguisement(s)

Coupes et médailles

Photos et vidéos

Remise exceptionnelle (-10%)

Total HT

TVA (20%)

TVA (10 %)

Total TTC

Angie SAS
RCS Antibes 883 659 518
N° de TVA Intracommunautaire FR91883659518

Réservation Enregistrée

Votre réservation est enregistrée, vous allez recevoir dans votre email la confirmation de votre réservation et un rappel du rendez-vous avec les détails de votre réservation.

Nous sommes ravis de vous accueillir !
Si vous avez la moindre question ou besoin de plus d’infos, n’hésitez surtout pas à nous contacter.

Temps et terrains
temps de parcours et map warrior paintball antibes

Lanceur

INCLUS

Billes

INCLUS

Masque

INCLUS

Plastron

INCLUS

Combinaison

INCLUS

Gants

OPTION

Protège cou

OPTION

Fumigène

OPTION

Nourriture et boissons

OPTION

Espace de réception

À DISPOSITION

gotcha

De 7 à 9 ans

Le Gotcha est le plus simple et le plus adapté aux jeunes joueurs de paintball. Plus lent à utiliser car il doit être manuellement recharger il s’apparente à un fusil à pompe et sûr pour les enfants de 7 ans et plus.
Ergonomie
Puissance
Cadence
Description

Précision

De 10 à 17 ans

Ce lanceur semi-automatique de calibre .50 est une excellente option pour les débutants et les adolescents. Son mécanisme permet une fluidité de tir et une stabilité sans pareil. Léger et équilibré, le Précision est l’allié des joueurs recherchant la perfection sur le terrain.
Ergonomie
Puissance
Cadence

Lanceur

INCLUS

Billes

INCLUS

Masque

INCLUS

Plastron

INCLUS

Combinaison

INCLUS

Gants

OPTION

Protège cou

OPTION

Fumigène

OPTION

Nourriture et boissons

OPTION

Espace de réception

À DISPOSITION

temps de parcours et map warrior paintball antibes
Description

BT4 Combat

À partir de 15 ans

Le Lanceur Combat est le compagnon idéal pour les amateurs d’action qui cherchent un équipement fiable et puissant. Le BT4 est le tank du paintball, conçu pour ceux qui aiment être en première ligne. Robuste et fiable, il peut résister aux conditions les plus difficiles
Ergonomie
Puissance
Cadence

Lanceur

INCLUS

Billes

INCLUS

Masque

INCLUS

Plastron

INCLUS

Combinaison

INCLUS

Gants

OPTION

Protège cou

OPTION

Fumigène

OPTION

Nourriture et boissons

OPTION

Espace de réception

À DISPOSITION

temps de parcours et map warrior paintball antibes
Description

Emek

À partir de 16 ans

L’Emek est une combinaison parfaite adaptée à tous les styles de jeu grâce à son système de tir pneumatique offrant une précision et une cadence de tir incroyablement efficaces et extrêmement fiables.
Ergonomie
Puissance
Cadence

Lanceur

INCLUS

Billes

INCLUS

Masque

INCLUS

Plastron

INCLUS

Combinaison

INCLUS

Gants

OPTION

Protège cou

OPTION

Fumigène

OPTION

Nourriture et boissons

OPTION

Espace de réception

À DISPOSITION

temps de parcours et map warrior paintball antibes
// ==================================================== // PIOTNET STRIPE - GESTION UX PAIEMENT - v3.0.0 // Améliorations : détection bloqueur popup, ciblage // bouton élargi, surveillance immédiate, mobile fix // ==================================================== document.addEventListener('DOMContentLoaded', function () { console.log('[PIOTNET-STRIPE] Initialisation v3.0.0'); (function () { 'use strict'; console.log('[PIOTNET-STRIPE] Script démarré v3.0.0'); /* ============================ * CONFIGURATION * ============================ */ const THEME_CONFIG = { buttonColor: '#C97064', overlayOpacity: 0.8 }; const CONFIG = { ERROR_CHECK_INTERVAL: 500, MAX_WAIT_TIME: 45000, // ✅ FIX MOBILE : délai adaptatif selon l'appareil LOADING_DELAY: /Mobi|Android/i.test(navigator.userAgent) ? 800 : 350, DEBUG_MODE: true, SERVER_LOGGING: true, LOG_ENDPOINT: '/wp-admin/admin-ajax.php?action=stripe_payment_log' }; window.PIOTNET_CONFIG = CONFIG; /* ============================ * ÉTAT GLOBAL * ============================ */ let errorCheckInterval = null; let timeoutTimer = null; let isMonitoring = false; let isProcessingPayment = false; let currentTransactionId = null; function debugLog(msg, data = null) { if (CONFIG.DEBUG_MODE) console.log('[PAYMENT-UX]', msg, data ?? ''); } /* ============================ * DÉTECTION DU MODE STRIPE * ============================ */ function detectPaymentMode() { if (typeof window.STRIPE_MODE_DETECTED !== 'undefined') { console.log('[PIOTNET-STRIPE] Mode détecté depuis Piotnet (PHP):', window.STRIPE_MODE_DETECTED); return window.STRIPE_MODE_DETECTED; } console.log('[PIOTNET-STRIPE] Variable PHP non disponible, détection depuis le DOM...'); const scripts = document.querySelectorAll('script'); for (const script of scripts) { const content = script.textContent || script.innerHTML; if (content.includes('pk_test_')) return 'test'; if (content.includes('pk_live_')) return 'live'; } const stripeElements = document.querySelectorAll('[data-stripe-publishable-key], [data-pafe-stripe-key]'); for (const elem of stripeElements) { const key = elem.getAttribute('data-stripe-publishable-key') || elem.getAttribute('data-pafe-stripe-key'); if (key) { if (key.startsWith('pk_test_')) return 'test'; if (key.startsWith('pk_live_')) return 'live'; } } console.log('[PIOTNET-STRIPE] Aucune clé détectée, mode par défaut: LIVE'); return 'live'; } /* ============================ * DÉTECTION BLOQUEUR DE POPUP ← NOUVEAU v3.0.0 * ============================ */ function isPopupBlocked() { try { // Tentative d'ouverture d'une fenêtre invisible hors écran const testWin = window.open('', '_blank', 'width=1,height=1,left=-9999,top=-9999'); // Null ou undefined = bloqué directement if (!testWin) return true; // Certains bloqueurs retournent un objet mais le ferment immédiatement if (testWin.closed) return true; // Fermer la fenêtre test proprement testWin.close(); return false; } catch (e) { // Exception = bloqué (notamment sur certains navigateurs mobiles) debugLog('Exception lors du test popup:', e.message); return true; } } /* ============================ * EXTRACTION DES DONNÉES CLIENT * ============================ */ function extractClientData() { const data = {}; const emailField = document.querySelector('input[type="email"], input[name*="email"], input[id*="email"]'); if (emailField && emailField.value) data.email = emailField.value; const nameFields = document.querySelectorAll('input[name*="nom"], input[name*="name"], input[id*="nom"], input[id*="name"]'); let fullName = ''; nameFields.forEach(field => { if (field.value && !field.type.match(/email|tel|number/)) { fullName += (fullName ? ' ' : '') + field.value; } }); if (fullName) data.customerName = fullName.trim(); const phoneField = document.querySelector('input[type="tel"], input[name*="phone"], input[name*="telephone"], input[id*="phone"], input[id*="tel"]'); if (phoneField && phoneField.value) data.phone = phoneField.value; data.userAgent = navigator.userAgent; data.screenResolution = `${window.screen.width}x${window.screen.height}`; data.viewportSize = `${window.innerWidth}x${window.innerHeight}`; const ua = navigator.userAgent.toLowerCase(); if (/mobile|android|iphone|ipod|blackberry|iemobile|opera mini/i.test(ua)) { data.deviceType = 'mobile'; } else if (/tablet|ipad/i.test(ua)) { data.deviceType = 'tablet'; } else { data.deviceType = 'desktop'; } data.referrer = document.referrer || 'direct'; const urlParams = new URLSearchParams(window.location.search); const utmParams = {}; ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'].forEach(param => { if (urlParams.has(param)) utmParams[param] = urlParams.get(param); }); if (Object.keys(utmParams).length > 0) data.utmParams = utmParams; if (!sessionStorage.getItem('stripe_session_id')) { sessionStorage.setItem('stripe_session_id', 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9)); } data.sessionId = sessionStorage.getItem('stripe_session_id'); data.timestamp = Date.now(); return data; } /* ============================ * DÉTECTION DU TYPE D'ERREUR * ============================ */ function detectErrorType(errorMessage) { const msg = errorMessage.toLowerCase(); if (msg.includes('declined') || msg.includes('refus')) return 'Carte refusée'; if (msg.includes('insufficient') || msg.includes('fonds')) return 'Fonds insuffisants'; if (msg.includes('expired') || msg.includes('expir')) return 'Carte expirée'; if (msg.includes('cvc') || msg.includes('cvv') || msg.includes('security code')) return 'Code CVC incorrect'; if (msg.includes('invalid number') || msg.includes('numéro invalide')) return 'Numéro de carte invalide'; if (msg.includes('authentication') || msg.includes('3d secure')) return 'Authentification 3DS échouée'; if (msg.includes('popup') || msg.includes('bloqué') || msg.includes('blocked')) return 'Popup bloquée'; if (msg.includes('timeout') || msg.includes('délai')) return 'Timeout'; if (msg.includes('network') || msg.includes('réseau') || msg.includes('connection')) return 'Erreur réseau'; return 'Autre erreur'; } /* ============================ * LOGGING SERVEUR * ============================ */ function serverLog(level, message, context = null, extraData = {}) { debugLog(`[${level.toUpperCase()}] ${message}`, context); if (!CONFIG.SERVER_LOGGING) return; const logData = { level, message, context, timestamp: new Date().toISOString(), url: window.location.href, userAgent: navigator.userAgent, transactionId: currentTransactionId, ...extraData }; fetch(CONFIG.LOG_ENDPOINT, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }, body: JSON.stringify(logData), keepalive: true }).catch(err => { console.error('[PAYMENT-UX] Erreur logging serveur:', err); }); } /* ============================ * CSS (injection) * ============================ */ function addStyles() { if (document.getElementById('piotnet-responsive-styles')) return; const style = document.createElement('style'); style.id = 'piotnet-responsive-styles'; style.textContent = ` @keyframes fadeInCenter {0%{opacity:0;transform:translate(-50%,-50%) scale(.9)}100%{opacity:1;transform:translate(-50%,-50%) scale(1)}} @keyframes fadeOutCenter {0%{opacity:1;transform:translate(-50%,-50%) scale(1)}100%{opacity:0;transform:translate(-50%,-50%) scale(.9)}} @keyframes spin {to{transform:rotate(360deg)}} .piotnet-popup-overlay{position:fixed;inset:0;background:rgba(0,0,0,${THEME_CONFIG.overlayOpacity});z-index:999998;display:flex;align-items:center;justify-content:center;padding:20px;box-sizing:border-box} .piotnet-popup{background:#fff;border-radius:16px;box-shadow:0 10px 30px rgba(0,0,0,.25);max-width:520px;width:100%;max-height:90vh;overflow:hidden;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);animation:fadeInCenter .25s ease-out} .piotnet-popup.closing{animation:fadeOutCenter .2s ease-in} .piotnet-popup-header{padding:22px 26px 14px;border-bottom:1px solid #eee;text-align:center;position:relative} .piotnet-popup-title{font-family:Arial,sans-serif;font-size:18px;font-weight:bold;color:#222;margin:0;text-transform:uppercase;letter-spacing:.4px} .piotnet-popup-close{position:absolute;top:12px;right:16px;background:none;border:none;font-size:22px;color:#888;cursor:pointer;padding:6px;width:34px;height:34px;display:flex;align-items:center;justify-content:center;border-radius:50%} .piotnet-popup-close:hover{background:#f4f4f4;color:#333} .piotnet-popup-content{padding:22px 24px 26px;text-align:center} .piotnet-popup-content p{margin:0 0 16px;font-family:Arial,sans-serif;font-size:15px;color:#555;line-height:1.55} .piotnet-loading-spinner{width:56px;height:56px;margin:18px auto;position:relative} .piotnet-loading-spinner::before{content:"";position:absolute;inset:0;border:4px solid #e3e3e3;border-top-color:#3498db;border-radius:50%;animation:spin 1s linear infinite} .piotnet-loading-spinner::after{content:"";position:absolute;top:8px;left:8px;right:8px;bottom:8px;border:4px solid transparent;border-top-color:#27ae60;border-radius:50%;animation:spin 1.25s linear infinite reverse} .piotnet-error-details{background:#f8f9fa;border:1px solid #dee2e6;border-radius:10px;padding:14px;margin:18px 0;text-align:left} .piotnet-error-details h4{margin:0 0 6px;font-size:14px;color:#333} .piotnet-error-details p{margin:0;font-size:14px;color:#666} .piotnet-popup-buttons{display:flex;gap:12px;justify-content:center;flex-wrap:wrap} .piotnet-popup-warning{background:#fff8e1;border:1px solid #ffe082;border-radius:10px;padding:14px;margin:18px 0;text-align:left} .piotnet-popup-warning h4{margin:0 0 6px;font-size:14px;color:#f57c00} .piotnet-popup-warning p{margin:0;font-size:13px;color:#795548;line-height:1.5} .piotnet-popup-warning ol{margin:8px 0 0 16px;padding:0;font-size:13px;color:#795548;line-height:1.8} .piotnet-popup .piotnet-popup-button{background:#fff;border:1px solid ${THEME_CONFIG.buttonColor};color:${THEME_CONFIG.buttonColor};padding:10px 20px;border-radius:10px;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s ease-in-out;text-transform:uppercase;text-decoration:none} .piotnet-popup .piotnet-popup-button.primary:hover,.piotnet-popup .piotnet-popup-button.primary:focus{background:${THEME_CONFIG.buttonColor};color:#fff} .piotnet-hide-native-error{display:none !important} @media (max-width:600px){ .piotnet-popup{max-width:95%;border-radius:12px} .piotnet-popup-header{padding:18px 20px 12px} .piotnet-popup-title{font-size:16px} .piotnet-popup-content{padding:18px 20px 22px} .piotnet-popup-content p{font-size:14px} .piotnet-loading-spinner{width:48px;height:48px} .piotnet-popup-buttons{flex-direction:column} .piotnet-popup-button{width:100%} } `; document.head.appendChild(style); debugLog('Styles CSS injectés'); } /* ============================ * TRADUCTIONS * ============================ */ const STRIPE_TRANSLATIONS = { 'Your card was declined.': 'Votre carte a été refusée.', 'Your card has insufficient funds.': 'Fonds insuffisants.', 'Your card has expired.': 'Votre carte a expiré.', 'Your card\'s security code is incorrect.': 'Code de sécurité incorrect.', 'An error occurred while processing your card.': 'Une erreur est survenue lors du traitement de votre carte.', 'Your card number is incorrect.': 'Numéro de carte incorrect.', 'Your card is not supported.': 'Votre carte n\'est pas supportée.', 'Processing error': 'Erreur de traitement' }; function translateError(message) { return STRIPE_TRANSLATIONS[message] || message; } /* ============================ * HELPERS * ============================ */ function findParentForm(element) { let current = element; while (current && current !== document.body) { if (current.tagName === 'FORM') return current; current = current.parentElement; } return null; } function isPaymentButtonEnabled(btn) { return btn && !btn.disabled && !btn.classList.contains('pafe-form-builder-button-disabled'); } function areStripeElementsComplete() { const stripeFields = document.querySelectorAll('.StripeElement'); if (stripeFields.length === 0) return true; for (const field of stripeFields) { if (field.classList.contains('StripeElement--empty') || field.classList.contains('StripeElement--invalid')) { debugLog('❌ Champ Stripe incomplet ou invalide', field); return false; } } return true; } function isElementVisible(element) { if (!element) return false; const style = window.getComputedStyle(element); if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') return false; const rect = element.getBoundingClientRect(); if (rect.width === 0 && rect.height === 0) return false; return true; } /* ============================ * ✅ FIX : SÉLECTEUR BOUTON ÉLARGI ← NOUVEAU v3.0.0 * Cible tous les boutons Piotnet/PAFE/Elementor * ============================ */ const PAYMENT_BUTTON_SELECTORS = [ '[data-pafe-form-builder-stripe-submit]', '.pafe-form-builder-button', '.elementor-button.pafe-form-builder-button' ].join(','); function isPaymentButton(element) { return !!element.closest(PAYMENT_BUTTON_SELECTORS); } function getPaymentButton(element) { return element.closest(PAYMENT_BUTTON_SELECTORS); } /* ============================ * VALIDATION DU FORMULAIRE * ============================ */ function isFormValid(form) { debugLog('Validation du formulaire...', form); const requiredFields = form.querySelectorAll('[required], [aria-required="true"]'); debugLog(`Champs requis trouvés: ${requiredFields.length}`); for (const field of requiredFields) { if (field.closest('.StripeElement')) continue; const isCheckboxOrRadio = field.type === 'checkbox' || field.type === 'radio'; const isEmpty = isCheckboxOrRadio ? !field.checked : !field.value.trim(); if (isEmpty) { debugLog('❌ Champ requis vide', field); field.scrollIntoView({ behavior: 'smooth', block: 'center' }); if (field.reportValidity) { field.reportValidity(); } else { field.focus(); } return false; } } debugLog('✅ Formulaire valide'); return true; } /* ============================ * GESTION DES POPUPS * ============================ */ function removeAllPopups() { debugLog('Suppression de toutes les popups'); document.querySelectorAll('.piotnet-popup-overlay').forEach(overlay => overlay.remove()); } function createLoadingPopup() { debugLog('Création de la popup de chargement'); removeAllPopups(); const overlay = document.createElement('div'); overlay.className = 'piotnet-popup-overlay'; overlay.innerHTML = `

Traitement en cours...

Veuillez patienter, nous interrogeons votre banque.

`; document.body.appendChild(overlay); debugLog('Popup de chargement créée'); } function createErrorPopup(errorMessage) { debugLog('Création de la popup d\'erreur', errorMessage); removeAllPopups(); const translatedMessage = translateError(errorMessage); const overlay = document.createElement('div'); overlay.className = 'piotnet-popup-overlay'; overlay.innerHTML = `

Paiement non abouti

Détails de l'erreur

${translatedMessage}

`; document.body.appendChild(overlay); const closeBtn = overlay.querySelector('.piotnet-popup-close'); const retryBtn = overlay.querySelector('.piotnet-retry-button'); const closeAndReset = () => { debugLog('Fermeture de la popup et réinitialisation'); const popup = overlay.querySelector('.piotnet-popup'); popup.classList.add('closing'); setTimeout(() => { overlay.remove(); resetAfterError(); }, 200); }; closeBtn.addEventListener('click', closeAndReset); retryBtn.addEventListener('click', closeAndReset); } // ✅ NOUVEAU v3.0.0 : Popup dédiée bloqueur de popup function createPopupBlockedWarning() { debugLog('Création de la popup avertissement bloqueur'); removeAllPopups(); const overlay = document.createElement('div'); overlay.className = 'piotnet-popup-overlay'; overlay.innerHTML = `

Action requise

⚠️ Votre navigateur bloque les fenêtres de paiement

La fenêtre de saisie de votre carte bancaire ne peut pas s'ouvrir.
Pour finaliser votre abonnement, veuillez autoriser les popups pour ce site :

  1. Cliquez sur l'icône 🔒 ou ⚙️ dans la barre d'adresse
  2. Sélectionnez "Autoriser les popups" pour ce site
  3. Rechargez la page et réessayez
`; document.body.appendChild(overlay); overlay.querySelector('.piotnet-popup-close').addEventListener('click', () => overlay.remove()); overlay.querySelector('.piotnet-popup-close-btn').addEventListener('click', () => overlay.remove()); } /* ============================ * RÉINITIALISATION APRÈS ERREUR * ============================ */ function resetAfterError() { debugLog('🔄 Réinitialisation après erreur'); stopMonitoring(); isProcessingPayment = false; isMonitoring = false; document.querySelectorAll('.piotnet-hide-native-error').forEach(el => { el.classList.remove('piotnet-hide-native-error'); debugLog('Message natif réaffiché pour prochaine tentative', el); }); debugLog('✅ Réinitialisation terminée - Prêt pour un nouveau paiement'); } /* ============================ * SURVEILLANCE DES ERREURS ET SUCCÈS * ============================ */ function stopMonitoring() { debugLog('Arrêt de la surveillance'); if (errorCheckInterval) { clearInterval(errorCheckInterval); errorCheckInterval = null; } if (timeoutTimer) { clearTimeout(timeoutTimer); timeoutTimer = null; } isMonitoring = false; } function checkForSuccess() { const successSelectors = [ '.elementor-message-success', '.pafe-form-builder-success', '.pafe-success-message', '[data-pafe-form-builder-success]' ]; for (const selector of successSelectors) { const successElement = document.querySelector(selector); if (successElement && isElementVisible(successElement) && successElement.textContent.trim()) { const successMessage = successElement.textContent.trim(); debugLog('✅ Succès détecté', successMessage); const clientData = extractClientData(); const paymentMode = detectPaymentMode(); serverLog('info', 'Paiement réussi - Succès détecté', { selector, message: successMessage, successElementId: successElement.id || 'non-défini', successElementClass: successElement.className || 'non-défini', currentUrl: window.location.href, pageTitle: document.title }, { email: clientData.email || 'non-capturé', customer_name: clientData.customerName || 'non-capturé', paymentMode }); stopMonitoring(); debugLog('Loader maintenu affiché jusqu\'à la redirection'); return true; } } return false; } function checkForErrors() { if (checkForSuccess()) { debugLog('Paiement réussi, arrêt de la surveillance'); return false; } const errorSelectors = [ '.elementor-message-danger', '.pafe-form-builder-error', '.stripe-error', '.card-errors', '[data-pafe-form-builder-error]', '.pafe-error-message' ]; for (const selector of errorSelectors) { const errorElement = document.querySelector(selector); if (errorElement && isElementVisible(errorElement) && errorElement.textContent.trim()) { const errorText = errorElement.textContent.trim(); if (errorText.length < 5) { debugLog('Message d\'erreur trop court, ignoré:', errorText); continue; } debugLog('❌ Erreur détectée (visible)', errorText); const clientData = extractClientData(); const errorType = detectErrorType(errorText); const paymentMode = detectPaymentMode(); serverLog('error', 'Erreur de paiement détectée', { selector, errorMessage: errorText, errorElementId: errorElement.id || 'non-défini', errorElementClass: errorElement.className || 'non-défini', currentUrl: window.location.href, pageTitle: document.title }, { ...clientData, error_type: errorType, error_details: errorText, paymentMode }); errorElement.classList.add('piotnet-hide-native-error'); debugLog('Message natif masqué'); stopMonitoring(); createErrorPopup(errorText); return true; } } const invalidStripeField = document.querySelector('.StripeElement--invalid'); if (invalidStripeField && isElementVisible(invalidStripeField)) { debugLog('Champ Stripe invalide détecté (visible)'); stopMonitoring(); createErrorPopup('Veuillez vérifier les informations de votre carte.'); return true; } return false; } function startSurveillance() { if (isMonitoring) { debugLog('⚠️ Surveillance déjà en cours'); return; } isMonitoring = true; debugLog('Surveillance démarrée (succès + erreurs)'); // ✅ FIX v3.0.0 : Surveillance démarrée IMMÉDIATEMENT avant la popup errorCheckInterval = setInterval(() => { checkForErrors(); }, CONFIG.ERROR_CHECK_INTERVAL); timeoutTimer = setTimeout(() => { if (isMonitoring) { debugLog('⏱️ Timeout atteint'); const clientData = extractClientData(); const paymentMode = detectPaymentMode(); serverLog('warning', 'Timeout de paiement atteint', { maxWaitTime: CONFIG.MAX_WAIT_TIME, currentUrl: window.location.href, pageTitle: document.title }, { email: clientData.email || 'non-capturé', customer_name: clientData.customerName || 'non-capturé', paymentMode, error_type: 'Timeout' }); stopMonitoring(); createErrorPopup('La validation du paiement a pris trop de temps. Veuillez vérifier les informations de votre carte et réessayer.'); } }, CONFIG.MAX_WAIT_TIME); } /* ============================ * DÉTECTION DES CLICS * ============================ */ function setupPaymentClickDetection() { debugLog('Configuration de la détection des clics...'); document.addEventListener('click', function (e) { // ✅ FIX v3.0.0 : Sélecteur élargi pour capturer tous les boutons Piotnet/PAFE const btn = getPaymentButton(e.target); if (!btn) return; debugLog('🎯 Clic détecté sur bouton de paiement', btn); currentTransactionId = 'txn_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); debugLog('🆔 Transaction ID généré:', currentTransactionId); const clientData = extractClientData(); const paymentMode = detectPaymentMode(); const formElement = btn.closest('form'); serverLog('info', 'Clic sur bouton de paiement', { buttonText: btn.textContent.trim(), buttonId: btn.id || 'non-défini', buttonClass: btn.className || 'non-défini', formId: formElement ? (formElement.id || 'non-défini') : 'aucun-formulaire', currentUrl: window.location.href, pageTitle: document.title }, { email: clientData.email || 'non-capturé', customer_name: clientData.customerName || 'non-capturé', paymentMode }); if (isProcessingPayment) { debugLog('⚠️ Paiement déjà en cours, clic ignoré'); return; } // ✅ NOUVEAU v3.0.0 : Détection bloqueur de popup AVANT tout traitement if (isPopupBlocked()) { debugLog('🚫 Bloqueur de popup détecté'); serverLog('warning', 'Popup bloquée - Paiement impossible', { currentUrl: window.location.href, pageTitle: document.title }, { email: clientData.email || 'non-capturé', customer_name: clientData.customerName || 'non-capturé', paymentMode, error_type: 'Popup bloquée' }); createPopupBlockedWarning(); return; // Stopper ici, ne pas lancer le paiement } setTimeout(() => { debugLog('Vérification des conditions...'); if (!isPaymentButtonEnabled(btn)) { debugLog('❌ Bouton désactivé'); return; } if (!areStripeElementsComplete()) { debugLog('❌ Champs Stripe incomplets'); return; } const form = findParentForm(btn); if (form && !isFormValid(form)) { debugLog('❌ Formulaire invalide'); return; } isProcessingPayment = true; debugLog('✅ Lancement du paiement'); const clientData2 = extractClientData(); const paymentMode2 = detectPaymentMode(); serverLog('info', 'Lancement du traitement de paiement', { formValid: true, stripeElementsComplete: true, currentUrl: window.location.href, pageTitle: document.title }, { email: clientData2.email || 'non-capturé', customer_name: clientData2.customerName || 'non-capturé', paymentMode: paymentMode2 }); // ✅ FIX v3.0.0 : Surveillance démarrée AVANT la popup (erreurs rapides capturées) startSurveillance(); createLoadingPopup(); }, CONFIG.LOADING_DELAY); }, true); debugLog('Détection des clics configurée'); } /* ============================ * INITIALISATION * ============================ */ function init() { debugLog('Initialisation...'); addStyles(); setupPaymentClickDetection(); debugLog('✅ Script paiement initialisé v3.0.0'); } init(); if (typeof jQuery !== 'undefined') { jQuery(document).on('pafe_ajax_form_success', function () { debugLog('Événement AJAX détecté, réinitialisation du flag'); isProcessingPayment = false; isMonitoring = false; }); } console.log('[PIOTNET-STRIPE] Script v3.0.0 complètement chargé'); })(); });