All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kapott.hbci.swift.DTAUS Maven / Gradle / Ivy

There is a newer version: 4.0.0
Show newest version
/**********************************************************************
 *
 * This file is part of HBCI4Java.
 * Copyright (c) 2001-2008 Stefan Palme
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 **********************************************************************/

package org.kapott.hbci.swift;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.kapott.hbci.datatypes.SyntaxDTAUS;
import org.kapott.hbci.exceptions.HBCI_Exception;
import org.kapott.hbci.exceptions.InvalidArgumentException;
import org.kapott.hbci.exceptions.InvalidUserDataException;
import org.kapott.hbci.manager.HBCIUtils;
import org.kapott.hbci.manager.LogFilter;
import org.kapott.hbci.structures.Konto;
import org.kapott.hbci.structures.Value;

/** 

Hilfsklasse zum Erzeugen von DTAUS-Datensätzen für die Verwendung in Sammelüberweisungen und Sammellastschriften. Diese Klasse kann verwendet werden, um den DTAUS-Datenstrom zu erzeugen, der für Sammellastschriften und -überweisungen als Job-Parameter angegeben werden muss.

In einem DTAUS-Objekt werden ein oder mehrere Transaktionen gespeichert. Dabei müssen alle Transaktionen entweder Lastschriften oder Überweisungen sein. Außerdem wird für alle Transaktionen das gleiche "Auftraggeberkonto" angenommen (bei Überweisungen also das Belastungskonto, bei Lastschriften das Konto, auf das der Betrag gutgeschrieben wird).

In der Regel wird zunächst ein DTAUS-Objekt erzeugt. Dazu wird der Konstruktor {@link #DTAUS(Konto,int)} verwendet, womit gleichzeit das zu verwendende Auftraggeberkonto und der Typ des Sammelauftrages (TYPE_CREDIT für Sammelüberweisungen, TYPE_DEBIT für Sammellastschriften) festgelegt wird. Anschließend können beliebig viele {@link DTAUS.Transaction}-Objekte erzeugt werden, welche jeweils eine Transaktion darstellen. Jedes so erzeugte Objekt kann mit {@link #addEntry(DTAUS.Transaction)} zum Sammelauftrag hinzugefügt werden. Die Methode {@link #toString()} liefert schließlich den so erzeugten Sammelauftrag im DTAUS-Format.

*/ // TODO: API ändern (Setter/Getter), damit wir sauber die LogFilter für // kritische Daten setzen können public class DTAUS { /** Daten einer einzelnen Transaktion, die in einen Sammelauftrag übernommen werden soll. Vor dem Hinzufügen dieser Transaktion zum Sammelauftrag müssen alle Felder dieses Transaktions-Objektes mit den jeweiligen Auftragsdaten gefüllt werden. */ public class Transaction { /**

Konto des Zahlungsempfängers bzw. des Zahlungspflichtigen. Soll dieser Einzelauftrag in eine Sammelüberweisung eingestellt werden, so muss in diesem Feld die Kontoverbindung des Zahlungsempfängers eingestellt werden. Bei Sammellastschriften ist hier die Kontoverbindung des Zahlungspflichtigen einzustellen.

Von dem verwendeten {@link Konto}-Objekt müssen mindestens die Felder blz, number und name richtig belegt sein.

*/ public Konto otherAccount; /** interne Kunden-ID. Wie die verwendet wird weiß ich leider nicht genau, kann im Prinzip leer gelassen werden (ansonsten Maximallänge 11 Zeichen). */ public String internalCustomerId; /** Textschlüssel für den Auftrag. Bei Sammelüberweisungen ist dieses Feld mit '51' vorbelegt, bei Sammellastschriften mit '05'. Dieser Wert kann überschrieben werden, gültige Werte finden sich in den Job-Restrictions (siehe {@link org.kapott.hbci.GV.HBCIJob#getJobRestrictions()}). */ public String key; /** Zusätzlicher Textschlüssel (wird i.d.R. bankintern verwendet). Dieser Wert muss aus drei Ziffern bestehen und ist mit '000' vorbelegt. Das manuelle Setzen dieses Wertes ist in den meisten Fällen nicht nötig (außer für Leute, die wissen was sie tun ;-) ). */ public String addkey; /** Geldbetrag, der bei diesem Einzelauftrag überwiesen (Sammelüberweisungen) bzw. eingezogen (Sammellastschriften) werden soll */ public Value value; private ArrayList usage; /** Erzeugen eine neuen Objektes für die Aufnahme von Daten für eine Transaktion */ public Transaction() { addkey="000"; key=(type==TYPE_CREDIT?"51":"05"); usage=new ArrayList(); } /** Hinzufügen einer Verwendungszweckzeile zu diesem Auftrag. */ public void addUsage(String st) { LogFilter.getInstance().addSecretData(st,"X",LogFilter.FILTER_MOST); usage.add(st); } /** Gibt eine Liste der Verwendungszweckzeilen (String) zurück. */ public List getUsage() { return usage; } public String toString() { StringBuffer ret=new StringBuffer(); try { ret.append("0000C"); ret.append(expand(myAccount.blz,8,(byte)0x20,ALIGN_RIGHT)); ret.append(expand(otherAccount.blz,8,(byte)0x20,ALIGN_RIGHT)); ret.append(expand(otherAccount.number,10,(byte)0x30,ALIGN_RIGHT)); sumBLZ+=Long.parseLong(otherAccount.blz); sumNumber+=Long.parseLong(otherAccount.number); if (internalCustomerId==null) { ret.append(expand("",13,(byte)0x30,ALIGN_LEFT)); } else { ret.append((char)0); ret.append(expand(SyntaxDTAUS.check(internalCustomerId),11,(byte)0x30,ALIGN_LEFT)); ret.append((char)0); } ret.append(expand(key,2,(byte)0x30,ALIGN_RIGHT)); ret.append(expand(addkey,3,(byte)0x30,ALIGN_RIGHT)); ret.append((char)0x20); ret.append(expand(Long.toString(value.getCurr().equals("DEM")?value.getLongValue():0),11,(byte)0x30,ALIGN_RIGHT)); ret.append(expand(myAccount.blz,8,(byte)0x20,ALIGN_RIGHT)); ret.append(expand(myAccount.number,10,(byte)0x30,ALIGN_RIGHT)); ret.append(expand(Long.toString(value.getCurr().equals("EUR")?value.getLongValue():0),11,(byte)0x30,ALIGN_RIGHT)); ret.append(expand("",3,(byte)0x20,ALIGN_LEFT)); ret.append(expand(SyntaxDTAUS.check(otherAccount.name),27,(byte)0x20,ALIGN_LEFT)); ret.append(expand("",8,(byte)0x20,ALIGN_LEFT)); if (value.getCurr().equals("EUR")) sumEUR+=value.getLongValue(); else if (value.getCurr().equals("DEM")) sumDM+=value.getLongValue(); ret.append(expand(SyntaxDTAUS.check(myAccount.name),27,(byte)0x20,ALIGN_LEFT)); String st=""; if (usage.size()!=0) st=SyntaxDTAUS.check(usage.get(0)); ret.append(expand(st,27,(byte)0x20,ALIGN_LEFT)); ret.append((char)curr); ret.append(expand("",2,(byte)0x20,ALIGN_LEFT)); int posForNumOfExt=ret.length(); ret.append("00"); int basicLenOfCSet=128+27+27+5; int realLenOfCSet=basicLenOfCSet; int numOfExt=0; // erweiterungsteile // TODO: name2 für myAccount und otherAccount vorerst weggelassen for (int i=1;i128) { int diff=128-(realLenOfCSet%128); ret.append(expand("",diff,(byte)0x20,ALIGN_LEFT)); realLenOfCSet+=diff; } ret.append("02"); ret.append(expand(st,27,(byte)0x20,ALIGN_LEFT)); realLenOfCSet+=29; numOfExt++; } if ((realLenOfCSet%128)!=0) { int diff=128-(realLenOfCSet%128); ret.append(expand("",diff,(byte)0x20,ALIGN_LEFT)); realLenOfCSet+=diff; } ret.replace(posForNumOfExt,posForNumOfExt+2,expand(Integer.toString(numOfExt),2,(byte)0x30,ALIGN_RIGHT)); ret.replace(0,4,expand(Integer.toString(basicLenOfCSet+29*numOfExt),4,(byte)0x30,ALIGN_RIGHT)); } catch (NullPointerException e) { throw new HBCI_Exception("probably one or more DTAUS values which MUST be set are null - please refer the API doc", e); } return ret.toString(); } } /** Typ des Sammelauftrages: Sammelüberweisung */ public static final int TYPE_CREDIT=1; /** Typ des Sammelauftrages: Sammellastschrift */ public static final int TYPE_DEBIT=2; /** TODO: doku fehlt */ public static final byte CURR_DM=0x20; /** TODO: doku fehlt */ public static final byte CURR_EUR=0x31; private static final byte ALIGN_LEFT=1; private static final byte ALIGN_RIGHT=2; private Konto myAccount; private int type; private Date execdate; private byte curr; private String referenceId; private ArrayList entries; private long sumDM; private long sumEUR; private long sumBLZ; private long sumNumber; /** Entspricht {@link #DTAUS(Konto, int, Date) DTAUS(myAccount,type,null)} */ public DTAUS(Konto myAccount,int type) { this(myAccount,type,null); } /** Erzeugen eines neuen Objektes für die Aufnahme von Sammelaufträgen. myAccount ist dabei das "eigene" Konto, welches bei Sammelüberweisungen als Belastungskonto und bei Sammellastschriften als Gutschriftkonto verwendet wird. Von dem {@link Konto}-Objekt müssen mindestens die Felder blz, number, curr und name richtig gesetzt sein.
execdate gibt das Datum an, wann dieser Sammelauftrag ausgeführt werden soll. ACHTUNG: execdate wird zur Zeit noch nicht ausgewertet! @param myAccount Gegenkonto für die enthaltenen Aufträge @param type
  • TYPE_CREDIT für Sammelüberweisungen,
  • TYPE_DEBIT für Sammellastschriften
@param execdate Ausführungsdatum für diesen Sammelauftrag; null, wenn kein Ausführungsdatum gesetzt werden soll (sofortige Ausführung) */ public DTAUS(Konto myAccount,int type,Date execdate) { LogFilter.getInstance().addSecretData(myAccount.blz,"X",LogFilter.FILTER_MOST); LogFilter.getInstance().addSecretData(myAccount.customerid,"X",LogFilter.FILTER_IDS); LogFilter.getInstance().addSecretData(myAccount.name,"X",LogFilter.FILTER_IDS); LogFilter.getInstance().addSecretData(myAccount.name2,"X",LogFilter.FILTER_IDS); LogFilter.getInstance().addSecretData(myAccount.number,"X",LogFilter.FILTER_IDS); LogFilter.getInstance().addSecretData(myAccount.subnumber,"X",LogFilter.FILTER_MOST); this.myAccount=myAccount; this.type=type; this.execdate=execdate; entries=new ArrayList(); if (myAccount.curr.equals("EUR")) this.curr=CURR_EUR; else if (myAccount.curr.equals("DEM")) this.curr=CURR_DM; else throw new InvalidUserDataException("*** invalid currency of this account: "+myAccount.curr); } /** TODO: doku fehlt */ public DTAUS(String dtaus) { entries=new ArrayList(); parseDTAUS(dtaus); } /** Hinzufügen eines einzelnen Auftrages zu diesem Sammelauftrag. Das {@link DTAUS.Transaction}-Objekt, welches hier als Argument benötigt wird, muss mit 'dtaus.new Transaction()' erzeugt werden ('dtaus' ist dabei das aktuelle DTAUS-Objekt). @param entry Hinzuzufügender Einzelauftrag */ public void addEntry(Transaction entry) { entries.add(entry); } /** TODO: doku fehlt */ public byte getCurr() { return curr; } /** TODO: doku fehlt */ public ArrayList getEntries() { return entries; } /** TODO: doku fehlt */ public Date getExecdate() { return execdate; } /** TODO: doku fehlt */ public Konto getMyAccount() { return myAccount; } /** TODO: doku fehlt */ public int getType() { return type; } /** Setzt das Feld Nr 10 ("Referennummer des Einreichers") */ public void setReferenceId(String referenceId) { this.referenceId = referenceId; } /** Gibt den Wert von Feld Nr 10 ("Referenznummer des Einreichers") zurück */ public String getReferenceId() { return (this.referenceId!=null)?this.referenceId:""; } /** Rückgabe des Sammelauftrages im DTAUS-Format. Der Rückgabewert dieser Methode kann direkt als Parameterwert für den Parameter 'data' bei Sammelaufträgen verwendet werden (für eine Parameterbeschreibung siehe Paketbeschreibung des Paketes org.kapott.hbci.GV). @return DTAUS-Datenstrom für diesen Sammelauftrag */ public String toString() { StringBuffer ret=new StringBuffer(); sumBLZ=0; sumNumber=0; sumDM=0; sumEUR=0; // A-set ret.append("0128A"); switch (type) { case TYPE_CREDIT: ret.append("GK"); break; case TYPE_DEBIT: ret.append("LK"); break; default: throw new InvalidUserDataException("*** type of DTAUS order not set (DEBIT/CREDIT)"); } ret.append(expand(myAccount.blz,8,(byte)0x20,ALIGN_RIGHT)); ret.append(expand("",8,(byte)0x30,ALIGN_LEFT)); ret.append(expand(SyntaxDTAUS.check(myAccount.name),27,(byte)0x20,ALIGN_LEFT)); SimpleDateFormat form=new SimpleDateFormat("ddMMyy"); ret.append(form.format(new Date())); ret.append(expand("", 4, (byte)0x20, ALIGN_LEFT)); ret.append(expand(myAccount.number, 10, (byte)0x30, ALIGN_RIGHT)); ret.append(expand(getReferenceId(), 10, (byte)0x30, ALIGN_RIGHT)); ret.append(expand("", 15, (byte)0x20, ALIGN_LEFT)); if (execdate==null) { ret.append(expand("",8,(byte)0x20,ALIGN_LEFT)); } else { form=new SimpleDateFormat("ddMMyyyy"); ret.append(form.format(execdate)); } ret.append(expand("",24,(byte)0x20,ALIGN_LEFT)); ret.append((char)curr); // C-sets for (Iterator i=entries.iterator();i.hasNext();) { Transaction entry= i.next(); ret.append(entry.toString()); } // E-set ret.append("0128E"); ret.append(expand("",5,(byte)0x20,ALIGN_LEFT)); ret.append(expand(Integer.toString(entries.size()),7,(byte)0x30,ALIGN_RIGHT)); ret.append(expand(Long.toString(curr==CURR_DM?sumDM:0), 13,(byte)0x30,ALIGN_RIGHT)); ret.append(expand(Long.toString(sumNumber),17,(byte)0x30,ALIGN_RIGHT)); ret.append(expand(Long.toString(sumBLZ),17,(byte)0x30,ALIGN_RIGHT)); ret.append(expand(Long.toString(curr==CURR_EUR?sumEUR:0), 13,(byte)0x30,ALIGN_RIGHT)); ret.append(expand("",51,(byte)0x20,ALIGN_LEFT)); return ret.toString(); } private String expand(String st,int len,byte filler,int align) { if (st.length()len) { throw new InvalidArgumentException("*** string too long: \""+st+"\" has "+st.length()+" chars, but max is "+len); } return st; } private void parseDTAUS(String dtaus) { HBCIUtils.log("parsing DTAUS data",HBCIUtils.LOG_DEBUG); // satz A String header=dtaus.substring(0,5); if (!header.equals("0128A")) { throw new HBCI_Exception("*** DTAUS stream does not start with '0128A'"); } char typ=dtaus.charAt(5); if (typ=='G') { this.type=TYPE_CREDIT; } else if (typ=='L') { this.type=TYPE_DEBIT; } else { throw new HBCI_Exception("*** Invalid type: "+typ); } setReferenceId(dtaus.substring(70, 80).trim()); String myBLZ=dtaus.substring(7,15).trim(); String myName=dtaus.substring(23,50).trim(); String myNumber=dtaus.substring(60,70).trim(); try { SimpleDateFormat format=new SimpleDateFormat("ddMMyyyy"); this.execdate=format.parse(dtaus.substring(95,103).trim()); } catch (ParseException e) { this.execdate=null; } this.curr=(byte)dtaus.charAt(127); if (this.curr!=CURR_DM && this.curr!=CURR_EUR) { throw new HBCI_Exception("*** Invalid currency: "+this.curr); } this.myAccount=new Konto("DE",myBLZ,myNumber); this.myAccount.curr=(this.curr==CURR_EUR)?"EUR":"DEM"; this.myAccount.name=myName; // satz C beginn int posi=128; // schleife für einzelne aufträge (c-sets) while (true) { Transaction entry=new Transaction(); if (dtaus.charAt(posi+4)!='C') { // gefundener abschnitt ist kein c-set break; } int setCLen=Integer.parseInt(dtaus.substring(posi,posi+4)); posi+=4; HBCIUtils.log("SetCLen = "+setCLen+" data bytes (--> "+((setCLen-187)/29.0)+" extensions)", HBCIUtils.LOG_DEBUG); // "C" überspringen posi++; // skip myBLZ posi+=8; String otherBLZ=dtaus.substring(posi,posi+8).trim(); posi+=8; String otherNumber=dtaus.substring(posi,posi+10).trim(); posi+=10; entry.internalCustomerId=dtaus.substring(posi+1,posi+1+11).trim(); posi+=13; entry.key=dtaus.substring(posi,posi+2).trim(); posi+=2; entry.addkey=dtaus.substring(posi,posi+3).trim(); posi+=3; // skip bankintern posi++; String value_st=null; if (this.curr==CURR_EUR) { value_st=dtaus.substring(posi+29,posi+29+11).trim(); } else { value_st=dtaus.substring(posi,posi+11).trim(); } posi+=40; // skip reserve posi+=3; String otherName=dtaus.substring(posi,posi+27).trim(); posi+=27; // skip fillbytes posi+=8; // skip myName posi+=27; entry.addUsage(dtaus.substring(posi,posi+27).trim()); posi+=27; // skip währung // TODO: hier konsistenz überprüfen posi++; // skip reserve posi+=2; int nofExtensions=Integer.parseInt(dtaus.substring(posi,posi+2)); posi+=2; HBCIUtils.log("field 'nofExtensions' = "+nofExtensions,HBCIUtils.LOG_DEBUG); String otherName2=null; for (int i=0;i 128) { posi=((posi/128)+1)*128; } String code=dtaus.substring(posi,posi+2).trim(); posi+=2; String data=dtaus.substring(posi,posi+27).trim(); posi+=27; if (code.equals("01")) { otherName2=data; } else if (code.equals("02")) { entry.addUsage(data); } else if (code.equals("03")) { this.myAccount.name2=data; } } posi=((posi/128)+1)*128; entry.otherAccount=new Konto("DE",otherBLZ,otherNumber); entry.otherAccount.curr=(this.curr==CURR_EUR)?"EUR":"DEM"; entry.otherAccount.name=otherName; entry.otherAccount.name2=otherName2; entry.value=new Value(Long.parseLong(value_st), (this.curr==CURR_EUR)?"EUR":"DEM"); addEntry(entry); } // e-satz if (!dtaus.substring(posi,posi+5).equals("0128E")) { throw new HBCI_Exception("*** e-set does not start with 0128E"); } posi+=5; // skip reserve posi+=5; int x=Integer.parseInt(dtaus.substring(posi,posi+7)); if (x!=entries.size()) { throw new HBCI_Exception("*** there were "+entries.size()+" c-sets, but e-set says "+x); } // TODO: restliche konsistenzchecks machen HBCIUtils.log("parsinng of DTAUS data finished", HBCIUtils.LOG_DEBUG); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy