Source for file DTA.php
Documentation is available at DTA.php
// +----------------------------------------------------------------------+
// +----------------------------------------------------------------------+
// | Copyright (c) 2003-2005 Hermann Stainer, Web-Gear |
// | http://www.web-gear.com/ |
// | All rights reserved. |
// +----------------------------------------------------------------------+
// | DTA is a class that provides functions to create DTA files used in |
// | Germany to exchange informations about money transactions with banks |
// | or online banking programs. |
// | This LICENSE is in the BSD license style. |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | Redistributions in binary form must reproduce the above copyright |
// | notice, this list of conditions and the following disclaimer in the |
// | documentation and/or other materials provided with the distribution. |
// | Neither the name of Hermann Stainer, Web-Gear nor the names of his |
// | contributors may be used to endorse or promote products derived from |
// | this software without specific prior written permission. |
// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
// | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// | POSSIBILITY OF SUCH DAMAGE. |
// +----------------------------------------------------------------------+
// | Author: Hermann Stainer <hs@web-gear.com> |
// +----------------------------------------------------------------------+
// $Id: DTA.php,v 1.2.0 2005/01/25 15:00:00 hstainer Exp $
* Determines the type of the DTA file:
* DTA file contains credit payments.
* Determines the type of the DTA file:
* DTA file contains debit payments (default).
* Dta class provides functions to create and handle with DTA files
* used in Germany to exchange informations about money transactions with
* banks or online banking programs.
* @author Hermann Stainer <hs@web-gear.com>
* @version $Revision: 0.81 $
* Type of DTA file, DTA_CREDIT or DTA_DEBIT.
* Account data for the file sender.
* @var integer $account_file_sender
var $account_file_sender;
* Array of ASCII Codes of valid chars for DTA field data.
* @var array $validString_chars
* @var integer $timestamp
* Array of exchanges that the DTA file should contain.
* @var integer $exchanges
* Constructor. The type of the DTA file must be set. One file can
* only contain credits (DTA_CREDIT) OR debits (DTA_DEBIT).
* This is a definement of the DTA format.
* @param integer $type Determines the type of the DTA file. Either DTA_CREDIT or DTA_DEBIT. Must be set.
$this->account_file_sender = array ();
$this->validString_chars = array (32 , 36 , 37 , 38 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 , 50 , 51 , 52 , 53 , 54 , 55 , 56 , 57 , 65 , 66 , 67 , 68 , 69 , 70 , 71 , 72 , 73 , 74 , 75 , 76 , 77 , 78 , 79 , 80 , 81 , 82 , 83 , 84 , 85 , 86 , 87 , 88 , 89 , 90 , 196 , 214 , 220 , 223 );
$this->timestamp = time();
$this->exchanges = array ();
* Checks if the given string contains only chars valid for fields in DTA files.
* @param string $string String that is checked.
function validString ($string)
foreach ($occuring_chars as $char_ord => $char_amount) {
if (!in_array($char_ord, $this->validString_chars)) {
* Makes the given string valid for DTA files. German umlauts become uppercase,
* all other chars not allowed are replaced with space
* @param string $string String that should made valid.
function makeValidString ($string)
for ($index = 0; $index < strlen($result); $index++ ) {
* Set the sender of the DTA file. Must be set for valid DTA file.
* The given account data is also used as default sender's account.
* name Sender's name. Maximally 27 chars are allowed.
* bank_code Sender's bank code.
* account_number Sender's account number.
* additional_name If necessary, additional line for sender's name (maximally 27 chars).
* @param array $account Account data fot file sender.
function setAccountFileSender ($account)
if (empty ($account['additional_name'])) {
$account['additional_name'] = "";
$this->account_file_sender = array (
"name" => substr($this->makeValidString ($account['name']), 0 , 27 ),
"bank_code" => $account['bank_code'],
"account_number" => $account['account_number'],
"additional_name" => substr($this->makeValidString ($account['additional_name']), 0 , 27 )
* Adds an exchange. First the account data for the receiver of the exchange is set.
* In the case the DTA file contains credits, this is the payment receiver. In the other
* case (the DTA file contains debits), this is the account, from which money is taken away.
* If the sender is not specified, values of the file sender are used by default.
* Account data for receiver and sender contain
* name Name. Maximally 27 chars are allowed.
* account_number Account number.
* additional_name If necessary, additional line for name (maximally 27 chars).
* @param array $account_receiver Receiver's account data.
* @param double $amount Amount of money in this exchange. Currency: EURO
* @param array $purposes Array of up to 15 lines (maximally 27 chars each) for description of the exchange.
* @param array $account_sender Sender's account data.
function addExchange ($account_receiver, $amount, $purposes, $account_sender = array ())
if (empty ($account_receiver['additional_name'])) {
$account_receiver['additional_name'] = "";
if (empty ($account_sender['name'])) {
$account_sender['name'] = $this->account_file_sender['name'];
if (empty ($account_sender['bank_code'])) {
$account_sender['bank_code'] = $this->account_file_sender['bank_code'];
if (empty ($account_sender['account_number'])) {
$account_sender['account_number'] = $this->account_file_sender['account_number'];
if (empty ($account_sender['additional_name'])) {
$account_sender['additional_name'] = $this->account_file_sender['additional_name'];
$amount = round($amount * 100 );
$purposes = array ($purposes, "");
$purposes_data = $purposes;
foreach ($purposes_data as $purpose) {
$purposes[] = substr($this->makeValidString ($purpose), 0 , 27 );
$this->exchanges[] = array (
"sender_name" => substr($this->makeValidString ($account_sender['name']), 0 , 27 ),
"sender_bank_code" => $account_sender['bank_code'],
"sender_account_number" => $account_sender['account_number'],
"sender_additional_name" => substr($this->makeValidString ($account_sender['additional_name']), 0 , 27 ),
"receiver_name" => substr($this->makeValidString ($account_receiver['name']), 0 , 27 ),
"receiver_bank_code" => $account_receiver['bank_code'],
"receiver_account_number" => $account_receiver['account_number'],
"receiver_additional_name" => substr($this->makeValidString ($account_receiver['additional_name']), 0 , 27 ),
* Returns the full content of the generated DTA file. All added exchanges are processed.
function getFileContent ()
$sum_account_numbers = 0;
// record length (128 Bytes)
$content .= str_pad ("128", 4 , "0", STR_PAD_LEFT );
// file mode (credit or debit)
$content .= ($this->type == DTA_CREDIT) ? "G" : "L";
// Customer File ("K") / Bank File ("B")
$content .= str_pad ($this->account_file_sender['bank_code'], 8 , "0", STR_PAD_LEFT );
// only used if Bank File, otherwise NULL
$content .= str_pad ($this->account_file_sender['name'], 27 , " ", STR_PAD_RIGHT );
$content .= strftime("%d%m%y", $this->timestamp);
// sender's account number
$content .= str_pad ($this->account_file_sender['account_number'], 10 , "0", STR_PAD_LEFT );
// sender's reference number (optional)
// execution date ("DDMMYYYY", optional)
foreach ($this->exchanges as $exchange) {
$sum_account_numbers += $exchange['receiver_account_number'];
$sum_bank_codes += $exchange['receiver_bank_code'];
$sum_amounts += $exchange['amount'];
$additional_purposes = $exchange['purposes'];
$additional_parts = array ();
if (strlen($exchange['receiver_additional_name']) > 0 ) {
$additional_parts[] = array ("type" => "01",
"content" => $exchange['receiver_additional_name']
foreach ($additional_purposes as $additional_purpose) {
$additional_parts[] = array ("type" => "02",
"content" => $additional_purpose
if (strlen($exchange['sender_additional_name']) > 0 ) {
$additional_parts[] = array ("type" => "03",
"content" => $exchange['sender_additional_name']
$additional_parts_number = count($additional_parts);
// record length (187 Bytes + 29 Bytes for each additional part)
$content .= str_pad (187 + $additional_parts_number * 29 , 4 , "0", STR_PAD_LEFT );
$content .= str_pad ($exchange['sender_bank_code'], 8 , "0", STR_PAD_LEFT );
$content .= str_pad ($exchange['receiver_bank_code'], 8 , "0", STR_PAD_LEFT );
// receiver's account number
$content .= str_pad ($exchange['receiver_account_number'], 10 , "0", STR_PAD_LEFT );
// internal customer number (11 chars) or NULL
// payment mode (text key)
$content .= ($this->type == DTA_CREDIT) ? "51" : "05";
$content .= str_pad ($exchange['sender_bank_code'], 8 , "0", STR_PAD_LEFT );
// sender's account number
$content .= str_pad ($exchange['sender_account_number'], 10 , "0", STR_PAD_LEFT );
$content .= str_pad ($exchange['amount'], 11 , "0", STR_PAD_LEFT );
$content .= str_pad ($exchange['receiver_name'], 27 , " ", STR_PAD_RIGHT );
$content .= str_pad ($exchange['sender_name'], 27 , " ", STR_PAD_RIGHT );
// first line of purposes
$content .= str_pad ($first_purpose, 27 , " ", STR_PAD_RIGHT );
// amount of additional parts
$content .= str_pad ($additional_parts_number, 2 , "0", STR_PAD_LEFT );
if (count($additional_parts) > 0 ) {
for ($index = 1; $index <= 2; $index++ ) {
if (count($additional_parts) > 0 ) {
$additional_part = array ("type" => " ",
$content .= $additional_part['type'];
// additional part content
$content .= str_pad ($additional_part['content'], 27 , " ", STR_PAD_RIGHT );
for ($part = 3; $part <= 5; $part++ ) {
if (count($additional_parts) > 0 ) {
for ($index = 1; $index <= 4; $index++ ) {
if (count($additional_parts) > 0 ) {
$additional_part = array ("type" => " ",
$content .= $additional_part['type'];
// additional part content
$content .= str_pad ($additional_part['content'], 27 , " ", STR_PAD_RIGHT );
// record length (128 bytes)
$content .= str_pad ("128", 4 , "0", STR_PAD_LEFT );
// number of records type C
$content .= str_pad (count($this->exchanges), 7 , "0", STR_PAD_LEFT );
// sum of account numbers
$content .= str_pad ($sum_account_numbers, 17 , "0", STR_PAD_LEFT );
$content .= str_pad ($sum_bank_codes, 17 , "0", STR_PAD_LEFT );
$content .= str_pad ($sum_amounts, 13 , "0", STR_PAD_LEFT );
* @param string $filename Filename.
function saveFile ($filename)
$content = $this->getFileContent ();
$Dta_fp = @fopen($filename, "w");
$result = @fwrite($Dta_fp, $content);
Documentation generated on Mon, 11 Mar 2019 14:19:42 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|