Contrôle de la conformité d'un numéro de carte bancaire (algorithme de luhn)

Soyez le premier à donner votre avis sur cette source.

Snippet vu 24 455 fois - Téléchargée 16 fois

Contenu du snippet

Voici une fonction simple qui permet de contrôler la conformité d'un numéro de carte bancaire.

Il suffit de passer en paramètre les 16 chiffres de la carte et la fonction renverra true si le numéro est conforme et false si il n'est pas conforme.

Cette fonction utilise l'algorithme de LUHN pour tester la conformité du numéro.

Attention : Cette fonction ne garantie pas que le numéro de carte bancaire est valide. Un numéro peut être conforme mais pas forcément valide. Seul un établissement bancaire pourra garantir la validité d'un numéro.

Source / Exemple :


<?php
	/**

  • Test la conformité d'un numéro de carte bancaire.
*
  • @param string $num
  • /
function test_cb($num){ if(strlen($num) == 16){ // 16 caractères // Séparation de tous les caractères $c = array(); for($i=0; $i<16; $i++){ if(is_numeric(substr($num,$i,1))){ // Uniquement des chiffres $c[$i] = substr($num,$i,1); }else{ return false; } } // Contrôle $m1 = 0; for($i=0; $i<16; $i++){ if(($i%2)==0){ $x = $c[$i]*2; if($x>9){ $m1 += $x-9; }else{ $m1 += $x; } }else{ $m1 += $c[$i]; } } if(($m1%10)!=0){ // Doit être multiple de 10 return false; } // Pas d'erreur return true; }else{ return false; } } ?>

A voir également

Ajouter un commentaire

Commentaires

fs074995
Messages postés
8
Date d'inscription
jeudi 3 août 2006
Statut
Membre
Dernière intervention
18 février 2009
-
Bonjour
Mais pourquoi faire compliqué si cela peut être simple
origine: wiki alogarithme de luhn

01.//Fonction algorithme de Luhn
02.function isLuhnNum($num){
03. //longueur de la chaine $num
04. $length = strlen($num);
05. //resultat de l'addition de tous les chiffres
06. $tot = 0;
07. for($i=$length-1;$i>=0;$i--)
08. {
09. $digit = substr($num, $i, 1);
10. if ((($length - $i) / 2) == 0){
11. $digit = $digit*2;
12. if ($digit>9){
13. $digit = $digit-9;
14. }
15. }
16. $tot += $digit;
17. }
18. return (($tot / 10) == 0);
19.}

Ceci dit cela peut être utile à beaucoup Merci
verdy_p
Messages postés
203
Date d'inscription
vendredi 27 janvier 2006
Statut
Membre
Dernière intervention
29 janvier 2019
-
Désolé, FS074995, mais ton code est *presque* bon, mais incorrect (tu a mis une division flottante par 2 au lieu d'un modulo 2 entier pour tester la parité de la position du chiffre par rapport à la fin du nombre, ainsi qu'une division flottante par 10 au lieu d'un modulo 10 pour tester la somme finale). Ton résultat sera donc faux.

Voici une version corrigée (qui en plus sait ignorer les séparateurs comme les blancs, points ou tirets et ne tient compte que des chiffres):
//Fonction algorithme de Luhn
function isLuhnNum($num) {
//longueur de la chaine $num
$len = strlen($num);
$pair = true;
$tot = 0;
for ($i = 0; $i < $len; $i++)
if (($digit = substr($num, $len - $i - 1, 1))
>= '0' && $digit <= '9')
$tot += $digit +
( ($pair = ! $pair)
? $digit - (($digit >= 5) ? 9 : 0)
: 0
);
return ($tot % 10) == 0;
}

Note: la variable $pair est nécessaire ci-dessus si on veut filter les non-chiffres dans la chaîne.

En revanche, si la chaîne est assurée de n'avoir plus QUE des chiffres, alors $pair est inutile et il suffit juste de tester ($i & 1) == 0 ci-dessus:

function isLuhnNum($num) {
//longueur de la chaine $num
$len = strlen($num);
$tot = 0;
for ($i = 0; $i < $len; $i++) $tot +($digit substr($num, $len - $i - 1, 1)
+ ( ($i & 1) == 0 ?
? $digit - (($digit >= 5) ? 9 : 0)
: 0;
return ($tot % 10) == 0;
}

L'algo de Luhn complet devrait aussi prendre en compte et accepter les lettres (pour vérifier les numéros de comptes de la banque postale par exemple) : à chaque lettre correspond un chiffre équivalent (pour l'algorithme du LUHN uniquement, mais significatif autrement), fonction de son rang dans l'alphabet:
A=0, B=1, C=2, ..., H=9,
I=0, J=1, K=2, ..., S=9,
T=0, U=1, V=1, ..., Z=4
verdy_p
Messages postés
203
Date d'inscription
vendredi 27 janvier 2006
Statut
Membre
Dernière intervention
29 janvier 2019
-
Note: dans la seconde version, j'ai oublié de coller 2 parenthèses ci-dessus, et en plus j'ai inversé le test de parité: le dernier chiffre n'est pas doublé (c'est l'avant-dernier qui l'est) :
$tot +($digit substr($num, $len - $i - 1, 1))
+ ( ($i & 1) != 0 ?
? $digit - (($digit >= 5) ? 9 : 0)
: 0);

La première version en revanche (qui teste et élimine les séparateurs) était correcte et est plus proche de celle visant à supporter aussi les lettres à convertir en chiffre.
Seb33300
Messages postés
16
Date d'inscription
dimanche 9 avril 2006
Statut
Membre
Dernière intervention
25 janvier 2011
-
En fait au départ je comptais utiliser un 2eme algo de contrôle à la suite pour plus de fiabilité et du coup je voulais bien séparer la vérification de la chaine / contrôle 1 / contrôle 2

Et finalement je n'ai pas mis en place le 2nd contrôle.
verdy_p
Messages postés
203
Date d'inscription
vendredi 27 janvier 2006
Statut
Membre
Dernière intervention
29 janvier 2019
-
Seb, il aurait fallu quand même éviter les deux bogues de la division par 2 et par 10. Pas la peine de poster ici un code tapé en vitesse qui donne un résultat faux et ne décrit pas l'alogo correctement (alors qu'il est documenté correctement partout ailleurs).

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.