Un formulaire de paiement qui fonctionne pour une seule carte réussie n’est pas testé — il est démontré. Les défauts coûteux vivent dans les états autour de ce succès : le paiement refusé puis réessayé deux fois, le client qui a fermé la fenêtre d’authentification à mi-parcours, le remboursement émis contre une commande jamais capturée. Une liste de contrôle pratique pour tester un formulaire de paiement est donc une liste de résultats à atteindre, et non une liste de champs à remplir.
Ce qui suit est la séquence qui trouve le plus de bugs par heure d’effort, avec le raisonnement derrière chaque élément et les préoccupations côté développeur qui décident si les correctifs tiennent.
Commencez par les états, pas par les champs
La plupart des équipes commencent par tester des entrées : un numéro valide, un numéro invalide, une date d’expiration manquante. Cela attrape des problèmes d’interface, et cela vaut la peine d’être fait, mais cela laisse la moitié la plus difficile du système intacte.
L’approche productive consiste à énumérer les états dans lesquels une commande peut se trouver et à confirmer que chacun est atteignable, visible et correct. Les états typiques incluent en attente de paiement, autorisé mais non capturé, capturé, refusé avec option de réessai, refusé définitivement, authentification en attente, authentification échouée, abandonné à mi-parcours, remboursé en totalité, remboursé en partie, et contesté. Écrivez d’abord votre propre liste ; ses lacunes sont généralement là où se trouvent les bugs.
Une fois la liste établie, chaque élément devient une question à réponse testable : comment l’historique des commandes du client rend-il cet état, la vue d’administration est-elle d’accord, et l’export comptable le traite-t-il correctement ?
À quoi devrait ressembler le chemin de refus ?
Un refus n’est pas un événement unique. L’expérience du client dépend du caractère récupérable ou non du refus, et la passerelle vous indique généralement à quelle catégorie il appartient.
Un refus causé par des fonds insuffisants est récupérable : le client peut utiliser une autre carte, et le formulaire devrait conserver tout ce qu’il a déjà saisi, y compris l’adresse et les coordonnées, afin que le réessai coûte quelques secondes plutôt qu’une nouvelle saisie complète. Un refus qui signifie que l’émetteur veut parler au titulaire n’est pas récupérable via votre interface, et dire à l’utilisateur de réessayer lui fait perdre son temps. Une erreur de traitement se situe entre les deux : elle est souvent transitoire, et un réessai est raisonnable.
Testez chacun de ces cas séparément avec une carte qui produit le résultat précis, et vérifiez trois choses pour chacun : le message que voit le client, l’état enregistré dans votre propre base de données, et si le bouton de réessai est même proposé. Un formulaire qui offre un réessai pour un refus définitif génère des tickets d’assistance, et un formulaire qui cache le réessai pour une erreur transitoire perd des ventes.
Avez-vous testé le chemin de réessai ?
Les réessais sont là où les défaillances d’idempotence se révèlent, et ils sont faciles à négliger parce qu’une seule tentative fonctionne parfaitement.
Les scénarios qui valent la peine d’être exécutés sont : le client appuie deux fois de suite sur le bouton payer ; le réseau tombe après l’envoi de la requête mais avant l’arrivée de la réponse ; le client abandonne la page et recommence depuis le panier ; et le paiement est authentifié, échoue à la capture, puis est réessayé avec une autre carte. Dans chaque cas, vérifiez qu’une seule commande existe, qu’un seul débit est tenté, et que l’état montré au client correspond à ce que la passerelle a enregistré.
Le cas de la double soumission est le plus courant et le plus dommageable. Désactiver le bouton après le premier appui ne suffit pas à lui seul, car la seconde requête peut déjà être en vol. Le correctif durable est une clé générée une fois par tentative de paiement et honorée par l’appel de paiement, afin qu’une répétition de la même tentative renvoie le résultat d’origine au lieu d’en créer un second.
Remboursements, annulations et captures partielles
Ces chemins sont fréquemment laissés non testés jusqu’à ce qu’un client en réclame un, ce qui est un mauvais moment pour découvrir une lacune.
Testez un remboursement total et confirmez que l’état de la commande change, que le client est notifié, et que le montant se réconcilie. Testez ensuite un remboursement partiel et vérifiez qu’un second remboursement ultérieur ne dépasse pas le montant d’origine et que l’historique de la commande affiche la somme correctement. Testez une annulation, qui survient lorsqu’une autorisation est libérée avant toute capture, et confirmez que le client voit une annulation plutôt qu’un débit.
Si votre flux prend en charge la capture d’un montant inférieur au montant autorisé — courant dans l’hôtellerie, où la note finale diffère de la pré-autorisation — testez que la libération de la différence est visible quelque part. Le bug dans ce domaine est presque toujours comptable : le paiement a réussi, le client est content, et le rapport de chiffre d’affaires est faux pendant un mois.
La liste de contrôle
Regroupée à peu près dans l’ordre où elle devrait être exécutée :
- Un paiement réussi avec une carte correctement formée de chaque réseau que vous prenez en charge.
- Un paiement refusé pour fonds insuffisants, réessayé avec succès avec une seconde carte.
- Un paiement refusé définitivement, sans réessai proposé et avec une explication claire.
- Une erreur de traitement transitoire, réessayée après un court délai.
- Une double soumission du bouton payer, vérifiée pour détecter des commandes en double.
- Une connexion interrompue après la soumission, vérifiée pour un état récupérable plutôt qu’un orphelin.
- Un paiement abandonné, avec la commande laissée dans un état qu’un humain peut expliquer.
- Une authentification terminée, une authentification échouée, et une authentification abandonnée.
- Une carte au-delà de son mois d’expiration, soumise à la limite, le premier et le dernier jour de validité.
- Un code de sécurité de mauvaise longueur pour le réseau détecté.
- Le remplissage automatique, y compris le navigateur remplissant une carte enregistrée et le client modifiant un champ.
- Un remboursement total, un remboursement partiel et un second remboursement partiel après le premier.
- Une session qui expire pendant que le formulaire est ouvert, soumis malgré tout.
- Une connexion très lente, soumise deux fois avec la seconde arrivant avant la fin de la première.
- Un remplissage du formulaire entier au clavier uniquement, et une passe de lecteur d’écran sur les messages d’erreur.
C’est délibérément plus long que la plupart des listes de contrôle de lancement, car les cinq derniers éléments sont ceux qui atteignent les clients lorsqu’ils sont manqués, et aucun d’eux ne nécessite une infrastructure inhabituelle pour être testé.
Pour les développeurs : matrice d’états et revue d’idempotence
Deux artefacts rendent cela gérable. Le premier est une matrice d’états : des lignes pour chaque état que vous pouvez atteindre, des colonnes pour la vue client, la vue d’administration, l’enregistrement en base de données et la notification envoyée. Les cellules vides sont les défauts. La remplir prend un après-midi et révèle généralement que deux écrans ne sont pas d’accord sur ce que signifie un paiement en attente.
Le second est une revue d’idempotence du point de terminaison de paiement lui-même. Confirmez que la requête porte une clé unique par tentative de paiement plutôt que par tentative au niveau réseau, que la clé est stockée avec la transaction, et qu’une requête répétée avec la même clé renvoie le résultat d’origine au lieu d’exécuter le travail de nouveau. Vérifiez aussi le chemin d’expiration : si votre client cesse d’attendre, le serveur peut encore terminer le débit, et le client ne doit pas se voir montrer un échec pour un paiement qui a réussi.
À côté de cela, examinez la façon dont le formulaire traite les données qu’il ne devrait pas conserver. Les numéros de carte qui atteignent vos propres serveurs ont besoin d’être masqués dans chaque affichage, et les codes de sécurité ne doivent pas du tout être écrits dans les journaux — le guide du code de sécurité explique pourquoi cette règle est absolue plutôt qu’une préférence. Les dates d’expiration méritent leurs propres tests de limites, décrits dans le guide de la date d’expiration, car le dernier jour du mois imprimé est une défaillance classique.
Enfin, décidez ce qui se passe lorsqu’un appel de passerelle échoue d’une manière que vous n’aviez pas anticipée. Un flux de paiement a besoin d’une réponse définie pour le cas inconnu, et elle devrait être une réponse qui ne débite pas le client deux fois et ne laisse pas la commande invisible.
Où obtenir des numéros pour la liste de contrôle
Les cartes de cette liste de contrôle se répartissent en deux groupes. Les cas qui nécessitent un résultat de passerelle précis — un refus, un défi d’authentification — exigent les numéros de test que votre prestataire de paiement documente pour son bac à sable, et le guide des cartes de test des prestataires explique comment ces catalogues fonctionnent. Tout le reste, y compris chaque cas où l’étape de paiement est simulée, peut utiliser des données générées.
Le générateur de numéros de carte produit des numéros pour un réseau choisi ou un lot mixte, chacun avec une date d’expiration et un code de sécurité fictif, si bien qu’un jeu de fixtures peut être assemblé en une minute. Chaque valeur est structurellement valide et n’a jamais été émise à un compte, ce qui rend le jeu sûr à conserver dans le dépôt et inutile pour quiconque le trouverait.
Étapes suivantes
Prenez la liste de contrôle ci-dessus, marquez les éléments que vous pouvez déjà démontrer et ceux que vous ne pouvez pas, et traitez le second groupe comme un blocage de lancement plutôt qu’un arriéré. Remplissez ensuite la matrice d’états pour les deux états que vous comprenez le moins, car c’est là que se cachent habituellement les désaccords entre écrans.