1
|
|
|
<?php
|
2
|
|
|
namespace SKien\Sepa;
|
3
|
|
|
|
4
|
|
|
/**
|
5
|
|
|
* Class representing Payment Instruction Info (PII).
|
6
|
|
|
*
|
7
|
|
|
* #### Usage:
|
8
|
|
|
* 1. Create a instance of this class and set all properties using the `SepaPmtInf::setXXX()` methods
|
9
|
|
|
* or `SepaPmtInf::fromArray()`.
|
10
|
|
|
* 2. Attach the instance to the `SepaDoc` using the `SepaDoc::addPaymentInstructionInfo()` method.
|
11
|
|
|
* 3. Generate the desired transactions (`new SepaTxInf()`) and assign them to this payment info instance.
|
12
|
|
|
*
|
13
|
|
|
* @package Sepa
|
14
|
|
|
* @author Stefanius <[email protected]>
|
15
|
|
|
* @copyright MIT License - see the LICENSE file for details
|
16
|
|
|
*/
|
17
|
|
|
class SepaPmtInf extends \DOMElement
|
18
|
|
|
{
|
19
|
|
|
use SepaHelper;
|
20
|
|
|
|
21
|
|
|
/** @var string unique id*/
|
22
|
|
|
protected string $strID = '';
|
23
|
|
|
/** @var string full name of applicant*/
|
24
|
|
|
protected string $strName = '';
|
25
|
|
|
/** @var string IBAN*/
|
26
|
|
|
protected string $strIBAN = '';
|
27
|
|
|
/** @var string BIC*/
|
28
|
|
|
protected string $strBIC = '';
|
29
|
|
|
/** @var string CI (Creditor Scheme Identification)*/
|
30
|
|
|
protected string $strCI = '';
|
31
|
|
|
/** @var string sequence type (Sepa::FRST, Sepa::SEQ_RECURRENT, Sepa::SEQ_ONE_OFF, Sepa::SEQ_FINAL)*/
|
32
|
|
|
protected string $strSeqType = '';
|
33
|
|
|
/** @var int requested collection/execution date */
|
34
|
|
|
protected int $uxtsCollExecDate = 0;
|
35
|
|
|
/** @var string an optional category purpose code (if all payments for the PII belongs to same purpose) */
|
36
|
|
|
protected string $strCategoryPurpose = '';
|
37
|
|
|
/** @var SepaDoc parent document */
|
38
|
|
|
private SepaDoc $sepaDoc;
|
39
|
|
|
/** @var int count of transactions contained in PII */
|
40
|
|
|
private int $iTxCount = 0;
|
41
|
|
|
/** @var \DOMElement DOM element containing count of transactions */
|
42
|
|
|
private ?\DOMElement $xmlTxCount = null;
|
43
|
|
|
/** @var float controlsum */
|
44
|
|
|
private float $dblCtrlSum = 0.0;
|
45
|
|
|
/** @var \DOMElement DOM element containing controlsum */
|
46
|
|
|
private ?\DOMElement $xmlCtrlSum = null;
|
47
|
|
|
|
48
|
|
|
/**
|
49
|
|
|
* Creating SEPA Payment Instruction Info (PII).
|
50
|
|
|
* @param SepaDoc $sepaDoc
|
51
|
|
|
*/
|
52
|
|
|
function __construct(SepaDoc $sepaDoc)
|
53
|
|
|
{
|
54
|
|
|
// store the parent doc and generate an unique id
|
55
|
|
|
parent::__construct("PmtInf");
|
56
|
|
|
|
57
|
|
|
// don't append any child at this point - created element have to be associated with a document after creation
|
58
|
|
|
$this->sepaDoc = $sepaDoc;
|
59
|
|
|
$this->strID = self::createUID();
|
60
|
|
|
}
|
61
|
|
|
|
62
|
|
|
/**
|
63
|
|
|
* Validate the object.
|
64
|
|
|
* > This method usually dont have to be called from outside. It is
|
65
|
|
|
* called, when an instance is attached to a SepaDoc!
|
66
|
|
|
* @return int Sepa::OK or error code
|
67
|
|
|
* @internal
|
68
|
|
|
*/
|
69
|
|
|
public function validate() : int
|
70
|
|
|
{
|
71
|
|
|
$iErr = $this->validateIBAN();
|
72
|
|
|
$iErr |= $this->validateBIC();
|
73
|
|
|
$iErr |= $this->validateCI();
|
74
|
|
|
$iErr |= $this->validateMandatory();
|
75
|
|
|
return $iErr;
|
76
|
|
|
}
|
77
|
|
|
|
78
|
|
|
/**
|
79
|
|
|
* Get the error message for given error code.
|
80
|
|
|
* Since a payment info can contain multiple errors, the result may contain more than
|
81
|
|
|
* one message separated by a separator. <br>
|
82
|
|
|
* The separator can be specified to meet the needs of different output destinations.
|
83
|
|
|
* Default value is a linefeed.
|
84
|
|
|
* @param int $iError the errorcode
|
85
|
|
|
* @param string $strLF Separator for multiple errors (default: PHP_EOL; posible values: '<br/>', ';', ...)
|
86
|
|
|
* @return string
|
87
|
|
|
*/
|
88
|
|
|
public function errorMsg(int $iError, string $strLF = PHP_EOL) : string
|
89
|
|
|
{
|
90
|
|
|
// route to the Sepa class to get localized message
|
91
|
|
|
return Sepa::errorMsgPmtInf($iError, $strLF);
|
92
|
|
|
}
|
93
|
|
|
|
94
|
|
|
/**
|
95
|
|
|
* Add a transaction.
|
96
|
|
|
* <b>Important:</b><br>
|
97
|
|
|
* The PPI <b>must</b> be attached to the SepaDoc <b>before</b> the first transaktion is added!
|
98
|
|
|
* @param SepaTxInf $oTxInf
|
99
|
|
|
* @return int Sepa::OK or error code from SepaTxInf::validate()
|
100
|
|
|
*/
|
101
|
|
|
public function addTransaction(SepaTxInf $oTxInf) : int
|
102
|
|
|
{
|
103
|
|
|
// element must been added as child to valid parent
|
104
|
|
|
if ($this->xmlCtrlSum === null || $this->xmlTxCount === null) {
|
105
|
|
|
trigger_error('element not added to parent (you must call SepaDoc::addPaymentInstructionInfo() before)!', E_USER_ERROR);
|
106
|
|
|
}
|
107
|
|
|
// transaction method have to fit to parent doc
|
108
|
|
|
if ($this->sepaDoc->getType() != $oTxInf->getType()) {
|
109
|
|
|
return Sepa::ERR_TX_INVALID_TYPE;
|
110
|
|
|
}
|
111
|
|
|
|
112
|
|
|
$iErr = $oTxInf->validate();
|
113
|
|
|
if ($iErr == Sepa::OK) {
|
114
|
|
|
if ($oTxInf->getType() == Sepa::CDD) {
|
115
|
|
|
$xmlTx = $this->addChild(null, 'DrctDbtTxInf');
|
116
|
|
|
|
117
|
|
|
$xmlNode = $this->addChild($xmlTx, 'PmtId');
|
118
|
|
|
$this->addChild($xmlNode, 'EndToEndId', $oTxInf->getPaymentId());
|
119
|
|
|
|
120
|
|
|
// Instructed Amount
|
121
|
|
|
$xmlNode = $this->addChild($xmlTx, 'InstdAmt', sprintf("%01.2f", $oTxInf->getValue()));
|
122
|
|
|
$xmlNode->SetAttribute('Ccy', 'EUR');
|
123
|
|
|
|
124
|
|
|
// Mandate Related Information
|
125
|
|
|
$xmlNode = $this->addChild($xmlTx, 'DrctDbtTx');
|
126
|
|
|
$xmlNode = $this->addChild($xmlNode, 'MndtRltdInf');
|
127
|
|
|
$this->addChild($xmlNode, 'MndtId', $oTxInf->getMandateId());
|
128
|
|
|
$this->addChild($xmlNode, 'DtOfSgntr', $oTxInf->getDateOfSignature());
|
129
|
|
|
$this->addChild($xmlNode, 'AmdmntInd', 'false');
|
130
|
|
|
|
131
|
|
|
// Debitor Information Name, IBAN, BIC
|
132
|
|
|
$xmlNode = $this->addChild($xmlTx, 'DbtrAgt');
|
133
|
|
|
$xmlNode = $this->addChild($xmlNode, 'FinInstnId');
|
134
|
|
|
$this->addChild($xmlNode, 'BIC', $oTxInf->getBIC());
|
135
|
|
|
|
136
|
|
|
$xmlNode = $this->addChild($xmlTx, 'Dbtr');
|
137
|
|
|
$this->addChild($xmlNode, 'Nm', $oTxInf->getName());
|
138
|
|
|
|
139
|
|
|
$xmlNode = $this->addChild($xmlTx, 'DbtrAcct');
|
140
|
|
|
$xmlNode = $this->addChild($xmlNode, 'Id');
|
141
|
|
|
$this->addChild($xmlNode, 'IBAN', $oTxInf->getIBAN());
|
142
|
|
|
|
143
|
|
|
// Ultimate Debitor if requested
|
144
|
|
|
$strUltmtDbtr = $oTxInf->getUltimateName();
|
145
|
|
|
if (strlen($strUltmtDbtr) > 0) {
|
146
|
|
|
$xmlNode = $this->addChild($xmlTx, 'UltmtDbtr');
|
147
|
|
|
$this->addChild($xmlNode, 'Nm', $strUltmtDbtr);
|
148
|
|
|
}
|
149
|
|
|
if (($strPurpose = $oTxInf->getPurpose()) != '') {
|
150
|
|
|
$xmlNode = $this->addChild($xmlTx, 'Purp');
|
151
|
|
|
$this->addChild($xmlNode, 'Cd', $strPurpose);
|
152
|
|
|
}
|
153
|
|
|
} else {
|
154
|
|
|
$xmlTx = $this->addChild(null, 'CdtTrfTxInf');
|
155
|
|
|
|
156
|
|
|
$xmlNode = $this->addChild($xmlTx, 'PmtId');
|
157
|
|
|
$this->addChild($xmlNode, 'EndToEndId', $oTxInf->getPaymentId());
|
158
|
|
|
|
159
|
|
|
// Amount
|
160
|
|
|
$xmlNode = $this->addChild($xmlTx, 'Amt');
|
161
|
|
|
$xmlNode = $this->addChild($xmlNode, 'InstdAmt', sprintf("%01.2f", $oTxInf->getValue()));
|
162
|
|
|
$xmlNode->SetAttribute('Ccy', 'EUR');
|
163
|
|
|
|
164
|
|
|
// Creditor Information Name, IBAN, BIC
|
165
|
|
|
$xmlNode = $this->addChild($xmlTx, 'CdtrAgt');
|
166
|
|
|
$xmlNode = $this->addChild($xmlNode, 'FinInstnId');
|
167
|
|
|
$this->addChild($xmlNode, 'BIC', $oTxInf->getBIC());
|
168
|
|
|
|
169
|
|
|
$xmlNode = $this->addChild($xmlTx, 'Cdtr');
|
170
|
|
|
$this->addChild($xmlNode, 'Nm', $oTxInf->getName());
|
171
|
|
|
|
172
|
|
|
$xmlNode = $this->addChild($xmlTx, 'CdtrAcct');
|
173
|
|
|
$xmlNode = $this->addChild($xmlNode, 'Id');
|
174
|
|
|
$this->addChild($xmlNode, 'IBAN', $oTxInf->getIBAN());
|
175
|
|
|
|
176
|
|
|
// Ultimate Creditor if requested
|
177
|
|
|
$strUltmtCbtr = $oTxInf->getUltimateName();
|
178
|
|
|
if (strlen($strUltmtCbtr) > 0) {
|
179
|
|
|
$xmlNode = $this->addChild($xmlTx, 'UltmtCbtr');
|
180
|
|
|
$this->addChild($xmlNode, 'Nm', $strUltmtCbtr);
|
181
|
|
|
}
|
182
|
|
|
if (($strPurpose = $oTxInf->getPurpose()) != '') {
|
183
|
|
|
$xmlNode = $this->addChild($xmlTx, 'Purp');
|
184
|
|
|
$this->addChild($xmlNode, 'Cd', $strPurpose);
|
185
|
|
|
}
|
186
|
|
|
}
|
187
|
|
|
|
188
|
|
|
// Remittance Information
|
189
|
|
|
$xmlNode = $this->addChild($xmlTx, 'RmtInf');
|
190
|
|
|
$this->addChild($xmlNode, 'Ustrd', $oTxInf->getDescription());
|
191
|
|
|
|
192
|
|
|
// calculate count and controlsum of transactions
|
193
|
|
|
$this->calc($oTxInf->getValue());
|
194
|
|
|
} else {
|
195
|
|
|
$this->sepaDoc->incInvalidCount();
|
196
|
|
|
}
|
197
|
|
|
return $iErr;
|
198
|
|
|
}
|
199
|
|
|
|
200
|
|
|
/**
|
201
|
|
|
* Create a element and set it as child for given parent.
|
202
|
|
|
* @param \DOMElement $xmlParent parent for the node. If null, child of current instance is created
|
203
|
|
|
* @param string $strNode nodename
|
204
|
|
|
* @param int|string $value nodevalue. If empty, no value will be assigned (to create node only containing child elements)
|
205
|
|
|
* @return \DOMElement
|
206
|
|
|
*/
|
207
|
|
|
protected function addChild(?\DOMElement $xmlParent, string $strNode, $value = '') : \DOMElement
|
208
|
|
|
{
|
209
|
|
|
if ($xmlParent == null) {
|
210
|
|
|
$xmlParent = $this;
|
211
|
|
|
}
|
212
|
|
|
$xmlNode = $this->sepaDoc->createElement($strNode);
|
213
|
|
|
if (!empty($value)) {
|
214
|
|
|
$xmlNode->nodeValue = (string)$value;
|
215
|
|
|
}
|
216
|
|
|
$xmlParent->appendChild($xmlNode);
|
217
|
|
|
|
218
|
|
|
return $xmlNode;
|
219
|
|
|
}
|
220
|
|
|
|
221
|
|
|
/**
|
222
|
|
|
* Calculate transaction count and controlsum for PII and update overall in parent doc.
|
223
|
|
|
* @param float $dblValue
|
224
|
|
|
*/
|
225
|
|
|
protected function calc(float $dblValue) : void
|
226
|
|
|
{
|
227
|
|
|
if ($this->xmlTxCount !== null && $this->xmlCtrlSum !== null) {
|
228
|
|
|
$this->iTxCount++;
|
229
|
|
|
$this->xmlTxCount->nodeValue = (string)$this->iTxCount;
|
230
|
|
|
$this->dblCtrlSum += $dblValue;
|
231
|
|
|
$this->xmlCtrlSum->nodeValue = sprintf("%01.2f", $this->dblCtrlSum);
|
232
|
|
|
|
233
|
|
|
$this->sepaDoc->calc($dblValue);
|
234
|
|
|
}
|
235
|
|
|
}
|
236
|
|
|
|
237
|
|
|
/**
|
238
|
|
|
* Return the internal unique ID.
|
239
|
|
|
* @return string
|
240
|
|
|
*/
|
241
|
|
|
public function getId() : string
|
242
|
|
|
{
|
243
|
|
|
return $this->strID;
|
244
|
|
|
}
|
245
|
|
|
|
246
|
|
|
/**
|
247
|
|
|
* Get the collection date.
|
248
|
|
|
* @return string
|
249
|
|
|
*/
|
250
|
|
|
public function getCollExecDate(string $type) : string
|
251
|
|
|
{
|
252
|
|
|
// no delay for CCT
|
253
|
|
|
$iDays = 0;
|
254
|
|
|
if ($type == Sepa::CDD) {
|
255
|
|
|
// CDD: Requested Collection Date depends on sequence type
|
256
|
|
|
$this->strSeqType == Sepa::SEQ_RECURRENT ? $iDays = 2 : $iDays = 5;
|
257
|
|
|
}
|
258
|
|
|
$dtCollect = self::calcDelayedDate($iDays, $this->uxtsCollExecDate);
|
259
|
|
|
return date('Y-m-d', $dtCollect);
|
260
|
|
|
}
|
261
|
|
|
|
262
|
|
|
/**
|
263
|
|
|
* Set the xml node containing transactions count.
|
264
|
|
|
* @param \DOMElement $xmlNode
|
265
|
|
|
*/
|
266
|
|
|
public function setTxCountNode(\DOMElement $xmlNode) : void
|
267
|
|
|
{
|
268
|
|
|
$this->xmlTxCount = $xmlNode;
|
269
|
|
|
}
|
270
|
|
|
|
271
|
|
|
/**
|
272
|
|
|
* Set the xml node containing control sum.
|
273
|
|
|
* @param \DOMElement $xmlNode
|
274
|
|
|
*/
|
275
|
|
|
public function setCtrlSumNode(\DOMElement $xmlNode) : void
|
276
|
|
|
{
|
277
|
|
|
$this->xmlCtrlSum = $xmlNode;
|
278
|
|
|
}
|
279
|
|
|
|
280
|
|
|
/**
|
281
|
|
|
* Set properties through associative array.
|
282
|
|
|
* Example array:
|
283
|
|
|
* ```php
|
284
|
|
|
* $aPPI = [
|
285
|
|
|
* 'strName' => '<name>',
|
286
|
|
|
* 'strCI' => '<CI>',
|
287
|
|
|
* 'strIBAN' => '<IBAN>',
|
288
|
|
|
* 'strBIC' => '<BIC>',
|
289
|
|
|
* 'strSeqType' => Sepa::SEQ_xxx,
|
290
|
|
|
* 'strCollExecDate' => 'setCollExecDate',
|
291
|
|
|
* ];
|
292
|
|
|
* ```
|
293
|
|
|
* The array does not have to contain all of the properties. The missing properties
|
294
|
|
|
* can be set later using the respective `setXXX()` method.
|
295
|
|
|
*
|
296
|
|
|
* @param array<string> $aProperties see description
|
297
|
|
|
*/
|
298
|
|
|
public function fromArray(array $aProperties) : void
|
299
|
|
|
{
|
300
|
|
|
// use the setter methods to ensure that all validations are made!
|
301
|
|
|
$aPropertyMap = [
|
302
|
|
|
'strName' => 'setName',
|
303
|
|
|
'strIBAN' => 'setIBAN',
|
304
|
|
|
'strBIC' => 'setBIC',
|
305
|
|
|
'strCI' => 'setCI',
|
306
|
|
|
'strSeqType' => 'setSeqType',
|
307
|
|
|
'strCollExecDate' => 'setCollExecDate',
|
308
|
|
|
];
|
309
|
|
|
foreach ($aPropertyMap as $strKey => $strFunc) {
|
310
|
|
|
if (isset($aProperties[$strKey])) {
|
311
|
|
|
$this->$strFunc($aProperties[$strKey]);
|
312
|
|
|
}
|
313
|
|
|
}
|
314
|
|
|
}
|
315
|
|
|
|
316
|
|
|
/**
|
317
|
|
|
* Set full name (lastname, firstname; company name; ...).
|
318
|
|
|
* @param string $strName
|
319
|
|
|
*/
|
320
|
|
|
public function setName(string $strName) : void
|
321
|
|
|
{
|
322
|
|
|
$this->strName = self::validString($strName, Sepa::MAX70);
|
323
|
|
|
}
|
324
|
|
|
|
325
|
|
|
/**
|
326
|
|
|
* Set IBAN.
|
327
|
|
|
* @param string $strIBAN
|
328
|
|
|
*/
|
329
|
|
|
public function setIBAN(string $strIBAN) : void
|
330
|
|
|
{
|
331
|
|
|
$this->strIBAN = $strIBAN;
|
332
|
|
|
}
|
333
|
|
|
|
334
|
|
|
/**
|
335
|
|
|
* Set BIC.
|
336
|
|
|
* @param string $strBIC
|
337
|
|
|
*/
|
338
|
|
|
public function setBIC(string $strBIC) : void
|
339
|
|
|
{
|
340
|
|
|
$this->strBIC = $strBIC;
|
341
|
|
|
}
|
342
|
|
|
|
343
|
|
|
/**
|
344
|
|
|
* Set CI (Creditor Scheme Identification).
|
345
|
|
|
* @param string $strCI
|
346
|
|
|
*/
|
347
|
|
|
public function setCI(string $strCI) : void
|
348
|
|
|
{
|
349
|
|
|
$this->strCI = $strCI;
|
350
|
|
|
}
|
351
|
|
|
|
352
|
|
|
/**
|
353
|
|
|
* Set sequence type (Sepa::FRST, Sepa::SEQ_RECURRENT, Sepa::SEQ_ONE_OFF, Sepa::SEQ_FINAL).
|
354
|
|
|
* @param string $strSeqType
|
355
|
|
|
*/
|
356
|
|
|
public function setSeqType(string $strSeqType) : void
|
357
|
|
|
{
|
358
|
|
|
$this->strSeqType = $strSeqType;
|
359
|
|
|
}
|
360
|
|
|
|
361
|
|
|
/**
|
362
|
|
|
* Set the requested collection/execution date.
|
363
|
|
|
* If no date set, the next possible date for execution/collection is calculated.
|
364
|
|
|
* > <b>Note:</b><br>
|
365
|
|
|
* > Banks are not obliged to process order data that was submitted more than 15 calendar days
|
366
|
|
|
* BEFORE the execution date.
|
367
|
|
|
* @param \DateTime|int|string $date may be string (format YYYY-MM-DD), int (unixtimestamp) or DateTime - object
|
368
|
|
|
*/
|
369
|
|
|
public function setCollExecDate($date) : void
|
370
|
|
|
{
|
371
|
|
|
if (is_object($date) && get_class($date) == 'DateTime') {
|
372
|
|
|
// DateTime -object
|
373
|
|
|
$this->uxtsCollExecDate = $date->getTimestamp();
|
374
|
|
|
} else if (is_numeric($date)) {
|
375
|
|
|
$this->uxtsCollExecDate = intval($date);
|
376
|
|
|
} else if (is_string($date)) {
|
377
|
|
|
$uxts = strtotime($date);
|
378
|
|
|
if ($uxts !== false) {
|
379
|
|
|
$this->uxtsCollExecDate = $uxts;
|
380
|
|
|
} |
381
|
|
|
}
|
382
|
|
|
}
|
383
|
|
|
|
384
|
|
|
/**
|
385
|
|
|
* Set the payment instruction category purpose.
|
386
|
|
|
* This is an optional value!
|
387
|
|
|
* If set, only ISO 20022 codes of the ExternalCategoryPurpose1Code list are allowed.
|
388
|
|
|
* Referr to the actual list that is available in worksheet '4-CategoryPurpose 'of the Excel
|
389
|
|
|
* file provided in the download at
|
390
|
|
|
* [www.iso20022.org](https://www.iso20022.org/catalogue-messages/additional-content-messages/external-code-sets)
|
391
|
|
|
* > <b>Attention:</b><br>
|
392
|
|
|
* > There is no validation whether in this module nor through the provided XSD schemas for
|
393
|
|
|
* this value. To avoid rejection of your data, you have to take care for valid values on your own.
|
394
|
|
|
* @link ./Category-Purpose-Codes
|
395
|
|
|
* @param string $strCategoryPurpose
|
396
|
|
|
*/
|
397
|
|
|
public function setCategoryPurpose(string $strCategoryPurpose) : void
|
398
|
|
|
{
|
399
|
|
|
$this->strCategoryPurpose = strtoupper(substr($strCategoryPurpose, 0, 4));
|
400
|
|
|
}
|
401
|
|
|
|
402
|
|
|
/**
|
403
|
|
|
* Get full name (lastname, firstname; company name; ...).
|
404
|
|
|
* @return string
|
405
|
|
|
*/
|
406
|
|
|
public function getName() : string
|
407
|
|
|
{
|
408
|
|
|
return $this->strName;
|
409
|
|
|
}
|
410
|
|
|
|
411
|
|
|
/**
|
412
|
|
|
* Get IBAN.
|
413
|
|
|
* @return string
|
414
|
|
|
*/
|
415
|
|
|
public function getIBAN() : string
|
416
|
|
|
{
|
417
|
|
|
return $this->strIBAN;
|
418
|
|
|
}
|
419
|
|
|
|
420
|
|
|
/**
|
421
|
|
|
* Get BIC.
|
422
|
|
|
* @return string
|
423
|
|
|
*/
|
424
|
|
|
public function getBIC() : string
|
425
|
|
|
{
|
426
|
|
|
return $this->strBIC;
|
427
|
|
|
}
|
428
|
|
|
|
429
|
|
|
/**
|
430
|
|
|
* Get CI (Creditor Scheme Identification).
|
431
|
|
|
* @return string
|
432
|
|
|
*/
|
433
|
|
|
public function getCI() : string
|
434
|
|
|
{
|
435
|
|
|
return $this->strCI;
|
436
|
|
|
}
|
437
|
|
|
|
438
|
|
|
/**
|
439
|
|
|
* Get sequence type (Sepa::FRST, Sepa::SEQ_RECURRENT, Sepa::SEQ_ONE_OFF, Sepa::SEQ_FINAL).
|
440
|
|
|
* @return string
|
441
|
|
|
*/
|
442
|
|
|
public function getSeqType() : string
|
443
|
|
|
{
|
444
|
|
|
return $this->strSeqType;
|
445
|
|
|
}
|
446
|
|
|
|
447
|
|
|
/**
|
448
|
|
|
* Get the payment instruction category purpose
|
449
|
|
|
* @return string
|
450
|
|
|
*/
|
451
|
|
|
public function getCategoryPurpose() : string
|
452
|
|
|
{
|
453
|
|
|
return $this->strCategoryPurpose;
|
454
|
|
|
}
|
455
|
|
|
|
456
|
|
|
/**
|
457
|
|
|
* Validate the IBAN.
|
458
|
|
|
* @return int Sepa::OK or errorcode
|
459
|
|
|
*/
|
460
|
|
|
private function validateIBAN() : int
|
461
|
|
|
{
|
462
|
|
|
$iErr = Sepa::OK;
|
463
|
|
|
if (!Sepa::checkValidation(Sepa::V_NO_IBAN_VALIDATION)) {
|
464
|
|
|
if (strlen($this->strIBAN) == 0) {
|
465
|
|
|
$iErr = Sepa::ERR_PMT_IBAN_MISSING;
|
466
|
|
|
} else if (Sepa::validateIBAN($this->strIBAN) != Sepa::OK) {
|
467
|
|
|
$iErr = Sepa::ERR_PMT_INVALID_IBAN;
|
468
|
|
|
}
|
469
|
|
|
}
|
470
|
|
|
return $iErr;
|
471
|
|
|
}
|
472
|
|
|
|
473
|
|
|
/**
|
474
|
|
|
* Validate the BIC.
|
475
|
|
|
* @return int Sepa::OK or errorcode
|
476
|
|
|
*/
|
477
|
|
|
private function validateBIC() : int
|
478
|
|
|
{
|
479
|
|
|
$iErr = Sepa::OK;
|
480
|
|
|
if (!Sepa::checkValidation(Sepa::V_NO_BIC_VALIDATION)) {
|
481
|
|
|
if (strlen($this->strBIC) == 0) {
|
482
|
|
|
$iErr = Sepa::ERR_PMT_BIC_MISSING;
|
483
|
|
|
} else if (Sepa::validateBIC($this->strBIC) != Sepa::OK) {
|
484
|
|
|
$iErr = Sepa::ERR_PMT_INVALID_BIC;
|
485
|
|
|
}
|
486
|
|
|
}
|
487
|
|
|
return $iErr;
|
488
|
|
|
}
|
489
|
|
|
|
490
|
|
|
/**
|
491
|
|
|
* Validate the CI.
|
492
|
|
|
* @return int Sepa::OK or errorcode
|
493
|
|
|
*/
|
494
|
|
|
private function validateCI() : int
|
495
|
|
|
{
|
496
|
|
|
$iErr = Sepa::OK;
|
497
|
|
|
if (!Sepa::checkValidation(Sepa::V_NO_CI_VALIDATION)) {
|
498
|
|
|
if (strlen($this->strCI) == 0) {
|
499
|
|
|
$iErr = Sepa::ERR_PMT_CI_MISSING;
|
500
|
|
|
} else if (Sepa::validateCI($this->strCI) != Sepa::OK) {
|
501
|
|
|
$iErr = Sepa::ERR_PMT_INVALID_CI;
|
502
|
|
|
}
|
503
|
|
|
}
|
504
|
|
|
return $iErr;
|
505
|
|
|
}
|
506
|
|
|
|
507
|
|
|
/**
|
508
|
|
|
* Validate mandatory fields.
|
509
|
|
|
* @return int Sepa::OK or errorcode
|
510
|
|
|
*/
|
511
|
|
|
private function validateMandatory() : int
|
512
|
|
|
{
|
513
|
|
|
$iErr = Sepa::OK;
|
514
|
|
|
if (!Sepa::checkValidation(Sepa::V_IGNORE_MISSING_VALUE)) {
|
515
|
|
|
if (strlen($this->strName) == 0) {
|
516
|
|
|
$iErr |= Sepa::ERR_PMT_NAME_MISSING;
|
517
|
|
|
}
|
518
|
|
|
if (strlen($this->strSeqType) == 0) {
|
519
|
|
|
$iErr |= Sepa::ERR_PMT_SEQ_TYPE_MISSING;
|
520
|
|
|
} else if (!$this->isValidateSeqType($this->strSeqType)) {
|
521
|
|
|
$iErr |= Sepa::ERR_PMT_INVALID_SEQ_TYPE;
|
522
|
|
|
}
|
523
|
|
|
}
|
524
|
|
|
return $iErr;
|
525
|
|
|
}
|
526
|
|
|
|
527
|
|
|
/**
|
528
|
|
|
* Check for valid sequence type.
|
529
|
|
|
* @param string $strSeqType type to check
|
530
|
|
|
* @return bool
|
531
|
|
|
*/
|
532
|
|
|
private function isValidateSeqType(string $strSeqType) : bool
|
533
|
|
|
{
|
534
|
|
|
$aValid = [
|
535
|
|
|
Sepa::SEQ_FIRST,
|
536
|
|
|
Sepa::SEQ_RECURRENT,
|
537
|
|
|
Sepa::SEQ_ONE_OFF,
|
538
|
|
|
Sepa::SEQ_FINAL
|
539
|
|
|
];
|
540
|
|
|
return in_array($strSeqType, $aValid);
|
541
|
|
|
}
|
542
|
|
|
}
|
543
|
|
|
|