Contrôle d'un IBAN

Contrôle d'un IBAN

Maj 31/08/2018

IBANControl est un contrôle Suneido permettant de vérifier et de valider la saisie d’un IBAN (International Bank Account Number) complet et correct.

Préambule

L'IBAN comprend 34 caractères au maximum et a une longueur fixe dans chaque pays, supérieure à 14 caractères : code du pays (2 lettres) + clef de contrôle (2 chiffres de 02 à 98) + Basic Bank Account Number (de 11 à 30 caractères). L'IBAN est vérifié avec un calcul modulo 97 .

Le code de IBANControl

// Copyright (C) 2018 Suneido Software Corp. All rights reserved worldwide.
// Contributed by Jean-Luc Chervais
PatternControl
  {
 Name: "IBAN"
 New(width = 34, mandatory = false)
  {
  super(pattern: .Pattern(),
   width: width,
   mandatory: mandatory,
   status: "IBAN")
  .mandatory = mandatory
  }
 IbanFormats: ('AA## >>>> >>>> >>>', 'AA## >>>> >>>> >>>>',
  'AA## >>>> >>>> >>>> >', 'AA## >>>> >>>> >>>> >>', 'AA## >>>> >>>> >>>> >>>',
  'AA## >>>> >>>> >>>> >>>>', 'AA## >>>> >>>> >>>> >',
  'AA## >>>> >>>> >>>> >>>> >>', 'AA## >>>> >>>> >>>> >>>> >>>',
  'AA## >>>> >>>> >>>> >>>> >>>>', 'AA## >>>> >>>> >>>> >>>> >>>> >',
  'AA## >>>> >>>> >>>> >>>> >>>> >>', 'AA## >>>> >>>> >>>> >>>> >>>> >>>',
  'AA## >>>> >>>> >>>> >>>> >>>> >>>>', 'AA## >>>> >>>> >>>> >>>> >>>> >>>> >',
  'AA## >>>> >>>> >>>> >>>> >>>> >>>> >', 'AA## >>>> >>>> >>>> >>>> >>>> >>>> >>',
  'AA## >>>> >>>> >>>> >>>> >>>> >>>> >>', 'AA## >>>> >>>> >>>> >>>> >>>> >>>> >>>',
  'AA## >>>> >>>> >>>> >>>> >>>> >>>> >>>>',
  'AA## >>>> >>>> >>>> >>>> >>>> >>>> >>>> >',
  'AA## >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>')
 Pattern()
  {
  return .IbanFormats.Join("|")
  }
 Valid?()
  {
  value = .Get()
  if (.mandatory is false and value is '')
   return true
  return super.Valid?() and IBANValid?(value)
  }
 }

Le code de IBANValid?

// Copyright (C) 2018 Suneido Software Corp. All rights reserved worldwide.
// Contributed by Jean-Luc Chervais
function (iban)
  {
 iban = iban.Tr(" ")
 cpcc = (iban[0 .. 4])
 bban = (iban[4 .. 34])
 ibanmod = bban $ cpcc 
   dict = #("0":0, "1":1, "2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8, "9":9
   A:10, B:11, C:12, D:13, E:14, F:15, G:16, H:17, I:18, J:19,
   K:20, L:21, M:22, N:23, O:24, P:25, Q:26, R:27, S:28, T:29,
   U:30, V:31, W:32, X:33, Y:34, Z:35)
 num = ""
 for (i = 0; i <= ibanmod.Size() - 1; ++i)
  {
  num $= dict[ibanmod[i]]
  }
 restepar97 = 0
 for (i = 0; i <= num.Size() - 1; ++i)
  {
 restepar97 = (restepar97 * 10 + Number (num[i])) % 97
  }
 return restepar97 is 1
 }

Le code de IBANValidTest

// Copyright (C) 2018 Suneido Software Corp. All rights reserved worldwide.
// Contributed by Jean-Luc Chervais
Test
  {
 Test_main()
  {
  Assert(IBANValid?('GB87 BARC 2065 8244 9716 55')is true)
  Assert(IBANValid?('FR76 1020 7000 2604 0260 1177 083')is true)
  Assert(IBANValid?('FR76 3000 2069 7100 0007 2002 D05')is false)
  Assert(IBANValid?('BE43 0689 9999 9501')is true)
  }
 }

Explications

IBANControl est un PatternControl avec comme masque de saisie AA## >>>> >>>> >>A représente une lettre majuscule, # un chiffre et > un chiffre ou une lettre majuscule. (On pourrait vérifier aussi que AA soit égal à un code Iso3166CountryCodes et que ## soit >1 et <99).

Les données entrées avec ce masque sont alors vérifiées avec la fonction IBANValid?

IBANValid? est une fonction prenant en paramètre d’entrée un RIB :

function (iban)
  {

On enlève de l'IBAN tous les espaces :

iban = iban.Tr(" ")

On crée une variable avec les 4 premiers caractères (cp comme code pays et cc comme code de contrôle) :

cpcc = (iban[0 .. 4])

On crée une autre variable avec les autres caractères (bban comme Basic Bank Account Number) :

bban = (iban[4 .. 34])

On place ensuite les 4 premiers caractères à la fin pour constituer notre variable ibanmod (iban modifié) :

ibanmod = bban $ cpcc

On crée un dictionnaire nommé dict contenant la correspondance entre chaque caractère possible d'ibanmod avec une valeur numérique :

dict = #("0":0, "1":1, "2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8, "9":9
   A:10, B:11, C:12, D:13, E:14, F:15, G:16, H:17, I:18, J:19,
   K:20, L:21, M:22, N:23, O:24, P:25, Q:26, R:27, S:28, T:29,
   U:30, V:31, W:32, X:33, Y:34, Z:35)

On initialise la variable num :

num = ""

Pour chaque caractère d'ibanmod, ...

 for (i = 0; i <= ibanmod.Size() - 1; ++i)

... on concatène à num la valeur correspondante du caractère traité dans le dictionnaire (par ex : U donne 30) :

{
  num $= dict[ibanmod[i]]
}

L'IBAN est juste si la division du nombre num par 97 donne un reste égal à 1 (modulo) . Mais l’IBAN est un entier trop long pour effectuer le calcul en une seule fois compatible avec un entier 32 bits. Le calcul sera donc effectué chiffre par chiffre, comme pour une division faite à la main.

On initialise la variable restepar97 :

restepar97 = 0

Pour chaque caractère de num, ...

for (i = 0; i <= num.Size() - 1; ++i)

... on utilise le premier chiffre de num que l'on divise par 97 et on garde le reste : % 97 (modulo 97), le reste est ensuite multiplié par 10 et on ajoute le chiffre suivant, et on continue ainsi jusqu'au dernier chiffre :

  {
  restepar97 = (restepar97 * 10 + Number (num[i])) % 97
  }

L'IBAN est juste si le reste (modulo) est égal a 1

return restepar97 is 1
}

Et voilà votre IBAN est validé si (le résultat) return is true ou non si return is false

Et comme d’habitude on met en place un ensemble de tests pour valider le tout :

Test
  {
 Test_main()
  {
  Assert(IBANValid?('GB87 BARC 2065 8244 9716 55')is true)
  Assert(IBANValid?('FR76 1020 7000 2604 0260 1177 083')is true)
  Assert(IBANValid?('FR76 3000 2069 7100 0007 2002 D05')is false)
  Assert(IBANValid?('BE43 0689 9999 9501')is true)
  }
 }

Sources