芝麻web文件管理V1.00
编辑当前文件:/home/strato/chroot/opt/RZphp5/includes/Payment/DTAZV.php
* @author Hermann Stainer
* @copyright 2008 Martin Schütte * @copyright 2003-2005 Hermann Stainer, Web-Gear * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version CVS: $Id: DTAZV.php,v 1.8 2009/06/05 09:26:47 mschuett Exp $ * @link http://pear.php.net/package/Payment_DTA */ /** * needs base class */ require_once 'DTABase.php'; /** * DTAZV class provides functions to create and handle with DTAZV * files used in Germany to exchange informations about european * money transactions with banks or online banking programs. * * @category Payment * @package Payment_DTA * @author Martin Schütte
* @author Hermann Stainer
* @copyright 2008 Martin Schütte * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version Release: @package_version@ * @link http://pear.php.net/package/Payment_DTA */ class DTAZV extends DTABase { /** * The maximum allowed amount per transfer (in cents). * * By default set to the maximum amount for a "EU-Standardüberweisung" * that does not have to be reported. * * @see setMaxAmount() * @var integer $max_amount * @access private */ var $max_amount; /** * Constructor. * * @access public */ function DTAZV() { $this->DTABase(); $this->max_amount = 12500*100; } /** * Set the sender of the DTAZV file. Must be set for valid DTAZV file. * The given account data is also used as default sender's account. * Account data contains * name Sender's name. Maximally 35 chars are allowed. * additional_name Sender's additional name (max. 35 chars) * street Sender's street/PO Box (max. 35 chars) * city Sender's city (max. 35 chars) * bank_code Sender's bank code (BLZ, 8-digit) * account_number Sender's account number (10-digit) * * @param array $account Account data fot file sender. * * @access public * @return boolean */ function setAccountFileSender($account) { $account['account_number'] = strval($account['account_number']); $account['bank_code'] = strval($account['bank_code']); if (strlen($account['name']) > 0 && strlen($account['bank_code']) > 0 && strlen($account['bank_code']) <= 8 && ctype_digit($account['bank_code']) && strlen($account['account_number']) > 0 && strlen($account['account_number']) <= 10 && ctype_digit($account['account_number'])) { if (empty($account['additional_name'])) { $account['additional_name'] = ""; } if (empty($account['street'])) { $account['street'] = ""; } if (empty($account['city'])) { $account['city'] = ""; } $this->account_file_sender = array( "name" => substr($this->makeValidString($account['name']), 0, 35), "additional_name" => substr($this->makeValidString($account['additional_name']), 0, 35), "street" => substr($this->makeValidString($account['street']), 0, 35), "city" => substr($this->makeValidString($account['city']), 0, 35), "bank_code" => $account['bank_code'], "account_number" => $account['account_number'] ); $result = true; } else { $result = false; } return $result; } /** * 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 sender contain * name Sender's name. Maximally 35 chars are allowed. * additional_name Sender's additional name (max. 35 chars) * street Sender's street/PO Box (max. 35 chars) * city Sender's city (max. 35 chars) * bank_code Sender's bank code (8-digit BLZ) * account_number Sender's account number (10-digit) * * Account data for receiver contain * name Receiver's name. Maximally 35 chars are allowed. * additional_name Receiver's additional name (max. 35 chars) * street Receiver's street/PO Box (max. 35 chars) * city Receiver's city (max. 35 chars) * bank_code Receiver's bank code (8 or 11 char BIC) * account_number Receiver's account number (up to 34 char IBAN) * * @param array $account_receiver Receiver's account data. * @param double $amount Amount of money (Euro) in this exchange. * @param array $purposes Array of up to 4 lines (max. 35 chars each) * for description of the exchange. * @param array $account_sender Sender's account data. * * @access public * @return boolean */ function addExchange($account_receiver, $amount, $purposes, $account_sender = array()) { if (empty($account_receiver['additional_name'])) { $account_receiver['additional_name'] = ""; } if (empty($account_receiver['street'])) { $account_receiver['street'] = ""; } if (empty($account_receiver['city'])) { $account_receiver['city'] = ""; } if (empty($account_sender['name'])) { $account_sender['name'] = $this->account_file_sender['name']; } if (empty($account_sender['additional_name'])) { $account_sender['additional_name'] = $this->account_file_sender['additional_name']; } if (empty($account_sender['street'])) { $account_sender['street'] = $this->account_file_sender['street']; } if (empty($account_sender['city'])) { $account_sender['city'] = $this->account_file_sender['city']; } 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']; } // check arguments if (strlen($account_receiver['bank_code']) == 8) { if (is_numeric($account_receiver['bank_code'])) { // german BLZ -> allowed with special format $account_receiver['bank_code'] = '///' . $account_receiver['bank_code']; } else { // short BIC -> fill to 11 chars $account_receiver['bank_code'] = $account_receiver['bank_code'] . 'XXX'; } } $account_sender['account_number'] = strval($account_sender['account_number']); $account_sender['bank_code'] = strval($account_sender['bank_code']); /* * notes for IBAN: currently only checked for length; * we can use PEAR::Validate_Finance_IBAN once it * gets a 'beta' or 'stable' status * the minimum length of 12 is chosen arbitrarily as * an additional plausibility check; currently the * shortest real IBANs have 15 chars */ $cents = (int)(round($amount * 100)); if (strlen($account_receiver['name']) > 0 && strlen($account_receiver['bank_code']) == 11 && strlen($account_receiver['account_number']) > 12 && strlen($account_receiver['account_number']) <= 34 && strlen($account_sender['name']) > 0 && strlen($account_sender['bank_code']) > 0 && strlen($account_sender['bank_code']) <= 8 && ctype_digit($account_sender['bank_code']) && strlen($account_sender['account_number']) > 0 && strlen($account_sender['account_number']) <= 10 && ctype_digit($account_sender['account_number']) && is_numeric($amount) && $cents > 0 && $cents <= $this->max_amount && $this->sum_amounts <= PHP_INT_MAX - $cents && ((is_array($purposes) && count($purposes) >= 1 && count($purposes) <= 4) || (is_string($purposes) && strlen($purposes) > 0))) { $this->sum_amounts += $cents; if (is_string($purposes)) { $filtered_purposes = str_split($this->makeValidString($purposes), 35); $filtered_purposes = array_slice($filtered_purposes, 0, 14); } else { $filtered_purposes = array(); array_slice($purposes, 0, 4); foreach ($purposes as $purposeline) { $filtered_purposes[] = substr($this->makeValidString($purposeline), 0, 35); } } // ensure four lines $filtered_purposes = array_slice(array_pad($filtered_purposes, 4, ""), 0, 4); $this->exchanges[] = array( "sender_name" => substr($this->makeValidString($account_sender['name']), 0, 35), "sender_additional_name" => substr($this->makeValidString($account_sender['additional_name']), 0, 35), "sender_street" => substr($this->makeValidString($account_sender['street']), 0, 35), "sender_city" => substr($this->makeValidString($account_sender['city']), 0, 35), "sender_bank_code" => $account_sender['bank_code'], "sender_account_number" => $account_sender['account_number'], "receiver_name" => substr($this->makeValidString($account_receiver['name']), 0, 35), "receiver_additional_name" => substr($this->makeValidString($account_receiver['additional_name']), 0, 35), "receiver_street" => substr($this->makeValidString($account_receiver['street']), 0, 35), "receiver_city" => substr($this->makeValidString($account_receiver['city']), 0, 35), "receiver_bank_code" => $account_receiver['bank_code'], "receiver_account_number" => $account_receiver['account_number'], "amount" => $cents, "purposes" => $filtered_purposes ); $result = true; } else { $result = false; } return $result; } /** * Returns the full content of the generated DTAZV file. * All added exchanges are processed. * * @access public * @return string */ function getFileContent() { $content = ""; /* The checksum in DTAZV adds only the integer parts of all * transfered amounts and is different from the sum of amounts. */ $checksum_amounts = 0; $sum_amounts = 0; /** * data record Q */ // Q01 record length (256 Bytes) $content .= "0256"; // Q02 record type $content .= "Q"; // Q03 BLZ receiving this file (usually the sender's bank) $content .= str_pad($this->account_file_sender['bank_code'], 8, "0", STR_PAD_LEFT); // Q04 customer number (usually the sender's account) $content .= str_pad($this->account_file_sender['account_number'], 10, "0", STR_PAD_LEFT); // Q05 sender's address $content .= str_pad($this->account_file_sender['name'], 35, " ", STR_PAD_RIGHT); $content .= str_pad($this->account_file_sender['additional_name'], 35, " ", STR_PAD_RIGHT); $content .= str_pad($this->account_file_sender['street'], 35, " ", STR_PAD_RIGHT); $content .= str_pad($this->account_file_sender['city'], 35, " ", STR_PAD_RIGHT); // Q06 date of file creation $content .= strftime("%d%m%y", $this->timestamp); // Q07 daily counter // UNSURE if necessary $content .= "00"; // Q08 execution date $content .= strftime("%d%m%y", $this->timestamp); // Q09 notification to federal bank // according to specification (see above) // transfers <= 12500 Euro do not have to be reported $content .= "N"; // Q10 notification data $content .= "00"; // Q11 notification BLZ $content .= str_repeat("0", 8); // Q12 reserve $content .= str_repeat(" ", 68); assert(strlen($content) == 256); /** * data record(s) T */ foreach ($this->exchanges as $exchange) { $sum_amounts += intval($exchange['amount']); $checksum_amounts += intval($exchange['amount']/100); // T01 record length $content .= "0768"; // T02 record type $content .= "T"; // T03 sender's bank $content .= str_pad($exchange['sender_bank_code'], 8, "0", STR_PAD_LEFT); // T04a currency (fixed) $content .= "EUR"; // T04b sender's account $content .= str_pad($exchange['sender_account_number'], 10, "0", STR_PAD_LEFT); // T05 execution date (optional, if != Q6) $content .= str_repeat("0", 6); // T06 BLZ, empty for Standardüberweisung $content .= str_repeat("0", 8); // T07a currency, empty for Standardüberweisung $content .= str_repeat(" ", 3); // T07b account, empty for Standardüberweisung $content .= str_repeat("0", 10); // T08 receiver's BIC $content .= str_pad($exchange['receiver_bank_code'], 11, "X", STR_PAD_RIGHT); // T09a country code, empty for Standardüberweisung $content .= str_repeat(" ", 3); // T09b receiver's bank address, empty for Standardüberweisung $content .= str_repeat(" ", 4*35); // T10a receiver's country code --> use cc from IBAN $content .= substr($exchange['receiver_account_number'], 0, 2) . ' '; // T10b receiver's address $content .= str_pad($exchange['receiver_name'], 35, " ", STR_PAD_RIGHT); $content .= str_pad($exchange['receiver_additional_name'], 35, " ", STR_PAD_RIGHT); $content .= str_pad($exchange['receiver_street'], 35, " ", STR_PAD_RIGHT); $content .= str_pad($exchange['receiver_city'], 35, " ", STR_PAD_RIGHT); // T11 empty for Standardüberweisung $content .= str_repeat(" ", 2*35); // T12 receiver's IBAN $content .= '/' . str_pad($exchange['receiver_account_number'], 34, " ", STR_PAD_RIGHT); // T13 currency $content .= "EUR"; // T14a amount (integer) $content .= str_pad(intval($exchange['amount']/100), 14, "0", STR_PAD_LEFT); // T14b amount (decimal places) $content .= str_pad(($exchange['amount']%100)*10, 3, "0", STR_PAD_LEFT); // T15 purpose $content .= str_pad($exchange['purposes'][0], 35, " ", STR_PAD_RIGHT); $content .= str_pad($exchange['purposes'][1], 35, " ", STR_PAD_RIGHT); $content .= str_pad($exchange['purposes'][2], 35, " ", STR_PAD_RIGHT); $content .= str_pad($exchange['purposes'][3], 35, " ", STR_PAD_RIGHT); // T16--T20 instruction code, empty for Standardüberweisung $content .= str_repeat("0", 4*2); $content .= str_repeat(" ", 25); // T21 fees $content .= "00"; // T22 payment type $content .= "13"; // T23 free text for accounting $content .= str_repeat(" ", 27); // T24 contact details $content .= str_repeat(" ", 35); // T25 reporting key $content .= "0"; // T26 reserve $content .= str_repeat(" ", 51); // T26 following report extension $content .= "00"; } assert((strlen($content) - 256) % 768 == 0); /** * data record Z */ // Z01 record length $content .= "0256"; // Z02 record type $content .= "Z"; // Z03 sum of amounts (integer parts in T14a) assert($sum_amounts == $this->sum_amounts); $content .= str_pad(intval($checksum_amounts), 15, "0", STR_PAD_LEFT); // Z04 number of records type T $content .= str_pad(count($this->exchanges), 15, "0", STR_PAD_LEFT); // Z05 reserve $content .= str_repeat(" ", 221); assert(strlen($content) >= 512); assert((strlen($content) - 512) % 768 == 0); return $content; } /** * Set the maximum allowed amount per transfer. * Pass 0 to disable the check (will set to maximum integer value). * *
Warning
: Use at your own risk. * * Amounts > 12500 Euro usually have notification requirements. * * Amounts > 50000 Euro are not allowed in a "EU-Standardüberweisung", * thus yielding a malformed DTAZV. * * @param integer $newmax New maximum allowed amount in Euro or 0 to disable check. * * @access public * @since 1.3.2 * @link http://www.bundesbank.de/meldewesen/mw_aussenwirtschaft.en.php * info on notification requirements * @return void */ function setMaxAmount($newmax) { if ((int)$newmax == 0 || $newmax > PHP_INT_MAX/100) { $this->max_amount = PHP_INT_MAX; } else { $this->max_amount = (int)(round($newmax * 100)); } } }