IDEMPIERE-1200
Validate IBAN in C_BankAccount, C_BP_BankAccount, C_Payment, C_PaymentTransaction Config via IBAN_VALIDATION, Default is Y
This commit is contained in:
parent
b4f0213136
commit
04928f78b8
|
@ -0,0 +1,10 @@
|
|||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
-- IBAN validation IDEMPIERE-1200
|
||||
-- Jan 19, 2017 10:54:38 AM CET
|
||||
INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200086,0,0,TO_DATE('2017-01-19 10:54:37','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2017-01-19 10:54:37','YYYY-MM-DD HH24:MI:SS'),0,0,'Y','IBAN_VALIDATION','Y','Enables the validation of IBAN fields','D','S','1b324142-ae32-4cff-9ea9-792df3e4d142')
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201701191158_IDEMPIERE-1200') FROM dual
|
||||
;
|
|
@ -0,0 +1,7 @@
|
|||
-- IBAN validation IDEMPIERE-1200
|
||||
-- Jan 19, 2017 10:54:38 AM CET
|
||||
INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200086,0,0,TO_TIMESTAMP('2017-01-19 10:54:37','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2017-01-19 10:54:37','YYYY-MM-DD HH24:MI:SS'),0,0,'Y','IBAN_VALIDATION','Y','Enables the validation of IBAN fields','D','S','1b324142-ae32-4cff-9ea9-792df3e4d142')
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201701191158_IDEMPIERE-1200') FROM dual
|
||||
;
|
|
@ -22,6 +22,9 @@ import java.util.Properties;
|
|||
|
||||
import org.adempiere.util.PaymentUtil;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.IBAN;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
/**
|
||||
* BP Bank Account Model
|
||||
|
@ -207,6 +210,17 @@ public class MBPBankAccount extends X_C_BP_BankAccount
|
|||
setCreditCardVV(encrpytedCvv);
|
||||
}
|
||||
|
||||
if (MSysConfig.getBooleanValue(MSysConfig.IBAN_VALIDATION, false,
|
||||
Env.getContextAsInt(Env.getCtx(), "#AD_Client_ID"))) {
|
||||
if (!Util.isEmpty(getIBAN())) {
|
||||
setIBAN(IBAN.normalizeIBAN(getIBAN()));
|
||||
if (!IBAN.isCheckDigitValid(getIBAN())) {
|
||||
log.saveError("Error", "IBAN is invalid");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} // beforeSave
|
||||
|
||||
|
|
|
@ -123,6 +123,29 @@ public class MBankAccount extends X_C_BankAccount
|
|||
return msgreturn.toString();
|
||||
} // getName
|
||||
|
||||
|
||||
/**
|
||||
* Before Save
|
||||
* @param newRecord new record
|
||||
* @return success
|
||||
*/
|
||||
|
||||
protected boolean beforeSave(boolean newRecord) {
|
||||
|
||||
if (MSysConfig.getBooleanValue(MSysConfig.IBAN_VALIDATION, false,
|
||||
Env.getContextAsInt(Env.getCtx(), "#AD_Client_ID"))) {
|
||||
if (!Util.isEmpty(getIBAN())) {
|
||||
setIBAN(IBAN.normalizeIBAN(getIBAN()));
|
||||
if (!IBAN.isCheckDigitValid(getIBAN())) {
|
||||
log.saveError("Error", "IBAN is invalid");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} // beforeSave
|
||||
|
||||
/**
|
||||
* After Save
|
||||
* @param newRecord new record
|
||||
|
@ -135,23 +158,5 @@ public class MBankAccount extends X_C_BankAccount
|
|||
return insert_Accounting("C_BankAccount_Acct", "C_AcctSchema_Default", null);
|
||||
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
|
||||
|
|
|
@ -38,8 +38,10 @@ import org.compiere.process.ProcessInfo;
|
|||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.IBAN;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.Trx;
|
||||
import org.compiere.util.Util;
|
||||
import org.compiere.util.ValueNamePair;
|
||||
|
||||
/**
|
||||
|
@ -796,6 +798,17 @@ public class MPayment extends X_C_Payment
|
|||
}
|
||||
}
|
||||
|
||||
if (MSysConfig.getBooleanValue(MSysConfig.IBAN_VALIDATION, false,
|
||||
Env.getContextAsInt(Env.getCtx(), "#AD_Client_ID"))) {
|
||||
if (!Util.isEmpty(getIBAN())) {
|
||||
setIBAN(IBAN.normalizeIBAN(getIBAN()));
|
||||
if (!IBAN.isCheckDigitValid(getIBAN())) {
|
||||
log.saveError("Error", "IBAN is invalid");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} // beforeSave
|
||||
|
||||
|
|
|
@ -26,8 +26,10 @@ import org.compiere.process.DocAction;
|
|||
import org.compiere.process.ProcessCall;
|
||||
import org.compiere.process.ProcessInfo;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.IBAN;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.Trx;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -81,6 +83,17 @@ public class MPaymentTransaction extends X_C_PaymentTransaction implements Proce
|
|||
setCreditCardVV(encrpytedCvv);
|
||||
}
|
||||
|
||||
if (MSysConfig.getBooleanValue(MSysConfig.IBAN_VALIDATION, false,
|
||||
Env.getContextAsInt(Env.getCtx(), "#AD_Client_ID"))) {
|
||||
if (!Util.isEmpty(getIBAN())) {
|
||||
setIBAN(IBAN.normalizeIBAN(getIBAN()));
|
||||
if (!IBAN.isCheckDigitValid(getIBAN())) {
|
||||
log.saveError("Error", "IBAN is invalid");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ public class MSysConfig extends X_AD_SysConfig
|
|||
public static final String ENABLE_PAYMENTBOX_BUTTON = "ENABLE_PAYMENTBOX_BUTTON";
|
||||
public static final String GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS = "GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS";
|
||||
public static final String HTML_REPORT_THEME = "HTML_REPORT_THEME";
|
||||
public static final String IBAN_VALIDATION = "IBAN_VALIDATION" ;
|
||||
public static final String Invoice_ReverseUseNewNumber = "Invoice_ReverseUseNewNumber";
|
||||
public static final String JASPER_SWAP_MAX_PAGES = "JASPER_SWAP_MAX_PAGES";
|
||||
public static final String LASTRUN_RECORD_COUNT = "LASTRUN_RECORD_COUNT";
|
||||
|
|
|
@ -5,63 +5,87 @@ 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);
|
||||
|
||||
/**
|
||||
* @param iban
|
||||
* @return normalized IBAN
|
||||
*/
|
||||
|
||||
public static String normalizeIBAN(String iban)
|
||||
{
|
||||
if (iban!=null)
|
||||
{
|
||||
return iban.trim().replace(" ", "") ;
|
||||
}
|
||||
return null ;
|
||||
}
|
||||
/**
|
||||
* 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) {
|
||||
try {
|
||||
if (null == iban)
|
||||
return false;
|
||||
int validIBANLength = getValidIBANLength(iban);
|
||||
if (validIBANLength < 4)
|
||||
return false;
|
||||
if (iban.length() != validIBANLength)
|
||||
return 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());
|
||||
}
|
||||
BigInteger numericIBAN = getNumericIBAN(iban, false);
|
||||
|
||||
private static int getAlphabetPosition(char letter) {
|
||||
return Character.valueOf(Character.toUpperCase(letter)).compareTo(Character.valueOf('A'));
|
||||
}
|
||||
int checkDigit = numericIBAN.mod(new BigInteger("97")).intValue();
|
||||
return checkDigit == 1;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue