/* /// This class writes DTAUS files for german banks, direct debit orders /// see http://www.infodrom.org/projects/dtaus/dtaus.html for description of file format; /// the data comes from special request objects * DTA Specifiation: see http://www.ebics-zka.de/dokument/pdf/Anlage%203-Spezifikation%20der%20Datenformate%20-%20Version%202.3%20Endfassung%20vom%2005.11.2008.pdf * DTA File checker (online): https://www.xpecto.de/index.php?id=148,7 * Author: Timotheus Pokorra (http://tpokorra.blogspot.com/2008/09/dtaus-with-c.html) * Date: 22/09/2008 * Feel free to use this code in any way you like * Florian Harbich: The extended code you have here is licensed as "Creative Commons NC-BY-SA" * Please contact me at florian.harbich (at) die-rooter.de if you want to use this code * in commercial projects. * This file is licensed under Creative Commons Namensnennung-Keine kommerzielle Nutzung-Weitergabe unter gleichen Bedingungen 3.0 Deutschland license. * * Changelog: * May 2009: Timotheus Pokorra: fixed a bug with long references, make more extensions possible * Nov 2009: Florian Harbich (http://www.die-rooter.de/ITworks/archives/26-Writing-DTAUS-files-with-C-DTA-Dateien-mit-C-erzeugen.html): * - changed input data type to special request object classes * - fixed writing of dataset C extensions for all 13 allowed extra reference lines * - fixed writing of decimal places of amount and amount checksum (according to DTAUS documentation) * - fixed empty DM-Amount-Field: must be 0 instead of blank. * - added selection of transaction type: Direct debit or bank transfer * - added sample code * Jun 2010: Florian Harbich * - fixed extension block writing when no additional reference lines are specified * - fixed DTAUS Log reference Line writing * - CreateHumanReadableDTA method added for log file creation. */ using System; using System.Linq; using System.Collections.Specialized; using System.Text; using System.Collections.Generic; namespace Ict.Plugin.EP.Germany { /// /// States the type of Transaction for a BankTransactionRequest. /// public enum DTAUSTransactionType { /// /// Unknown type, this will fail when calling WriteDTAUSFile... /// Unknown, /// /// Direct debit request, the executive account will receive the money from the target accounts (Lastschrift-Einzug). /// DirectDebit, /// /// regular bank transfer, the executive account will transfer the money to the target accounts (Überweisung). /// BankTransfer } /// /// Container for bank transaction requests. This object can be used together with the DTAUSWriter class in order to /// create a DTAUS file for bank transactions. /// /// Florian Harbich /// 21.11.2009 16:11 /// $Revision: 201 $ /// $Id: DTAUSWriter.cs 201 2010-05-30 13:17:35Z flo $ public class BankTransactionRequest { public DTAUSTransactionType TransactionType { get; set; } /// /// List of all concrete direct debit transactions for this request. /// public List Transactions { get; private set; } /// /// Gets or sets the creation date of this request structure. /// public DateTime CreationDate { get; set; } /// /// Gets or sets the requested execution date of the direct debit transactions. /// For use with DTAUS files, this date must not be less than the creation date and not more than 15 days after the creation date. /// Can be null to indicate immediate execution. /// public DateTime? ExecutionDate { get; set; } /// /// Gets or sets the bank number (BLZ) from which the transaction originates. /// public int ExecutiveBankNumber { get; set; } /// /// Gets or sets the bank account number from which thetransaction originates. /// public long ExecutiveBankAccountNumber { get; set; } /// /// Gets or sets the bank account holder from which the direct debit originates. /// public string ExecutiveBankAccountHolder { get; set; } /// /// Initializes a new instance of the class. /// public BankTransactionRequest() { this.Transactions = new List(); this.TransactionType = DTAUSTransactionType.Unknown; } } /// /// Container for bank transactions. This object can be used in BankTransactionRequest objects /// together with the DTAUSWriter class in order to /// create a DTAUS file for bank transactions. /// /// Florian Harbich /// 21.11.2009 16:15 /// $Revision: 201 $ /// $Id: DTAUSWriter.cs 201 2010-05-30 13:17:35Z flo $ public class BankTransactionItem { /// /// List of Reference lines (Verwendungszweck) for this transaction. /// At least one line but not more than 14 are needed for use with DTAUS files. /// public List ReferenceLines { get; private set; } /// /// Gets or sets the bank number (BLZ) of the recipient account. /// public int TargetBankNumber { get; set; } /// /// Gets or sets the bank account number of the recipient account. /// public long TargetBankAccountNumber { get; set; } /// /// Gets or sets the bank account holder of the account stated in TargetBankAccountNumber /// (the recipient account). /// public string TargetBankAccountHolder { get; set; } /// /// Gets or sets the amount of money that is requested from the TargetBankAccount in Euro-Cents. /// For DTAUS files, this value must not be 0 or negative. /// public int AmountCents { get; set; } /// /// Initializes a new instance of the class. /// public BankTransactionItem() { this.ReferenceLines = new List(); } } /// /// This class writes DTAUS files for german banks, direct debit orders /// see http://www.infodrom.org/projects/dtaus/dtaus.html for description of file format; /// the data comes from an xml file /// public static class DTAUSWriter { /// /// States the alignment for length ensured strings. /// private enum Alignment { /// /// The string is left-aligned, missing characters are added to the right. /// AlignLeft, /// /// The string is right-aligned, missing characters are added to the left. /// AlignRight }; /// /// The Encoding used for DTAUS files. /// public static Encoding DTAUSFileEncoding = Encoding.ASCII; /// /// Creates a complete DTAUS data string for the given request object. /// /// The request to create the DTAUS dataset from. must not be null. /// the complete DTAUS dataset for the given request as an ascii byte[]. /// When any data in the request is invalid (bad string length etc.), /// an InvalidOperationException is created. See its message for detailed information. /// The request object must contain at least one transaction, /// else an ArgumentOutOfRangeException is thrown. /// The TransactionType of the request is not supported. public static byte[] WriteDTAUSFile(BankTransactionRequest request) { StringBuilder result = new StringBuilder(); if (request.Transactions.Count < 1) { throw new ArgumentOutOfRangeException("request", "the Direct debit request must contain at least one transaction object."); } WriteHeader(result, request); foreach (BankTransactionItem transaction in request.Transactions) { WriteTransactionBody(result, transaction, request); } WriteFooter(result, request); return DTAUSFileEncoding.GetBytes(result.ToString()); } /// /// Creates a human readable protocol for the passed DTA request. /// /// The request to transform into a human readable representation. /// Stringbuilder with the human readable DTA log text public static StringBuilder CreateHumanReadableDTA(BankTransactionRequest request) { StringBuilder humanReadableDTA = new StringBuilder(); humanReadableDTA.AppendLine("ANFANG DTA-Erstellung"); humanReadableDTA.AppendLine(); humanReadableDTA.AppendFormat("Erstellzeit: {0:G}", request.CreationDate); humanReadableDTA.AppendLine(); humanReadableDTA.Append("Ausführung: "); if (request.ExecutionDate.HasValue) { humanReadableDTA.AppendFormat("{0:G}", request.ExecutionDate); } else { humanReadableDTA.Append("sofort"); } humanReadableDTA.AppendLine(); humanReadableDTA.AppendFormat("Absender-Kontoinhaber: {0}", request.ExecutiveBankAccountHolder); humanReadableDTA.AppendLine(); humanReadableDTA.AppendFormat("Absender-Kontonummer: {0,10}", request.ExecutiveBankAccountNumber); humanReadableDTA.AppendLine(); humanReadableDTA.AppendFormat("Absender-BLZ: {0,8}", request.ExecutiveBankNumber); humanReadableDTA.AppendLine(); humanReadableDTA.Append("Transaktionsart: "); if (request.TransactionType == DTAUSTransactionType.BankTransfer) { humanReadableDTA.Append("Überweisung"); } else if (request.TransactionType == DTAUSTransactionType.DirectDebit) { humanReadableDTA.Append("Lastschrift-Einzug"); } else { humanReadableDTA.AppendFormat("{0}", request.TransactionType); } humanReadableDTA.AppendLine(); foreach (BankTransactionItem transaction in request.Transactions) { humanReadableDTA.AppendLine(); humanReadableDTA.AppendFormat(" Empfänger-Kontoinhaber: {0}", transaction.TargetBankAccountHolder); humanReadableDTA.AppendLine(); humanReadableDTA.AppendFormat(" Empfänger-Kontonummer: {0,10}", transaction.TargetBankAccountNumber); humanReadableDTA.AppendLine(); humanReadableDTA.AppendFormat(" Empfänger-BLZ: {0,8}", transaction.TargetBankNumber); humanReadableDTA.AppendLine(); humanReadableDTA.AppendFormat(" Betrag: {0:0.00} EUR", (double)transaction.AmountCents / 100); humanReadableDTA.AppendLine(); foreach (string reference in transaction.ReferenceLines) { humanReadableDTA.AppendFormat(" Verwendungszweck: {0}", reference); humanReadableDTA.AppendLine(); } } humanReadableDTA.AppendLine(); humanReadableDTA.AppendLine("ENDE DTA-Erstellung"); return humanReadableDTA; } #region internal helpers /// /// Checks if the length of the input string is exactly the required length. /// /// The input string to check. /// The required length of the input string. /// An error message to be created when the length does not match. /// When the input string length does not math the required length, /// an InvalidOperationException is created. See its message for detailed information. private static void CheckLength(string input, int requiredlength, string msg) { if (input.Length != requiredlength) { throw new InvalidOperationException("wrong length: " + msg); } } /// /// Formats the given input string such that /// * it uses only uppercase letters /// * it is not null and has no blanks at the beginning or end /// * it contains only valid characters for DTAUS files. /// /// The input to format, may be null. /// the formatted input as described in the summary. never null, may be empty. public static string FormatName(string input) { string allowedchars = " 0123456789.,&-/+*$%ABCDEFGHIJKLMNOPQRSTUVWXYZ"; input = (input ?? String.Empty).Trim().ToUpper(). Replace("Ü", "UE"). Replace("Ä", "AE"). Replace("Ö", "OE"). Replace("ß", "SS"); for (int count = 0; count < input.Length; count++) { if (allowedchars.IndexOf(input[count]) < 0) { input = input.Substring(0, count) + ' ' + input.Substring(count + 1); } } return input; } /// /// Returns a string whose length is exactly requredlength characters. /// /// The input string to pad up to the required length. /// The length of the string to be returned. /// The fieldname (only used in error message when the input string is too long). /// The character used to pad the input string to the required length. /// The Alignment of the padded string. /// A string containing the input string with length requiredlength. missing characters from /// input are padded using the fill character such that the input string is aligned acccording to the alignwhere parameter. ///The input length is longer than the requiredlength parameter. private static string EnsureLength(string input, int requiredlength, string fieldname, char fill, Alignment alignwhere) { string padded; if (input.Length > requiredlength) { throw new InvalidOperationException("Problem with length of " + fieldname + " " + input + "; should only be " + requiredlength.ToString()); } else if (input.Length < requiredlength) { if (alignwhere == Alignment.AlignRight) { padded = input.PadLeft(requiredlength, fill); } else { padded = input.PadRight(requiredlength, fill); } } else { padded = input; } return padded; } #endregion /// /// Writes the DTAUS dataset A (DTAUS Header) /// /// The StringBuilder to write the header to. /// The Direct debit request object for which the header is created. ///The execution date of the request is before the creation date or more than 15 days after the creation date. /// The TransactionType is not supported. private static void WriteHeader(StringBuilder result, BankTransactionRequest request) { DateTime creationDate = request.CreationDate.Date; DateTime? dateEffective = request.ExecutionDate; #region sanity checks if (String.IsNullOrEmpty(request.ExecutiveBankAccountHolder)) { throw new InvalidOperationException("No executive account holder is given for this transaction."); } if (request.ExecutiveBankAccountNumber <= 0) { throw new InvalidOperationException("The executive bank account number must not be 0 or negative!."); } if (request.ExecutiveBankNumber < 10000000 || request.ExecutiveBankNumber >= 90000000) { throw new InvalidOperationException("The executive bank number is invalid."); } if (dateEffective.HasValue) { double daysBetween = (dateEffective.Value.Date - creationDate).TotalDays; if (daysBetween < 0.0 || daysBetween > 15.0) { throw new InvalidOperationException("Date of execution must not be before today and no more than 15 days from today!"); } } #endregion /* DTAUS Dataset A Structure (see http://www.infodrom.org/projects/dtaus/dtaus.html) 1 0 4 Zeichen Länge des Datensatzes, immer 128 Bytes, also immer "0128" 2 4 1 Zeichen Datensatz-Typ, immer 'A' 3 5 2 Zeichen Art der Transaktionen "LB" für Lastschriften Bankseitig "LK" für Lastschriften Kundenseitig "GB" für Gutschriften Bankseitig "GK" für Gutschriften Kundenseitig 4 7 8 Zeichen Bankleitzahl des Auftraggebers 5 15 8 Zeichen CST, "00000000", nur belegt, wenn Diskettenabsender Kreditinstitut 6 23 27 Zeichen Name des Auftraggebers 7 50 6 Zeichen aktuelles Datum im Format DDMMJJ 8 56 4 Zeichen CST, " " (Blanks) 9 60 10 Zeichen Kontonummer des Auftraggebers 10 70 10 Zeichen Optionale Referenznummer (numerisch, leer = 10*'0') 11a 80 15 Zeichen Reserviert, 15 Blanks 11b 95 8 Zeichen Optionales Ausführungsdatum im Format DDMMJJJJ. Nicht jünger als Erstellungsdatum (A7), jedoch höchstens 15 Kalendertage später. Sonst Blanks. 11c 103 24 Zeichen Reserviert, 24 Blanks 12 127 1 Zeichen Währungskennzeichen " " = DM "1" = Euro Insgesamt 128 Zeichen */ result.Append("0128"); result.Append("A"); if (request.TransactionType == DTAUSTransactionType.DirectDebit) { result.Append("LK"); } else if (request.TransactionType == DTAUSTransactionType.BankTransfer) { result.Append("GK"); } else { throw new NotSupportedException("The Transaction type " + request.TransactionType + " is not yet supported."); } result.Append(EnsureLength(request.ExecutiveBankNumber.ToString(), 8, "ExecutiveBankSortcode", '0', Alignment.AlignLeft)); result.Append(new String('0', 8)); result.Append(EnsureLength(FormatName(request.ExecutiveBankAccountHolder), 27, "ExecutiveName", ' ', Alignment.AlignLeft)); result.AppendFormat("{0:ddMMyy}", creationDate); result.Append(new String(' ', 4)); result.Append(EnsureLength(request.ExecutiveBankAccountNumber.ToString(), 10, "ExecutiveAccountNumber", '0', Alignment.AlignRight)); result.Append(new String('0', 10)); result.Append(new String(' ', 15)); if (dateEffective.HasValue) { result.AppendFormat("{0:ddMMyyyy}", dateEffective.Value); } else { result.Append(new String(' ', 8)); } result.Append(new String(' ', 24)); result.Append("1"); } /// /// Writes a DTAUS dataset C block (Body) for the given direct debit request and transaction object. /// /// The StringBuilder to write the transaction to. /// The transaction to be written /// The request object that contains the direct debit recipient information. /// When any data in the request is invalid (bad string length etc.), /// an InvalidOperationException is created. See its message for detailed information. /// The TransactionType is not supported. private static void WriteTransactionBody(StringBuilder result, BankTransactionItem transaction, BankTransactionRequest request) { List extraReferences = new List(transaction.ReferenceLines); #region sanity checks if (String.IsNullOrEmpty(transaction.TargetBankAccountHolder)) { throw new InvalidOperationException("No target account holder is given for this transaction."); } if (transaction.TargetBankAccountNumber <= 0) { throw new InvalidOperationException("target account number must not be 0 or negative!."); } if (transaction.TargetBankNumber < 10000000 || transaction.TargetBankNumber >= 90000000) { throw new InvalidOperationException("target bank number is invalid."); } if (extraReferences.Count < 1) { throw new InvalidOperationException("No Reference text is given for this transaction."); } if (transaction.AmountCents <= 0) { throw new InvalidOperationException("The amount for each transaction must be greater than 0"); } if (extraReferences.Count > 14) { throw new InvalidOperationException("at most 14 reference lines can be given for each transaction."); } #endregion string primaryReferenceLine = extraReferences[0]; extraReferences.RemoveAt(0); /* Aufbau Datensatz C Nr. Start Länge Beschreibung 1 0 4 Zeichen Länge des Datensatzes, 187 + x * 29 (x..Anzahl Erweiterungsteile) 2 4 1 Zeichen Datensatz-Typ, immer 'C' 3 5 8 Zeichen Bankleitzahl des Auftraggebers (optional, ggf. '0' auffüllen) 4 13 8 Zeichen Bankleitzahl des Kunden 5 21 10 Zeichen Kontonummer des Kunden 6 31 13 Zeichen Verschiedenes 1. Zeichen: "0" 2. - 12. Zeichen: interne Kundennummer oder Nullen 13. Zeichen: "0" Die interne Nummer wird vom erstbeauftragten Institut zum endbegünstigten Institut weitergeleitet. Die Weitergabe der internenen Nummer an den Überweisungsempfänger ist der Zahlstelle freigestellt. 7 44 5 Zeichen Art der Transaktion (7a: 2 Zeichen, 7b: 3 Zeichen) "04000" Lastschrift des Abbuchungsauftragsverfahren "05000" Lastschrift des Einzugsermächtigungsverfahren "05005" Lastschrift aus Verfügung im elektronischen Cash-System "05006" Wie 05005 mit ausländischen Karten "05015" Lastschrift aus Verfügung im elec. Cash-System - POZ "51000" Überweisungs-Gutschrift "53000" Überweisung Lohn/Gehalt/Rente "54XXJ" Vermögenswirksame Leistung (VL) mit Sparzulage "56000" Überweisung öffentlicher Kassen Die im Textschlüssel mit XX bezeichnete Stelle ist 00 oder der Prozentsatz der Sparzulage. Die im Textschlüssel mit J bezeichnete Stelle wird bei Übernahme in eine Zahlung automatisch mit der jeweils aktuellen Jahresendziffer (z.B. 7, wenn 97) ersetzt. 8 49 1 Zeichen Reserviert, " " (Blank) 9 50 11 Zeichen Betrag (9 Vorkomma, 2 Nachkommastellen ohne Trennzeichen) 10 61 8 Zeichen Bankleitzahl des Auftraggebers 11 69 10 Zeichen Kontonummer des Auftraggebers 12 79 11 Zeichen Betrag in Euro (9 Vorkomma, 2 Nachkommastellen ohne Trennzeichen), nur belegt, wenn Euro als Währung angegeben wurde (A12, C17a), sonst Nullen 13 90 3 Zeichen Reserviert, 3 Blanks 14a 93 27 Zeichen Name des Kunden 14b 120 8 Zeichen Reserviert, 8 Blanks Insgesamt 128 Zeichen 15 128 27 Zeichen Name des Auftraggebers 16 155 27 Zeichen Verwendungszweck 17a 182 1 Zeichen Währungskennzeichen " " = DM "1" = Euro 17b 183 2 Zeichen Reserviert, 2 Blanks 18 185 2 Zeichen Anzahl der Erweiterungsdatensätze, "00" bis "15" 19 187 2 Zeichen Typ (1. Erweiterungsdatensatz) "01" Name des Kunden "02" Verwendungszweck "03" Name des Auftraggebers 20 189 27 Zeichen Beschreibung gemäß Typ 21 216 2 Zeichen wie C19, oder Blanks (2. Erweiterungsdatensatz) 22 218 27 Zeichen wie C20, oder Blanks 23 245 11 Zeichen 11 Blanks Insgesamt 256 Zeichen */ result.AppendFormat("{0:0000}", 187 + (extraReferences.Count * 29)); result.Append("C"); result.Append(new String('0', 8)); result.Append(EnsureLength(transaction.TargetBankNumber.ToString(), 8, "PartnerBankSortcode", '0', Alignment.AlignRight)); result.Append(EnsureLength(transaction.TargetBankAccountNumber.ToString(), 10, "PartnerBankAccountNumber", '0', Alignment.AlignRight)); result.Append("0"); result.Append(new String('0', 11)); result.Append("0"); if (request.TransactionType == DTAUSTransactionType.DirectDebit) { result.Append("05000"); // Einzugsermaechtigung } else if (request.TransactionType == DTAUSTransactionType.BankTransfer) { result.Append("51000"); // Überweisungs-Gutschrift } else { throw new NotSupportedException("The Transaction type " + request.TransactionType + " is not yet supported."); } result.Append(" "); result.Append(new String('0', 11)); // With Euro-Transactions, the Amount is in Field C12, not here. result.Append(EnsureLength(request.ExecutiveBankNumber.ToString(), 8, "ExecutiveBankSortcode", '0', Alignment.AlignRight)); result.Append(EnsureLength(request.ExecutiveBankAccountNumber.ToString(), 10, "ExecutiveBankAccountNumber", '0', Alignment.AlignRight)); string amountFormatted = Convert.ToDouble(transaction.AmountCents).ToString(new String('0', 11)); CheckLength(amountFormatted, 11, "The Amount of this transaction is too big to be used in a DTA file."); result.Append(amountFormatted); result.Append(new String(' ', 3)); result.Append(EnsureLength(FormatName(transaction.TargetBankAccountHolder), 27, "PartnerName", ' ', Alignment.AlignLeft)); result.Append(new String(' ', 8)); result.Append(EnsureLength(FormatName(request.ExecutiveBankAccountHolder), 27, "ExecutiveName", ' ', Alignment.AlignLeft)); result.Append(EnsureLength(FormatName(primaryReferenceLine), 27, "PartnerKeyReference", ' ', Alignment.AlignLeft)); result.Append("1"); result.Append(new string(' ', 2)); WriteAllReferenceExtensions(result, extraReferences); } /// /// Writes all extra reference lines as extension blocks to the given StringBuilder. /// /// The Stringbuilder to write to. /// The list of reference lines to be written. must not be more than 13. /// When more than 13 reference lines are given, /// an InvalidOperationException is created. private static void WriteAllReferenceExtensions(StringBuilder result, List references) { if (references.Count > 13) { throw new InvalidOperationException("A Transaction can have at most 13 additional reference lines."); } //First add the yet missing extension count (Field C18). result.AppendFormat("{0:00}", references.Count); //The first two extensions will complete the 128 characters of the dataset C base block: 2*(2+27) + 11 chars for (int i = 0; i < 2; i++) { string reference = null; if (i < references.Count) { reference = references[i]; } WriteReferenceExtension(result, reference); } result.Append(new String(' ', 11)); if (references.Count > 2) { //The remaining extensions (#<=13) must be written in blocks of 4 extensions with a total of 128 chars. //4*(2+27) + 12 //the last extension block can have only one extension (because the total is 15), but must still be //128 chars wide, so the remainder is simply filled with empty blocks. //Because the references list is checked to have less than 14 items, the maximum block count is always ensured. for (int block = 0; block < 5; block++) { //first block of four starts with the third extension (index 2) and so on int offset = (4*block) + 2; if (offset < references.Count) { //4 extensions will form a 128 chars block and always have to be written together. //if not enough extensions are available, fill the remaining block with blanks. for (int i = 0; i < 4 ; i++) { int currentIndex = offset + i; string reference = null; if (currentIndex < references.Count) { reference = references[currentIndex]; } WriteReferenceExtension(result, reference); } result.Append(new String(' ', 12)); } else { //no more extensions, so do not start a new 128 chars block and terminate extension writing. break; } } } } /// /// Creates the datafields for a reference extension of a dataset C extension block. /// when the input string is null or empty, an empty extension is written. /// /// The Stringbuilder where the extension is written to. /// The reference line to be written. ///The length of the (DTA formatted) reference line is longer than the allowed field size. private static void WriteReferenceExtension(StringBuilder result, string referenceLine) { //XXX: change signature to DTAExtensionData{ExtensionType type, string contents} and be able to write the extra executive and target name fields, too //A check would be needed to ensure that at most 1 type 00 and type 01 extension is defined and //the BankTransactionRequest/BankTransactionItem classes must be extended to Support the property "ExtraAccountHolderText" if (!String.IsNullOrEmpty(referenceLine)) { result.Append("02"); //C19: 02 = Verwendungszweck result.Append(EnsureLength(FormatName(referenceLine), 27, "Extension", ' ', Alignment.AlignLeft)); } else { result.Append(new string(' ', 2 + 27)); } } /// /// Writes the footer (DTAUS dataset E) of the given direct debit request. /// /// The StringBuilder to write to. /// The request of which the footer is generated. /// When any checksum field lengths exceed the allowed field length, /// an InvalidOperationException is created. See its message for detailed information. private static void WriteFooter(StringBuilder result, BankTransactionRequest request) { /* DTAUS Datensatz E (Footer) 1 0 4 Zeichen Länge des Datensatzes, immer 128 Bytes, also immer "0128" 2 4 1 Zeichen Datensatz-Typ, immer 'E' 3 5 5 Zeichen " " (Blanks) 4 10 7 Zeichen Anzahl der Datensätze vom Typ C 5 17 13 Zeichen Kontrollsumme Beträge in DM (11 Vorkommastellen und 2 Nachkommastellen ohne Trennzeichen) 6 30 17 Zeichen Kontrollsumme Kontonummern 7 47 17 Zeichen Kontrollsumme Bankleitzahlen 8 64 13 Zeichen Kontrollsumme Beträge in Euro (11 Vorkommastellen und 2 Nachkommastellen ohne Trennzeichen), nur belegt, wenn Euro als Währung angegeben wurde (A12, C17a) 9 77 51 Zeichen 51 Blanks Insgesamt 128 Zeichen */ string bankAccountNumberSumFormatted = request.Transactions.Sum(item => item.TargetBankAccountNumber).ToString(new String('0', 17)); CheckLength(bankAccountNumberSumFormatted, 17, "The bank account number sum of this request is too big to be used in a DTA file. Try using less transactions."); string bankNumberSumFormatted = request.Transactions.Sum(item => (long)item.TargetBankNumber).ToString(new String('0', 17)); CheckLength(bankNumberSumFormatted, 17, "The bank number sum of this transaction is too big to be used in a DTA file. Try using less transactions."); string amountSumFormatted = request.Transactions.Sum(item => item.AmountCents).ToString(new String('0', 13)); CheckLength(amountSumFormatted, 13, "The total Amount of all transactions in this request is too big to be used in a DTA file. try using less transactions."); string transactionCountFormatted = request.Transactions.Count.ToString(new String('0', 7)); CheckLength(transactionCountFormatted, 7, "The total transaction count is too big to be used in a single DTA file. try using less transactions."); result.Append("0128"); result.Append("E"); result.Append(new String(' ', 5)); result.Append(transactionCountFormatted); result.Append(new String('0', 13)); result.Append(bankAccountNumberSumFormatted); result.Append(bankNumberSumFormatted); result.Append(amountSumFormatted); result.Append(new String(' ', 51)); } #region Sample usage /// /// Sample usage method that donates the given amount to the class extending developer Florian Harbich. /// /// The account holder (you). /// The account number (your bank account number). /// The bank number (your bank number (BLZ)). /// The amount you would like to donate, in cents. /// byte[] containing the DTAUS file to donate some money to me. public static byte[] DonateToDeveloper(string accountHolder, long accountNumber, int bankNumber, int amountCents) { BankTransactionRequest request = new BankTransactionRequest() { CreationDate = DateTime.Now, ExecutionDate = null, ExecutiveBankAccountHolder = accountHolder, ExecutiveBankAccountNumber = accountNumber, ExecutiveBankNumber = bankNumber, TransactionType = DTAUSTransactionType.BankTransfer }; BankTransactionItem transaction = new BankTransactionItem() { AmountCents = amountCents, TargetBankAccountHolder = "Florian Harbich", TargetBankAccountNumber = 834915, TargetBankNumber = 60450050, }; transaction.ReferenceLines.Add("Donation for DTAUS"); transaction.ReferenceLines.Add("writing library"); transaction.ReferenceLines.Add("in csharp"); transaction.ReferenceLines.Add("from " + accountHolder); request.Transactions.Add(transaction); return DTAUSWriter.WriteDTAUSFile(request); } #endregion } }