751 lines
33 KiB
PHP
751 lines
33 KiB
PHP
<?php
|
|
/**
|
|
* 2007-2017 Decanet
|
|
*
|
|
* NOTICE OF LICENSE
|
|
*
|
|
* This source file is subject to the Academic Free License (AFL 3.0)
|
|
* that is bundled with this package in the file LICENSE.txt.
|
|
* It is also available through the world-wide-web at this URL:
|
|
* http://opensource.org/licenses/afl-3.0.php
|
|
* If you did not receive a copy of the license and are unable to
|
|
* obtain it through the world-wide-web, please send an email
|
|
* to license@prestashop.com so we can send you a copy immediately.
|
|
*
|
|
* DISCLAIMER
|
|
*
|
|
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
|
* versions in the future. If you wish to customize PrestaShop for your
|
|
* needs please refer to http://www.decanet.fr for more information.
|
|
*
|
|
* @author Decanet SA <contact@decanet.fr>
|
|
* @copyright 2007-2017 Decanet SA
|
|
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
|
* International Registered Trademark & Property of PrestaShop SA
|
|
*/
|
|
|
|
/**
|
|
* SEPA SSD (Sepa Direct Debit) 2.0
|
|
* This class creates a Sepa Direct Debit xml File.
|
|
*/
|
|
class SepaDD
|
|
{
|
|
private $config;
|
|
private $xml;
|
|
private $batch_array = array();
|
|
|
|
public function __construct($config)
|
|
{
|
|
//Check the config
|
|
$config_validator = $this->validateConfig($config);
|
|
if ($config_validator) {
|
|
$this->config = $config;
|
|
} else {
|
|
throw new Exception('Invalid config file: '.$config_validator);
|
|
}
|
|
//Prepare the document
|
|
$this->prepareDocument();
|
|
$this->createGroupHeader();
|
|
}
|
|
/**
|
|
* Build the main document node and set xml namespaces.
|
|
*/
|
|
private function prepareDocument()
|
|
{
|
|
//Create the xml Instance
|
|
$this->xml = new DOMDocument('1.0', 'UTF-8');
|
|
//Create the document node
|
|
$document_node = $this->xml->createElement('Document');
|
|
//set the namespace
|
|
$document_attribute_xmlns = $this->xml->createAttribute('xmlns');
|
|
if (isset($this->config['version']) && $this->config['version'] == '3') {
|
|
$document_attribute_xmlns->value = 'urn:iso:std:iso:20022:tech:xsd:pain.008.001.03';
|
|
} else {
|
|
$document_attribute_xmlns->value = 'urn:iso:std:iso:20022:tech:xsd:pain.008.001.02';
|
|
}
|
|
$document_node->appendChild($document_attribute_xmlns);
|
|
//set the namespace url
|
|
$document_attribute_xmlnsxsi = $this->xml->createAttribute('xmlns:xsi');
|
|
$document_attribute_xmlnsxsi->value = 'http://www.w3.org/2001/XMLSchema-instance';
|
|
$document_node->appendChild($document_attribute_xmlnsxsi);
|
|
//create the Direct Debit node
|
|
$cstmr_drct_dbt_initn_node = $this->xml->createElement('CstmrDrctDbtInitn');
|
|
$document_node->appendChild($cstmr_drct_dbt_initn_node);
|
|
//append the document node to the xml Instance
|
|
$this->xml->appendChild($document_node);
|
|
}
|
|
|
|
/**
|
|
* Function to create the GroupHeader (GrpHdr) in the CstmrDrctDbtInit Node
|
|
*/
|
|
private function createGroupHeader()
|
|
{
|
|
//Retrieve the CstmrDrctDbtInitn node
|
|
$cstmr_drct_dbt_initn_node = $this->getCstmrDrctDbtInitnNode();
|
|
//Create the required nodes
|
|
$grp_hdr_node = $this->xml->createElement('GrpHdr');
|
|
$msg_id_node = $this->xml->createElement('MsgId');
|
|
$cre_dt_tm_node = $this->xml->createElement('CreDtTm');
|
|
$nb_of_txs_node = $this->xml->createElement('NbOfTxs');
|
|
$ctrl_sum_node = $this->xml->createElement('CtrlSum');
|
|
$initg_pty_node = $this->xml->createElement('InitgPty');
|
|
$nm_node = $this->xml->createElement('Nm');
|
|
//Set the values for the nodes
|
|
$msg_id_node->nodeValue = $this->makeMsgId();
|
|
$cre_dt_tm_node->nodeValue = date('c');
|
|
|
|
//if using lower than PHP 5.4.0, there is no ENT_XML1
|
|
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
|
|
$nm_node->nodeValue = htmlentities($this->config['name'], ENT_XML1, 'UTF-8');
|
|
} else {
|
|
$nm_node->nodeValue = htmlentities($this->config['name'], ENT_QUOTES, 'UTF-8');
|
|
}
|
|
//Append the nodes
|
|
$initg_pty_node->appendChild($nm_node);
|
|
$grp_hdr_node->appendChild($msg_id_node);
|
|
$grp_hdr_node->appendChild($cre_dt_tm_node);
|
|
// $grp_hdr_node->appendChild($reqd_exctn_dt_tm_node);
|
|
$grp_hdr_node->appendChild($nb_of_txs_node);
|
|
$grp_hdr_node->appendChild($ctrl_sum_node);
|
|
$grp_hdr_node->appendChild($initg_pty_node);
|
|
//Append the header to its parent
|
|
$cstmr_drct_dbt_initn_node->appendChild($grp_hdr_node);
|
|
}
|
|
|
|
/**
|
|
* Public function to add payments
|
|
* @param the payment to be added in the form of an array
|
|
* @throws Exception if payment array is invalid.
|
|
*/
|
|
public function addPayment($payment)
|
|
{
|
|
//First validate the payment array
|
|
$validation_result = $this->validatePayment($payment);
|
|
if ($validation_result !== true) {
|
|
throw new Exception('Invalid Payment, error with: '.$validation_result);
|
|
}
|
|
//Get the CstmrDrctDbtInitnNode
|
|
$cstmr_drct_dbt_initn_node = $this->getCstmrDrctDbtInitnNode();
|
|
|
|
//if there is a batch, the batch will create this information.
|
|
if ($this->config['batch'] == false) {
|
|
$pmt_inf_node = $this->xml->createElement('PmtInf');
|
|
$pmt_inf_id_node = $this->xml->createElement('PmtInfId');
|
|
$pmt_mtd_node = $this->xml->createElement('PmtMtd');
|
|
$btch_bookg_node = $this->xml->createElement('BtchBookg');
|
|
$nb_of_txs_node = $this->xml->createElement('NbOfTxs');
|
|
$ctrl_sum_node = $this->xml->createElement('CtrlSum');
|
|
$pmt_tp_inf_node = $this->xml->createElement('PmtTpInf');
|
|
$svc_lvl_node = $this->xml->createElement('SvcLvl');
|
|
$cd_svc_lvl_node = $this->xml->createElement('Cd');
|
|
$lcl_instrm_node = $this->xml->createElement('LclInstrm');
|
|
$cd_lcl_instrm_node = $this->xml->createElement('Cd');
|
|
$seq_tp_node = $this->xml->createElement('SeqTp');
|
|
$reqd_colltn_dt_node = $this->xml->createElement('ReqdColltnDt');
|
|
$cdtr_node = $this->xml->createElement('Cdtr');
|
|
$nm_cdtr_node = $this->xml->createElement('Nm');
|
|
$cdtr_acct_node = $this->xml->createElement('CdtrAcct');
|
|
$id_cdtr_acct_node = $this->xml->createElement('Id');
|
|
$iban_cdtr_acct_node = $this->xml->createElement('IBAN');
|
|
if (isset($this->config['BIC'])) {
|
|
$cdtr_agt_node = $this->xml->createElement('CdtrAgt');
|
|
$fin_instn_id_cdtr_agt_node = $this->xml->createElement('FinInstnId');
|
|
if (isset($this->config['version']) && $this->config['version'] == '3') {
|
|
$bic_cdtr_agt_node = $this->xml->createElement('BICFI');
|
|
} else {
|
|
$bic_cdtr_agt_node = $this->xml->createElement('BIC');
|
|
}
|
|
}
|
|
$chrg_br_node = $this->xml->createElement('ChrgBr');
|
|
$cdtr_schme_id_node = $this->xml->createElement('CdtrSchmeId');
|
|
$nm_cdtr_schme_id_node = $this->xml->createElement('Nm');
|
|
$id_cdtr_schme_id_node = $this->xml->createElement('Id');
|
|
$prvt_id_node = $this->xml->createElement('PrvtId');
|
|
$othr_node = $this->xml->createElement('Othr');
|
|
$id_othr_node = $this->xml->createElement('Id');
|
|
$schme_nm_node = $this->xml->createElement('SchmeNm');
|
|
$prtry_node = $this->xml->createElement('Prtry');
|
|
$pmt_inf_id_node->nodeValue = $this->makeId();
|
|
$pmt_mtd_node->nodeValue = 'DD';//Direct Debit
|
|
$btch_bookg_node->nodeValue = 'false';
|
|
$nb_of_txs_node->nodeValue = '1';
|
|
$ctrl_sum_node->nodeValue = $this->intToDecimal($payment['amount']);
|
|
$cd_svc_lvl_node->nodeValue = 'SEPA';
|
|
$cd_lcl_instrm_node->nodeValue = 'CORE';
|
|
$seq_tp_node->nodeValue = $payment['type'];//Define a check for: FRST RCUR OOFF FNAL
|
|
$reqd_colltn_dt_node->nodeValue = $payment['collection_date'];
|
|
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
|
|
$nm_cdtr_node->nodeValue = htmlentities($this->config['name'], ENT_XML1, 'UTF-8');
|
|
} else {
|
|
$nm_cdtr_node->nodeValue = htmlentities($this->config['name'], ENT_QUOTES, 'UTF-8');
|
|
}
|
|
$iban_cdtr_acct_node->nodeValue = $this->config['IBAN'];
|
|
if (isset($this->config['BIC'])) {
|
|
$bic_cdtr_agt_node->nodeValue = $this->config['BIC'];
|
|
}
|
|
$chrg_br_node->nodeValue = 'SLEV';
|
|
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
|
|
$nm_cdtr_schme_id_node->nodeValue = htmlentities($this->config['name'], ENT_XML1, 'UTF-8');
|
|
} else {
|
|
$nm_cdtr_schme_id_node->nodeValue = htmlentities($this->config['name'], ENT_QUOTES, 'UTF-8');
|
|
}
|
|
$id_othr_node->nodeValue = $this->config['creditor_id'];
|
|
$prtry_node->nodeValue = 'SEPA';
|
|
} else {//Get the batch node for this kind of payment to add the DrctDbtTxInf node.
|
|
$batch = $this->getBatch($payment['type'], $payment['collection_date']);
|
|
}
|
|
//Create the payment node.
|
|
$drct_dbt_tx_inf_node = $this->xml->createElement('DrctDbtTxInf');
|
|
$pmt_id_node = $this->xml->createElement('PmtId');
|
|
$end_to_end_id_node = $this->xml->createElement('EndToEndId');
|
|
$instd_amt_node = $this->xml->createElement('InstdAmt');
|
|
$drct_dbt_tx_node = $this->xml->createElement('DrctDbtTx');
|
|
$mndt_rltd_inf_node = $this->xml->createElement('MndtRltdInf');
|
|
$mndt_id_node = $this->xml->createElement('MndtId');
|
|
$dt_of_sgntr_node = $this->xml->createElement('DtOfSgntr');
|
|
if (isset($payment['BIC'])) {
|
|
$dbtr_agt_node = $this->xml->createElement('DbtrAgt');
|
|
$fin_instn_id_dbtr_agt_node = $this->xml->createElement('FinInstnId');
|
|
if (isset($this->config['version']) && $this->config['version'] == '3') {
|
|
$bic_dbtr_agt_node = $this->xml->createElement('BICFI');
|
|
} else {
|
|
$bic_dbtr_agt_node = $this->xml->createElement('BIC');
|
|
}
|
|
}
|
|
$dbtr_node = $this->xml->createElement('Dbtr');
|
|
$nm_dbtr_node = $this->xml->createElement('Nm');
|
|
$dbtr_acct_node = $this->xml->createElement('DbtrAcct');
|
|
$id_dbtr_acct_node = $this->xml->createElement('Id');
|
|
$iban_dbtr_acct_node = $this->xml->createElement('IBAN');
|
|
$rmt_inf_node = $this->xml->createElement('RmtInf');
|
|
$ustrd_node = $this->xml->createElement('Ustrd');
|
|
|
|
//Set the payment node information
|
|
$instd_amt_node->setAttribute('Ccy', $this->config['currency']);
|
|
$instd_amt_node->nodeValue = $this->intToDecimal($payment['amount']);
|
|
$mndt_id_node->nodeValue = $payment['mandate_id'];
|
|
$dt_of_sgntr_node->nodeValue = $payment['mandate_date'];
|
|
if (isset($payment['BIC'])) {
|
|
$bic_dbtr_agt_node->nodeValue = $payment['BIC'];
|
|
}
|
|
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
|
|
$nm_dbtr_node->nodeValue = htmlentities($payment['name'], ENT_XML1, 'UTF-8');
|
|
} else {
|
|
$nm_dbtr_node->nodeValue = htmlentities($payment['name'], ENT_QUOTES, 'UTF-8');
|
|
}
|
|
$iban_dbtr_acct_node->nodeValue = $payment['IBAN'];
|
|
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
|
|
$ustrd_node->nodeValue = htmlentities($payment['description'], ENT_XML1, 'UTF-8');
|
|
} else {
|
|
$ustrd_node->nodeValue = htmlentities($payment['description'], ENT_QUOTES, 'UTF-8');
|
|
}
|
|
$end_to_end_id_node->nodeValue = $this->makeId();
|
|
//Fold the nodes, if batch is enabled, some of this will be done by the batch.
|
|
if ($this->config['batch'] == false) {
|
|
$pmt_inf_node->appendChild($pmt_inf_id_node);
|
|
$pmt_inf_node->appendChild($pmt_mtd_node);
|
|
$pmt_inf_node->appendChild($btch_bookg_node);
|
|
$pmt_inf_node->appendChild($nb_of_txs_node);
|
|
$pmt_inf_node->appendChild($ctrl_sum_node);
|
|
$svc_lvl_node->appendChild($cd_svc_lvl_node);
|
|
$pmt_tp_inf_node->appendChild($svc_lvl_node);
|
|
$lcl_instrm_node->appendChild($cd_lcl_instrm_node);
|
|
$pmt_tp_inf_node->appendChild($lcl_instrm_node);
|
|
$pmt_tp_inf_node->appendChild($seq_tp_node);
|
|
$pmt_inf_node->appendChild($pmt_tp_inf_node);
|
|
$pmt_inf_node->appendChild($reqd_colltn_dt_node);
|
|
$cdtr_node->appendChild($nm_cdtr_node);
|
|
$pmt_inf_node->appendChild($cdtr_node);
|
|
$id_cdtr_acct_node->appendChild($iban_cdtr_acct_node);
|
|
$cdtr_acct_node->appendChild($id_cdtr_acct_node);
|
|
$pmt_inf_node->appendChild($cdtr_acct_node);
|
|
$fin_instn_id_cdtr_agt_node->appendChild($bic_cdtr_agt_node);
|
|
$cdtr_agt_node->appendChild($fin_instn_id_cdtr_agt_node);
|
|
$pmt_inf_node->appendChild($cdtr_agt_node);
|
|
$pmt_inf_node->appendChild($chrg_br_node);
|
|
$cdtr_schme_id_node->appendChild($nm_cdtr_schme_id_node);
|
|
$othr_node->appendChild($id_othr_node);
|
|
$schme_nm_node->appendChild($prtry_node);
|
|
$othr_node->appendChild($schme_nm_node);
|
|
$prvt_id_node->appendChild($othr_node);
|
|
$id_cdtr_schme_id_node->appendChild($prvt_id_node);
|
|
$cdtr_schme_id_node->appendChild($id_cdtr_schme_id_node);
|
|
$pmt_inf_node->appendChild($cdtr_schme_id_node);
|
|
}
|
|
$pmt_id_node->appendChild($end_to_end_id_node);
|
|
$drct_dbt_tx_inf_node->appendChild($pmt_id_node);
|
|
$drct_dbt_tx_inf_node->appendChild($instd_amt_node);
|
|
$mndt_rltd_inf_node->appendChild($mndt_id_node);
|
|
$mndt_rltd_inf_node->appendChild($dt_of_sgntr_node);
|
|
$drct_dbt_tx_node->appendChild($mndt_rltd_inf_node);
|
|
$drct_dbt_tx_inf_node->appendChild($drct_dbt_tx_node);
|
|
if (isset($payment['BIC'])) {
|
|
$fin_instn_id_dbtr_agt_node->appendChild($bic_dbtr_agt_node);
|
|
$dbtr_agt_node->appendChild($fin_instn_id_dbtr_agt_node);
|
|
$drct_dbt_tx_inf_node->appendChild($dbtr_agt_node);
|
|
}
|
|
$dbtr_node->appendChild($nm_dbtr_node);
|
|
$drct_dbt_tx_inf_node->appendChild($dbtr_node);
|
|
$id_dbtr_acct_node->appendChild($iban_dbtr_acct_node);
|
|
$dbtr_acct_node->appendChild($id_dbtr_acct_node);
|
|
$drct_dbt_tx_inf_node->appendChild($dbtr_acct_node);
|
|
$rmt_inf_node->appendChild($ustrd_node);
|
|
$drct_dbt_tx_inf_node->appendChild($rmt_inf_node);
|
|
$pmt_id_node->appendChild($end_to_end_id_node);
|
|
if ($this->config['batch'] == false) {
|
|
//Add to the document
|
|
$pmt_inf_node->appendChild($drct_dbt_tx_inf_node);
|
|
$cstmr_drct_dbt_initn_node->appendChild($pmt_inf_node);
|
|
} else {
|
|
//Update the batch metrics
|
|
$batch['ctrlSum']->nodeValue += $payment['amount'];
|
|
$batch['nbOfTxs']->nodeValue++;
|
|
//Add to the batch
|
|
$batch['node']->appendChild($drct_dbt_tx_inf_node);
|
|
}
|
|
}
|
|
/**
|
|
* Function to finalize and save the document after all payments are added.
|
|
* @return The xml to be echoed or saved to file.
|
|
*/
|
|
public function save()
|
|
{
|
|
$this->finalize();
|
|
$result = $this->xml->saveXML();
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Function to validate xml against the pain.008.001.02 schema definition.
|
|
* @param $xml The xml, as a string, to validate agianst the schema.
|
|
*/
|
|
public function validate($xml)
|
|
{
|
|
$domdoc = new DOMDocument();
|
|
$domdoc->loadXML($xml);
|
|
if (isset($this->config['version']) && $this->config['version'] == '3') {
|
|
return $domdoc->schemaValidate('pain.008.001.03.xsd');
|
|
} else {
|
|
return $domdoc->schemaValidate('pain.008.001.02.xsd');
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Function to add a custom node to the document.
|
|
* @param $parent_xpath A valid XPATH expression defining the parent of the new node
|
|
* @param $name The name of the new node
|
|
* @param $value The value of the new node (Optional, default '')
|
|
* @param $attr Key => Value array defining the attributes (Optional, default none)
|
|
*/
|
|
public function addCustomNode($parent_xpath, $name, $value = '', $attr = array())
|
|
{
|
|
$xpath = new DOMXPath($this->xml);
|
|
$parent = $xpath->query($parent_xpath);
|
|
if ($parent == false || $parent->length == 0) {
|
|
throw new Exception('Invalid XPATH expression, or no results found: '.$parent_xpath);
|
|
}
|
|
$newnode = $this->xml->createElement($name);
|
|
if ($value != '') {
|
|
$newnode->nodeValue = $value;
|
|
}
|
|
if (!empty($attr)) {
|
|
foreach ($attr as $attr_name => $attr_value) {
|
|
$newnode->setAttribute($attr_name, $attr_value);
|
|
}
|
|
}
|
|
$parent->item(0)->appendChild($newnode);
|
|
}
|
|
/**
|
|
* Function to finalize the document, completes the header with metadata, and processes batches.
|
|
*/
|
|
private function finalize()
|
|
{
|
|
if (!empty($this->batch_array)) {
|
|
$cstmr_drct_dbt_initn_node = $this->getCstmrDrctDbtInitnNode();
|
|
foreach ($this->batch_array as $batch) {
|
|
$batch['ctrlSum']->nodeValue = $this->intToDecimal($batch['ctrlSum']->nodeValue);
|
|
$cstmr_drct_dbt_initn_node->appendChild($batch['node']);
|
|
}
|
|
}
|
|
$trx_count = $this->xml->getElementsByTagName('DrctDbtTxInf');
|
|
$trx_count = $trx_count->length;
|
|
$trx_amounts = $this->xml->getElementsByTagName('InstdAmt');
|
|
$trx_amount_array = array();
|
|
foreach ($trx_amounts as $amount) {
|
|
$trx_amount_array[] = $amount->nodeValue;
|
|
}
|
|
$trx_amount = $this->calcTotalAmount($trx_amount_array);
|
|
$xpath = new DOMXPath($this->xml);
|
|
$nb_of_txs_xpath = '//Document/CstmrDrctDbtInitn/GrpHdr/NbOfTxs';
|
|
$ctrl_sum_xpath = '//Document/CstmrDrctDbtInitn/GrpHdr/CtrlSum';
|
|
$nb_of_txs_node = $xpath->query($nb_of_txs_xpath)->item(0);
|
|
$ctrl_sum_node = $xpath->query($ctrl_sum_xpath)->item(0);
|
|
$nb_of_txs_node->nodeValue = $trx_count;
|
|
$ctrl_sum_node->nodeValue = $trx_amount;
|
|
}
|
|
/**
|
|
* Check the config file for required fields and validity.
|
|
* NOTE: A function entry in this field will NOT be evaluated if the field is not present in the
|
|
* config array. if this is necessary, please include it in the $required array as well.
|
|
* @param $config the config to check.
|
|
* @return TRUE if valid, error string if invalid.
|
|
*/
|
|
private function validateConfig($config)
|
|
{
|
|
$required = array('name',
|
|
'IBAN',
|
|
'batch',
|
|
'creditor_id',
|
|
'currency');
|
|
$functions = array('IBAN' => 'validateIBAN', 'BIC' => 'validateBIC');
|
|
|
|
foreach ($required as $requirement) {
|
|
if (array_key_exists($requirement, $config)) {
|
|
//It exists, check if not empty
|
|
if (empty($config[$requirement])) {
|
|
return $requirement.' is empty.';
|
|
}
|
|
} else {
|
|
return $requirement.' does not exist.';
|
|
}
|
|
}
|
|
|
|
foreach ($functions as $target => $function) {
|
|
if (array_key_exists($target, $config)) {
|
|
//Perform the RegEx
|
|
$function_result = call_user_func('SELF::'.$function, $config[$target]);
|
|
if ($function_result) {
|
|
continue;
|
|
} else {
|
|
return $target.' does not validate.';
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Check a payment for validity
|
|
* @param $payment The payment array
|
|
* @return TRUE if valid, error string if invalid.
|
|
*/
|
|
private function validatePayment($payment)
|
|
{
|
|
$required = array('name',
|
|
'IBAN',
|
|
'amount',
|
|
'type',
|
|
'collection_date',
|
|
'mandate_id',
|
|
'mandate_date',
|
|
'description');
|
|
$functions = array('IBAN' => 'validateIBAN',
|
|
'BIC' => 'validateBIC',
|
|
'amount' => 'validateAmount',
|
|
'collection_date' => 'validateDate',
|
|
'mandate_date' => 'validateDate',
|
|
'type' => 'validateDDType');
|
|
foreach ($required as $requirement) {
|
|
//Check if the config has the required parameter
|
|
if (array_key_exists($requirement, $payment)) {
|
|
//It exists, check if not empty
|
|
if (empty($payment[$requirement])) {
|
|
return $requirement.' is empty.';
|
|
}
|
|
} else {
|
|
return $requirement.' does not exist.';
|
|
}
|
|
}
|
|
foreach ($functions as $target => $function) {
|
|
//Check if it is even there in the config
|
|
if (array_key_exists($target, $payment)) {
|
|
//Perform the RegEx
|
|
$function_result = call_user_func('SELF::'.$function, $payment[$target]);
|
|
if ($function_result) {
|
|
continue;
|
|
} else {
|
|
return $target.' does not validate.';
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Validate an IBAN Number.
|
|
* @param $iban the IBAN number to check.
|
|
* @return BOOLEAN TRUE if valid, FALSE if invalid.
|
|
*/
|
|
public static function validateIBAN($iban)
|
|
{
|
|
$result = preg_match('/[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{4}[0-9]{7}([a-zA-Z0-9]?){0,16}/', $iban);
|
|
if ($result > 0 && $result !== false) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validate a BIC number.Payment Information
|
|
* @param $bic the BIC number to check.
|
|
* @return TRUE if valid, FALSE if invalid.
|
|
*/
|
|
public static function validateBIC($bic)
|
|
{
|
|
$result = preg_match('([a-zA-Z]{4}[a-zA-Z]{2}[a-zA-Z0-9]{2}([a-zA-Z0-9]{3})?)', $bic);
|
|
if ($result > 0 && $result !== false) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
/**
|
|
* Function to validate a ISO date.
|
|
* @param $date The date to validate.
|
|
* @return True if valid, error string if invalid.
|
|
*/
|
|
public static function validateDate($date)
|
|
{
|
|
$result = DateTime::createFromFormat('Y-m-d', $date);
|
|
if ($result === false) {
|
|
return false;
|
|
} else {
|
|
return $date.' is not a valid ISO Date';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function to validate the Direct Debit Transaction types
|
|
* @param Typecode
|
|
* @return True if valid, error string if invalid.
|
|
*/
|
|
public static function validateDDType($type)
|
|
{
|
|
$types = array('FRST', 'RCUR', 'FNAL', 'OOFF');
|
|
if (in_array($type, $types)) {
|
|
return true;
|
|
} else {
|
|
return $type.' is not a valid Sepa Direct Debit Transaction Type.';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function to validate an amount, to check that amount is in cents.
|
|
* @param $amount The amount to validate.
|
|
* @return TRUE if valid, FALSE if invalid.
|
|
*/
|
|
public static function validateAmount($amount)
|
|
{
|
|
return ctype_digit((int)($amount));
|
|
}
|
|
|
|
/**
|
|
* Function to convert an amount in cents to a decimal (with point).
|
|
* @param $int The amount as decimal string
|
|
* @return The decimal
|
|
*/
|
|
private function intToDecimal($int)
|
|
{
|
|
$before = Tools::substr($int, 0, -2);
|
|
$after = Tools::substr($int, -2);
|
|
if (empty($before)) {
|
|
$before = 0;
|
|
}
|
|
if (Tools::strlen($after) == 1) {
|
|
$after = '0'.$after;
|
|
}
|
|
return $before.'.'.$after;
|
|
}
|
|
|
|
/**
|
|
* Function to convert an amount in decimal to cents (without point).
|
|
* @param $decimal The amount as decimal
|
|
* @return The amount as integer string
|
|
*/
|
|
private function decimalToInt($decimal)
|
|
{
|
|
return str_replace('.', '', $decimal);
|
|
}
|
|
|
|
/**
|
|
* Function to calculate the sum of the amounts, given as decimals in an array.
|
|
* @param $array The array with decimals
|
|
* @return The decimal sum of the array
|
|
*/
|
|
private function calcTotalAmount($array)
|
|
{
|
|
$ints = array();
|
|
$sum = 0;
|
|
foreach ($array as $decimal) {
|
|
$ints[] = $this->decimalToInt($decimal);
|
|
}
|
|
$sum = array_sum($ints);
|
|
$sum = $this->intToDecimal($sum);
|
|
return $sum;
|
|
}
|
|
|
|
/**
|
|
* Create a random Message Id f$PmtInfNodeor the header, prefixed with a timestamp.
|
|
* @return the Message Id.
|
|
*/
|
|
private function makeMsgId()
|
|
{
|
|
$random = mt_rand();
|
|
$random = md5($random);
|
|
$random = Tools::substr($random, 0, 12);
|
|
$timestamp = date('dmYsi');
|
|
return $timestamp.'-'.$random;
|
|
}
|
|
|
|
/**
|
|
* Create a random id, combined with the name (truncated at 22 chars).
|
|
* @return the Id.
|
|
*/
|
|
private function makeId()
|
|
{
|
|
$random = mt_rand();
|
|
$random = md5($random);
|
|
$random = Tools::substr($random, 0, 12);
|
|
$name = $this->config['name'];
|
|
$length = Tools::strlen($name);
|
|
if ($length > 22) {
|
|
$name = Tools::substr($name, 0, 22);
|
|
}
|
|
return $name.'-'.$random;
|
|
}
|
|
|
|
/**
|
|
* Function to get the CstmrDrctDbtInitnNode from the current document.
|
|
* @return The CstmrDrctDbtInitn DOMNode.
|
|
* @throws Exception when the node does noet exist or there are more then one.
|
|
*/
|
|
private function getCstmrDrctDbtInitnNode()
|
|
{
|
|
$cstmr_drct_dbt_initn_node_list = $this->xml->getElementsByTagName('CstmrDrctDbtInitn');
|
|
if ($cstmr_drct_dbt_initn_node_list->length != 1) {
|
|
throw new Exception('Error retrieving node from document: No or Multiple CstmrDrctDbtInitn');
|
|
}
|
|
return $cstmr_drct_dbt_initn_node_list->item(0);
|
|
}
|
|
|
|
/**
|
|
* Function to create a batch (PmtInf with BtchBookg set true) element.
|
|
* @param $type The DirectDebit type for this batch.
|
|
* @param $date The required collection date.
|
|
*/
|
|
private function getBatch($type, $date)
|
|
{
|
|
//if the batch for this type and date already exists, return it.
|
|
if ($this->validateDDType($type) && $this->validateDate($date) &&
|
|
array_key_exists($type.'::'.$date, $this->batch_array)) {
|
|
return $this->batch_array[$type.'::'.$date];
|
|
}
|
|
//Create the PmtInf element and its subelements
|
|
// $reqd_exctn_dt_tm_node = $this->xml->createElement('ReqdExctnDt');
|
|
$pmt_inf_node = $this->xml->createElement('PmtInf');
|
|
$pmt_inf_id_node = $this->xml->createElement('PmtInfId');
|
|
$pmt_mtd_node = $this->xml->createElement('PmtMtd');
|
|
$btch_bookg_node = $this->xml->createElement('BtchBookg');
|
|
$nb_of_txs_node = $this->xml->createElement('NbOfTxs');
|
|
$ctrl_sum_node = $this->xml->createElement('CtrlSum');
|
|
$pmt_tp_inf_node = $this->xml->createElement('PmtTpInf');
|
|
$svc_lvl_node = $this->xml->createElement('SvcLvl');
|
|
$cd_svc_lvl_node = $this->xml->createElement('Cd');
|
|
$lcl_instrm_node = $this->xml->createElement('LclInstrm');
|
|
$cd_lcl_instrm_node = $this->xml->createElement('Cd');
|
|
$seq_tp_node = $this->xml->createElement('SeqTp');
|
|
$reqd_colltn_dt_node = $this->xml->createElement('ReqdColltnDt');
|
|
$cdtr_node = $this->xml->createElement('Cdtr');
|
|
$nm_cdtr_node = $this->xml->createElement('Nm');
|
|
$cdtr_acct_node = $this->xml->createElement('CdtrAcct');
|
|
$id_cdtr_acct_node = $this->xml->createElement('Id');
|
|
$iban_cdtr_acct_node = $this->xml->createElement('IBAN');
|
|
if (isset($this->config['BIC'])) {
|
|
$cdtr_agt_node = $this->xml->createElement('CdtrAgt');
|
|
$fin_instn_id_cdtr_agt_node = $this->xml->createElement('FinInstnId');
|
|
if (isset($this->config['version']) && $this->config['version'] == '3') {
|
|
$bic_cdtr_agt_node = $this->xml->createElement('BICFI');
|
|
} else {
|
|
$bic_cdtr_agt_node = $this->xml->createElement('BIC');
|
|
}
|
|
}
|
|
$chrg_br_node = $this->xml->createElement('ChrgBr');
|
|
$cdtr_schme_id_node = $this->xml->createElement('CdtrSchmeId');
|
|
$nm_cdtr_schme_id_node = $this->xml->createElement('Nm');
|
|
$id_cdtr_schme_id_node = $this->xml->createElement('Id');
|
|
$prvt_id_node = $this->xml->createElement('PrvtId');
|
|
$othr_node = $this->xml->createElement('Othr');
|
|
$id_othr_node = $this->xml->createElement('Id');
|
|
$schme_nm_node = $this->xml->createElement('SchmeNm');
|
|
$prtry_node = $this->xml->createElement('Prtry');
|
|
//Fill in the blanks
|
|
$pmt_inf_id_node->nodeValue = $this->makeId();
|
|
$pmt_mtd_node->nodeValue = 'DD';//Direct Debit
|
|
$btch_bookg_node->nodeValue = 'true';
|
|
$ctrl_sum_node->nodeValue = '0';
|
|
$cd_svc_lvl_node->nodeValue = 'SEPA';
|
|
$cd_lcl_instrm_node->nodeValue = 'CORE';
|
|
$seq_tp_node->nodeValue = $type;//Define a check for: FRST RCUR OOFF FNAL
|
|
$reqd_colltn_dt_node->nodeValue = $date;
|
|
|
|
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
|
|
$nm_cdtr_node->nodeValue = htmlentities($this->config['name'], ENT_XML1, 'UTF-8');
|
|
} else {
|
|
$nm_cdtr_node->nodeValue = htmlentities($this->config['name'], ENT_QUOTES, 'UTF-8');
|
|
}
|
|
$iban_cdtr_acct_node->nodeValue = $this->config['IBAN'];
|
|
if (isset($this->config['BIC'])) {
|
|
$bic_cdtr_agt_node->nodeValue = $this->config['BIC'];
|
|
}
|
|
$chrg_br_node->nodeValue = 'SLEV';
|
|
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
|
|
$nm_cdtr_schme_id_node->nodeValue = htmlentities($this->config['name'], ENT_XML1, 'UTF-8');
|
|
} else {
|
|
$nm_cdtr_schme_id_node->nodeValue = htmlentities($this->config['name'], ENT_QUOTES, 'UTF-8');
|
|
}
|
|
$id_othr_node->nodeValue = $this->config['creditor_id'];
|
|
$prtry_node->nodeValue = 'SEPA';
|
|
//Fold the batch information
|
|
$pmt_inf_node->appendChild($pmt_inf_id_node);
|
|
$pmt_inf_node->appendChild($pmt_mtd_node);
|
|
$pmt_inf_node->appendChild($btch_bookg_node);
|
|
$pmt_inf_node->appendChild($nb_of_txs_node);
|
|
$pmt_inf_node->appendChild($ctrl_sum_node);
|
|
$svc_lvl_node->appendChild($cd_svc_lvl_node);
|
|
$pmt_tp_inf_node->appendChild($svc_lvl_node);
|
|
// $pmt_inf_node->appendChild($reqd_exctn_dt_tm_node);
|
|
$lcl_instrm_node->appendChild($cd_lcl_instrm_node);
|
|
$pmt_tp_inf_node->appendChild($lcl_instrm_node);
|
|
$pmt_tp_inf_node->appendChild($seq_tp_node);
|
|
$pmt_inf_node->appendChild($pmt_tp_inf_node);
|
|
$pmt_inf_node->appendChild($reqd_colltn_dt_node);
|
|
$cdtr_node->appendChild($nm_cdtr_node);
|
|
$pmt_inf_node->appendChild($cdtr_node);
|
|
$id_cdtr_acct_node->appendChild($iban_cdtr_acct_node);
|
|
$cdtr_acct_node->appendChild($id_cdtr_acct_node);
|
|
$pmt_inf_node->appendChild($cdtr_acct_node);
|
|
if (isset($this->config['BIC'])) {
|
|
$fin_instn_id_cdtr_agt_node->appendChild($bic_cdtr_agt_node);
|
|
$cdtr_agt_node->appendChild($fin_instn_id_cdtr_agt_node);
|
|
$pmt_inf_node->appendChild($cdtr_agt_node);
|
|
}
|
|
$pmt_inf_node->appendChild($chrg_br_node);
|
|
//$cdtr_schme_id_node->appendChild($nm_cdtr_schme_id_node);
|
|
$othr_node->appendChild($id_othr_node);
|
|
$schme_nm_node->appendChild($prtry_node);
|
|
$othr_node->appendChild($schme_nm_node);
|
|
$prvt_id_node->appendChild($othr_node);
|
|
$id_cdtr_schme_id_node->appendChild($prvt_id_node);
|
|
$cdtr_schme_id_node->appendChild($id_cdtr_schme_id_node);
|
|
$pmt_inf_node->appendChild($cdtr_schme_id_node);
|
|
//Add it to the batch_array.
|
|
$this->batch_array[$type.'::'.$date]['node'] = $pmt_inf_node;
|
|
$this->batch_array[$type.'::'.$date]['ctrlSum'] = $ctrl_sum_node;
|
|
$this->batch_array[$type.'::'.$date]['nbOfTxs'] = $nb_of_txs_node;
|
|
//Return the batch array for this type and date.
|
|
return $this->batch_array[$type.'::'.$date];
|
|
}
|
|
}
|