IDEMPIERE-1200 Check consistency of IBAN
This commit is contained in:
parent
d5cba25082
commit
b4f0213136
|
@ -21,6 +21,8 @@ import java.util.Properties;
|
|||
|
||||
import org.compiere.util.CCache;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.IBAN;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -134,4 +136,22 @@ public class MBankAccount extends X_C_BankAccount
|
|||
return success;
|
||||
} // afterSave
|
||||
|
||||
protected boolean beforeSave (boolean newRecord)
|
||||
{
|
||||
if (!Util.isEmpty(getIBAN())) {
|
||||
setIBAN(getIBAN().trim().replace(" ", ""));
|
||||
try {
|
||||
if (!IBAN.isCheckDigitValid(getIBAN())) {
|
||||
log.saveError("Error", "IBAN is invalid");
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.saveError("Error", "IBAN is invalid");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // MBankAccount
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
package org.compiere.util;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class IBAN {
|
||||
/**
|
||||
* Determines if the given IBAN is valid based on the check digit.
|
||||
* To validate the checksum:
|
||||
* 1. Check that the total IBAN length is correct as per the country. If not, the IBAN is invalid.
|
||||
* 2. Move the four initial characters to the end of the string.
|
||||
* 3. Replace the letters in the string with digits, expanding the string as necessary, such that A=10, B=11 and Z=35.
|
||||
* 4. Convert the string to an integer and mod-97 the entire number.
|
||||
* If the remainder is 1 you have a valid IBAN number.
|
||||
* @param iban
|
||||
* @return boolean indicating if specific IBAN has a valid check digit
|
||||
*/
|
||||
public static boolean isCheckDigitValid(String iban) {
|
||||
if (null == iban) return false;
|
||||
|
||||
int validIBANLength = getValidIBANLength(iban);
|
||||
if (validIBANLength < 4) return false;
|
||||
if (iban.length() != validIBANLength) return false;
|
||||
|
||||
BigInteger numericIBAN = getNumericIBAN(iban, false);
|
||||
|
||||
int checkDigit = numericIBAN.mod(new BigInteger("97")).intValue();
|
||||
return checkDigit == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Using the IBAN.properties file gets the valid fixed length value for a country code.
|
||||
* Only uses the first 2 characters of the given string.
|
||||
* @param countryCode
|
||||
* @return
|
||||
*/
|
||||
public static int getValidIBANLength(String countryCode) {
|
||||
String code = countryCode.substring(0,2).toUpperCase();
|
||||
String length = ResourceBundle.getBundle(IBAN.class.getCanonicalName()).getString("length."+code);
|
||||
if (length == null) return -1;
|
||||
return Integer.valueOf(length).intValue();
|
||||
}
|
||||
|
||||
private static BigInteger getNumericIBAN(String iban, boolean isCheckDigitAtEnd) {
|
||||
String endCheckDigitIBAN = iban;
|
||||
if (!isCheckDigitAtEnd) {
|
||||
//Move first four characters to end of string to put check digit at end
|
||||
endCheckDigitIBAN = iban.substring(4) + iban.substring(0, 4);
|
||||
}
|
||||
StringBuffer numericIBAN = new StringBuffer();
|
||||
for (int i = 0; i < endCheckDigitIBAN.length(); i++) {
|
||||
if (Character.isDigit(endCheckDigitIBAN.charAt(i))) {
|
||||
numericIBAN.append(endCheckDigitIBAN.charAt(i));
|
||||
} else {
|
||||
numericIBAN.append(10 + getAlphabetPosition(endCheckDigitIBAN.charAt(i)));
|
||||
}
|
||||
}
|
||||
|
||||
return new BigInteger(numericIBAN.toString());
|
||||
}
|
||||
|
||||
private static int getAlphabetPosition(char letter) {
|
||||
return Character.valueOf(Character.toUpperCase(letter)).compareTo(Character.valueOf('A'));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
# IBAN related properties. Includes IBAN lengths for different countries
|
||||
length.AD=24
|
||||
length.AT=20
|
||||
length.BE=16
|
||||
length.BA=20
|
||||
length.BG=22
|
||||
length.CH=21
|
||||
length.CY=28
|
||||
length.CZ=24
|
||||
length.DE=22
|
||||
length.DK=18
|
||||
length.EE=20
|
||||
length.ES=24
|
||||
length.FO=18
|
||||
length.FI=18
|
||||
length.FR=27
|
||||
length.GB=22
|
||||
length.GI=23
|
||||
length.GL=18
|
||||
length.GR=27
|
||||
length.HU=28
|
||||
length.HR=21
|
||||
length.IE=22
|
||||
length.IS=26
|
||||
length.IT=27
|
||||
length.LI=21
|
||||
length.LT=20
|
||||
length.LU=20
|
||||
length.LV=21
|
||||
length.MA=24
|
||||
length.MC=27
|
||||
length.MK=19
|
||||
length.MT=31
|
||||
length.NL=18
|
||||
length.NO=15
|
||||
length.PL=28
|
||||
length.PT=25
|
||||
length.RO=24
|
||||
length.RS=22
|
||||
length.SE=24
|
||||
length.SI=19
|
||||
length.SK=24
|
||||
length.SM=27
|
||||
length.TN=24
|
||||
length.TR=26
|
Loading…
Reference in New Issue