La formule de Lhun permet de vérifier un numéro de carte bleue, un siret, un siren, … tellement utile pour les contrôles de formulaire que je me suis penché sur la question ne trouvant rien de probant sur Internet.
La partie front :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="luhn.aspx.cs" Inherits="luhn" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> </head> <body> <span id="spanResult" runat="server"></span> <form> Numéro à vérifier : <input type="text" name="numberToVerify" value="<%=numberToVerify %>" /> <input type="submit" name="mem" value="vérifier" /> </form> </body> </html> |
Juste un formulaire pour envoyer le chiffre, rien de bien palpitant 🙂
La partie programmée :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Text; using System.Text.RegularExpressions; public partial class luhn : System.Web.UI.Page { public string numberToVerify = ""; public int ttlAddition = 0, cpt = 1; public StringBuilder sb = new StringBuilder(); protected void Page_Load(object sender, EventArgs e) { numberToVerify = Request["numberToVerify"] ?? ""; if (numberToVerify != "") { string formatInput = Regex.Replace(numberToVerify, "[^a-zA-Z0-9_]+", "", RegexOptions.Compiled); string reverseCard = new string(formatInput.ToCharArray().Reverse().ToArray()); int[] arrDigits = Array.ConvertAll<string, int>( System.Text.RegularExpressions.Regex.Split(reverseCard.ToString(), @"(?!^)(?!$)"), str => int.Parse(str) ); int[] arrMult = new int[arrDigits.Length]; // première étape de Luhn : On démarre avec le dernier chiffre (à droite) et on se déplace vers la gauche, en doublant la valeur de tous les chiffres de rang pair for (int i = 0; i < arrDigits.Length; i++) { if (cpt == 1) arrMult[i] = arrDigits[i]; // la clé est traitée en 1er, le chiffre n'est pas doublé else { if (cpt % 2 == 0) arrMult[i] = 2 * arrDigits[i]; else arrMult[i] = arrDigits[i]; } cpt++; } // On additionne ensemble tous les chiffres de chaque nombre ainsi obtenu, si chiffre > 10 alors chiffre à additionner donne par ex : 18 = 1 + 8 for (int i = 0; i < arrMult.Length; i++) { if ((int)arrMult[i] >= 10) // si chiffre > 9 il faut re décomposer le chiffre, ex 18 donne : 1+8 { int[] intList = Array.ConvertAll<string, int>( System.Text.RegularExpressions.Regex.Split(arrMult[i].ToString(), @"(?!^)(?!$)"), str => int.Parse(str) ); for (int j = 0; j < intList.Count(); j++) { ttlAddition += (int)intList[j]; } } else ttlAddition += (int)arrMult[i]; } // si modulo par 10 de l'addition est nul alors notre chiffre est valide if (ttlAddition % 10 == 0) spanResult.InnerHtml = "Vérification OK"; else spanResult.InnerHtml = "Vérification Fausse"; } } } |
Quelques remarques :
- Bien penser à ajouter le using regularExpressions qui permet de simplifier grandement les choses avec le Regex. Entre autre je m’en sers pour convertir un string en array de chiffres à 1 digit > « 123 » => [1][2][3], pas trouvé mieux pour la méthode !
- J’ai coupé le traitement en deux parties que vous visualisiez bien le fonctionnement, cela peut bien entendu être simplifié mais en cas de souci ça permet de vérifier les deux tableaux, le premier avec les digits, le deuxième avec les multiples de deux pour les colonnes impaires sauf pour la première colonne.
- Par rapport à Wikipedia, il existe un cas particulier par rapport au SIRET de la poste que je n’ai pas traité dans ce cas ! Je verrai avec le temps si j’en ai besoin …
Quelques liens utiles :
https://fr.wikipedia.org/wiki/Formule_de_Luhn
https://portal.hardis-group.com/pages/viewpage.action?pageId=120357227