Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Couple of updates #2

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 7 additions & 28 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
</licenses>

<properties>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
Expand Down Expand Up @@ -91,12 +91,11 @@
</build>

<dependencies>
<!-- Apache commons-lang -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>com.neovisionaries</groupId>
<artifactId>nv-i18n</artifactId>
<version>1.22</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand All @@ -110,26 +109,6 @@
<type>jar</type>
<scope>test</scope>
</dependency>

<!-- Joda Time - Java date and time API -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.1</version>
</dependency>

<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.1</version>
</dependency>

<!-- Google Guava -->
<dependency>
<groupId>com.google.guava</groupId>
Expand Down
1 change: 0 additions & 1 deletion src/main/java/nl/irp/sepa/BankToCustomerStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import iso.std.iso._20022.tech.xsd.camt_053_001.CashAccount20;
import iso.std.iso._20022.tech.xsd.camt_053_001.CashBalance3;
import iso.std.iso._20022.tech.xsd.camt_053_001.CopyDuplicate1Code;
import iso.std.iso._20022.tech.xsd.camt_053_001.DateTimePeriodDetails;
import iso.std.iso._20022.tech.xsd.camt_053_001.Document;
import iso.std.iso._20022.tech.xsd.camt_053_001.GroupHeader42;
import iso.std.iso._20022.tech.xsd.camt_053_001.Pagination;
Expand Down
61 changes: 36 additions & 25 deletions src/main/java/nl/irp/sepa/IBANUtils.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package nl.irp.sepa;

import java.math.BigInteger;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import com.neovisionaries.i18n.CountryCode;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;

public class IBANUtils {

private static final int IBANNUMBER_MIN_SIZE = 15;
private static final int IBANNUMBER_MAX_SIZE = 34;
private static final BigInteger IBANNUMBER_MAGIC_NUMBER = new BigInteger("97");

/**
* Format the code as a human readable string.
* The IBAN should not contain spaces when transmitted electronically.
Expand All @@ -31,34 +36,40 @@ public static String clean(String iban) {
}

public static boolean validate(String iban) {

// Check ISO 3166-1 country code
final String country = iban.substring(0, 2);
if(!StringUtils.isAlpha(country))
try {
final String country = iban.substring(0, 2);
CountryCode.valueOf(country);
}
catch (IllegalArgumentException e) {
return false;
}

String newAccountNumber = iban.trim();

// Check that the total IBAN length is correct as per the country. If not, the IBAN is invalid. We could also check
// for specific length according to country, but for now we won't
if (newAccountNumber.length() < IBANNUMBER_MIN_SIZE || newAccountNumber.length() > IBANNUMBER_MAX_SIZE) {
return false;
//if (!ISOCountries.getInstance().isValidCode(country)) {
// this.invalidCause = "Invalid ISO country code: "+country;
// return false;
//}

//The basis of the IBAN validation is to convert the IBAN into a number and to perform a basic
//Mod-97 calculation (as described in ISO 7064) on it. If the IBAN is valid, then the remainder
//equals 1. Rule process of IBAN validation is:
//Check that the total IBAN length is correct as per the country. If not, the IBAN is invalid.
//Move the four initial characters to the end of the string.
//Replace each letter in the string with two digits, thereby expanding the string, where A=10, B=11, ..., Z=35.
//Interpret the string as a decimal integer and compute the remainder of that number on division by 97.
/*
final StringBuffer bban = new StringBuffer(code.substring(4));
if (bban.length()==0) {
this.invalidCause="Empty Basic Bank Account Number";
}

// Move the four initial characters to the end of the string.
newAccountNumber = newAccountNumber.substring(4) + newAccountNumber.substring(0, 4);

// Replace each letter in the string with two digits, thereby expanding the string, where A = 10, B = 11, ..., Z = 35.
StringBuilder numericAccountNumber = new StringBuilder();
for (int i = 0; i < newAccountNumber.length(); i++) {
numericAccountNumber.append(Character.getNumericValue(newAccountNumber.charAt(i)));
}

// Interpret the string as a decimal integer and compute the remainder of that number on division by 97.
try {
BigInteger ibanNumber = new BigInteger(numericAccountNumber.toString());
return ibanNumber.mod(IBANNUMBER_MAGIC_NUMBER).intValue() == 1;
}
catch (NumberFormatException e) {
return false;
}
*/

//ISO 7064,
return true;
}

public static String removeNonAlpha(final String iban) {
Expand Down
37 changes: 13 additions & 24 deletions src/main/java/nl/irp/sepa/SEPACreditTransfer.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
package nl.irp.sepa;

import static com.google.common.base.Preconditions.checkArgument;
import static nl.irp.sepa.Utils.*;
import iso.std.iso._20022.tech.xsd.pain_001_001.ChargeBearerType1Code;
import iso.std.iso._20022.tech.xsd.pain_001_001.CreditTransferTransactionInformation10;
import iso.std.iso._20022.tech.xsd.pain_001_001.CustomerCreditTransferInitiationV03;
import iso.std.iso._20022.tech.xsd.pain_001_001.Document;
import iso.std.iso._20022.tech.xsd.pain_001_001.GroupHeader32;
import iso.std.iso._20022.tech.xsd.pain_001_001.LocalInstrument2Choice;
import iso.std.iso._20022.tech.xsd.pain_001_001.ObjectFactory;
import iso.std.iso._20022.tech.xsd.pain_001_001.PaymentIdentification1;
import iso.std.iso._20022.tech.xsd.pain_001_001.PaymentInstructionInformation3;
import iso.std.iso._20022.tech.xsd.pain_001_001.PaymentMethod3Code;
import iso.std.iso._20022.tech.xsd.pain_001_001.PaymentTypeInformation19;
import iso.std.iso._20022.tech.xsd.pain_001_001.ServiceLevel8Choice;

import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.Date;
import java.util.UUID;
import iso.std.iso._20022.tech.xsd.pain_001_001.*;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.datatype.DatatypeConfigurationException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.UUID;

import org.joda.time.LocalDate;
import static com.google.common.base.Preconditions.checkArgument;
import static nl.irp.sepa.Utils.*;

/**
* The Customer SEPA Credit Transfer Initiation message is sent by the initiating party to the debtor bank. It
Expand Down Expand Up @@ -69,7 +57,7 @@ public void write(OutputStream os) throws JAXBException {
* @param name Name of the party that initiates the payment.
* @throws DatatypeConfigurationException
*/
public void buildGroupHeader(String msgId, String name, Date date) {
public void buildGroupHeader(String msgId, String name, LocalDateTime date) {
groupHeader = new GroupHeader32();
// Point to point reference, as assigned by the instructing party, and sent to the next
// party in the chain to unambiguously identify the message.
Expand All @@ -83,7 +71,7 @@ public void buildGroupHeader(String msgId, String name, Date date) {
groupHeader.setMsgId(msgId);

// Date and time at which the message was created.
groupHeader.setCreDtTm( createXMLGregorianCalendar(date));
groupHeader.setCreDtTm( createXMLGregorianCalendarDate(date));

// Number of individual transactions contained in the message.
groupHeader.setNbOfTxs("0");
Expand All @@ -106,9 +94,10 @@ public void buildGroupHeader(String msgId, String name, Date date) {
* included in the credit transfer initiation.
* @param pmtInfId Unique identification, as assigned by a sending party, to unambiguously identify the
* payment information group within the message.
* @param date This is the date on which the debtor's account is to be debited.
* @param reqdExctnDt This is the date on which the debtor's account is to be debited.
* @param debtorNm Party that owes an amount of money to the (ultimate) creditor.
* @param debtorAccountIBAN Unambiguous identification of the account of the debtor to which a debit
* @param financialInstitutionBIC BIC number of the financial institution
* entry will be made as a result of the transaction.
* @return
* @throws DatatypeConfigurationException
Expand Down Expand Up @@ -146,7 +135,7 @@ public Betaalgroep betaalgroep(
paymentInstructionInformation.setPmtTpInf(paymentTypeInformation);

// This is the date on which the debtor's account is to be debited.
paymentInstructionInformation.setReqdExctnDt( createXMLGregorianCalendarDate(reqdExctnDt.toDate()));
paymentInstructionInformation.setReqdExctnDt( Utils.createXMLGregorianCalendarDate(reqdExctnDt));

// Party that owes an amount of money to the (ultimate) creditor.
paymentInstructionInformation.setDbtr( createParty(debtorNm) );
Expand Down
58 changes: 17 additions & 41 deletions src/main/java/nl/irp/sepa/Utils.java
Original file line number Diff line number Diff line change
@@ -1,69 +1,45 @@
package nl.irp.sepa;

import static com.google.common.base.Preconditions.checkArgument;
import iso.std.iso._20022.tech.xsd.pain_001_001.AccountIdentification4Choice;
import iso.std.iso._20022.tech.xsd.pain_001_001.ActiveOrHistoricCurrencyAndAmount;
import iso.std.iso._20022.tech.xsd.pain_001_001.AmountType3Choice;
import iso.std.iso._20022.tech.xsd.pain_001_001.BranchAndFinancialInstitutionIdentification4;
import iso.std.iso._20022.tech.xsd.pain_001_001.CashAccount16;
import iso.std.iso._20022.tech.xsd.pain_001_001.CreditorReferenceInformation2;
import iso.std.iso._20022.tech.xsd.pain_001_001.CreditorReferenceType1Choice;
import iso.std.iso._20022.tech.xsd.pain_001_001.CreditorReferenceType2;
import iso.std.iso._20022.tech.xsd.pain_001_001.DocumentType3Code;
import iso.std.iso._20022.tech.xsd.pain_001_001.FinancialInstitutionIdentification7;
import iso.std.iso._20022.tech.xsd.pain_001_001.PartyIdentification32;
import iso.std.iso._20022.tech.xsd.pain_001_001.RemittanceInformation5;
import iso.std.iso._20022.tech.xsd.pain_001_001.StructuredRemittanceInformation7;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.regex.Pattern;
import iso.std.iso._20022.tech.xsd.pain_001_001.*;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.regex.Pattern;

import static com.google.common.base.Preconditions.checkArgument;

public class Utils {


private static Pattern bicRegex =
Pattern.compile("([a-zA-Z]{4}[a-zA-Z]{2}[a-zA-Z0-9]{2}([a-zA-Z0-9]{3})?)");

public static XMLGregorianCalendar createXMLGregorianCalendar(Date currentDateTime) {
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(currentDateTime);

XMLGregorianCalendar createDate;
public static XMLGregorianCalendar createXMLGregorianCalendarDate(LocalDate currentDateTime) {
try {
createDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(calendar);
createDate.setMillisecond(DatatypeConstants.FIELD_UNDEFINED);
createDate.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
return DatatypeFactory.newInstance().newXMLGregorianCalendarDate(
currentDateTime.getYear(), currentDateTime.getMonthValue(), currentDateTime.getDayOfMonth(),
DatatypeConstants.FIELD_UNDEFINED);
} catch (DatatypeConfigurationException e) {
throw new RuntimeException(e);
}

return createDate;
}

public static XMLGregorianCalendar createXMLGregorianCalendarDate(Date currentDateTime) {
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(currentDateTime);

XMLGregorianCalendar createDate;
public static XMLGregorianCalendar createXMLGregorianCalendarDate(LocalDateTime currentDateTime) {
try {
createDate = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(
calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH)+1, calendar.get(Calendar.DAY_OF_MONTH),
DatatypeConstants.FIELD_UNDEFINED);
return DatatypeFactory.newInstance().newXMLGregorianCalendar(
currentDateTime.getYear(), currentDateTime.getMonthValue(), currentDateTime.getDayOfMonth(),
currentDateTime.getHour(), currentDateTime.getMinute(), currentDateTime.getSecond(), DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED);
} catch (DatatypeConfigurationException e) {
throw new RuntimeException(e);
}

return createDate;
}



/**
* Information supplied to enable the matching of an entry with the items that the
* transfer is intended to settle, such as commercial invoices in an accounts' receivable
Expand Down
15 changes: 7 additions & 8 deletions src/main/java/nl/irp/sepa/sdd/DirectDebitInitiation.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import static nl.irp.sepa.sdd.Utils.createParty;
import static nl.irp.sepa.sdd.Utils.createPaymentIdentification;
import static nl.irp.sepa.sdd.Utils.createRmtInf;
import static nl.irp.sepa.sdd.Utils.createXMLGregorianCalendar;
import static nl.irp.sepa.sdd.Utils.createXMLGregorianCalendarDate;
import iso.std.iso._20022.tech.xsd.pain_008_001.ChargeBearerType1Code;
import iso.std.iso._20022.tech.xsd.pain_008_001.CustomerDirectDebitInitiationV02;
Expand All @@ -28,6 +27,8 @@

import java.io.OutputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.UUID;
Expand All @@ -36,8 +37,6 @@
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.joda.time.LocalDate;


/**
* This document describes the Implementation Guidelines for the XML SEPA Direct Debit Initiation message
Expand All @@ -64,7 +63,7 @@ public DirectDebitInitiation() {
* @param name
* @param date
*/
public void buildGroupHeader(String msgId, String name, Date date) {
public void buildGroupHeader(String msgId, String name, LocalDateTime date) {
groupHeader = new GroupHeader39();

// if no msgId is given create one
Expand All @@ -75,7 +74,7 @@ public void buildGroupHeader(String msgId, String name, Date date) {
groupHeader.setMsgId(msgId);

// Date and time at which the message was created.
groupHeader.setCreDtTm( createXMLGregorianCalendar(date));
groupHeader.setCreDtTm( nl.irp.sepa.Utils.createXMLGregorianCalendarDate(date));

// Number of individual transactions contained in the message.
groupHeader.setNbOfTxs("0");
Expand All @@ -100,7 +99,7 @@ public void write(OutputStream os) throws JAXBException {
}

public PaymentInstruction paymentInstruction(
String pmtInfId, Date reqdColltnDt,
String pmtInfId, LocalDate reqdColltnDt,
String creditor, SequenceType1Code type,
String creditorCountry, List<String> addressLines,
String creditorAccount, String creditorBic) {
Expand All @@ -125,7 +124,7 @@ public class PaymentInstruction {
* collected from the debtor.
*/
public PaymentInstruction(
String pmtInfId, Date reqdColltnDt,
String pmtInfId, LocalDate reqdColltnDt,
String creditor, SequenceType1Code type,
String creditorCountry, List<String> addressLines,
String creditorAccount, String creditorBic) {
Expand Down Expand Up @@ -260,7 +259,7 @@ private DirectDebitTransaction6 t(String mandateId, LocalDate dtOfSgntr, String

MandateRelatedInformation6 mandateInf = new MandateRelatedInformation6();
mandateInf.setMndtId(mandateId);
mandateInf.setDtOfSgntr( createXMLGregorianCalendarDate(dtOfSgntr.toDate()));
mandateInf.setDtOfSgntr(createXMLGregorianCalendarDate(dtOfSgntr));
mandateInf.setAmdmntInd(false);
transaction.setMndtRltdInf(mandateInf);

Expand Down
Loading