mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-12-27 15:10:28 +01:00
429 lines
14 KiB
PHP
429 lines
14 KiB
PHP
|
<?php
|
|||
|
/*
|
|||
|
* SepaXmlCreator - by Thomas Schiffler.de
|
|||
|
* http://www.ThomasSchiffler.de/2013_09/code-schnipsel/sepa-sammeluberweisung-xml-datei-mit-php-erstellen
|
|||
|
*
|
|||
|
* Copyright (c) 2013 Thomas Schiffler (http://www.ThomasSchiffler.de
|
|||
|
* GPL (http://www.opensource.org/licenses/gpl-license.php) license.
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
class SepaBuchung{
|
|||
|
var $end2end, $iban, $bic, $kontoinhaber, $verwendungszweck, $amount;
|
|||
|
|
|||
|
// Mandatsinformationen für Lastschriften
|
|||
|
var $mandatId, $mandatDatum, $mandatAenderung;
|
|||
|
|
|||
|
function __construct() {
|
|||
|
$this->end2end = "NOTPROVIDED";
|
|||
|
}
|
|||
|
|
|||
|
function setEnd2End($end2end) {
|
|||
|
$this->end2end = $this->normalizeString($end2end);
|
|||
|
}
|
|||
|
|
|||
|
function setIban($iban) {
|
|||
|
$this->iban = str_replace(' ','',$iban);
|
|||
|
}
|
|||
|
|
|||
|
function setBic($bic) {
|
|||
|
$this->bic = $bic;
|
|||
|
}
|
|||
|
|
|||
|
function setName($name) {
|
|||
|
$this->kontoinhaber = $this->normalizeString($name);
|
|||
|
}
|
|||
|
|
|||
|
function setVerwendungszweck($verwendungszweck) {
|
|||
|
$this->verwendungszweck = $this->normalizeString($verwendungszweck);
|
|||
|
}
|
|||
|
|
|||
|
function setBetrag($betrag) {
|
|||
|
$this->amount = $betrag;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Methode zum Setzen des Mandates - notwendig beim Generieren von Lastschriften. Wenn gewünscht kann
|
|||
|
* nur die Mandats-ID gesetzt werden, hierbei wird das aktuelle Tagesdatum als Datum der Mandatserteilung
|
|||
|
* genommen. Das Datum ist im Format (YYYY-mm-dd - bsp. 2013-11-02 zu übergeben)
|
|||
|
*
|
|||
|
* @param String $id
|
|||
|
* @param String $mandatDatum
|
|||
|
* @param boolean $mandatAenderung - true wenn das Mandat seit letzer Erteilung geändert wurde
|
|||
|
*/
|
|||
|
function setMandat($id, $mandatDatum = null, $mandatAenderung = true) {
|
|||
|
$this->mandatId = $id;
|
|||
|
$this->mandatAenderung = $mandatAenderung;
|
|||
|
|
|||
|
if (!isset($mandatDatum)) {
|
|||
|
$this->mandatDatum = date('Y-m-d', time());
|
|||
|
} else {
|
|||
|
$this->mandatDatum = $mandatDatum;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function normalizeString($input) {
|
|||
|
// Only below characters can be used within the XML tags according the guideline.
|
|||
|
// a b c d e f g h i j k l m n o p q r s t u v w x y z
|
|||
|
// A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
|
|||
|
// 0 1 2 3 4 5 6 7 8 9
|
|||
|
// / - ? : ( ) . , ‘ +
|
|||
|
// Space
|
|||
|
//
|
|||
|
// Create a normalized array and cleanup the string $XMLText for unexpected characters in names
|
|||
|
$normalizeChars = array(
|
|||
|
'Á'=>'A', 'À'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Å'=>'A', 'Ä'=>'Ae', 'Æ'=>'AE', 'Ç'=>'C',
|
|||
|
'É'=>'E', 'È'=>'E', 'Ê'=>'E', 'Ë'=>'E', 'Í'=>'I', 'Ì'=>'I', 'Î'=>'I', 'Ï'=>'I', 'Ð'=>'Eth',
|
|||
|
'Ñ'=>'N', 'Ó'=>'O', 'Ò'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O',
|
|||
|
'Ú'=>'U', 'Ù'=>'U', 'Û'=>'U', 'Ü'=>'Ue', 'Ý'=>'Y',
|
|||
|
|
|||
|
'á'=>'a', 'à'=>'a', 'â'=>'a', 'ã'=>'a', 'å'=>'a', 'ä'=>'ae', 'æ'=>'ae', 'ç'=>'c',
|
|||
|
'é'=>'e', 'è'=>'e', 'ê'=>'e', 'ë'=>'e', 'í'=>'i', 'ì'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'eth',
|
|||
|
'ñ'=>'n', 'ó'=>'o', 'ò'=>'o', 'ô'=>'o', 'õ'=>'o', 'ö'=>'oe', 'ø'=>'o',
|
|||
|
'ú'=>'u', 'ù'=>'u', 'û'=>'u', 'ü'=>'ue', 'ý'=>'y',
|
|||
|
|
|||
|
'ß'=>'ss', 'þ'=>'thorn', 'ÿ'=>'y',
|
|||
|
|
|||
|
'&'=>'u.', '@'=>'at', '#'=>'h', '$'=>'s', '%'=>'perc', '^'=>'-','*'=>'-'
|
|||
|
);
|
|||
|
|
|||
|
$output = strtr($input, $normalizeChars);
|
|||
|
|
|||
|
return $output;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
class SepaXmlCreator {
|
|||
|
var $buchungssaetze = array();
|
|||
|
|
|||
|
var $accountName, $accountIban, $accountBic;
|
|||
|
var $offset = 0, $fixedDate;
|
|||
|
var $waehrung = "EUR";
|
|||
|
|
|||
|
// Mode = 1 -> Überweisung / Mode = 2 -> Basislastschrift
|
|||
|
var $mode = 1;
|
|||
|
var $isFirst = true;
|
|||
|
|
|||
|
// Gläubiger-ID
|
|||
|
var $glaeubigerId;
|
|||
|
|
|||
|
// XML-Errors
|
|||
|
private $xmlerrors;
|
|||
|
|
|||
|
function setDebitorValues($name, $iban, $bic) {
|
|||
|
trigger_error('Use setAccountValues($name, $iban, $bic) instead', E_USER_DEPRECATED);
|
|||
|
|
|||
|
$this->setAccountValues($name, $iban, $bic);
|
|||
|
}
|
|||
|
|
|||
|
function setAccountValues($name, $iban, $bic) {
|
|||
|
|
|||
|
$this->accountName = $name;
|
|||
|
$this->accountIban = $iban;
|
|||
|
$this->accountBic = $bic;
|
|||
|
}
|
|||
|
|
|||
|
function setGlaeubigerId($glaeubigerId) {
|
|||
|
$this->glaeubigerId = $glaeubigerId;
|
|||
|
}
|
|||
|
|
|||
|
function setCurrency($currency) {
|
|||
|
$this->waehrung = $currency;
|
|||
|
}
|
|||
|
|
|||
|
function addBuchung($buchungssatz) {
|
|||
|
array_push($this->buchungssaetze, $buchungssatz);
|
|||
|
}
|
|||
|
|
|||
|
function setAusfuehrungOffset($offset) {
|
|||
|
$this->offset = $offset;
|
|||
|
}
|
|||
|
|
|||
|
function setAusfuehrungDatum($datum) {
|
|||
|
$this->fixedDate = $datum;
|
|||
|
}
|
|||
|
|
|||
|
function generateSammelueberweisungXml() {
|
|||
|
// Set Mode = 1 -> Sammelüberweisung
|
|||
|
$this->mode = 1;
|
|||
|
return $this->getGeneratedXml();
|
|||
|
}
|
|||
|
|
|||
|
function generateBasislastschriftXml() {
|
|||
|
// Set Mode = 2 -> Basislastschrift
|
|||
|
$this->mode = 2;
|
|||
|
|
|||
|
return $this->getGeneratedXml();
|
|||
|
}
|
|||
|
|
|||
|
function setIsFolgelastschrift() {
|
|||
|
$this->isFirst = false;
|
|||
|
}
|
|||
|
|
|||
|
function getGeneratedXml() {
|
|||
|
$dom = new DOMDocument('1.0', 'utf-8');
|
|||
|
|
|||
|
// Build Document-Root
|
|||
|
$document = $dom->createElement('Document');
|
|||
|
if ($this->mode == 2) {
|
|||
|
$document->setAttribute('xmlns', 'urn:iso:std:iso:20022:tech:xsd:pain.008.002.02');
|
|||
|
$document->setAttribute('xsi:schemaLocation', 'urn:iso:std:iso:20022:tech:xsd:pain.008.002.02 pain.008.002.02.xsd');
|
|||
|
} else {
|
|||
|
$document->setAttribute('xmlns', 'urn:iso:std:iso:20022:tech:xsd:pain.001.002.03');
|
|||
|
$document->setAttribute('xsi:schemaLocation', 'urn:iso:std:iso:20022:tech:xsd:pain.001.002.03 pain.001.002.03.xsd');
|
|||
|
}
|
|||
|
$document->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
|
|||
|
$dom->appendChild($document);
|
|||
|
|
|||
|
// Build Content-Root
|
|||
|
if ($this->mode == 2) {
|
|||
|
$content = $dom->createElement('CstmrDrctDbtInitn');
|
|||
|
} else {
|
|||
|
$content = $dom->createElement('CstmrCdtTrfInitn');
|
|||
|
}
|
|||
|
|
|||
|
$document->appendChild($content);
|
|||
|
|
|||
|
// Build Header
|
|||
|
$header = $dom->createElement('GrpHdr');
|
|||
|
$content->appendChild($header);
|
|||
|
|
|||
|
$creationTime = time();
|
|||
|
|
|||
|
// Msg-ID
|
|||
|
$header->appendChild($dom->createElement('MsgId', $this->accountBic . '00' . date('YmdHis', $creationTime)));
|
|||
|
$header->appendChild($dom->createElement('CreDtTm', date('Y-m-d', $creationTime) . 'T' . date('H:i:s', $creationTime) . '.000Z'));
|
|||
|
$header->appendChild($dom->createElement('NbOfTxs', count($this->buchungssaetze)));
|
|||
|
$header->appendChild($initatorName = $dom->createElement('InitgPty'));
|
|||
|
$initatorName->appendChild($dom->createElement('Nm', $this->accountName));
|
|||
|
|
|||
|
// PaymentInfo
|
|||
|
$paymentInfo = $dom->createElement('PmtInf');
|
|||
|
$content->appendChild($paymentInfo);
|
|||
|
|
|||
|
$paymentInfo->appendChild($dom->createElement('PmtInfId', 'PMT-ID0-' . date('YmdHis', $creationTime)));
|
|||
|
switch ($this->mode) {
|
|||
|
case 2:
|
|||
|
// 2 = Basislastschrift
|
|||
|
$paymentInfo->appendChild($dom->createElement('PmtMtd', 'DD'));
|
|||
|
break;
|
|||
|
default:
|
|||
|
// Default / 1 = Überweisung
|
|||
|
$paymentInfo->appendChild($dom->createElement('PmtMtd', 'TRF'));
|
|||
|
break;
|
|||
|
}
|
|||
|
$paymentInfo->appendChild($dom->createElement('BtchBookg', 'false'));
|
|||
|
$paymentInfo->appendChild($dom->createElement('NbOfTxs', count($this->buchungssaetze)));
|
|||
|
$paymentInfo->appendChild($dom->createElement('CtrlSum', number_format($this->getUmsatzsumme(), 2, '.', '')));
|
|||
|
$paymentInfo->appendChild($tmp1 = $dom->createElement('PmtTpInf'));
|
|||
|
$tmp1->appendChild($tmp2 = $dom->createElement('SvcLvl'));
|
|||
|
$tmp2->appendChild($dom->createElement('Cd', 'SEPA'));
|
|||
|
|
|||
|
if ($this->mode == 2) {
|
|||
|
// zusätzliche Attribute für Lastschriften
|
|||
|
$tmp1->appendChild($tmp2 = $dom->createElement('LclInstrm'));
|
|||
|
$tmp2->appendChild($dom->createElement('Cd', 'CORE'));
|
|||
|
if ($this->isFirst) {
|
|||
|
$tmp1->appendChild($dom->createElement('SeqTp', 'FRST'));
|
|||
|
} else {
|
|||
|
$tmp1->appendChild($dom->createElement('SeqTp', 'RCUR'));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Ausführungsdatum berechnen
|
|||
|
if (isset($this->fixedDate)) {
|
|||
|
$ausfuehrungsdatum = $this->fixedDate;
|
|||
|
} else {
|
|||
|
$ausfuehrungszeit = $creationTime;
|
|||
|
if ($this->offset > 0) {
|
|||
|
$ausfuehrungszeit = $ausfuehrungszeit + (24 * 3600 * $this->offset);
|
|||
|
}
|
|||
|
|
|||
|
$ausfuehrungsdatum = date('Y-m-d', $ausfuehrungszeit);
|
|||
|
}
|
|||
|
|
|||
|
if ($this->mode == 2) {
|
|||
|
$paymentInfo->appendChild($dom->createElement('ReqdColltnDt', $ausfuehrungsdatum));
|
|||
|
} else {
|
|||
|
$paymentInfo->appendChild($dom->createElement('ReqdExctnDt', $ausfuehrungsdatum));
|
|||
|
}
|
|||
|
|
|||
|
// eigene Account-Daten Daten
|
|||
|
if ($this->mode == 2) {
|
|||
|
$paymentInfo->appendChild($tmp1 = $dom->createElement('Cdtr'));
|
|||
|
} else {
|
|||
|
$paymentInfo->appendChild($tmp1 = $dom->createElement('Dbtr'));
|
|||
|
}
|
|||
|
$tmp1->appendChild($dom->createElement('Nm', $this->accountName));
|
|||
|
|
|||
|
if ($this->mode == 2) {
|
|||
|
$paymentInfo->appendChild($tmp1 = $dom->createElement('CdtrAcct'));
|
|||
|
} else {
|
|||
|
$paymentInfo->appendChild($tmp1 = $dom->createElement('DbtrAcct'));
|
|||
|
}
|
|||
|
|
|||
|
$tmp1->appendChild($tmp2 = $dom->createElement('Id'));
|
|||
|
$tmp2->appendChild($dom->createElement('IBAN', $this->accountIban));
|
|||
|
|
|||
|
if ($this->mode == 2) {
|
|||
|
$paymentInfo->appendChild($tmp1 = $dom->createElement('CdtrAgt'));
|
|||
|
} else {
|
|||
|
$paymentInfo->appendChild($tmp1 = $dom->createElement('DbtrAgt'));
|
|||
|
}
|
|||
|
|
|||
|
$tmp1->appendChild($tmp2 = $dom->createElement('FinInstnId'));
|
|||
|
$tmp2->appendChild($dom->createElement('BIC', $this->accountBic));
|
|||
|
|
|||
|
$paymentInfo->appendChild($dom->createElement('ChrgBr', 'SLEV'));
|
|||
|
|
|||
|
if ($this->mode == 2) {
|
|||
|
$paymentInfo->appendChild($tmp1 = $dom->createElement('CdtrSchmeId'));
|
|||
|
$tmp1->appendChild($tmp2 = $dom->createElement('Id'));
|
|||
|
$tmp2->appendChild($tmp3 = $dom->createElement('PrvtId'));
|
|||
|
$tmp3->appendChild($tmp4 = $dom->createElement('Othr'));
|
|||
|
$tmp4->appendChild($dom->createElement('Id', $this->glaeubigerId));
|
|||
|
$tmp4->appendChild($tmp5 = $dom->createElement('SchmeNm'));
|
|||
|
$tmp5->appendChild($dom->createElement('Prtry', 'SEPA'));
|
|||
|
}
|
|||
|
|
|||
|
// Buchungssätze hinzufügen
|
|||
|
foreach ($this->buchungssaetze as $buchungssatz) {
|
|||
|
if ($this->mode == 2) {
|
|||
|
$paymentInfo->appendChild($buchung = $dom->createElement('DrctDbtTxInf'));
|
|||
|
} else {
|
|||
|
$paymentInfo->appendChild($buchung = $dom->createElement('CdtTrfTxInf'));
|
|||
|
}
|
|||
|
|
|||
|
// End2End setzen
|
|||
|
if (isset($buchungssatz->end2end)) {
|
|||
|
$buchung->appendChild($tmp1 = $dom->createElement('PmtId'));
|
|||
|
$tmp1->appendChild($dom->createElement('EndToEndId', $buchungssatz->end2end));
|
|||
|
}
|
|||
|
|
|||
|
// Betrag
|
|||
|
if ($this->mode == 2) {
|
|||
|
$buchung->appendChild($tmp2 = $dom->createElement('InstdAmt', number_format($buchungssatz->amount, 2, '.', '')));
|
|||
|
$tmp2->setAttribute('Ccy', $this->waehrung);
|
|||
|
} else {
|
|||
|
$buchung->appendChild($tmp1 = $dom->createElement('Amt'));
|
|||
|
$tmp1->appendChild($tmp2 = $dom->createElement('InstdAmt', number_format($buchungssatz->amount, 2, '.', '')));
|
|||
|
$tmp2->setAttribute('Ccy', $this->waehrung);
|
|||
|
}
|
|||
|
|
|||
|
if ($this->mode == 2) {
|
|||
|
// Lastschrift -> Mandatsinformationen
|
|||
|
$buchung->appendChild($tmp1 = $dom->createElement('DrctDbtTx'));
|
|||
|
$tmp1->appendChild($tmp2 = $dom->createElement('MndtRltdInf'));
|
|||
|
$tmp2->appendChild($dom->createElement('MndtId', $buchungssatz->mandatId));
|
|||
|
$tmp2->appendChild($dom->createElement('DtOfSgntr', $buchungssatz->mandatDatum));
|
|||
|
if ($buchungssatz->mandatAenderung) {
|
|||
|
$tmp2->appendChild($dom->createElement('AmdmntInd', 'true'));
|
|||
|
} else {
|
|||
|
$tmp2->appendChild($dom->createElement('AmdmntInd', 'false'));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Institut
|
|||
|
if ($this->mode == 2) {
|
|||
|
$buchung->appendChild($tmp1 = $dom->createElement('DbtrAgt'));
|
|||
|
} else {
|
|||
|
$buchung->appendChild($tmp1 = $dom->createElement('CdtrAgt'));
|
|||
|
}
|
|||
|
$tmp1->appendChild($tmp2 = $dom->createElement('FinInstnId'));
|
|||
|
$tmp2->appendChild($dom->createElement('BIC', $buchungssatz->bic));
|
|||
|
|
|||
|
// Inhaber
|
|||
|
if ($this->mode == 2) {
|
|||
|
$buchung->appendChild($tmp1 = $dom->createElement('Dbtr'));
|
|||
|
} else {
|
|||
|
$buchung->appendChild($tmp1 = $dom->createElement('Cdtr'));
|
|||
|
}
|
|||
|
$tmp1->appendChild($dom->createElement('Nm', $buchungssatz->kontoinhaber));
|
|||
|
|
|||
|
// IBAN
|
|||
|
if ($this->mode == 2) {
|
|||
|
$buchung->appendChild($tmp1 = $dom->createElement('DbtrAcct'));
|
|||
|
} else {
|
|||
|
$buchung->appendChild($tmp1 = $dom->createElement('CdtrAcct'));
|
|||
|
}
|
|||
|
$tmp1->appendChild($tmp2 = $dom->createElement('Id'));
|
|||
|
$tmp2->appendChild($dom->createElement('IBAN', $buchungssatz->iban));
|
|||
|
|
|||
|
if ($this->mode == 2) {
|
|||
|
$buchung->appendChild($tmp1 = $dom->createElement('UltmtDbtr'));
|
|||
|
$tmp1->appendChild($dom->createElement('Nm', $buchungssatz->kontoinhaber));
|
|||
|
}
|
|||
|
|
|||
|
// Verwendungszweck
|
|||
|
if (strlen($buchungssatz->verwendungszweck) > 0) {
|
|||
|
$buchung->appendChild($tmp1 = $dom->createElement('RmtInf'));
|
|||
|
$tmp1->appendChild($dom->createElement('Ustrd', $buchungssatz->verwendungszweck));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// XML exportieren
|
|||
|
return $dom->saveXML();
|
|||
|
}
|
|||
|
|
|||
|
function getUmsatzsumme() {
|
|||
|
$betrag = 0;
|
|||
|
|
|||
|
foreach ($this->buchungssaetze as $buchungssatz) {
|
|||
|
$betrag = $betrag + $buchungssatz->amount;
|
|||
|
}
|
|||
|
|
|||
|
return $betrag;
|
|||
|
}
|
|||
|
|
|||
|
public function validateBasislastschriftXml($xmlfile) {
|
|||
|
return $this->validateXML($xmlfile, 'pain.008.002.02.xsd');
|
|||
|
}
|
|||
|
|
|||
|
public function validateUeberweisungXml($xmlfile) {
|
|||
|
return $this->validateXML($xmlfile, 'pain.001.002.03.xsd');
|
|||
|
}
|
|||
|
|
|||
|
protected function validateXML($xmlfile, $xsdfile) {
|
|||
|
libxml_use_internal_errors(true);
|
|||
|
|
|||
|
$feed = new DOMDocument();
|
|||
|
|
|||
|
$result = $feed->load($xmlfile);
|
|||
|
if ($result === false) {
|
|||
|
$this->xmlerrors[] = "Document is not well formed\n";
|
|||
|
}
|
|||
|
if (@($feed->schemaValidate(dirname(__FILE__) . '/' . $xsdfile))) {
|
|||
|
|
|||
|
return true;
|
|||
|
} else {
|
|||
|
$this->xmlerrors[] = "! Document is not valid:\n";
|
|||
|
$errors = libxml_get_errors();
|
|||
|
|
|||
|
foreach ($errors as $error) {
|
|||
|
$this->xmlerrors[] = "---\n" . sprintf("file: %s, line: %s, column: %s, level: %s, code: %s\nError: %s",
|
|||
|
basename($error->file),
|
|||
|
$error->line,
|
|||
|
$error->column,
|
|||
|
$error->level,
|
|||
|
$error->code,
|
|||
|
$error->message
|
|||
|
);
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
public function printXmlErrors() {
|
|||
|
|
|||
|
if (!is_array($this->xmlerrors)) return;
|
|||
|
foreach ($this->xmlerrors as $error) {
|
|||
|
echo $error;
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
?>
|