begin process at 2010 02 10 06:23:08
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Maths & Algorithmes

 > CONTRÔLE DE LA CONFORMITÉ D'UN NUMÉRO DE CARTE BANCAIRE (ALGORITHME DE LUHN)

CONTRÔLE DE LA CONFORMITÉ D'UN NUMÉRO DE CARTE BANCAIRE (ALGORITHME DE LUHN)


 Information sur la source

Note :
Aucune note
Catégorie :Maths & Algorithmes Classé sous :carte bancaire, carte bleu, validité, conformité, contole Niveau :Débutant Date de création :13/02/2009 Date de mise à jour :13/02/2009 15:55:32 Vu :6 076

Auteur : Seb33300

Ecrire un message privé
Site perso
Commentaire sur cette source (11)
Ajouter un commentaire et/ou une note

 Description

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

  • <?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;
  • }
  • }
  • ?>
<?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;
		}
	}
?>



 Historique

13 février 2009 15:53:39 :
Ajout des balises <?php ?> pour la colorisation syntaxique.
13 février 2009 15:55:32 :
Fautes d'orthographes

 Sources de la même categorie

Source avec une capture CALCUL DE TVA MARGE AVEC REMISE FOURNISSEUR SPÉCIALE POUR LE... par lcomb
Source avec Zip EVALUER UNE EXPRESSION À PARTIR D'UNE CHAINE DE CARACTÈRE par TheWeasel47
FONCTION EQUATION LÉGÈRE par ff5
Source avec Zip Source avec une capture TRACEUR DE COURBE EN COORDONNÉES CARTÉSIENNES (MAJ) par fredbonmatin
CONVERTIR LES RÉFÉRENCES DE COLONNE EXCEL DE CHIFFRE EN LETT... par computman007

 Sources en rapport avec celle ci

Source avec Zip REGEXP POUR VÉRIFIER LA VALIDITÉ D'UNE ADRESSE MAIL SUIVANT ... par janhsh
TESTER LA VALIDITÉ D'UNE ADRESSE EMAIL SANS ATTENDRE DE RÉPO... par frdtech

Commentaires et avis

Commentaire de fs074995 le 16/02/2009 06:58:10

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

Commentaire de verdy_p le 16/02/2009 08:30:13

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

Commentaire de verdy_p le 16/02/2009 09:02:14

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.

Commentaire de Seb33300 le 16/02/2009 09:15:07

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.

Commentaire de verdy_p le 16/02/2009 20:48:33

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).

Commentaire de Seb33300 le 16/02/2009 20:52:57

Quelle division par 2 et par 10 ?

Commentaire de verdy_p le 17/02/2009 00:29:26

tu as mis « / 2 » et « / 10 » au lieu de « % 2 » et « % 10 » !

Commentaire de Seb33300 le 17/02/2009 09:15:55

Quelle ligne... ?

Plutôt que de dire n'importe quoi tu ferais mieux de lire et tester le code avant de me cracher dessus.

Commentaire de verdy_p le 17/02/2009 10:46:43

Lignes 10 et 18, il faut tout te dire ! Franchement il n'y a pas 10 000 endroits. Quand on ne veut pas regarder...

C'est toi qui ne veux pas lire ton propre texte, et qui "crache". Reconnais que tu t'es trompé (moi-même j'ai aussitôt admis m'être trompé dans le premier jet dans le deuxième code édité un peu trop vite, en omettant deux parenthèses, mais je me suis corrigé; je peux aussi faire des erreurs, mais ton problème est que tu n'admets pas les tiennes).

Ton code est faux car il n'acceptera QUE un numéro entièrement fait de zéros. Pour tous les autres, la division du chiffre par 12 en PH est une division flottante qui retournera un entier un un entier plus un demi, donc différente de zéro (donc le code dans le "if" ne sera pas exécuté) et le chiffre ne sera pas doublé. Tous les chiffres seront donc simplement ajoutés les uns aux autres dans la boucle (aucun ne sera doublé sauf les zéros où c'est sans effet). Dans la dernière ligne la division par 10 est également flottante et divisera la somme des chiffres par 10. Cette division ne sera nulle que si la somme des chiffres est elle-même nulle. De fait ton code ne retourne 0 (OK) que si la somme des chiffres (produite par la boucle) est nulle, donc si tous les chiffres sont nuls. CQFD.

Ton code est donc inutilisable car tu as confondu la division "/" avec le modulo "%" demandé dans les deux lignes: c'est bien un modulo qu'il faut utiliser pour tester la parité (on peut aussi utiliser "x & 1" au lieu de "x % 2"), et pour tester si la somme est un multiple de 10; la division est hors de propos.

Commentaire de verdy_p le 17/02/2009 10:59:16

Excuse moi Seb, mais tu te trompes d'interlocuteur (et je me trompe aussi): mes commentaires postés ici ne concernais QUE le code de la réponse donnée par FS074995: c'est ce code qui est faux, et c'est LUI (enfin plutôt son code) que j'ai critiqué, pas toi. D'ailleurs je l'avais indiqué très explicitement dans ma première réponse à ce sujet en le nommant dans le deuxième mot. Mes corrections concernaient SON code, pas le tien qui est correct (même s'il est un peu lourd et n'explote pas complètement la syntaxe PHP et contient plusieurs RETURN).

Dans la correction que j'ai postée, je ne teste pas la longueur (16) car je ne suppose pas que l'algo est réservé aux numéros de cartes bancaires (à ce sujet, il y a des numéros de carte à 13 ou 15 chiffres, et même des cartes de crédit à 20 chiffres...), mais il fonctionne aussi pour certains numéros de comptes bancaires (mais pas les RIB français qui utilisent une somme modulo 97, des chiffres groupés par 6 depuis la gauche, la clé RIB à deux chiffres étant entre 01 et 97 où 97 remplace 00 dans les clés réelles, ce qui ne change rien au modulo 97, ni les numéros IBAN qui utilisent un algorithme modifié là aussi pour accepter les lettres).

Commentaire de verdy_p le 17/02/2009 11:11:21

Concernant les longueurs de numéros, on a aussi 17 chiffres (6 pour l'émetteur, plus 10 pour le numéro de carte, plus 1 pour la clé) dans les cartes S'Miles par exemple.

Pour les cartes de crédit revolving comme Aurore, on a un autre format à 19 chiffres (6 pour l'émetteur, plus 10 pour le numéro de compte carte, plus 3 pour l'index de la carte et la clé); je n'ai pas vérifié si l'algo de Luhn était utilisé pour ces cartes et il est probable qu'il y a d'autres sommes de contrôle cachées dans certaines composantes, comme c'est aussi le cas pour les numéros de compte bancaire

Pour les cartes CB émises par certaines banques on a le même problème car 16 chiffres sont insuffisants pour éviter l'utilisation abusive ou accidentelle de codes existants: c'est la raison pour laquelle les numéros de carte à 16 chiffres ont maintenant une extension à 3 ou 4 chiffres imprimé derrière la carte dans la zone de signature, un autre numéro de contrôle de validité destiné à renforcer le code de Luhn et à vérifier la période de validité d'une carte émise quand il y en aura plusieurs pour le même compte).

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Validité cookie ou pas pour visiteur [ par must ] Bonjour,voila veux faire un compteur de visites,mais qu'il ne s'increment pas 40 fois si on viens sur la page souhaitéeKe veux me servir d'un cookie,m regex : validité d'une url absolue ou relative [ par Totofweb ] SalutJe fais mon module de bbcode, et je dois remplacer [lien=monurl.php] ou [lien=http://www.monurl.com/index.php?id=4] par &lt;a href="[l'url qui a test de validité de session [ par joduak ] Pour tester si ma session est toujours valable je fais: &nbsp;&nbsp;&nbsp; if(!isset ($_SESSION())) { &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; echo "pl Test Validité URL [ par blat ] Bonjour, Je cherche comment tester la validité d'une URL. Par là j'entend tester si le fichier vers lequel l'url pointe existe toujours sur le serveu verification de la validité de l'image uploadé !! [ par Fildomen ] Salut !!!Est ce qu'il ya un moyen ( un script sur le net :-D) , qui permet de savoir si un fichier upload&#233; est bien une image valide !!! pcke je Verifier la validité d'une heure [ par gg79 ] Bonjour je suis assez novice en php et je voudrais savoir s'il existe une fonction qui permet de tester la validiter d'un time (genre chekdate mais po Vérifier validité liste mail *.txt [ par Tit0x ] Bonjour,J'ai une liste de contact dans un fichier *.txt et j'aimerais tester leur validitée mais je ne sais pas comment m'y prendre =/     Si quelqu'u verifier la validité d'un nom de domaine en php [ par monster_garage ] bonjourje developpe un site d'hebergement, et j'i besoin d'un script qui verfie la disponibilté d'un nom de domaine.comment faire ceci en php;merci bc Validité... [ par xeroxiss ] Bonsoir,Je suis façe a un petit problème au niveau d'une insertion de date et de validation dans une base de donnée... Mon but est de créer une annonc test validité plusieurs adresse mails [ par younes371 ] Bonjour, Je veux envoyer des emails à plusieurs utilisateurs avec verification d'adresses mails ... J'ai ce script qui verifie la validite d'une adr


Nos sponsors


Sondage...

Comparez les prix


HTC Magic

Entre 429€ et 429€

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,624 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales