OpenXE/www/plugins/sepa/SepaXmlCreator.php

429 lines
14 KiB
PHP
Raw Normal View History

2021-05-21 08:49:41 +02:00
<?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;
}
}
}
?>