


Inscrivez-vous avec PayPal Tutorial (2/3): Un vrai registre avec PayPal Project
Feb 23, 2025 am 09:34 AM
Les plats clés
- Le tutoriel couvre le processus de création d'un compte PayPal et de l'intégrer avec un formulaire d'enregistrement et une base de données pour un vrai projet.
- Le projet consiste à créer un formulaire d'inscription, à rediriger les utilisateurs vers PayPal pour le paiement et à mettre en ?uvre PayPal IPN comme plan de sauvegarde au cas où les utilisateurs ferment leur navigateur.
- Le tutoriel fournit des instructions détaillées sur la configuration de la structure de la base de données et de l'interface utilisateur, de la création d'un bouton PayPal, de la configuration d'un compte Sandbox PayPal et du codage des gestionnaires PDT et IPN.
- Le tutoriel répond également aux questions fréquemment posées sur l'inscription à PayPal, notamment en garantissant la sécurité du compte, en s'inscrivant sans carte de crédit, en avantages sociaux d'un compte d'entreprise et en s'inscrivant à l'extérieur des états-Unis.
Chapitre deux
Ce chapitre présente un vrai projet: ?Enregistrement avec paiement?, du début à la fin, pour mieux expliquer la configuration et l'intégration du compte PayPal avec le formulaire de registre et la base de données.Scénario de projet
- Tout d'abord, nous avons un formulaire d'inscription.
- Après avoir rempli correctement le formulaire (toutes les validations passées), l'utilisateur clique sur le bouton ?Enregistrer?.
- puis rediriger vers PayPal, les utilisateurs paient les frais d'inscription.
- Après payé, PayPal redirigera vers la page des résultats, et 10 secondes de redirection automatique vers notre site Web, puis PayPal PDT traitera le dossier de paiement.
- Mais, l'utilisateur peut fermer le navigateur, nous devons donc implémenter PayPal IPN pour le plan de sauvegarde.
Structure de la base de données
Diagramme E-R:

- Temp_register Tableau: Compte d'utilisateur temporaire Store et mot de passe utilisateur, attendez le paiement. Si payé, le tuple sera supprimé et passera à la table des utilisateurs.
- Tableau de paiement: UID est une clé étrangère faisant référence aux utilisateurs, pour connecter les informations des utilisateurs et les informations de paiement.
- Tableau des utilisateurs: stocker les informations des utilisateurs, le jeton est un jeton de vérification dans l'e-mail de confirmation. Si l'utilisateur vérifie son compte utilisateur, vérifié sera défini comme 1.
Schéma de base de données:
<span>CREATE TABLE IF NOT EXISTS <span>`payment`</span> ( </span><span><span>`payId`</span> int(11) NOT NULL AUTO_INCREMENT, </span><span><span>`timestamp`</span> bigint(20) DEFAULT NULL, </span><span><span>`paid`</span> float DEFAULT NULL COMMENT 'user paid amount returned by paypal', </span><span><span>`bankFee`</span> float DEFAULT NULL, </span><span><span>`currency`</span> varchar(4) DEFAULT NULL, </span><span><span>`txnId`</span> varchar(32) DEFAULT NULL COMMENT 'Transaction ID: specify single unique transaction from paypal. if this field is NOT NULL, means this payment has been process already. So if IPN returns to PHP, we can refuse to update our database.', </span><span><span>`status`</span> varchar(16) DEFAULT NULL, </span><span><span>`uid`</span> int(11) DEFAULT NULL COMMENT 'FK to users PK', </span><span>PRIMARY KEY (<span>`payId`</span>), </span><span>KEY <span>`uid`</span> (<span>`uid`</span>) </span><span>) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; </span><span>CREATE TABLE IF NOT EXISTS <span>`temp_register`</span> ( </span><span><span>`tRegId`</span> int(11) NOT NULL AUTO_INCREMENT, </span><span><span>`fullName`</span> varchar(255) DEFAULT NULL, </span><span><span>`uAcc`</span> varchar(255) DEFAULT NULL, </span><span><span>`uPwd`</span> varchar(32) DEFAULT NULL, </span><span>PRIMARY KEY (<span>`tRegId`</span>) </span><span>) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='prevent unpaid user take uAcc(UNIQUE) in our users table' AUTO_INCREMENT=1 ; </span><span>CREATE TABLE IF NOT EXISTS <span>`users`</span> ( </span><span><span>`uid`</span> int(11) NOT NULL AUTO_INCREMENT, </span><span><span>`fullName`</span> varchar(255) DEFAULT NULL, </span><span><span>`uAcc`</span> varchar(255) NOT NULL, </span><span><span>`uPwd`</span> varchar(32) NOT NULL, </span><span><span>`token`</span> varchar(32) DEFAULT NULL, </span><span><span>`verified`</span> tinyint(1) NOT NULL DEFAULT '0', </span><span><span>`priviledge`</span> enum('delegate','admin','developer') NOT NULL DEFAULT 'delegate', </span><span>PRIMARY KEY (<span>`uid`</span>) </span><span>) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; </span><span>ALTER TABLE <span>`payment`</span> </span><span>ADD CONSTRAINT <span>`payment_ibfk_1`</span> FOREIGN KEY (<span>`uid`</span>) REFERENCES <span>`users`</span> (<span>`uid`</span>);</span>
Interface utilisateur

Projet Workflow
- Remplissez le formulaire et toutes les entrées sont validées.
- Cliquez sur le bouton Enregistrer, redirigez vers PayPal.
- Paypal Sandbox ?Pay maintenant?:
- Rediriger la page de résultat PayPal.
- attendre la redirection (PDT Works) Afficher la page Success / Fail ou fermer le navigateur (IPN Works).
Configuration de la bac à sable PayPal
Avant de commencer à coder, nous devons d'abord configurer le compte PayPal Sandbox. Supposons que vous ayez enregistré un compte de développeur PayPal et que vous avez créé un compte d'utilisateur commercial et un compte d'acheteur dans Sandbox.


1. Activer PDT et paramètres
Configurez votre fonction PDT Handler Fonction Calling URL.
2. Activer l'IPN et les paramètres
Configurez votre fonction d'appel IPN Fonction d'appel URL.
2. Créez un bouton PayPal et des paramètres de paramètres PayPal


<span>CREATE TABLE IF NOT EXISTS <span>`payment`</span> ( </span><span><span>`payId`</span> int(11) NOT NULL AUTO_INCREMENT, </span><span><span>`timestamp`</span> bigint(20) DEFAULT NULL, </span><span><span>`paid`</span> float DEFAULT NULL COMMENT 'user paid amount returned by paypal', </span><span><span>`bankFee`</span> float DEFAULT NULL, </span><span><span>`currency`</span> varchar(4) DEFAULT NULL, </span><span><span>`txnId`</span> varchar(32) DEFAULT NULL COMMENT 'Transaction ID: specify single unique transaction from paypal. if this field is NOT NULL, means this payment has been process already. So if IPN returns to PHP, we can refuse to update our database.', </span><span><span>`status`</span> varchar(16) DEFAULT NULL, </span><span><span>`uid`</span> int(11) DEFAULT NULL COMMENT 'FK to users PK', </span><span>PRIMARY KEY (<span>`payId`</span>), </span><span>KEY <span>`uid`</span> (<span>`uid`</span>) </span><span>) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; </span><span>CREATE TABLE IF NOT EXISTS <span>`temp_register`</span> ( </span><span><span>`tRegId`</span> int(11) NOT NULL AUTO_INCREMENT, </span><span><span>`fullName`</span> varchar(255) DEFAULT NULL, </span><span><span>`uAcc`</span> varchar(255) DEFAULT NULL, </span><span><span>`uPwd`</span> varchar(32) DEFAULT NULL, </span><span>PRIMARY KEY (<span>`tRegId`</span>) </span><span>) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='prevent unpaid user take uAcc(UNIQUE) in our users table' AUTO_INCREMENT=1 ; </span><span>CREATE TABLE IF NOT EXISTS <span>`users`</span> ( </span><span><span>`uid`</span> int(11) NOT NULL AUTO_INCREMENT, </span><span><span>`fullName`</span> varchar(255) DEFAULT NULL, </span><span><span>`uAcc`</span> varchar(255) NOT NULL, </span><span><span>`uPwd`</span> varchar(32) NOT NULL, </span><span><span>`token`</span> varchar(32) DEFAULT NULL, </span><span><span>`verified`</span> tinyint(1) NOT NULL DEFAULT '0', </span><span><span>`priviledge`</span> enum('delegate','admin','developer') NOT NULL DEFAULT 'delegate', </span><span>PRIMARY KEY (<span>`uid`</span>) </span><span>) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; </span><span>ALTER TABLE <span>`payment`</span> </span><span>ADD CONSTRAINT <span>`payment_ibfk_1`</span> FOREIGN KEY (<span>`uid`</span>) REFERENCES <span>`users`</span> (<span>`uid`</span>);</span>Il est facile de découvrir que le bouton est en fait un formulaire, nous devons donc publier des données à l'aide de ses entrées. Lorsque nous générons notre bouton ?Enregistrer?, l'URL de redirection doit contenir ?& cmd = _s-xclick? et ?& hosted_button_id = ha9dzbckxkcl2?. Maintenant, le compte Sandbox PayPal a été configuré. Commencez ensuite à coder vos gestionnaires PDT et IPN.
Fonction du gestionnaire PDT
Code source:
Explication:
Fonction PayPal Call Pdthandler (), puis ce processus de fonction de gestionnaire _pdt (). Comme vous le voyez, il re?oit des paramètres fournis par PayPal, de l'URL ($ _get). Nous publions donc des jetons et du TX à PayPal, via FSOCK SSL. Ensuite, PayPal renverra le dossier de paiement et le résultat de paiement (succès / échec). _Pdt () transmet ces données à _validatePayPal () qui enregistre les données dans la base de données. Ensuite, la page redirige en fonction du retour.Fonction de gestionnaire IPN
Code source:
<span>/** </span><span>* PAYPAL: PDT HANDLER: </span><span>* ==================== </span><span>* called by PayPal, send tokens back </span><span>* get payment details and payment result </span><span>* <span>@return $ret array contains result true/false, and user account or error message </span></span><span>*/ </span><span>private function _PDT() </span><span>{ </span><span>// some indexes can not be missing: </span><span>$ruler = array( </span><span>'tx', // token from paypal </span><span>); </span><span>if(count(array_diff($ruler, array_keys($_GET)))) </span><span>{ </span><span>return array('result' => false, 'error' => 'Index missing ... ', 'index' => $_GET, 'missing' => array_diff($ruler, array_keys($_GET))); </span><span>} </span><span>// read the post from PayPal system and add 'cmd' </span><span>$req = 'cmd=_notify-synch'; </span><span>// get token and prepare request url (send back to paypal) </span><span>$tx_token = $_GET['tx'];$auth_token = "_PJaHiwRfwMmWzW-9nuPuSguYxC-1d9KpxaasaNANtIvyOcmqY6jXNkRmxW"; </span><span>// $auth_token = "OxDenzKmrWPyEXU0YzIg2zs-VAe7ufCADyjbfxF_RpREL4rLEslZrSa21R4"; </span> <span>$req .= "&tx=<span><span>$tx_token</span>&at=<span>$auth_token</span>"</span>; </span> <span>// post back to PayPal system to validate </span> <span>$header = "POST /cgi-bin/webscr HTTP/1.0rn"; </span> <span>$header .= "Host: www.sandbox.paypal.comrn"; </span><span>// $header .= "Host: www.paypal.comrn"; </span> <span>$header .= "Content-Type: application/x-www-form-urlencodedrn"; </span><span>$header .= "Content-Length: " . strlen($req) . "rnrn"; </span> <span>$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30); // open socket </span><span>// $fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30); // open socket </span> <span>if (!$fp) </span><span>{ </span><span>// HTML FAIL </span><span>return array('result' => false, 'error' => 'HTTP error ... '); </span><span>} </span><span>else </span><span>{ </span><span>fputs ($fp, $header . $req); </span><span>// read the body data </span><span>$res = ''; </span><span>$headerdone = false; </span><span>while (!feof($fp)) </span><span>{ </span><span>$line = fgets ($fp, 1024); </span><span>if (strcmp($line, "rn") == 0) </span><span>{ </span><span>$headerdone = true; // read the header </span><span>} </span><span>else if ($headerdone) </span><span>{ </span><span>$res .= $line; // header has been read. now read the contents </span><span>} </span><span>} </span> <span>// parse the data </span><span>$lines = explode("n", $res); </span><span>$keyarray = array(); </span><span>if (strcmp ($lines[0], "SUCCESS") == 0) </span><span>{ </span><span>for ($i=1; $i_validatePaypal($keyarray); </span><span>} </span><span>// log for manual investigation </span><span>else if (strcmp ($lines[0], "FAIL") == 0) </span><span>{ </span><span>// skipped </span><span>return array('result' => false, 'error' => 'Transaction failed ... '); </span><span>} </span><span>} </span><span>fclose ($fp); </span><span>return $ret; </span><span>}</span>
Explication:
PayPal Call ipnHandler () Fonction, puis ce processus de fonction de gestionnaire _ ipn (). Comme vous le voyez, il re?oit les données fournies par PayPal, de la demande ($ _POST). Nous publions donc les détails de paiement à PayPal, via Curl, c'est le processus de poignée de main. Puis PayPal renvoie le résultat de paiement (vérifié / non valide). S'il est vérifié, _ipn () transmet ces données à _validatePayPal () qui enregistre les données dans la base de données.Dans le fichier zip, il contient des modèles, des fichiers JavaScript, CSS, Bootstrap, JQuery, Debug Plugin et Smarty Plugin, et tout le code source PHP de base.
Télécharger le projet (344KB)Les questions fréquemment posées sur l'inscription à PayPal
Comment puis-je m'assurer que mon compte PayPal est sécurisé lors de l'inscription?
La sécurité est une priorité absolue lors de la mise en place d'un compte PayPal. Pour vous assurer que votre compte est sécurisé, utilisez un mot de passe solide et unique qui comprend un mélange de lettres, de chiffres et de caractères spéciaux. Assurez-vous également de fournir des informations personnelles précises lors de l'inscription. PayPal utilise ces informations pour vérifier votre identité et protéger votre compte contre les activités frauduleuses.
Puis-je m'inscrire à un compte PayPal sans carte de crédit?
Oui, vous pouvez vous inscrire à un compte PayPal sans une carte de crédit. Pendant le processus d'inscription, vous pouvez choisir de relier un compte bancaire au lieu d'une carte de crédit. Cependant, la liaison d'une carte de crédit peut fournir des options de paiement et des fonctionnalités de sécurité supplémentaires.
Quels sont les avantages de l'inscription à un compte commercial PayPal sur un compte personnel?
Un compte commercial PayPal offre plusieurs avantages sur un compte personnel. Il s'agit notamment de la possibilité d'accepter les paiements des clients, de l'accès aux prêts commerciaux et des avances de liquidités, et l'option de création et d'envoi de factures. Un compte commercial vous permet également de fonctionner sous un nom d'entreprise ou de groupe.
Comment puis-je m'inscrire à un compte PayPal si je vis en dehors des états-Unis?
PayPal est disponible dans plus de 200 pays et régions du monde. Pour vous inscrire à un compte PayPal en dehors des états-Unis, visitez le site Web de PayPal pour votre pays ou région spécifique. Le processus d'enregistrement est similaire à celui des états-Unis.
Quelles informations dois-je fournir lors de votre inscription à un compte PayPal?
Lors de votre inscription à un compte PayPal, vous devrez fournir Votre nom juridique, votre adresse, votre numéro de téléphone et votre adresse e-mail. Vous devrez également créer un mot de passe et choisir deux questions de sécurité pour aider à protéger votre compte.
Combien de temps faut-il pour s'inscrire à un compte PayPal?
Le processus d'enregistrement pour un compte PayPal est rapide et facile. Il ne faut généralement que quelques minutes. Cependant, il peut prendre quelques jours à PayPal pour vérifier vos informations de compte bancaire ou de carte de crédit.
Puis-je m'inscrire à plus d'un compte PayPal?
Oui, vous pouvez vous inscrire à plus Un compte PayPal. Cependant, chaque compte doit avoir une adresse e-mail unique et des informations financières. Vous pouvez avoir un compte personnel et un compte commercial.
Que se passe-t-il si j'oublie mon mot de passe PayPal lors de l'inscription?
Si vous oubliez votre mot de passe PayPal pendant l'inscription, vous pouvez le réinitialiser en cliquant sur Le ?mot de passe oublié?? lien sur la page de connexion. Vous serez ensuite invité à saisir votre adresse e-mail et PayPal vous enverra un e-mail avec des instructions sur la fa?on de réinitialiser votre mot de passe.
Puis-je modifier les informations que j'ai fournies lors de l'inscription PayPal?
Oui, vous pouvez modifier les informations que vous avez fournies lors de l'inscription PayPal. Pour ce faire, connectez-vous à votre compte PayPal, accédez à votre profil et sélectionnez les informations que vous souhaitez modifier.
Y a-t-il des frais pour s'inscrire à un compte PayPal?
Non, Il n'y a aucun frais pour s'inscrire à un compte PayPal. Cependant, PayPal facture des frais pour certaines transactions, tels que la réception des paiements pour les biens et services ou l'envoi d'argent dans un autre pays.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undress AI Tool
Images de déshabillage gratuites

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
échangez les visages dans n'importe quelle vidéo sans effort grace à notre outil d'échange de visage AI entièrement gratuit?!

Article chaud

Outils chauds

Bloc-notes++7.3.1
éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Il existe trois fa?ons courantes d'initier des demandes HTTP dans Node.js: utilisez des modules intégrés, Axios et Node-Fetch. 1. Utilisez le module HTTP / HTTPS intégré sans dépendances, ce qui convient aux scénarios de base, mais nécessite un traitement manuel de la couture des données et de la surveillance des erreurs, tels que l'utilisation de https.get () pour obtenir des données ou envoyer des demandes de post via .write (); 2.AXIOS est une bibliothèque tierce basée sur la promesse. Il a une syntaxe concise et des fonctions puissantes, prend en charge l'async / attendre, la conversion JSON automatique, l'intercepteur, etc. Il est recommandé de simplifier les opérations de demande asynchrones; 3.Node-Fetch fournit un style similaire à la récupération du navigateur, basé sur la promesse et la syntaxe simple

Les types de données JavaScript sont divisés en types primitifs et types de référence. Les types primitifs incluent la cha?ne, le nombre, le booléen, le nul, un non défini et le symbole. Les valeurs sont immuables et les copies sont copiées lors de l'attribution des valeurs, de sorte qu'elles ne se affectent pas; Les types de référence tels que les objets, les tableaux et les fonctions stockent les adresses de mémoire, et les variables pointant vers le même objet s'afferchent mutuellement. Le typeof et l'instance de OFF peuvent être utilisés pour déterminer les types, mais prêtent attention aux problèmes historiques de typeofnull. Comprendre ces deux types de différences peut aider à écrire un code plus stable et fiable.

Bonjour, développeurs JavaScript! Bienvenue dans JavaScript News de cette semaine! Cette semaine, nous nous concentrerons sur: le différend de marque d'Oracle avec Deno, les nouveaux objets Time JavaScript sont pris en charge par les navigateurs, les mises à jour Google Chrome et certains outils de développeurs puissants. Commen?ons! Le différend de marque d'Oracle avec la tentative de Deno Oracle d'enregistrer une marque "JavaScript" a provoqué la controverse. Ryan Dahl, le créateur de Node.js et Deno, a déposé une pétition pour annuler la marque, et il pense que JavaScript est un niveau ouvert et ne devrait pas être utilisé par Oracle

Cacheapi est un outil fourni par le navigateur pour mettre en cache les demandes de réseau, qui est souvent utilisée en conjonction avec travailleur de service pour améliorer les performances du site Web et l'expérience hors ligne. 1. Il permet aux développeurs de stocker manuellement des ressources telles que des scripts, des feuilles de style, des photos, etc.; 2. Il peut faire correspondre les réponses du cache en fonction des demandes; 3. Il prend en charge la suppression des caches spécifiques ou la nettoyage du cache entier; 4. Il peut mettre en ?uvre des stratégies de priorité de cache ou de priorité de réseau grace à l'écoute des événements Fetch; 5. Il est souvent utilisé pour le support hors ligne, accélérez la vitesse d'accès répétée, préchargement des ressources clés et du contenu de mise à jour des antécédents; 6. Lorsque vous l'utilisez, vous devez faire attention au contr?le de la version du cache, aux restrictions de stockage et à la différence entre le mécanisme de mise en cache HTTP.

La promesse est le mécanisme central pour gérer les opérations asynchrones en JavaScript. Comprendre les appels de cha?ne, la gestion des erreurs et les combinants est la clé pour ma?triser leurs applications. 1. L'appel de la cha?ne renvoie une nouvelle promesse à travers. Puis () pour réaliser la concaténation des processus asynchrones. Chaque .then () re?oit le résultat précédent et peut renvoyer une valeur ou une promesse; 2. La gestion des erreurs doit utiliser .catch () pour attraper des exceptions pour éviter les défaillances silencieuses, et peut renvoyer la valeur par défaut dans Catch pour continuer le processus; 3. Combinateurs tels que promesse.all () (réussi avec succès uniquement après tout succès), promesse.race () (le premier achèvement est retourné) et promesse.allsetTled () (en attente de toutes les achèvements)

Des méthodes intégrées de la matrice JavaScript telles que .map (), .filter () et .reduce () peuvent simplifier le traitement des données; 1) .map () est utilisé pour convertir les éléments un en un pour générer de nouveaux tableaux; 2) .filter () est utilisé pour filtrer les éléments par condition; 3) .reduce () est utilisé pour agréger les données en tant que valeur unique; Une mauvaise utilisation doit être évitée lorsqu'elle est utilisée, entra?nant des effets secondaires ou des problèmes de performance.

La boucle d'événement de JavaScript gère les opérations asynchrones en coordonnant les piles d'appels, les webapis et les files d'attente de taches. 1. La pile d'appels exécute du code synchrone, et lors de la rencontre de taches asynchrones, il est remis à WebAPI pour le traitement; 2. Une fois que le WebAPI a terminé la tache en arrière-plan, il met le rappel dans la file d'attente correspondante (macro tache ou micro tache); 3. La boucle d'événement vérifie si la pile d'appels est vide. S'il est vide, le rappel est retiré de la file d'attente et poussé dans la pile d'appels pour l'exécution; 4. Micro taches (comme Promise. puis) ??prendre la priorité sur les taches macro (telles que Settimeout); 5. Comprendre la boucle d'événements permet d'éviter de bloquer le thread principal et d'optimiser l'ordre d'exécution du code.

Les bulles d'événements se propagent de l'élément cible vers l'extérieur vers le n?ud d'ancêtre, tandis que la capture d'événements se propage de la couche externe vers l'intérieur vers l'élément cible. 1. événements Bubbles: Après avoir cliqué sur l'élément enfant, l'événement déclenche l'auditeur de l'élément parent vers le haut. Par exemple, après avoir cliqué sur le bouton, il sortira d'abord cliqué sur l'enfant, puis parent. 2. Capture d'événement: définissez le troisième paramètre sur true, afin que l'auditeur soit exécuté dans l'étape de capture, tels que le déclenchement de l'écouteur de capture de l'élément parent avant de cliquer sur le bouton. 3. Les utilisations pratiques incluent la gestion unifiée des événements d'éléments enfants, le prétraitement d'interception et l'optimisation des performances. 4. Le flux d'événements DOM est divisé en trois étapes: capture, cible et bulle, et l'écouteur par défaut est exécuté dans l'étape de la bulle.
