Ho fatto una revisione del controllo della correttezza del codice IBAN già precedentemente pubblicato sul mio blog.
Il codice è risultato molto più essenziale rispetto al precedente che faceva uso di una funzione di divisione personalizzata per trovare il resto della divisione intera (modulo) tra il valore dell'IBAN, (dividendo) convertito in numerico e il divisore 97.
La classe C# CheckIban
/*
* Copyright Luciano Bastianello lbastianello at aim.com
* Data: 04/04/2008 7.36
* Questo software è liberamente utilizzabile.
* E' ceduto nello stato in cui si trova, non sono responsabile per
* malfunzionamenti o danni arrecati dal suo utilizzo.
* E' vietata la distribuzione del sorgente senza la presente intestazione
* da riprodurre in toto
*/
using System;
using System.Text;
namespace CheckIbanCs
{
/// <summary>
/// Determina il controllo della validità dell'IBAN per italia
/// e San Marino
/// </summary>
public sealed class CheckIban
{
// costanti
private const int MOD_NUM = 97;
private const string STATI = "IT,SM";
private const int L_IBAN = 27;
// membri privati
private static string mIBAN = string.Empty;
// rendiamo privato il costruttore per impedire
// l'istanziazione "privata" della classe
private CheckIban()
{
}
/// <summary>
/// Membro Esposto IBAN
/// </summary>
public static string IBAN
{
get
{
return mIBAN;
}
set
{
mIBAN = value;
}
}
/// <summary>
/// Validazione IBAN
/// </summary>
/// <param name="pIBAN">Codice IBAN da validare</param>
/// <returns>Testo</returns>
public static string ValidateIBAN(string pIBAN)
{
string retValue = string.Empty;
// trasformiamo in maiuscolo il codice depurato degli spazi
string codiceIBAN = pIBAN.Trim().ToUpper();
// se si ottiene una stringa vuota sono dolori! :)
if (codiceIBAN == string.Empty)
return "IBAN vuoto";
// Controllo lunghezza
if (codiceIBAN.Length != L_IBAN)
return string.Format("Verificare lunghezza IBAN dovrebbbe essere {0}",L_IBAN);
// test codice paese
if (!CheckPaese(codiceIBAN.Substring(0,2)))
return "Codice Stato diverso da [IT,SM]";
try
{
// trasformazione in stringa numerica
string codiceNumerico = CalcolaCodiceNumerico(codiceIBAN);
int i;
// applichiamo il modulo 97 su 6 caratteri alla volta
while (codiceNumerico.Length > 6)
{
i = int.Parse(codiceNumerico.Substring(0,6)) % MOD_NUM;
codiceNumerico = i.ToString() + codiceNumerico.Substring(6);
}
// la stringa restante con lunghezza <= 6 può essere
// convertita agevolmente
i = int.Parse(codiceNumerico) % MOD_NUM;
// se il valore modulo 97 non è uno il check digit
// dell'IBAN è errato
if (i != 1)
retValue = "Codice Errato";
else
retValue = "Codice Corretto";
}
catch (Exception ex)
{
retValue = ex.Message;
}
return retValue;
}
/// <summary>
/// Validazione IBAN
/// </summary>
/// <returns>Testo</returns>
public static string ValidateIBAN()
{
return ValidateIBAN(IBAN);
}
/// <summary>
/// Controllo del codice dello Stato
/// </summary>
/// <param name="codicePaese"></param>
/// <returns>Corretto/Errato</returns>
private static bool CheckPaese(string codicePaese)
{
return (STATI.IndexOf(codicePaese) != -1);
}
/// <summary>
/// Generazione stringa numerica a partire dal codice IBAN
/// Secondo le norme vengono spostati in fondo i primi 4
/// caratteri dell'IBAN
/// </summary>
/// <param name="codiceIBAN"></param>
/// <returns></returns>
private static string CalcolaCodiceNumerico(string codiceIBAN)
{
StringBuilder sb = new StringBuilder();
const string lettere = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// per ogni carattere contenuto nella stringa riformattata per il calcolo
// troviamo la posizione relativa nella stringa lettere e
// aggiungiamo il valore ottenuto sull'oggetto stringbuilder
foreach (char c in codiceIBAN.Substring(4) + codiceIBAN.Substring(0,4))
{
int x = lettere.IndexOf(c);
if (x == -1)
throw (new Exception("Caratteri non validi nella stringa"));
sb.Append(x);
}
return sb.ToString();
}
}
}
La classe CheckIban VB.NET
' Copyright Luciano Bastianello lbastianello at aim.com
' Data: 04/04/2008 7.36
' Questo software è liberamente utilizzabile.
' E' ceduto nello stato in cui si trova, non sono responsabile per
' malfunzionamenti o danni arrecati dal suo utilizzo.
' E' vietata la distribuzione del sorgente senza la presente intestazione
' da riprodurre in toto
Imports System.Text
''' <summary>
''' Determina il controllo della validità dell'IBAN per italia
''' e San Marino
''' </summary>
Public NotInheritable Class CheckIban
' costanti
Private Const MOD_NUM As Integer = 97
Private Const STATI As String = "IT,SM"
Private Const L_IBAN As Integer = 27
' membri privati
Private Shared mIBAN As String = String.Empty
' rendiamo privato il costruttore per impedire
' l'istanziazione "privata" della classe
Private Sub New()
End Sub
''' <summary>
''' Membro Esposto IBAN
''' </summary>
Public Shared Property IBAN() As String
Get
Return mIBAN
End Get
Set
mIBAN = value
End Set
End Property
''' <summary>
''' Validazione IBAN
''' </summary>
''' <param name="pIBAN">Codice IBAN da validare</param>
''' <returns>Testo</returns>
Public Shared Function ValidateIBAN(ByVal pIBAN As String) As String
Dim retValue As String = String.Empty
' trasformiamo in maiuscolo il codice depurato degli spazi
Dim codiceIBAN As String = pIBAN.Trim().ToUpper()
' se si ottiene una stringa vuota sono dolori! :)
If codiceIBAN = String.Empty Then
Return "IBAN vuoto"
End If
' Controllo lungehzza
If codiceIBAN.Length <> L_IBAN Then
Return String.Format("Verificare lunghezza IBAN dovrebbbe essere {0}", L_IBAN)
End If
' test codice paese
If Not CheckPaese(codiceIBAN.Substring(0, 2)) Then
Return "Codice Stato diverso da [IT,SM]"
End If
Try
' trasformazione in stringa numerica
Dim codiceNumerico As String = CalcolaCodiceNumerico(codiceIBAN)
Dim i As Integer
' applichiamo il modulo 97 su 6 caratteri alla volta
While codiceNumerico.Length > 6
i = Integer.Parse(codiceNumerico.Substring(0, 6)) Mod MOD_NUM
codiceNumerico = i.ToString() + codiceNumerico.Substring(6)
End While
' la stringa restante con lunghezza <= 6 può essere
' convertita agevolmente
i = Integer.Parse(codiceNumerico) Mod MOD_NUM
' se il valore modulo 97 non è uno il check digit
' dell'IBAN è errato
If i <> 1 Then
retValue = "Codice Errato"
Else
retValue = "Codice Corretto"
End If
Catch ex As Exception
retValue = ex.Message
End Try
Return retValue
End Function
''' <summary>
''' Validazione IBAN
''' </summary>
''' <returns>Testo</returns>
Public Shared Function ValidateIBAN() As String
Return ValidateIBAN(IBAN)
End Function
''' <summary>
''' Controllo del codice dello Stato
''' </summary>
''' <param name="codicePaese"></param>
''' <returns>Corretto/Errato</returns>
Private Shared Function CheckPaese(ByVal codicePaese As String) As Boolean
Return (STATI.IndexOf(codicePaese) <> -1)
End Function
''' <summary>
''' Generazione stringa numerica a partire dal codice IBAN
''' Secondo le norme vengono spostati in fondo i primi 4
''' caratteri dell'IBAN
''' </summary>
''' <param name="codiceIBAN"></param>
''' <returns></returns>
Private Shared Function CalcolaCodiceNumerico(ByVal codiceIBAN As String) As String
Dim sb As New StringBuilder()
Const lettere As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
' per ogni carattere contenuto nella stringa riformattata per il calcolo
' troviamo la posizione relativa nella stringa lettere e
' aggiungiamo il valore ottenuto sull'oggetto stringbuilder
For Each c As Char In codiceIBAN.Substring(4) + codiceIBAN.Substring(0, 4)
Dim x As Integer = lettere.IndexOf(c)
If x = -1 Then
Throw (New Exception("Caratteri non validi nella stringa"))
End If
sb.Append(x)
Next
Return sb.ToString()
End Function
End Class
5 commenti:
Sigh! è purtoppo cannato !!!
prova questo
IT97A010051150000000000076
ti garantisco che è esatto
Ti prego di verificare prima di affermare come vere cose che non lo sono
Il codice che hai portato ad esempio è sbagliato , infatti è lungo 26 caratteri, l'iban italiano prevede 27 caratteri e più precisamente (da destra a sinistra):
12 per il conto corrente
5 cab
5 abi
1 check digit BBAN
2 check digit IBAN
2 codice stato
Se "svolgiamo" il codice con tutta probabilità ad essere sbagliati sono abi/cab/contocorrente, manca un carattere.
La ringrazio per Blog intiresny
Considerato che la "I" di Iban sta per INTERNAZIONALE, mi sembra che il tuo algoritmo sia concettualmente sbagliato visto che da per sbagliato qualunque codice IBAN che non sia italiano o di San Marino... non trovi?
Il codice fa i controlli SOLO per Italia e San Marino (IT,SM) per gli altri paesi è una feature che non ho mai implementato nell'esempio.
A suo tempo mi sono documentato riguardo la codifica e il controllo degli Iban europei e internazionali, non avendo una "base dati" da testare ho desistito in quanto non intendo proporre qualche cosa che non sono in grado di controllare.
Per quanto riguarda gli iban italiani invece partivo da una considerevole mole di dati che mi ha permesso di preparare il progetto e pubblicarlo.
Posta un commento