XREC_DIM - Version 1.0.1

Version Notes

First Release

Download this release

Release Info

Developer xrec.nl
Extension XREC_DIM
Version 1.0.1
Comparing to
See all releases


Version 1.0.1

Files changed (53) hide show
  1. app/code/community/Xrec/Dim/Block/Payment/Dim/Fail.php +11 -0
  2. app/code/community/Xrec/Dim/Block/Payment/Dim/Form.php +12 -0
  3. app/code/community/Xrec/Dim/Block/Payment/Dim/Info.php +5 -0
  4. app/code/community/Xrec/Dim/Helper/Data.php +87 -0
  5. app/code/community/Xrec/Dim/Helper/Dim.php +290 -0
  6. app/code/community/Xrec/Dim/Model/Dim.php +258 -0
  7. app/code/community/Xrec/Dim/controllers/DimController.php +284 -0
  8. app/code/community/Xrec/Dim/etc/config.xml +169 -0
  9. app/code/community/Xrec/Dim/etc/system.xml +228 -0
  10. app/code/community/Xrec/Dim/sql/dim_setup/mysql4-install-1.0.0.php +32 -0
  11. app/code/community/Xrec/Dim/sql/dim_setup/mysql4-uninstall-1.0.0.php +17 -0
  12. app/design/frontend/base/default/layout/dim.xml +18 -0
  13. app/design/frontend/base/default/template/xrec/form/dim.phtml +36 -0
  14. app/design/frontend/base/default/template/xrec/page/exception.phtml +10 -0
  15. app/design/frontend/base/default/template/xrec/page/fail.phtml +65 -0
  16. app/etc/modules/Xrec_Dim.xml +12 -0
  17. lib/Communicator/.DS_Store +0 -0
  18. lib/Communicator/B2BCommunicator.php +56 -0
  19. lib/Communicator/Configuration/Configuration.php +185 -0
  20. lib/Communicator/CoreCommunicator.php +292 -0
  21. lib/Communicator/Entities/AcquirerStatusRequest.php +160 -0
  22. lib/Communicator/Entities/AcquirerStatusResponse.php +333 -0
  23. lib/Communicator/Entities/AcquirerTrxRequest.php +206 -0
  24. lib/Communicator/Entities/AmendmentRequest.php +351 -0
  25. lib/Communicator/Entities/AmendmentResponse.php +76 -0
  26. lib/Communicator/Entities/CancellationRequest.php +318 -0
  27. lib/Communicator/Entities/CancellationResponse.php +76 -0
  28. lib/Communicator/Entities/DirectoryRequest.php +82 -0
  29. lib/Communicator/Entities/DirectoryResponse.php +111 -0
  30. lib/Communicator/Entities/ErrorResponse.php +52 -0
  31. lib/Communicator/Entities/NewMandateRequest.php +289 -0
  32. lib/Communicator/Entities/NewMandateResponse.php +76 -0
  33. lib/Communicator/Libraries/CommunicatorException.php +34 -0
  34. lib/Communicator/Libraries/Logger.php +74 -0
  35. lib/Communicator/Libraries/MessageIdGenerator.php +35 -0
  36. lib/Communicator/Libraries/XmlSecurity.php +198 -0
  37. lib/Communicator/Libraries/XmlUtility.php +15 -0
  38. lib/Communicator/Libraries/XmlValidator.php +56 -0
  39. lib/Communicator/Libraries/xmlseclibs.php +1853 -0
  40. lib/Communicator/schemas/idx.merchant-acquirer.1.0.xsd +369 -0
  41. lib/Communicator/schemas/pain.009.001.04.xsd +534 -0
  42. lib/Communicator/schemas/pain.010.001.04.xsd +615 -0
  43. lib/Communicator/schemas/pain.011.001.04.xsd +574 -0
  44. lib/Communicator/schemas/pain.012.001.04.xsd +573 -0
  45. lib/Communicator/schemas/xmldsig-core-schema.xsd +309 -0
  46. package.xml +18 -0
  47. skin/frontend/dim/.DS_Store +0 -0
  48. skin/frontend/dim/css/style.css +9 -0
  49. skin/frontend/dim/images/dim.jpg +0 -0
  50. var/xrec/.DS_Store +0 -0
  51. var/xrec/.htaccess +2 -0
  52. var/xrec/dim/.DS_Store +0 -0
  53. var/xrec/dim/cer/.DS_Store +0 -0
app/code/community/Xrec/Dim/Block/Payment/Dim/Fail.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Xrec_Dim_Block_Payment_Idl_Fail extends Mage_Core_Block_Template
4
+ {
5
+ public function _construct()
6
+ {
7
+ parent::_construct();
8
+ $this->setTemplate('xrec/page/fail.phtml');
9
+ }
10
+
11
+ }
app/code/community/Xrec/Dim/Block/Payment/Dim/Form.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Xrec_Dim_Block_Payment_Dim_Form extends Mage_Payment_Block_Form
4
+ {
5
+
6
+ public function _construct()
7
+ {
8
+ parent::_construct();
9
+ $this->setTemplate('xrec/form/dim.phtml');
10
+ }
11
+
12
+ }
app/code/community/Xrec/Dim/Block/Payment/Dim/Info.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ class Xrec_Dim_Block_Payment_Dim_Info extends Mage_Payment_Block_Info
4
+ {
5
+ }
app/code/community/Xrec/Dim/Helper/Data.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Xrec_Dim_Helper_Data extends Mage_Core_Helper_Abstract
4
+ {
5
+
6
+ /**
7
+ * @param string $transactionId
8
+ * @return mixed
9
+ */
10
+ public function getStatusById($transactionId)
11
+ {
12
+ /** @var $connection Varien_Db_Adapter_Interface */
13
+ $connection = Mage::getSingleton('core/resource')->getConnection('core_read');
14
+ $status = $connection->fetchAll(
15
+ sprintf(
16
+ "SELECT `bank_status` FROM `%s` WHERE `transaction_id` = %s",
17
+ Mage::getSingleton('core/resource')->getTableName('dim_payments'),
18
+ $connection->quote($transactionId)
19
+ )
20
+ );
21
+
22
+ return $status[0];
23
+ }
24
+
25
+ /**
26
+ * @param string $transactionId
27
+ * @return null
28
+ */
29
+ public function getOrderIdByTransactionId($transactionId)
30
+ {
31
+ /** @var $connection Varien_Db_Adapter_Interface */
32
+ $connection = Mage::getSingleton('core/resource')->getConnection('core_read');
33
+ $id = $connection->fetchAll(
34
+ sprintf(
35
+ "SELECT `order_id` FROM `%s` WHERE `transaction_id` = %s",
36
+ Mage::getSingleton('core/resource')->getTableName('dim_payments'),
37
+ $connection->quote($transactionId)
38
+ )
39
+ );
40
+
41
+ if (sizeof($id) > 0)
42
+ {
43
+ return $id[0]['order_id'];
44
+ }
45
+ return null;
46
+ }
47
+
48
+ public function getPaymentByTransactionId($transactionId)
49
+ {
50
+ /** @var $connection Varien_Db_Adapter_Interface */
51
+ $connection = Mage::getSingleton('core/resource')->getConnection('core_read');
52
+ $data = $connection->fetchAll(
53
+ sprintf(
54
+ "SELECT * FROM `%s` WHERE `transaction_id` = %s",
55
+ Mage::getSingleton('core/resource')->getTableName('dim_payments'),
56
+ $connection->quote($transactionId)
57
+ )
58
+ );
59
+
60
+ if (sizeof($data) > 0)
61
+ {
62
+ return $data[0];
63
+ }
64
+ return array();
65
+ }
66
+
67
+
68
+ /**
69
+ * Check if testmode is enabled.
70
+ */
71
+ public function getTestModeEnabled()
72
+ {
73
+ return $this->getConfig('testmode');
74
+ }
75
+
76
+ /**
77
+ * Get store config
78
+ *
79
+ * @param string $key
80
+ * @return string
81
+ */
82
+ public function getConfig($key = null)
83
+ {
84
+ return Mage::getStoreConfig("payment/xrec/{$key}");
85
+ }
86
+
87
+ }
app/code/community/Xrec/Dim/Helper/Dim.php ADDED
@@ -0,0 +1,290 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once 'Communicator/CoreCommunicator.php';
4
+ require_once 'Communicator/B2BCommunicator.php';
5
+
6
+ class Xrec_Dim_Helper_Dim
7
+ {
8
+ /** @var CoreCommunicator */
9
+ protected $coreCommunicator;
10
+ protected $issuerAuthenticationUrl;
11
+ protected $transactionId;
12
+ protected $dimSequenceType;
13
+ protected $dimBankId = null;
14
+ protected $bankStatus = null;
15
+
16
+ protected $urlProd = 'https://machtigen.secure-ing.com/EMRoutingWS/handler/ing';
17
+ protected $urlTest = 'https://machtigen.secure-ing.com/TestRoutingWS/handler/ing';
18
+
19
+ /**
20
+ * @return mixed
21
+ */
22
+ public function getIssuerAuthenticationUrl()
23
+ {
24
+ return $this->issuerAuthenticationUrl;
25
+ }
26
+
27
+ /**
28
+ * @param mixed $issuerAuthenticationUrl
29
+ */
30
+ public function setIssuerAuthenticationUrl($issuerAuthenticationUrl)
31
+ {
32
+ $this->issuerAuthenticationUrl = $issuerAuthenticationUrl;
33
+ }
34
+
35
+ /**
36
+ * @return mixed
37
+ */
38
+ public function getTransactionId()
39
+ {
40
+ return $this->transactionId;
41
+ }
42
+
43
+ /**
44
+ * @param mixed $transactionId
45
+ */
46
+ public function setTransactionId($transactionId)
47
+ {
48
+ $this->transactionId = $transactionId;
49
+ }
50
+
51
+ /**
52
+ * @return string
53
+ */
54
+ public function getDimBankId()
55
+ {
56
+ return $this->dimBankId;
57
+ }
58
+
59
+ /**
60
+ * @param string $dimBankId
61
+ */
62
+ public function setDimBankId($dimBankId)
63
+ {
64
+ $this->dimBankId = $dimBankId;
65
+ }
66
+
67
+ /**
68
+ * @return null
69
+ */
70
+ public function getBankStatus()
71
+ {
72
+ return $this->bankStatus;
73
+ }
74
+
75
+ /**
76
+ * @param null $bankStatus
77
+ */
78
+ public function setBankStatus($bankStatus)
79
+ {
80
+ $this->bankStatus = $bankStatus;
81
+ }
82
+
83
+ /**
84
+ * @return mixed
85
+ */
86
+ public function getDimSequenceType()
87
+ {
88
+ return $this->dimSequenceType;
89
+ }
90
+
91
+ /**
92
+ * @param mixed $dimSequenceType
93
+ */
94
+ public function setDimSequenceType($dimSequenceType)
95
+ {
96
+ $this->dimSequenceType = $dimSequenceType;
97
+ }
98
+
99
+ protected function getConfiguration()
100
+ {
101
+ $urlDirectoryReq = Mage::Helper('dim/data')->getConfig('AcquirerUrl_DirectoryReq');
102
+ $urlTransactionReq = Mage::Helper('dim/data')->getConfig('AcquirerUrl_TransactionReq');
103
+ $urlStatusReq = Mage::Helper('dim/data')->getConfig('AcquirerUrl_StatusReq');
104
+
105
+ $testMode = Mage::Helper('dim/data')->getConfig('testMode');
106
+ if ($testMode) {
107
+ $urlDirectoryReq = Mage::Helper('dim/data')->getConfig('AcquirerUrl_DirectoryReqTest');
108
+ $urlTransactionReq = Mage::Helper('dim/data')->getConfig('AcquirerUrl_TransactionReqTest');
109
+ $urlStatusReq = Mage::Helper('dim/data')->getConfig('AcquirerUrl_StatusReqTest');
110
+ }
111
+ $cerPath = Mage::getBaseDir('var') . '/xrec/dim/cer/';
112
+
113
+ $returnUrl = Mage::Helper('dim/data')->getConfig('merchantReturnURL');
114
+ if (substr($returnUrl, -1) !== '/') {
115
+ $returnUrl .= '/';
116
+ }
117
+ /*
118
+ * @param string $passphrase
119
+ * @param string $keyFile
120
+ * @param string $crtFile
121
+ * @param string $crtFileAquirer
122
+ * @param string $contractID
123
+ * @param string $contractSubID
124
+ * @param string $merchantReturnURL
125
+ * @param string $AcquirerUrl_DirectoryReq
126
+ * @param string $AcquirerUrl_TransactionReq
127
+ * @param string $AcquirerUrl_StatusReq
128
+ * @param bool $enableXMLLogs
129
+ * @param string $logPath
130
+ * @param string $folderNamePattern
131
+ * @param string $fileNamePrefix
132
+ * @param bool $enableInternalLogs
133
+ * @param string $fileName
134
+ */
135
+ return new Configuration(
136
+ Mage::Helper('dim/data')->getConfig('passphrase'),
137
+ $cerPath . Mage::Helper('dim/data')->getConfig('keyFile'),
138
+ $cerPath . Mage::Helper('dim/data')->getConfig('crtFile'),
139
+ $cerPath . Mage::Helper('dim/data')->getConfig('crtFileAquirer'),
140
+ Mage::Helper('dim/data')->getConfig('merchantID'),
141
+ Mage::Helper('dim/data')->getConfig('merchantSubID'),
142
+ $returnUrl . 'dim/dim/return',
143
+ $urlDirectoryReq ? $urlDirectoryReq : $this->urlProd,
144
+ $urlTransactionReq ? $urlTransactionReq : $this->urlProd,
145
+ $urlStatusReq ? $urlStatusReq : ($testMode ? $this->urlTest : $this->urlProd),
146
+ true,
147
+ Mage::getBaseDir('var') . '/logs/xrec/dim/',
148
+ 'Y-m-d',
149
+ 'His.u',
150
+ true,
151
+ 'eMandates.txt'
152
+ );
153
+ }
154
+
155
+ /**
156
+ * @param Mage_Sales_Model_Order $order
157
+ * @return bool
158
+ */
159
+ public function doNewMandateRequest($order)
160
+ {
161
+ if (!$order->getPayment()) {
162
+ Mage::throwException('Ongeldige betaling!');
163
+ }
164
+ $dimBankId = $this->dimBankId ? $this->dimBankId : 'INGBNL2A';
165
+ /*if (Mage::Helper('dim/data')->getConfig('SequenceTypeCustomer')) {
166
+ $dimSequenceType = Mage::Helper('dim/data')->getConfig('SequenceType');
167
+ } else {
168
+ $dimSequenceType = $this->dimSequenceType ? $this->dimSequenceType : 'OOFF';
169
+ }*/
170
+ $dimSequenceType = $this->dimSequenceType ? $this->dimSequenceType : 'OOFF';
171
+ $reason = Mage::Helper('dim/data')->getConfig('eMandateReason');
172
+
173
+ // Initiate a CoreCommunicator
174
+ $coreCommunicator = new CoreCommunicator($this->getConfiguration());
175
+ /**
176
+ * @param string $entranceCode
177
+ * @param string $language
178
+ * @param string $messageId
179
+ * @param string $eMandateId
180
+ * @param string $eMandateReason
181
+ * @param string $debtorReference
182
+ * @param string $debtorBankId
183
+ * @param string $purchaseId
184
+ * @param string $sequenceType
185
+ * @param string $maxAmount - optional
186
+ * @param DateInterval $expirationPeriod - optional
187
+ */
188
+ $newMandateRequest = new NewMandateRequest(
189
+ $order->getPayment()->getId(),
190
+ 'nl',
191
+ MessageIdGenerator::NewMessageId(),
192
+ $order->getPayment()->getId(),
193
+ $reason ? $reason : 'Webshop purchase',
194
+ $order->getCustomerName(),
195
+ $dimBankId,
196
+ $order->getRealOrderId(),
197
+ $dimSequenceType,
198
+ Mage::app()->getStore()->roundPrice($order->getGrandTotal()),
199
+ self::evaluateExpirationPeriod('PT20M')
200
+ );
201
+ $newMandateResponse = $coreCommunicator->NewMandate($newMandateRequest);
202
+ if ($newMandateResponse->IsError) {
203
+ Mage::throwException($newMandateResponse->Error->ErrorCode . ': ' . $newMandateResponse->Error->ConsumerMessage);
204
+ return false;
205
+ } else {
206
+ $this->issuerAuthenticationUrl = $newMandateResponse->IssuerAuthenticationUrl;
207
+ $this->transactionId = $newMandateResponse->TransactionId;
208
+ }
209
+
210
+ return true;
211
+ }
212
+
213
+ public function doDirectoryRequest()
214
+ {
215
+ try {
216
+ // Initiate a CoreCommunicator
217
+ $coreCommunicator = new CoreCommunicator($this->getConfiguration());
218
+ $diRes = $coreCommunicator->Directory();
219
+ if ($diRes->IsError) {
220
+ Mage::throwException($diRes->Error->ErrorCode . ': ' . $diRes->Error->ConsumerMessage);
221
+ } else {
222
+ $buckets = array();
223
+ foreach ($diRes->DebtorBanks as $bank) {
224
+ $buckets[$bank->DebtorBankCountry][] = $bank;
225
+ }
226
+ return $buckets;
227
+ }
228
+ } catch (Exception $e) {
229
+ Mage::throwException($e->getMessage());
230
+ }
231
+
232
+ }
233
+
234
+ public function doGetStatus($transactionId)
235
+ {
236
+ $conf = $this->getConfiguration();
237
+ // Initiate a CoreCommunicator
238
+ $coreCommunicator = new CoreCommunicator($conf);
239
+ $statusRequest = new StatusRequest($transactionId);
240
+ try {
241
+ $sRes = $coreCommunicator->GetStatus($statusRequest);
242
+ if ($sRes->IsError) {
243
+ Mage::getModel('dim/dim')->updatePayment($transactionId, $sRes->Error->ErrorCode);
244
+ Mage::throwException($sRes->Error->ErrorCode . ': ' . $sRes->Error->ConsumerMessage);
245
+ } else {
246
+ $this->bankStatus = $sRes->Status;
247
+ Mage::getModel('dim/dim')->updatePayment($transactionId, $sRes->Status);
248
+ }
249
+ return $sRes->Status;
250
+ } catch (Exception $e) {
251
+ Mage::throwException($e->getMessage());
252
+ }
253
+
254
+ }
255
+
256
+ /**
257
+ * Parse the $str and return a date interval
258
+ *
259
+ * @param string $str
260
+ * @return string
261
+ */
262
+ public static function evaluateExpirationPeriod($str)
263
+ {
264
+ $interval = '';
265
+
266
+ if (is_numeric($str)) { // when only a number is entered
267
+ $interval = 'P' . $str . 'D';
268
+ } else if (strstr($str, ':')) { // when he have a time [hours:minutes:seconds]
269
+ $arr = explode(':', $str);
270
+ $interval = "PT";
271
+ if (!empty($arr[0])) {
272
+ $interval .= $arr[0] . 'H';
273
+ }
274
+ if (!empty($arr[1])) {
275
+ $interval .= $arr[1] . 'M';
276
+ }
277
+ if (!empty($arr[2])) {
278
+ $interval .= $arr[2] . 'S';
279
+ }
280
+ } else {
281
+ $interval = $str;
282
+ }
283
+
284
+ if (empty($interval)) {
285
+ return null;
286
+ }
287
+
288
+ return new DateInterval(strtoupper($interval));
289
+ }
290
+ }
app/code/community/Xrec/Dim/Model/Dim.php ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Copyright (c) 2012-2014, xrec.nl
5
+ * All rights reserved.
6
+ **/
7
+ class Xrec_Dim_Model_Dim extends Mage_Payment_Model_Method_Abstract
8
+ {
9
+
10
+ // Payment statusses
11
+ const DIM_OPEN = 'Open';
12
+ const DIM_SUCCESS = 'Success';
13
+ const DIM_CANCELLED = 'Cancelled';
14
+ const DIM_FAILURE = 'Failure';
15
+ const DIM_PENDING = 'Pending';
16
+ const DIM_EXPIRED = 'Expired';
17
+
18
+ const SEQUENCE_TYPE_OOFF = 'Machtiging eenmalige SEPA incasso.';
19
+ const SEQUENCE_TYPE_RCUR = 'Machtiging doorlopende SEPA incasso.';
20
+
21
+ // Payment flags
22
+ const PAYMENT_FLAG_PROCESSED = 'De betaling is ontvangen en verwerkt.';
23
+ const PAYMENT_FLAG_RETRY = 'De consument probeert het bedrag nogmaals af te rekenen.';
24
+ const PAYMENT_FLAG_CANCELD = 'De consument heeft de betaling geannuleerd.';
25
+ const PAYMENT_FLAG_PENDING = 'Afwachten tot de betaling binnen is.';
26
+ const PAYMENT_FLAG_EXPIRED = 'De betaling is verlopen doordat de consument niets met de betaling heeft gedaan.';
27
+ const PAYMENT_FLAG_INPROGRESS = 'De klant is doorverwezen naar de geselecteerde bank.';
28
+ const PAYMENT_FLAG_FAILED = 'De betaling is niet gelukt (er is geen verdere informatie beschikbaar).';
29
+ const PAYMENT_FLAG_FRAUD = 'Het totale bedrag komt niet overeen met de afgerekende bedrag. (Mogelijke fraude).';
30
+ const PAYMENT_FLAG_DCHECKED = 'De betaalstatus is al een keer opgevraagd.';
31
+ const PAYMENT_FLAG_UNKOWN = 'Er is een onbekende fout opgetreden.';
32
+
33
+ /**
34
+ * unique internal payment method identifier
35
+ *
36
+ * @var string [a-z0-9_]
37
+ */
38
+ protected $_code = 'dim';
39
+ protected $_formBlockType = 'dim/payment_dim_form';
40
+ protected $_infoBlockType = 'dim/payment_dim_info';
41
+ protected $_paymentMethod = 'DIM';
42
+
43
+ /**
44
+ * Here are examples of flags that will determine functionality availability
45
+ * of this module to be used by frontend and backend.
46
+ *
47
+ * @see all flags and their defaults in Mage_Payment_Model_Method_Abstract
48
+ *
49
+ * It is possible to have a custom dynamic logic by overloading
50
+ * public function can* for each flag respectively
51
+ */
52
+
53
+ /**
54
+ * Is this payment method a gateway (online auth/charge) ?
55
+ */
56
+ protected $_isGateway = true;
57
+
58
+ /**
59
+ * Can authorize online?
60
+ */
61
+ protected $_canAuthorize = true;
62
+
63
+ /**
64
+ * Can capture funds online?
65
+ */
66
+ protected $_canCapture = true;
67
+
68
+ /**
69
+ * Can capture partial amounts online?
70
+ */
71
+ protected $_canCapturePartial = false;
72
+
73
+ /**
74
+ * Can refund online?
75
+ */
76
+ protected $_canRefund = false;
77
+
78
+ /**
79
+ * Can void transactions online?
80
+ */
81
+ protected $_canVoid = true;
82
+
83
+ /**
84
+ * Can use this payment method in administration panel?
85
+ */
86
+ protected $_canUseInternal = true;
87
+
88
+ /**
89
+ * Can show this payment method as an option on checkout payment page?
90
+ */
91
+ protected $_canUseCheckout = true;
92
+
93
+ /**
94
+ * Is this payment method suitable for multi-shipping checkout?
95
+ */
96
+ protected $_canUseForMultishipping = true;
97
+
98
+ /**
99
+ * Can save credit card information for future processing?
100
+ */
101
+ protected $_canSaveCc = false;
102
+
103
+ public function __construct()
104
+ {
105
+ parent::__construct();
106
+
107
+ $this->_dim = Mage::Helper('dim/dim');
108
+ $this->_table = Mage::getSingleton('core/resource')->getTableName('dim_payments');
109
+ $this->_mysqlr = Mage::getSingleton('core/resource')->getConnection('core_read');
110
+ $this->_mysqlw = Mage::getSingleton('core/resource')->getConnection('core_write');
111
+ }
112
+
113
+ /**
114
+ * Get checkout session namespace
115
+ *
116
+ * @return Mage_Checkout_Model_Session
117
+ */
118
+ protected function _getCheckout()
119
+ {
120
+ return Mage::getSingleton('checkout/session');
121
+ }
122
+
123
+ /**
124
+ * Get current quote
125
+ *
126
+ * @return Mage_Sales_Model_Quote
127
+ */
128
+ public function getQuote()
129
+ {
130
+ return $this->_getCheckout()->getQuote();
131
+ }
132
+
133
+ /**
134
+ * Check whether payment method can be used
135
+ *
136
+ * @param Mage_Sales_Model_Quote
137
+ * @return bool
138
+ */
139
+ public function isAvailable($quote = NULL)
140
+ {
141
+ $enabled = (bool)Mage::Helper('dim/data')->getConfig('active');
142
+
143
+ if (!$enabled) {
144
+ return false;
145
+ }
146
+
147
+ return parent::isAvailable($quote);
148
+ }
149
+
150
+
151
+ /**
152
+ * @param string $currencyCode
153
+ * @return bool
154
+ */
155
+ public function canUseForCurrency($currencyCode)
156
+ {
157
+ if (!parent::canUseForCurrency($currencyCode)) {
158
+ return false;
159
+ }
160
+
161
+ if ($currencyCode !== 'EUR') {
162
+ return false;
163
+ }
164
+
165
+ return true;
166
+ }
167
+
168
+ /**
169
+ * On click payment button, this function is called to assign data
170
+ *
171
+ * @param mixed $data
172
+ * @return self
173
+ */
174
+ public function assignData($data)
175
+ {
176
+ if (!($data instanceof Varien_Object)) {
177
+ $data = new Varien_Object($data);
178
+ }
179
+
180
+ if (strlen(Mage::registry('dim_bank_id')) == 0) {
181
+ Mage::register('dim_bank_id', $data->getDimBankId());
182
+ Mage::register('dim_sequence_type', $data->getDimSequenceType());
183
+ return $this;
184
+ }
185
+ return $this;
186
+ }
187
+
188
+
189
+ /**
190
+ * Stores the payment information in the dim_payments table.
191
+ * @param $orderId
192
+ * @param $transactionId
193
+ * @param string $status
194
+ * @param string $sequenceType
195
+ * @param string $method
196
+ * @throws Mage_Core_Exception
197
+ */
198
+ public function setPayment($orderId, $transactionId, $status = 'Pending', $sequenceType = null, $method = 'dim')
199
+ {
200
+ if (is_null($orderId) || is_null($transactionId)) {
201
+ Mage::throwException('Ongeldige order_id of transaction_id...');
202
+ }
203
+
204
+ $data = array(
205
+ 'order_id' => $orderId,
206
+ 'bank_status' => $status,
207
+ 'transaction_id' => $transactionId,
208
+ 'method' => $method,
209
+ 'sequence_type' => $sequenceType,
210
+ 'created_at' => date('Y-m-d H:i:s'),
211
+ 'updated_at' => date('Y-m-d H:i:s')
212
+ );
213
+
214
+ $this->_mysqlw->insert($this->_table, $data);
215
+ }
216
+
217
+ /**
218
+ * @param string $transactionId
219
+ * @param null|string $status
220
+ * @throws Mage_Core_Exception
221
+ */
222
+ public function updatePayment($transactionId, $status = null)
223
+ {
224
+ if (is_null($transactionId) || is_null($status)) {
225
+ Mage::throwException('Geen transactionId en/of status gevonden!');
226
+ }
227
+
228
+ $data = array(
229
+ 'bank_status' => $status,
230
+ 'updated_at' => date('Y-m-d H:i:s')
231
+ );
232
+
233
+
234
+ $where = sprintf("transaction_id = %s", $this->_mysqlw->quote($transactionId));
235
+
236
+ $this->_mysqlw->update($this->_table, $data, $where);
237
+ }
238
+
239
+ /**
240
+ * Redirects the client on click 'Place Order' to selected iDEAL bank
241
+ *
242
+ * @return string
243
+ */
244
+ public function getOrderPlaceRedirectUrl()
245
+ {
246
+ return Mage::getUrl(
247
+ 'dim/dim/payment',
248
+ array(
249
+ '_secure' => TRUE,
250
+ '_query' => array(
251
+ 'dim_bank_id' => Mage::registry('dim_bank_id'),
252
+ 'dim_sequence_type' => Mage::registry('dim_sequence_type')
253
+ )
254
+ )
255
+ );
256
+ }
257
+
258
+ }
app/code/community/Xrec/Dim/controllers/DimController.php ADDED
@@ -0,0 +1,284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Copyright (c) 2012-2014, xrec.nl
5
+ * All rights reserved.
6
+ **/
7
+ class Xrec_Dim_DimController extends Mage_Core_Controller_Front_Action
8
+ {
9
+
10
+ /**
11
+ * @var Xrec_Dim_Helper_Dim
12
+ */
13
+ protected $dim;
14
+
15
+ /**
16
+ * @var Xrec_Dim_Helper_Data
17
+ */
18
+ protected $data;
19
+
20
+ /**
21
+ * @var Xrec_Dim_Model_Dim
22
+ */
23
+ protected $model;
24
+
25
+ /**
26
+ * Get core
27
+ */
28
+ public function _construct()
29
+ {
30
+ $this->dim = Mage::Helper('dim/dim');
31
+ $this->data = Mage::Helper('dim/data');
32
+ $this->model = Mage::getModel('dim/dim');
33
+ parent::_construct();
34
+ }
35
+
36
+
37
+ /**
38
+ * @param string $e Exceptiom message
39
+ * @param null $order_id An OrderID
40
+ */
41
+ protected function _showException($e = '', $orderId = NULL)
42
+ {
43
+ $this->loadLayout();
44
+ $order = Mage::getModel('sales/order')->load($orderId);
45
+ $block = $this->getLayout()
46
+ ->createBlock('Mage_Core_Block_Template')
47
+ ->setTemplate('xrec/page/exception.phtml')
48
+ ->setData('exception', $e)
49
+ ->setData('order', $order);
50
+
51
+ $this->getLayout()->getBlock('content')->append($block);
52
+ $this->renderLayout();
53
+ }
54
+
55
+ /**
56
+ * Gets the current checkout session with order information
57
+ *
58
+ * @return Mage_Checkout_Model_Session
59
+ */
60
+ protected function _getCheckout()
61
+ {
62
+ return Mage::getSingleton('checkout/session');
63
+ }
64
+
65
+ /**
66
+ * After clicking 'Place Order' the method 'getOrderPlaceRedirectUrl()' gets called and redirects to here with the bank_id
67
+ * Then this action creates an payment with a transaction_id that gets inserted in the database (mollie_payments, sales_payment_transaction)
68
+ */
69
+ public function paymentAction()
70
+ {
71
+ if ($this->getRequest()->getParam('order_id')) {
72
+ /** @var $order Mage_Sales_Model_Order */
73
+ $order = Mage::getModel('sales/order')->load($this->getRequest()->getParam('order_id'));
74
+ $order->setState(Mage_Sales_Model_Order::STATE_PROCESSING, Mage_Sales_Model_Order::STATE_PENDING_PAYMENT, $this->__(Xrec_Dim_Model_Dim::PAYMENT_FLAG_RETRY), FALSE)->save();
75
+ } else {
76
+ // Load last order by IncrementId
77
+ /** @var $order Mage_Sales_Model_Order */
78
+ $orderIncrementId = $this->_getCheckout()->getLastRealOrderId();
79
+ $order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId);
80
+ }
81
+
82
+ try {
83
+ $dimBankId = $this->getRequest()->getParam('dim_bank_id');
84
+ if (!$this->data->getConfig('SequenceTypeCustomer')) {
85
+ $dimSequenceType = $this->data->getConfig('SequenceType');
86
+ } else {
87
+ $dimSequenceType = $this->getRequest()->getParam('dim_sequence_type');
88
+ }
89
+
90
+ $this->dim->setDimBankId($dimBankId);
91
+ $this->dim->setDimSequenceType($dimSequenceType);
92
+
93
+ if ($this->dim->doNewMandateRequest($order)) {
94
+
95
+ if (!$order->getId()) {
96
+ Mage::log('Geen order voor verwerking gevonden');
97
+ Mage::throwException('Geen order voor verwerking gevonden');
98
+ }
99
+
100
+ $this->model->setPayment($order->getId(), $this->dim->getTransactionId(), Xrec_Dim_Model_Dim::DIM_PENDING, $dimSequenceType);
101
+
102
+ // Creates transaction
103
+ /** @var $payment Mage_Sales_Model_Order_Payment */
104
+ $payment = Mage::getModel('sales/order_payment')
105
+ ->setMethod('dim')
106
+ ->setTransactionId($this->dim->getTransactionId())
107
+ ->setIsTransactionClosed(false);
108
+
109
+
110
+ $order->setPayment($payment);
111
+
112
+ $payment->addTransaction(Mage_Sales_Model_Order_Payment_Transaction::TYPE_AUTH);
113
+
114
+ if ($dimSequenceType == 'OOFF') {
115
+ $message = Xrec_Dim_Model_Dim::PAYMENT_FLAG_INPROGRESS .' '. Xrec_Dim_Model_Dim::SEQUENCE_TYPE_OOFF;
116
+ } else {
117
+ $message = Xrec_Dim_Model_Dim::PAYMENT_FLAG_INPROGRESS .' '. Xrec_Dim_Model_Dim::SEQUENCE_TYPE_RCUR;
118
+ }
119
+ $order->setState(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT, Mage_Sales_Model_Order::STATE_PENDING_PAYMENT, $message, false)->save();
120
+
121
+ $this->_redirectUrl($this->dim->getIssuerAuthenticationUrl());
122
+
123
+ } else {
124
+ Mage::throwException($this->dim->getErrorMessage());
125
+ }
126
+ } catch (Exception $e) {
127
+ Mage::log($e);
128
+ $this->_showException($e->getMessage(), $order->getId());
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Customer returning from the bank with an transaction_id
134
+ * Depending on what the state of the payment is they get redirected to the corresponding page
135
+ */
136
+ public function returnAction()
137
+ {
138
+ // Get transaction_id from url (Ex: http://yourmagento.com/index.php/dim/dim/return?trxid=0050000000012875&ec=834hn46 )
139
+ $transactionId = $this->getRequest()->getParam('trxid');
140
+ //$orderId = Mage::Helper('dim/data')->getOrderIdByTransactionId($transactionId);
141
+ $dimPayment = Mage::Helper('dim/data')->getPaymentByTransactionId($transactionId);
142
+ $orderId = isset($dimPayment['order_id']) ? $dimPayment['order_id'] : null;
143
+
144
+ try {
145
+ if (!empty($transactionId) && $orderId) {
146
+ $dimStatus = $this->dim->doGetStatus($transactionId);
147
+
148
+ if ($dimStatus == Xrec_Dim_Model_Dim::DIM_SUCCESS) {
149
+ if ($this->_getCheckout()->getQuote()->getItemsCount() > 0) {
150
+ foreach ($this->_getCheckout()->getQuote()->getItemsCollection() as $item) {
151
+ Mage::getSingleton('checkout/cart')->removeItem($item->getId());
152
+ }
153
+ Mage::getSingleton('checkout/cart')->save();
154
+ }
155
+
156
+ // Load order by id ($oId)
157
+ /** @var $order Mage_Sales_Model_Order */
158
+ $order = Mage::getModel('sales/order')->load($orderId);
159
+ /** @var $payment Mage_Sales_Model_Order_Payment */
160
+ $payment = $order->getPayment();
161
+ $payment->setMethod('dim')
162
+ ->setTransactionId($transactionId)
163
+ ->setIsTransactionClosed(TRUE);
164
+
165
+ if ($dimPayment['sequence_type'] == 'OOFF') {
166
+ $message = Xrec_Dim_Model_Dim::PAYMENT_FLAG_PROCESSED .' '. Xrec_Dim_Model_Dim::SEQUENCE_TYPE_OOFF;
167
+ } else {
168
+ $message = Xrec_Dim_Model_Dim::PAYMENT_FLAG_PROCESSED .' '. Xrec_Dim_Model_Dim::SEQUENCE_TYPE_RCUR;
169
+ }
170
+
171
+ $payment->addTransaction(Mage_Sales_Model_Order_Payment_Transaction::TYPE_CAPTURE);
172
+ $order->setState(Mage_Sales_Model_Order::STATE_PROCESSING, Mage_Sales_Model_Order::STATE_PROCESSING, $message, TRUE)->save();;
173
+
174
+ /*
175
+ * Send an email to the customer.
176
+ */
177
+ $order->sendNewOrderEmail()->setEmailSent(TRUE);
178
+
179
+ // Redirect to success page
180
+ $this->_redirect('checkout/onepage/success', array('_secure' => TRUE));
181
+ return;
182
+ } else {
183
+ // Create fail page
184
+ $this->loadLayout();
185
+
186
+ $block = $this->getLayout()
187
+ ->createBlock('Mage_Core_Block_Template')
188
+ ->setTemplate('xrec/page/fail.phtml')
189
+ ->setData('form', Mage::getUrl('dim/dim/form'))
190
+ ->setData('order', Mage::getModel('sales/order')->load($orderId));
191
+
192
+ $this->getLayout()->getBlock('content')->append($block);
193
+
194
+ $this->renderLayout();
195
+ return;
196
+ }
197
+ }
198
+ } catch (Exception $e) {
199
+ Mage::log($e);
200
+ $this->_showException($e->getMessage(), $orderId);
201
+ return;
202
+ }
203
+
204
+ $this->_redirectUrl(Mage::getBaseUrl());
205
+ }
206
+
207
+
208
+ /**
209
+ * This action is getting called by ing to report the payment status
210
+ */
211
+ public function reportAction()
212
+ {
213
+ // Get transaction_id from url (Ex: http://yourmagento.com/index.php/dim/dim/report?trxid=0050000000012875&ec=834hn46 )
214
+ $transactionId = $this->getRequest()->getParam('trxid');
215
+ $orderId = $this->getRequest()->getParam('order_id');
216
+
217
+ // Get order by transaction_id
218
+ $orderId = Mage::helper('dim/data')->getOrderIdByTransactionId($transactionId);
219
+
220
+ // Load order by id ($oId)
221
+ /** @var $order Mage_Sales_Model_Order */
222
+ $order = Mage::getModel('sales/order')->load($orderId);
223
+
224
+ try {
225
+ if ($transactionId !== '' && $order->getStatus() == Mage_Sales_Model_Order::STATE_PENDING_PAYMENT) {
226
+
227
+ $this->dim->doGetStatus($transactionId);
228
+
229
+ // Maakt een Order transactie aan
230
+ /** @var $payment Mage_Sales_Model_Order_Payment */
231
+ $payment = Mage::getModel('sales/order_payment')
232
+ ->setMethod('dim')
233
+ ->setTransactionId($transactionId)
234
+ ->setIsTransactionClosed(TRUE);
235
+
236
+ $order->setPayment($payment);
237
+
238
+ if ($this->dim->getBankStatus() == Xrec_Dim_Model_Dim::DIM_SUCCESS) {
239
+ /*
240
+ * Update the total amount paid, keep that in the order. We do not care if this is the correct
241
+ * amount or not at this moment.
242
+ */
243
+
244
+ $payment->addTransaction(Mage_Sales_Model_Order_Payment_Transaction::TYPE_CAPTURE);
245
+ $order->setState(Mage_Sales_Model_Order::STATE_PROCESSING, Mage_Sales_Model_Order::STATE_PROCESSING, $this->__(Xrec_Dim_Model_Dim::PAYMENT_FLAG_PROCESSED), TRUE);
246
+
247
+ /*
248
+ * Send an email to the customer.
249
+ */
250
+ $order->sendNewOrderEmail()->setEmailSent(TRUE);
251
+
252
+ } else {
253
+ // Stomme Magento moet eerst op 'cancel' en dan pas setState, andersom dan zet hij de voorraad niet terug.
254
+ $order->cancel();
255
+ $order->setState(Mage_Sales_Model_Order::STATE_CANCELED, Mage_Sales_Model_Order::STATE_CANCELED, $this->__(Xrec_Dim_Model_Dim::PAYMENT_FLAG_CANCELD), FALSE);
256
+ }
257
+
258
+ $order->save();
259
+ }
260
+ } catch (Exception $e) {
261
+ Mage::log($e);
262
+ $this->_showException($e->getMessage());
263
+ }
264
+ }
265
+
266
+ public function formAction()
267
+ {
268
+ if ($this->getRequest()->isPost()) {
269
+ $create_new_payment = Mage::getUrl(
270
+ 'dim/dim/payment',
271
+ array(
272
+ '_secure' => TRUE,
273
+ '_query' => array(
274
+ 'order_id' => $this->getRequest()->getPost('order_id'),
275
+ 'dim_bank_id' => $this->getRequest()->getPost('dim_bank_id'),
276
+ 'dim_sequence_type' => $this->getRequest()->getPost('dim_sequence_type')
277
+ )
278
+ )
279
+ );
280
+ $this->_redirectUrl($create_new_payment);
281
+ }
282
+ }
283
+
284
+ }
app/code/community/Xrec/Dim/etc/config.xml ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+
3
+ <config>
4
+ <modules>
5
+ <Xrec_Dim>
6
+ <version>1.0.0</version>
7
+ </Xrec_Dim>
8
+ </modules>
9
+
10
+ <global>
11
+ <models>
12
+ <dim>
13
+ <class>Xrec_Dim_Model</class>
14
+ </dim>
15
+ </models>
16
+ <blocks>
17
+ <dim>
18
+ <class>Xrec_Dim_Block</class>
19
+ </dim>
20
+ <payment>
21
+ <class>Xrec_Dim_Block</class>
22
+ <class>Mage_Payment_Block</class>
23
+ </payment>
24
+ </blocks>
25
+ <helpers>
26
+ <dim>
27
+ <class>Xrec_Dim_Helper</class>
28
+ </dim>
29
+ </helpers>
30
+ <payment>
31
+ <groups>
32
+ <xrec>xrec</xrec>
33
+ </groups>
34
+ </payment>
35
+ <resources>
36
+ <dim_setup>
37
+ <setup>
38
+ <module>Xrec_Dim</module>
39
+ </setup>
40
+ <connection>
41
+ <use>core_setup</use>
42
+ </connection>
43
+ </dim_setup>
44
+ <dim_write>
45
+ <connection>
46
+ <use>core_write</use>
47
+ </connection>
48
+ </dim_write>
49
+ <dim_read>
50
+ <connection>
51
+ <use>core_read</use>
52
+ </connection>
53
+ </dim_read>
54
+ </resources>
55
+ <layouts>
56
+ <xrec_exception>
57
+ <label>Xrec Exception</label>
58
+ <template>xrec/page/exception.phtml</template>
59
+ </xrec_exception>
60
+ <api_payment_fail>
61
+ <label>Payment Failed</label>
62
+ <template>xrec/page/fail.phtml</template>
63
+ </api_payment_fail>
64
+ </layouts>
65
+ </global>
66
+
67
+ <frontend>
68
+ <routers>
69
+ <dim>
70
+ <use>standard</use>
71
+ <args>
72
+ <module>Xrec_Dim</module>
73
+ <frontName>dim</frontName>
74
+ </args>
75
+ </dim>
76
+ </routers>
77
+ <translate>
78
+ <modules>
79
+ <Xrec_Dim>
80
+ <files>
81
+ <default>Xrec_Dim.csv</default>
82
+ </files>
83
+ </Xrec_Dim>
84
+ </modules>
85
+ </translate>
86
+ <layout>
87
+ <updates>
88
+ <dim>
89
+ <file>dim.xml</file>
90
+ </dim>
91
+ </updates>
92
+ </layout>
93
+ </frontend>
94
+
95
+ <adminhtml>
96
+ <translate>
97
+ <modules>
98
+ <Xrec_Dim>
99
+ <files>
100
+ <default>Xrec_Dim.csv</default>
101
+ </files>
102
+ </Xrec_Dim>
103
+ </modules>
104
+ </translate>
105
+ <acl>
106
+ <resources>
107
+ <all>
108
+ <title>Allow Everything</title>
109
+ </all>
110
+ <admin>
111
+ <children>
112
+ <system>
113
+ <children>
114
+ <config>
115
+ <children>
116
+ <xrec>
117
+ <title>Digitaal Incassomachtigen via uw bank</title>
118
+ </xrec>
119
+ </children>
120
+ </config>
121
+ </children>
122
+ </system>
123
+ </children>
124
+ </admin>
125
+ </resources>
126
+ </acl>
127
+ <layout>
128
+ <updates>
129
+ <dim>
130
+ <file>dim.xml</file>
131
+ </dim>
132
+ </updates>
133
+ </layout>
134
+ </adminhtml>
135
+
136
+ <!-- declare default configuration values for this module -->
137
+ <default>
138
+ <!-- 'payment' configuration section (tab) -->
139
+ <payment>
140
+ <dim>
141
+ <!-- by default this payment method is inactive -->
142
+ <active>1</active>
143
+ <!-- model to handle logic for this payment method -->
144
+ <model>dim/dim</model>
145
+ <!-- order status for new orders paid by this payment method -->
146
+ <!--<order_status>pending</order_status>-->
147
+ <!-- default title for payment checkout page and order view page -->
148
+ <title>Digitaal Incassomachtigen via uw bank</title>
149
+ <group>xrec</group>
150
+
151
+ </dim>
152
+ <xrec>
153
+ <!-- DEFAULT VALUES -->
154
+ <testMode>1</testMode>
155
+ <eMandateReason>webshop purchase</eMandateReason>
156
+ <AcquirerUrl_DirectoryReq>https://machtigen.secure-ing.com/EMRoutingWS/handler/ing</AcquirerUrl_DirectoryReq>
157
+ <AcquirerUrl_TransactionReq>https://machtigen.secure-ing.com/EMRoutingWS/handler/ing</AcquirerUrl_TransactionReq>
158
+ <AcquirerUrl_StatusReq>https://machtigen.secure-ing.com/EMRoutingWS/handler/ing</AcquirerUrl_StatusReq>
159
+ <AcquirerUrl_DirectoryReqTest>https://machtigen.secure-ing.com/TestRoutingWS/handler/ing</AcquirerUrl_DirectoryReqTest>
160
+ <AcquirerUrl_TransactionReqTest>https://machtigen.secure-ing.com/TestRoutingWS/handler/ing</AcquirerUrl_TransactionReqTest>
161
+ <AcquirerUrl_StatusReqTest>https://machtigen.secure-ing.com/TestRoutingWS/handler/ing</AcquirerUrl_StatusReqTest>
162
+ <merchantReturnURL>{{base_url}}</merchantReturnURL>
163
+ <SequenceType>OOFF</SequenceType>
164
+ <SequenceTypeCustomer>0</SequenceTypeCustomer>
165
+ </xrec>
166
+ </payment>
167
+ </default>
168
+
169
+ </config>
app/code/community/Xrec/Dim/etc/system.xml ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+
3
+ <config>
4
+ <sections>
5
+ <payment>
6
+ <groups>
7
+ <xrec translate="label" module="dim">
8
+ <label>Digitaal Incassomachtigen via uw bank</label>
9
+ <expanded>1</expanded>
10
+ <sort_order>-100</sort_order>
11
+ <frontend_type>text</frontend_type>
12
+ <show_in_default>1</show_in_default>
13
+ <show_in_website>1</show_in_website>
14
+ <show_in_store>1</show_in_store>
15
+
16
+ <fields>
17
+ <active translate="label tooltip">
18
+ <label>Enabled</label>
19
+ <frontend_type>select</frontend_type>
20
+ <source_model>adminhtml/system_config_source_yesno</source_model>
21
+ <sort_order>1</sort_order>
22
+ <show_in_default>1</show_in_default>
23
+ <show_in_website>1</show_in_website>
24
+ <show_in_store>1</show_in_store>
25
+ <tooltip><![CDATA[<b>Status:</b> <br/>]]> Enable or disable the Digitaal Incassomachtigen plugin.</tooltip>
26
+ </active>
27
+
28
+ <testMode translate="label">
29
+ <label>Testmode</label>
30
+ <frontend_type>select</frontend_type>
31
+ <source_model>adminhtml/system_config_source_yesno</source_model>
32
+ <sort_order>2</sort_order>
33
+ <show_in_default>1</show_in_default>
34
+ <show_in_website>1</show_in_website>
35
+ <show_in_store>1</show_in_store>
36
+ <tooltip><![CDATA[<b>Testmode:</b> <br/>]]> Gebruik de testmode om betalingen te testen zonder een echte betaling te doen.</tooltip>
37
+ </testMode>
38
+
39
+ <merchantID translate="label tooltip">
40
+ <label>Merchant ID</label>
41
+ <frontend_type>text</frontend_type>
42
+ <sort_order>11</sort_order>
43
+ <show_in_default>1</show_in_default>
44
+ <show_in_website>1</show_in_website>
45
+ <show_in_store>1</show_in_store>
46
+ <tooltip><![CDATA[<b>Merchant ID:</b> <br/>]]> Your merchant ID. The payment is added to this account.</tooltip>
47
+ <validate>validate-number</validate>
48
+ </merchantID>
49
+
50
+ <merchantSubID translate="label tooltip">
51
+ <label>Merchant SubID</label>
52
+ <frontend_type>text</frontend_type>
53
+ <sort_order>21</sort_order>
54
+ <show_in_default>1</show_in_default>
55
+ <show_in_website>1</show_in_website>
56
+ <show_in_store>0</show_in_store>
57
+ <frontend_class>validate-number</frontend_class>
58
+ <tooltip>eMandate.ContractSubId as supplied to you by the creditor bank. If you do not have a ContractSubId, use 0 for this field.</tooltip>
59
+ </merchantSubID>
60
+
61
+ <SequenceTypeCustomer translate="label tooltip">
62
+ <label>SequenceType Choice</label>
63
+ <frontend_type>select</frontend_type>
64
+ <source_model>adminhtml/system_config_source_yesno</source_model>
65
+ <sort_order>22</sort_order>
66
+ <show_in_default>1</show_in_default>
67
+ <show_in_website>1</show_in_website>
68
+ <show_in_store>0</show_in_store>
69
+ <tooltip>Allow to choice SequenceType by customer.</tooltip>
70
+ </SequenceTypeCustomer>
71
+
72
+ <SequenceType translate="label tooltip">
73
+ <label>Sequence Type</label>
74
+ <frontend_type>text</frontend_type>
75
+ <sort_order>23</sort_order>
76
+ <show_in_default>1</show_in_default>
77
+ <show_in_website>1</show_in_website>
78
+ <show_in_store>0</show_in_store>
79
+ <comment>OOFF = one-off | RCUR = recurring</comment>
80
+ <tooltip>Indicates type of eMandate: one-off Direct Debit or recurring.</tooltip>
81
+ </SequenceType>
82
+
83
+ <eMandateReason translate="label tooltip">
84
+ <label>Mandate Reason</label>
85
+ <frontend_type>text</frontend_type>
86
+ <sort_order>24</sort_order>
87
+ <show_in_default>1</show_in_default>
88
+ <show_in_website>1</show_in_website>
89
+ <show_in_store>0</show_in_store>
90
+ <tooltip>webshop purchase</tooltip>
91
+ </eMandateReason>
92
+
93
+ <merchantReturnURL translate="label tooltip">
94
+ <label>Return URL</label>
95
+ <frontend_type>text</frontend_type>
96
+ <sort_order>31</sort_order>
97
+ <show_in_default>1</show_in_default>
98
+ <show_in_website>1</show_in_website>
99
+ <show_in_store>0</show_in_store>
100
+ <frontend_class>required-entry</frontend_class>
101
+ <tooltip>A valid URL to which the debtor banks redirects to, after the debtor has authorized a transaction.</tooltip>
102
+ </merchantReturnURL>
103
+
104
+ <passphrase translate="label tooltip">
105
+ <label>Passphrase</label>
106
+ <frontend_type>text</frontend_type>
107
+ <sort_order>41</sort_order>
108
+ <show_in_default>1</show_in_default>
109
+ <show_in_website>1</show_in_website>
110
+ <show_in_store>0</show_in_store>
111
+ <frontend_class>required-entry</frontend_class>
112
+ <tooltip>The password for the private key of the signing certificate.</tooltip>
113
+ </passphrase>
114
+
115
+ <AcquirerUrl_DirectoryReq translate="label tooltip">
116
+ <label>AcquirerUrl_DirectoryReq</label>
117
+ <comment>https://machtigen.secure-ing.com/EMRoutingWS/handler/ing</comment>
118
+ <frontend_type>text</frontend_type>
119
+ <sort_order>51</sort_order>
120
+ <show_in_default>1</show_in_default>
121
+ <show_in_website>1</show_in_website>
122
+ <show_in_store>0</show_in_store>
123
+ <frontend_class>required-entry</frontend_class>
124
+ <tooltip>The URL to which the library sends Directory request messages.</tooltip>
125
+ </AcquirerUrl_DirectoryReq>
126
+
127
+ <AcquirerUrl_TransactionReq translate="label tooltip">
128
+ <label>AcquirerUrl_TransactionReq</label>
129
+ <comment>https://machtigen.secure-ing.com/EMRoutingWS/handler/ing</comment>
130
+ <frontend_type>text</frontend_type>
131
+ <sort_order>61</sort_order>
132
+ <show_in_default>1</show_in_default>
133
+ <show_in_website>1</show_in_website>
134
+ <show_in_store>0</show_in_store>
135
+ <frontend_class>required-entry</frontend_class>
136
+ <tooltip>The URL to which the library sends Transaction request messages (including eMandates messages).</tooltip>
137
+ </AcquirerUrl_TransactionReq>
138
+
139
+ <AcquirerUrl_StatusReq translate="label tooltip">
140
+ <label>AcquirerUrl_StatusReq</label>
141
+ <comment>https://machtigen.secure-ing.com/EMRoutingWS/handler/ing</comment>
142
+ <frontend_type>text</frontend_type>
143
+ <sort_order>71</sort_order>
144
+ <show_in_default>1</show_in_default>
145
+ <show_in_website>1</show_in_website>
146
+ <show_in_store>0</show_in_store>
147
+ <frontend_class>required-entry</frontend_class>
148
+ <tooltip>The URL to which the library sends Status request messages</tooltip>
149
+ </AcquirerUrl_StatusReq>
150
+
151
+ <AcquirerUrl_DirectoryReqTest translate="label tooltip">
152
+ <label>TEST AcquirerUrl_DirectoryReq</label>
153
+ <comment>https://machtigen.secure-ing.com/TestRoutingWS/handler/ing</comment>
154
+ <frontend_type>text</frontend_type>
155
+ <sort_order>81</sort_order>
156
+ <show_in_default>1</show_in_default>
157
+ <show_in_website>1</show_in_website>
158
+ <show_in_store>0</show_in_store>
159
+ <frontend_class>required-entry</frontend_class>
160
+ <tooltip>The URL to which the library sends Directory request messages.</tooltip>
161
+ </AcquirerUrl_DirectoryReqTest>
162
+
163
+ <AcquirerUrl_TransactionReqTest translate="label tooltip">
164
+ <label>TEST AcquirerUrl_TransactionReq</label>
165
+ <comment>https://machtigen.secure-ing.com/TestRoutingWS/handler/ing</comment>
166
+ <frontend_type>text</frontend_type>
167
+ <sort_order>91</sort_order>
168
+ <show_in_default>1</show_in_default>
169
+ <show_in_website>1</show_in_website>
170
+ <show_in_store>0</show_in_store>
171
+ <frontend_class>required-entry</frontend_class>
172
+ <tooltip>The URL to which the library sends Transaction request messages (including eMandates messages).</tooltip>
173
+ </AcquirerUrl_TransactionReqTest>
174
+
175
+ <AcquirerUrl_StatusReqTest translate="label tooltip">
176
+ <label>TEST AcquirerUrl_StatusReq</label>
177
+ <comment>https://machtigen.secure-ing.com/TestRoutingWS/handler/ing</comment>
178
+ <frontend_type>text</frontend_type>
179
+ <sort_order>101</sort_order>
180
+ <show_in_default>1</show_in_default>
181
+ <show_in_website>1</show_in_website>
182
+ <show_in_store>0</show_in_store>
183
+ <frontend_class>required-entry</frontend_class>
184
+ <tooltip>The URL to which the library sends Status request messages.</tooltip>
185
+ </AcquirerUrl_StatusReqTest>
186
+
187
+ <keyFile translate="label">
188
+ <label>Key File (.pem)</label>
189
+ <frontend_type>file</frontend_type>
190
+ <backend_model>adminhtml/system_config_backend_file</backend_model>
191
+ <upload_dir>var/xrec/dim/cer</upload_dir>
192
+ <sort_order>50</sort_order>
193
+ <show_in_default>1</show_in_default>
194
+ <show_in_website>0</show_in_website>
195
+ <show_in_store>0</show_in_store>
196
+ <comment>The file containing the private key to use for signing messages to the creditor bank (aka the signing certificate).</comment>
197
+ </keyFile>
198
+
199
+ <crtFile translate="label">
200
+ <label>Certificate File (.cer)</label>
201
+ <frontend_type>file</frontend_type>
202
+ <backend_model>adminhtml/system_config_backend_file</backend_model>
203
+ <upload_dir>var/xrec/dim/cer</upload_dir>
204
+ <sort_order>50</sort_order>
205
+ <show_in_default>1</show_in_default>
206
+ <show_in_website>0</show_in_website>
207
+ <show_in_store>0</show_in_store>
208
+ <comment>The file containing the public key of the signing certificate.</comment>
209
+ </crtFile>
210
+
211
+ <crtFileAquirer translate="label">
212
+ <label>Certificate File Aquirer (.cer)</label>
213
+ <frontend_type>file</frontend_type>
214
+ <backend_model>adminhtml/system_config_backend_file</backend_model>
215
+ <upload_dir>var/xrec/dim/cer</upload_dir>
216
+ <sort_order>50</sort_order>
217
+ <show_in_default>1</show_in_default>
218
+ <show_in_website>0</show_in_website>
219
+ <show_in_store>0</show_in_store>
220
+ <comment>The file containing the public key of the certificate to use to validate messages from the creditor bank.</comment>
221
+ </crtFileAquirer>
222
+
223
+ </fields>
224
+ </xrec>
225
+ </groups>
226
+ </payment>
227
+ </sections>
228
+ </config>
app/code/community/Xrec/Dim/sql/dim_setup/mysql4-install-1.0.0.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $installer = $this;
3
+ $installer->startSetup();
4
+
5
+ $installer->run(
6
+ sprintf("CREATE TABLE IF NOT EXISTS `%s` (
7
+ `order_id` int(11) NOT NULL,
8
+ `method` varchar(3) NOT NULL,
9
+ `transaction_id` varchar(32) NOT NULL,
10
+ `sequence_type` varchar(15) NOT NULL,
11
+ `bank_status` varchar(20) NOT NULL,
12
+ `created_at` datetime NOT NULL,
13
+ `updated_at` datetime DEFAULT NULL
14
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;",
15
+ $installer->getTable('dim_payments')
16
+ )
17
+ );
18
+
19
+ if(strlen(Mage::getStoreConfig("payment/xrec/merchantID")) == 0)
20
+ {
21
+ $installer->run(
22
+ sprintf("INSERT INTO `%s` (`severity`, `date_added`, `title`, `description`, `url`, `is_read`, `is_remove`)
23
+ VALUES ('4', '%s', 'Ga naar System -> Configuration -> Betaalmethodes om uw ING digitaal Incassomachtigen gegevens in te vullen om onze betaalmethode(s) te gebruiken',
24
+ 'Uw Digitaal Incassomachtigen instellingen moeten ingesteld worden. Als u dit niet doet dan kunnen uw klanten geen gebruik maken van de betaalmethode(s).',
25
+ 'http://www.xrec.nl/', '0', '0');",
26
+ $installer->getTable('adminnotification_inbox'),
27
+ date("Y/m/d H:i:s", time())
28
+ )
29
+ );
30
+ }
31
+
32
+ $installer->endSetup();
app/code/community/Xrec/Dim/sql/dim_setup/mysql4-uninstall-1.0.0.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $installer = $this;
3
+
4
+ $installer->startSetup();
5
+
6
+ $installer->run(
7
+ sprintf("DROP TABLE IF EXISTS `%s`",
8
+ $installer->getTable('dim_payments')
9
+ )
10
+ );
11
+
12
+ $installer->run("
13
+ DELETE FROM `{$installer->getTable('core_config_data')}` where `path` LIKE 'payment/xrec%';
14
+ DELETE FROM `{$installer->getTable('core_resource')}` where `code` = 'dim_setup';"
15
+ );
16
+
17
+ $installer->endSetup();
app/design/frontend/base/default/layout/dim.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <layout version="0.1.0">
3
+ <default>
4
+ <reference name="head">
5
+ <action method="addCss">
6
+ <stylesheet>/../../../dim/css/style.css</stylesheet>
7
+ </action>
8
+ </reference>
9
+ </default>
10
+
11
+ <dim_api_return>
12
+ <reference name="root">
13
+ <action method="setTemplate">
14
+ <template>page/1column.phtml</template>
15
+ </action>
16
+ </reference>
17
+ </dim_api_return>
18
+ </layout>
app/design/frontend/base/default/template/xrec/form/dim.phtml ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $_code = $this->getMethodCode();
3
+ $helper = Mage::Helper('dim/dim');
4
+ $data = Mage::Helper('dim/data');
5
+ $buckets = $helper->doDirectoryRequest();
6
+
7
+ $options = '';
8
+ foreach ($buckets as $key => $bucket) {
9
+ $options .= '<optgroup label="' . $key . '">';
10
+ foreach ($bucket as $bank) {
11
+ $options .= '<option value="' . $bank->DebtorBankId . '">' . $bank->DebtorBankName . '</option>';
12
+ }
13
+ $options .= '</optgroup>';
14
+ }
15
+
16
+ ?>
17
+
18
+ <ul class="form-list" id="payment_form_<?php echo $this->escapeHtml($_code) ?>" style="display:none;">
19
+ <li>
20
+ <label for="dim_bank_id"
21
+ class="required"><em>*</em><?php echo $this->__('Selecteer uw bank:') ?></label>
22
+ <select name="payment[dim_bank_id]" id="dim_bank_id" class="required-entry">
23
+ <?php echo $options; ?>
24
+ </select>
25
+ </li>
26
+ <?php if ($data->getConfig('SequenceTypeCustomer')) :?>
27
+ <li>
28
+ <label for="dim_sequence_type"
29
+ class="required"><em>*</em><?php echo $this->__('Machtiging type:') ?></label>
30
+ <select name="payment[dim_sequence_type]" id="dim_sequence_type" class="required-entry">
31
+ <option value="OOFF">Machtiging eenmalige SEPA incasso</option>
32
+ <option value="RCUR">Machtiging doorlopende SEPA incasso</option>
33
+ </select>
34
+ </li>
35
+ <?php endif;?>
36
+ </ul>
app/design/frontend/base/default/template/xrec/page/exception.phtml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+
2
+ <div class="page-title">
3
+ <h3>Betaling mislukt / Payment failed</h3>
4
+ </div>
5
+ <?php echo $this->getException(); ?>
6
+
7
+
8
+ <div class="buttons-set">
9
+ <p class="back-link"><a href="<?php echo $this->escapeHtml($this->getUrl()) ?>"><small>&laquo; </small><?php echo $this->__('Homepage') ?></a></p>
10
+ </div>
app/design/frontend/base/default/template/xrec/page/fail.phtml ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $_code = $this->getMethodCode();
3
+ $helper = Mage::Helper('dim/dim');
4
+ $data = Mage::Helper('dim/data');
5
+ $buckets = $helper->doDirectoryRequest();
6
+
7
+ $options = '';
8
+ foreach ($buckets as $key => $bucket) {
9
+ $options .= '<optgroup label="' . $key . '">';
10
+ foreach ($bucket as $bank) {
11
+ $options .= '<option value="' . $bank->DebtorBankId . '">' . $bank->DebtorBankName . '</option>';
12
+ }
13
+ $options .= '</optgroup>';
14
+ }
15
+ ?>
16
+ <div class="page-title">
17
+ <h3>Betaling mislukt / Payment failed</h3>
18
+ </div>
19
+
20
+ De betaling is helaas mislukt. Probeer het bedrag van
21
+ &euro;<?php echo number_format($this->getOrder()->getGrandTotal(),2) ?> nogmaals af te rekenen met Digitaal Incassomachtigen.
22
+
23
+ <br /><br />
24
+
25
+ <form name="xrec_dim_dim" id="xrec_dim_dim" action="<?php echo $this->escapeHtml($this->getForm()) ?>" method="post">
26
+ <input type="hidden" name="order_id" value="<?php echo $this->escapeHtml($this->getOrder()->getId()) ?>" />
27
+ <ul class="form-list">
28
+ <li>
29
+ <label for="dim_bank_id" class="required"><em>*</em>
30
+ <?php echo $this->__('Selecteer uw bank:') ?>
31
+ </label>
32
+ <select name="dim_bank_id" class="required-entry" id="dim_bank_id">
33
+ <?php echo $options?>
34
+ </select>
35
+ </li>
36
+ <?php if ($data->getConfig('SequenceTypeCustomer')) :?>
37
+ <li>
38
+ <label for="dim_sequence_type"
39
+ class="required"><em>*</em><?php echo $this->__('Machtiging type:') ?></label>
40
+ <select name="dim_sequence_type" id="dim_sequence_type" class="required-entry">
41
+ <option value="OOFF">Machtiging eenmalige SEPA incasso</option>
42
+ <option value="RCUR">Machtiging doorlopende SEPA incasso</option>
43
+ </select>
44
+ </li>
45
+ <?php endif;?>
46
+ <li>
47
+ <button class="form-button" style="padding:5px;" type="submit">Betalen</button>
48
+ </li>
49
+ </ul>
50
+ </form>
51
+
52
+ <div class="buttons-set">
53
+ <p class="back-link">
54
+ <a href="<?php echo $this->escapeHtml(Mage::getBaseUrl()) ?>">
55
+ <small>&laquo; </small>
56
+ <?php echo $this->__('Homepage') ?>
57
+ </a>
58
+ </p>
59
+ </div>
60
+
61
+ <script type="text/javascript">
62
+ //< ![CDATA[
63
+ var dimForm = new VarienForm('xrec_dim_dim');
64
+ //]]>
65
+ </script>
app/etc/modules/Xrec_Dim.xml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Xrec_Dim>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ <depends>
8
+ <Mage_Payment />
9
+ </depends>
10
+ </Xrec_Dim>
11
+ </modules>
12
+ </config>
lib/Communicator/.DS_Store ADDED
Binary file
lib/Communicator/B2BCommunicator.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once 'CoreCommunicator.php';
4
+
5
+ /**
6
+ * Description of Communicator
7
+ */
8
+ class B2BCommunicator extends CoreCommunicator {
9
+
10
+ const LOCAL_INSTRUMENT = 'B2B';
11
+ const PRODUCT_ID = 'NL:BVN:eMandatesB2B:1.0';
12
+
13
+ /**
14
+ * Initiates a new B2BCommunicator
15
+ */
16
+ function __construct(Configuration $configuration, $logger = false) {
17
+ parent::__construct($configuration, $logger);
18
+ }
19
+
20
+ /**
21
+ * Performs a CancellationRequest and returns the appropiate CancellationResponse
22
+ *
23
+ * @param CancellationRequest $cancellationRequest
24
+ * @return \CancellationResponse
25
+ */
26
+ public function Cancel(CancellationRequest $cancellationRequest) {
27
+ $cancellationRequest->logger = $this->logger;
28
+ $this->logger->Log("sending cancellation transaction request");
29
+ $c = get_called_class();
30
+
31
+ $AcquirerTrxReq = new AcquirerTrxRequest(
32
+ $c::PRODUCT_ID, $c::VERSION, new AcquirerTrxReqMerchant(
33
+ $this->Configuration->contractID, $this->Configuration->contractSubID, $this->Configuration->merchantReturnURL
34
+ ), $cancellationRequest->DebtorBankId, new AcquirerTrxReqTransaction(
35
+ $cancellationRequest->EntranceCode, !empty($cancellationRequest->ExpirationPeriod) ? $cancellationRequest->ExpirationPeriod : null, $cancellationRequest->Language, $cancellationRequest
36
+ )
37
+ );
38
+
39
+ try {
40
+ $this->logger->Log("building idx message");
41
+ // Serialize
42
+ $docTree = $AcquirerTrxReq->toXml($c::LOCAL_INSTRUMENT);
43
+
44
+ // Send the Request
45
+ $response = $this->PerformRequest($docTree, $this->Configuration->AcquirerUrl_TransactionReq);
46
+ // Validate the Response and validate signature
47
+ XmlValidator::isValidatXML($response, XmlValidator::SCHEMA_IDX, $this->logger);
48
+ $this->signer->verify($response, $this->Configuration->crtFileAquirer);
49
+
50
+ return new CancellationResponse($response);
51
+ } catch (Exception $ex) {
52
+ return new CancellationResponse($ex->getMessage(), (!empty($response) ? $response : ''));
53
+ }
54
+ }
55
+
56
+ }
lib/Communicator/Configuration/Configuration.php ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ /**.
5
+ * Description of Configuration
6
+ */
7
+ class Configuration {
8
+
9
+ /**
10
+ * A passphrase for the keyFile
11
+ * @var string
12
+ */
13
+ public $passphrase;
14
+
15
+ /**
16
+ * A string which specifies the path to the private key file used by the crtFile to sign messages to the creditor bank.
17
+ * @var string
18
+ */
19
+ public $keyFile;
20
+
21
+ /**
22
+ * A string which specifies the path to the certificate to use to sign messages to the creditor bank.
23
+ * @var string
24
+ */
25
+ public $crtFile;
26
+
27
+ /**
28
+ * A string which specifies the path to the certificate to use to validate messages from the creditor bank.
29
+ * @var string
30
+ */
31
+ public $crtFileAquirer;
32
+
33
+ /**
34
+ * eMandate.ContractID as supplied to you by the creditor bank.
35
+ * If the eMandate.ContractID has less than 9 digits, use leading zeros to fill out the field.
36
+ * @var string
37
+ */
38
+ public $contractID;
39
+
40
+ /**
41
+ * eMandate.ContractSubId as supplied to you by the creditor bank.
42
+ * If you do not have a ContractSubId, use 0 for this field.
43
+ * @var string
44
+ */
45
+ public $contractSubID;
46
+
47
+ /**
48
+ * A valid URL to which the debtor banks redirects to, after the debtor has authorized a transaction.
49
+ * @var string
50
+ */
51
+ public $merchantReturnURL;
52
+
53
+ /**
54
+ * The URL to which the library sends Directory request messages
55
+ * @var string
56
+ */
57
+ public $AcquirerUrl_DirectoryReq;
58
+
59
+ /**
60
+ * The URL to which the library sends Transaction messages (including eMandates messages).
61
+ * @var string
62
+ */
63
+ public $AcquirerUrl_TransactionReq;
64
+
65
+ /**
66
+ * The URL to which the library sends Status request messages.
67
+ * @var string
68
+ */
69
+ public $AcquirerUrl_StatusReq;
70
+
71
+ /**
72
+ * Enables or Disables the xml logs
73
+ * @var bool
74
+ */
75
+ public $enableXMLLogs;
76
+
77
+ /**
78
+ * Path to the logs folder
79
+ * eg: logs/
80
+ * @var string
81
+ */
82
+ public $logPath;
83
+
84
+ /**
85
+ * Folder name pattern for date() function
86
+ * eg: "Y-m-d" will produce: "2015-03-11"
87
+ * eg: end result will be: "logs/2015-03-11/115423.321-DirectoryRes.xml"
88
+ * @var string
89
+ */
90
+ public $folderNamePattern;
91
+
92
+ /**
93
+ * File name prefix pattern for date() function
94
+ * eg: "His.u" will produce: "115423.321"
95
+ * eg: end result will be: "logs/2015-03-11/115423.321-DirectoryRes.xml"
96
+ * @var string
97
+ */
98
+ public $fileNamePrefix;
99
+
100
+ /**
101
+ * Enables or Disables the internal logs
102
+ * @var bool
103
+ */
104
+ public $enableInternalLogs;
105
+
106
+ /**
107
+ * The file name for internal logs
108
+ * This file will be saved in the same path as the xml logs
109
+ * eg: "emandates.txt" will produce: "logs/2015-03-11/emandates.txt"
110
+ * @var type
111
+ */
112
+ public $fileName;
113
+
114
+ /**
115
+ * Constructor that highlights all required fields for this object
116
+ *
117
+ * @param string $passphrase
118
+ * @param string $keyFile
119
+ * @param string $crtFile
120
+ * @param string $crtFileAquirer
121
+ * @param string $contractID
122
+ * @param string $contractSubID
123
+ * @param string $merchantReturnURL
124
+ * @param string $AcquirerUrl_DirectoryReq
125
+ * @param string $AcquirerUrl_TransactionReq
126
+ * @param bool $enableXMLLogs
127
+ * @param string $logPath
128
+ * @param string $folderNamePattern
129
+ * @param string $fileNamePrefix
130
+ * @param bool $enableInternalLogs
131
+ * @param string $fileName
132
+ */
133
+ public function __construct($passphrase, $keyFile, $crtFile, $crtFileAquirer, $contractID, $contractSubID, $merchantReturnURL, $AcquirerUrl_DirectoryReq, $AcquirerUrl_TransactionReq, $AcquirerUrl_StatusReq, $enableXMLLogs, $logPath, $folderNamePattern, $fileNamePrefix, $enableInternalLogs, $fileName) {
134
+ $this->passphrase = $passphrase;
135
+ $this->keyFile = $keyFile;
136
+ $this->crtFile = $crtFile;
137
+ $this->crtFileAquirer = $crtFileAquirer;
138
+ $this->contractID = $contractID;
139
+ $this->contractSubID = $contractSubID;
140
+ $this->merchantReturnURL = $merchantReturnURL;
141
+ $this->AcquirerUrl_DirectoryReq = $AcquirerUrl_DirectoryReq;
142
+ $this->AcquirerUrl_TransactionReq = $AcquirerUrl_TransactionReq;
143
+ $this->AcquirerUrl_StatusReq = $AcquirerUrl_StatusReq;
144
+ $this->enableXMLLogs = $enableXMLLogs;
145
+ $this->logPath = $logPath;
146
+ $this->folderNamePattern = $folderNamePattern;
147
+ $this->fileNamePrefix = $fileNamePrefix;
148
+ $this->enableInternalLogs = $enableInternalLogs;
149
+ $this->fileName = $fileName;
150
+ }
151
+
152
+ /**
153
+ * Returns the Configuration object base on the configuration file settings
154
+ *
155
+ * @global array $emandates_config_params
156
+ * @return \Configuration
157
+ */
158
+ public static function getDefault() {
159
+ global $emandates_config_params;
160
+
161
+ return new Configuration(
162
+ $emandates_config_params['passphrase'],
163
+ $emandates_config_params['keyFile'],
164
+ $emandates_config_params['crtFile'],
165
+ $emandates_config_params['crtFileAquirer'],
166
+
167
+ $emandates_config_params['contractID'],
168
+ $emandates_config_params['contractSubID'],
169
+ $emandates_config_params['merchantReturnURL'],
170
+
171
+ $emandates_config_params['AcquirerUrl_DirectoryReq'],
172
+ $emandates_config_params['AcquirerUrl_TransactionReq'],
173
+ $emandates_config_params['AcquirerUrl_StatusReq'],
174
+
175
+ $emandates_config_params['enableXMLLogs'],
176
+ $emandates_config_params['logPath'],
177
+ $emandates_config_params['folderNamePattern'],
178
+ $emandates_config_params['fileNamePrefix'],
179
+
180
+ $emandates_config_params['enableInternalLogs'],
181
+ $emandates_config_params['fileName']
182
+ );
183
+ }
184
+
185
+ }
lib/Communicator/CoreCommunicator.php ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once dirname(__FILE__) . "/Configuration/Configuration.php";
4
+ require_once dirname(__FILE__) . "/B2BCommunicator.php";
5
+ require_once dirname(__FILE__) . "/Libraries/XmlUtility.php";
6
+
7
+ /* DIRECTORY */
8
+ require_once dirname(__FILE__) . "/Entities/DirectoryRequest.php";
9
+ require_once dirname(__FILE__) . "/Entities/DirectoryResponse.php";
10
+
11
+ /* TRANSACTION */
12
+ require_once dirname(__FILE__) . "/Entities/AcquirerTrxRequest.php";
13
+
14
+ /* NEW eMANDATE */
15
+ require_once dirname(__FILE__) . "/Entities/NewMandateRequest.php";
16
+ require_once dirname(__FILE__) . "/Entities/NewMandateResponse.php";
17
+
18
+ /* STATUS */
19
+ require_once dirname(__FILE__) . "/Entities/AcquirerStatusRequest.php";
20
+ require_once dirname(__FILE__) . "/Entities/AcquirerStatusResponse.php";
21
+
22
+ /* CANCEL */
23
+ require_once dirname(__FILE__) . "/Entities/CancellationRequest.php";
24
+ require_once dirname(__FILE__) . "/Entities/CancellationResponse.php";
25
+
26
+ /* AMEND */
27
+ require_once dirname(__FILE__) . "/Entities/AmendmentRequest.php";
28
+ require_once dirname(__FILE__) . "/Entities/AmendmentResponse.php";
29
+
30
+ /* Signer and Validator */
31
+ require_once dirname(__FILE__) . "/Libraries/XmlSecurity.php";
32
+ require_once dirname(__FILE__) . "/Libraries/XmlValidator.php";
33
+
34
+ require_once dirname(__FILE__) . '/Libraries/CommunicatorException.php';
35
+ require_once dirname(__FILE__) . '/Libraries/MessageIdGenerator.php';
36
+ require_once dirname(__FILE__) . '/Libraries/Logger.php';
37
+
38
+ /**
39
+ * Description of Communicator
40
+ */
41
+ class CoreCommunicator {
42
+
43
+ const LOCAL_INSTRUMENT = 'CORE';
44
+ const VERSION = '1.0.0';
45
+ const PRODUCT_ID = 'NL:BVN:eMandatesCore:1.0';
46
+
47
+ /**
48
+ * The configuration object used in the Communicator
49
+ *
50
+ * @var Configuration
51
+ */
52
+ protected $Configuration;
53
+
54
+ /**
55
+ * The logger object use to log xml and internal messages
56
+ *
57
+ * @var Logger
58
+ */
59
+ protected $logger;
60
+
61
+ /**
62
+ * The singer object used to sign requests and verify response
63
+ *
64
+ * @var XmlSecurity
65
+ */
66
+ protected $signer;
67
+
68
+ public function __construct(Configuration $configuration, $logger = false) {
69
+
70
+ $this->Configuration = $configuration;
71
+
72
+ $this->logger = ($logger ? $logger : new Logger($configuration));
73
+ $this->signer = new XmlSecurity($this->logger);
74
+
75
+ $this->logger->Log(get_called_class() . " initialized");
76
+ }
77
+
78
+ /**
79
+ * Performs a DirectoryRequest and returns the apropiate DirectoryResponse
80
+ *
81
+ * @return \DirectoryResponse
82
+ */
83
+ public function Directory() {
84
+ $this->logger->Log("sending new directory request");
85
+ $c = get_called_class();
86
+
87
+ $DirectoryReq = new DirectoryRequest(
88
+ $c::PRODUCT_ID, $c::VERSION, new Merchant($this->Configuration->contractID, $this->Configuration->contractSubID)
89
+ );
90
+
91
+
92
+ try {
93
+ $this->logger->Log("building idx message");
94
+ // Serialize the DirectoryReq
95
+ $docTree = $DirectoryReq->toXml();
96
+
97
+ // Send the Request
98
+ $response = $this->PerformRequest($docTree, $this->Configuration->AcquirerUrl_DirectoryReq);
99
+
100
+ // Validate the Response and validate signature
101
+
102
+ XmlValidator::isValidatXML($response, XmlValidator::SCHEMA_IDX, $this->logger);
103
+ $this->signer->verify($response, $this->Configuration->crtFileAquirer);
104
+
105
+ return new DirectoryResponse($response);
106
+ } catch (Exception $ex) {
107
+ return new DirectoryResponse($ex->getMessage(), (!empty($response) ? $response : ''));
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Performs a new mandate request using the provided mandate
113
+ *
114
+ * @param NewMandateRequest $NewMandateRequest
115
+ * @return NewMandateResponse
116
+ */
117
+ public function NewMandate(NewMandateRequest $NewMandateRequest) {
118
+ $NewMandateRequest->logger = $this->logger;
119
+ $this->logger->Log("sending new eMandate transaction");
120
+ $c = get_called_class();
121
+
122
+ $AcquirerTrxReq = new AcquirerTrxRequest(
123
+ $c::PRODUCT_ID, $c::VERSION, new AcquirerTrxReqMerchant(
124
+ $this->Configuration->contractID, $this->Configuration->contractSubID, $this->Configuration->merchantReturnURL
125
+ ), $NewMandateRequest->DebtorBankId, new AcquirerTrxReqTransaction(
126
+ $NewMandateRequest->EntranceCode, !empty($NewMandateRequest->ExpirationPeriod) ? $NewMandateRequest->ExpirationPeriod : null, $NewMandateRequest->Language, $NewMandateRequest
127
+ )
128
+ );
129
+
130
+ try {
131
+ $this->logger->Log("building idx message");
132
+ // Serialize
133
+ $docTree = $AcquirerTrxReq->toXml($c::LOCAL_INSTRUMENT);
134
+
135
+
136
+ // Send the Request
137
+ $response = $this->PerformRequest($docTree, $this->Configuration->AcquirerUrl_TransactionReq);
138
+
139
+ // Validate the Response and validate signature
140
+ XmlValidator::isValidatXML($response, XmlValidator::SCHEMA_IDX, $this->logger);
141
+ $this->signer->verify($response, $this->Configuration->crtFileAquirer);
142
+
143
+ return new NewMandateResponse($response);
144
+ } catch (Exception $ex) {
145
+ return new NewMandateResponse($ex->getMessage(), (!empty($response) ? $response : ''));
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Performs a status request usign the provided $statusRequest
151
+ *
152
+ * @param StatusRequest $statusRequest
153
+ * @return AcquirerStatusResponse
154
+ */
155
+ public function GetStatus(StatusRequest $statusRequest) {
156
+ $this->logger->Log("sending new status request");
157
+ $c = get_called_class();
158
+
159
+ $AcquirerStatusReq = new AcquirerStatusRequest(
160
+ $c::PRODUCT_ID, $c::VERSION, new AcquirerStatusReqMerchant(
161
+ $this->Configuration->contractID, $this->Configuration->contractSubID
162
+ ), new AcquirerStatusReqTransaction(
163
+ $statusRequest->TransactionId
164
+ )
165
+ );
166
+ try {
167
+ $this->logger->Log("building idx message");
168
+ // Serialize
169
+ $docTree = $AcquirerStatusReq->toXml();
170
+
171
+ // Send the Request
172
+ $response = $this->PerformRequest($docTree, $this->Configuration->AcquirerUrl_StatusReq);
173
+ // Validate the Response and validate signature
174
+ XmlValidator::isValidatXML($response, XmlValidator::SCHEMA_IDX, $this->logger);
175
+ $this->signer->verify($response, $this->Configuration->crtFileAquirer);
176
+
177
+ return new AcquirerStatusResponse($response, $this->logger);
178
+ } catch (Exception $ex) {
179
+ return new AcquirerStatusResponse($ex->getMessage(), $this->logger, (!empty($response) ? $response : ''));
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Performs an amendment to a mandate using the provided $amendmentRequest
185
+ *
186
+ * @param AmendmentRequest $amendmentRequest
187
+ * @return AmendmentResponse
188
+ */
189
+ public function Amend(AmendmentRequest $amendmentRequest) {
190
+ $amendmentRequest->logger = $this->logger;
191
+ $this->logger->Log("sending new amend request");
192
+ $c = get_called_class();
193
+
194
+ $AcquirerTrxReq = new AcquirerTrxRequest(
195
+ $c::PRODUCT_ID, $c::VERSION, new AcquirerTrxReqMerchant(
196
+ $this->Configuration->contractID, $this->Configuration->contractSubID, $this->Configuration->merchantReturnURL
197
+ ), $amendmentRequest->DebtorBankId, new AcquirerTrxReqTransaction(
198
+ $amendmentRequest->EntranceCode, !empty($amendmentRequest->ExpirationPeriod) ? $amendmentRequest->ExpirationPeriod : null, $amendmentRequest->Language, $amendmentRequest
199
+ )
200
+ );
201
+
202
+ try {
203
+ $this->logger->Log("building idx message");
204
+ // Serialize
205
+ $docTree = $AcquirerTrxReq->toXml($c::LOCAL_INSTRUMENT);
206
+
207
+ // Send the Request
208
+ $response = $this->PerformRequest($docTree, $this->Configuration->AcquirerUrl_TransactionReq);
209
+
210
+ // Validate the Response and validate signature
211
+ XmlValidator::isValidatXML($response, XmlValidator::SCHEMA_IDX, $this->logger);
212
+ $this->signer->verify($response, $this->Configuration->crtFileAquirer);
213
+
214
+ return new AmendmentResponse($response);
215
+ } catch (Exception $ex) {
216
+ return new AmendmentResponse($ex->getMessage(), (!empty($response) ? $response : ''));
217
+ }
218
+ }
219
+
220
+ /*
221
+ * *************************************************************************
222
+ * PROTECTED METHODS
223
+ * *************************************************************************
224
+ */
225
+
226
+ /**
227
+ * Sends the xml to the provided url and returns the response
228
+ * Throws an Exception if there was something wrong with the curl
229
+ *
230
+ * @param string $xml
231
+ * @param string $url
232
+ * @return string
233
+ * @throws Exception
234
+ */
235
+ protected function PerformRequest($docTree, $url) {
236
+
237
+ // Sign the xml
238
+ $docTree = $this->signer->sign($docTree, $this->Configuration->crtFile, $this->Configuration->keyFile, $this->Configuration->passphrase);
239
+
240
+ // Validate the request xml against the .xsd schema
241
+ if (XmlValidator::isValidatXML($docTree->saveXML(), XmlValidator::SCHEMA_IDX, $this->logger)) {
242
+
243
+ $this->logger->Log("sending request to {{$url}} ");
244
+
245
+ // Log the xml before sending
246
+ $this->logger->LogXmlMessage($docTree);
247
+
248
+ //setting the curl parameters.
249
+ $headers = array(
250
+ "Content-type: text/xml;charset=\"UTF-8\"",
251
+ );
252
+
253
+ $ch = curl_init();
254
+ curl_setopt($ch, CURLOPT_URL, $url);
255
+ curl_setopt($ch, CURLOPT_POST, 1);
256
+
257
+ // send xml request to server
258
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
259
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
260
+
261
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $docTree->saveXML());
262
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
263
+
264
+ curl_setopt($ch, CURLOPT_VERBOSE, 0);
265
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
266
+ $data = curl_exec($ch);
267
+
268
+ // check for curl errors
269
+ if ($data === false) {
270
+ $error = curl_error($ch);
271
+ curl_close($ch);
272
+
273
+ $this->logger->Log($error);
274
+ throw new Exception($error);
275
+ } else {
276
+ curl_close($ch);
277
+
278
+ $doc = @simplexml_load_string($data);
279
+ if (!$doc) {
280
+ $this->logger->Log("Raw Response : " . $data);
281
+ throw new CommunicatorException($data);
282
+ }
283
+
284
+ // Log the xml received
285
+ $this->logger->LogXmlMessage($data, true);
286
+
287
+ return $data;
288
+ }
289
+ }
290
+ }
291
+
292
+ }
lib/Communicator/Entities/AcquirerStatusRequest.php ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Describes a status request
5
+ *
6
+ */
7
+ class AcquirerStatusRequest {
8
+
9
+ const XMLNS = "http://www.betaalvereniging.nl/iDx/messages/Merchant-Acquirer/1.0.0";
10
+ const XSD = "http://www.w3.org/2001/XMLSchema";
11
+ const XSI = "http://www.w3.org/2001/XMLSchema-instance";
12
+
13
+ public $productID;
14
+ public $version;
15
+ public $dateTime;
16
+
17
+ /**
18
+ * The merchant object
19
+ * @var AcquirerStatusReqMerchant
20
+ */
21
+ public $merchant;
22
+
23
+ /**
24
+ * The transaction ID to check
25
+ * @var AcquirerStatusReqTransaction
26
+ */
27
+ public $Transaction;
28
+
29
+ /**
30
+ * Constructor that highlights all required fields for this object
31
+ *
32
+ * @param string $productID
33
+ * @param string $version
34
+ * @param AcquirerStatusReqMerchant $merchant
35
+ * @param AcquirerStatusReqTransaction $Transaction
36
+ */
37
+ function __construct($productID, $version, AcquirerStatusReqMerchant $merchant, AcquirerStatusReqTransaction $Transaction) {
38
+ $this->productID = $productID;
39
+ $this->version = $version;
40
+ $this->dateTime = date('Y-m-d\TH:i:s' . substr((string) microtime(), 1, 4) . '\Z');
41
+ $this->merchant = $merchant;
42
+ $this->Transaction = $Transaction;
43
+ }
44
+
45
+ /**
46
+ * Serializes the object into an AcquirerStatusReq
47
+ *
48
+ * @return \DOMDocument
49
+ */
50
+ public function toXml() {
51
+ $domtree = new DOMDocument('1.0', 'UTF-8');
52
+
53
+ /* create the root element of the xml tree */
54
+ $AcquirerStatusReq = $domtree->createElementNS(self::XMLNS, 'AcquirerStatusReq');
55
+ $AcquirerStatusReq->setAttribute('xmlns:xsd', self::XSD);
56
+ $AcquirerStatusReq->setAttribute('xmlns:xsi', self::XSI);
57
+
58
+ $AcquirerStatusReq->setAttribute('productID', $this->productID);
59
+ $AcquirerStatusReq->setAttribute('version', $this->version);
60
+ $domtree->appendChild($AcquirerStatusReq);
61
+
62
+ /* create the timetamp */
63
+ $createDateTimestamp = $domtree->createElement('createDateTimestamp', $this->dateTime);
64
+ $AcquirerStatusReq->appendChild($createDateTimestamp);
65
+
66
+ /* create the merchant element and it's sub elements */
67
+ $Merchant = $domtree->createElement('Merchant'); {
68
+ $Merchant->appendChild($domtree->createElement('merchantID', $this->merchant->merchantID));
69
+ $Merchant->appendChild($domtree->createElement('subID', $this->merchant->merchantSubID));
70
+ }
71
+ $AcquirerStatusReq->appendChild($Merchant);
72
+
73
+ /* create the Transaction elem */
74
+ $AcquirerStatusReq->appendChild($domtree->importNode($this->Transaction->toXML(), true));
75
+
76
+ return $domtree;
77
+ }
78
+
79
+ }
80
+
81
+ /**
82
+ * Description of Merchant
83
+ *
84
+ */
85
+ class AcquirerStatusReqMerchant {
86
+
87
+ public $merchantID;
88
+ public $merchantSubID;
89
+
90
+ /**
91
+ * Constructor that highlights the required fields
92
+ *
93
+ * @param string $merchantID
94
+ * @param string $merchantSubID
95
+ */
96
+ public function __construct($merchantID, $merchantSubID) {
97
+ $this->merchantID = $merchantID;
98
+ $this->merchantSubID = $merchantSubID;
99
+ }
100
+
101
+ }
102
+
103
+ /**
104
+ * Description of Transaction
105
+ *
106
+ */
107
+ class AcquirerStatusReqTransaction {
108
+
109
+ public $transactionID;
110
+
111
+ /**
112
+ * Constructor that highlights the required fields
113
+ *
114
+ * @param string $transactionID
115
+ */
116
+ function __construct($transactionID) {
117
+ $this->transactionID = $transactionID;
118
+ }
119
+
120
+ /**
121
+ * Serializes the object into a Transaction
122
+ *
123
+ * @return DOMElement
124
+ */
125
+ public function toXML() {
126
+ $domtree = new DOMDocument('1.0', 'UTF-8');
127
+
128
+ /* create the Transaction elem */
129
+ $Transaction = $domtree->createElement('Transaction');
130
+
131
+ /* create the transactionID elem */
132
+ $transactionID = $domtree->createElement('transactionID', $this->transactionID);
133
+ $Transaction->appendChild($transactionID);
134
+
135
+ return $Transaction;
136
+ }
137
+
138
+ }
139
+
140
+ /**
141
+ * Describes a status request
142
+ */
143
+ class StatusRequest {
144
+
145
+ /**
146
+ * The transaction ID to check
147
+ * @var string
148
+ */
149
+ public $TransactionId;
150
+
151
+ /**
152
+ * Constructor that highlights all required fields for this object
153
+ *
154
+ * @param string $TransactionId
155
+ */
156
+ function __construct($TransactionId) {
157
+ $this->TransactionId = $TransactionId;
158
+ }
159
+
160
+ }
lib/Communicator/Entities/AcquirerStatusResponse.php ADDED
@@ -0,0 +1,333 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Represents a status response
5
+ */
6
+ class AcquirerStatusResponse {
7
+
8
+ const STATUS_OPEN = "Open";
9
+ const STATUS_PENDING = "Pending";
10
+ const STATUS_SUCCESS = "Success";
11
+ const STATUS_FAILURE = "Failure";
12
+ const STATUS_EXPIRED = "Expired";
13
+ const STATUS_CANCELLED = "Cancelled";
14
+
15
+ /**
16
+ * true if an error occurred, or false when no errors were encountered
17
+ * @var bool
18
+ */
19
+ public $IsError = false;
20
+
21
+ /**
22
+ * Object that holds the error if one occurs; when there are no errors, this is set to null
23
+ * @var ErrorResponse
24
+ */
25
+ public $Error = null;
26
+
27
+ /**
28
+ * The transaction ID
29
+ * @var type
30
+ */
31
+ public $TransactionId = null;
32
+
33
+ /**
34
+ * Possible values: Open, Pending, Success, Failure, Expired, Cancelled
35
+ * @var string
36
+ */
37
+ public $Status = null;
38
+
39
+ /**
40
+ * DateTime when the status was created, or null if no such date available (for example, when mandate has expired)
41
+ * @var DateTime
42
+ */
43
+ public $StatusDateTimestamp = null;
44
+
45
+ /**
46
+ * The acceptance report returned in the status response
47
+ * @var AcceptanceReport
48
+ */
49
+ public $AcceptanceReport;
50
+
51
+ /**
52
+ * The object used to log internal messages and the xml files
53
+ *
54
+ * @var Logger
55
+ */
56
+ public $logger;
57
+
58
+ /**
59
+ * The response XML
60
+ *
61
+ * @var string
62
+ */
63
+ public $RawMessage;
64
+
65
+ /**
66
+ * Deserializes the xml provided into a AcquirerStatusRes
67
+ *
68
+ * @param string $xml
69
+ * @throws CommunicatorException
70
+ */
71
+ public function __construct($xml, $logger, $response_xml = false) {
72
+ $this->logger = $logger;
73
+
74
+ $this->RawMessage = (!empty($response_xml) || $response_xml === '' ? $response_xml : $xml);
75
+ $data = XmlUtility::parse($xml);
76
+
77
+ if ($data->getName() == 'AcquirerErrorRes' || $data->getName() == 'Exception') {
78
+ $this->_buildAcquirerErrorRes($data);
79
+ } else if ($data->getName() != 'AcquirerStatusRes') {
80
+ throw new CommunicatorException($data->getName() . ' was not expected.');
81
+ } else {
82
+ $this->Status = (string) $data->Transaction->status;
83
+
84
+ if ($this->Status == AcquirerStatusResponse::STATUS_SUCCESS) {
85
+ //validate status response p012
86
+ $this->_validateResponseDocument($xml);
87
+ }
88
+ $this->_buildStatusResponse($data);
89
+ }
90
+ }
91
+
92
+ private function _buildAcquirerErrorRes($data) {
93
+ $this->Error = new ErrorResponse($data);
94
+ $this->IsError = true;
95
+ }
96
+
97
+ private function _buildStatusResponse($data) {
98
+ $this->TransactionId = (string) $data->Transaction->transactionID;
99
+ $this->StatusDateTimestamp = new DateTime((string) $data->Directory->DirectoryDateTimestamp);
100
+
101
+ if ($this->Status == AcquirerStatusResponse::STATUS_SUCCESS) {
102
+ $temp_dom = new DOMDocument('1.0', 'UTF-8');
103
+ $temp_dom->loadXML($data->asXML());
104
+ $Document = $temp_dom->getElementsByTagName('Document');
105
+
106
+ $domtree = new DOMDocument('1.0', 'UTF-8');
107
+ $domtree->appendChild($domtree->importNode($Document->item(0), true));
108
+
109
+ $this->AcceptanceReport = new AcceptanceReport($domtree);
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Validates the Document of the xml provided
115
+ *
116
+ * @param string $xml
117
+ */
118
+ private function _validateResponseDocument($xml) {
119
+ $temp_dom = new DOMDocument('1.0', 'UTF-8');
120
+ $temp_dom->loadXML($xml);
121
+ $Document = $temp_dom->getElementsByTagName('Document');
122
+
123
+ $domtree = new DOMDocument('1.0', 'UTF-8');
124
+ $domtree->appendChild($domtree->importNode($Document->item(0), true));
125
+
126
+ XmlValidator::isValidatXML($domtree->saveXML(), XmlValidator::SCHEMA_PAIN012, $this->logger);
127
+ }
128
+
129
+ }
130
+
131
+ /**
132
+ * Received as part of a status response, corresponding to the pain.012 message
133
+ */
134
+ class AcceptanceReport {
135
+
136
+ /**
137
+ * Message Identification
138
+ * @var string
139
+ */
140
+ public $MessageId;
141
+
142
+ /**
143
+ * Message timestamp
144
+ * @var DateTime
145
+ */
146
+ public $DateTime;
147
+
148
+ /**
149
+ * Validation reference
150
+ * @var string
151
+ */
152
+ public $ValidationReference;
153
+
154
+ /**
155
+ * Original Message ID
156
+ * @var string
157
+ */
158
+ public $OriginalMessageId;
159
+
160
+ /**
161
+ * Refers to the type of validation request that preceded the acceptance report
162
+ * @var string
163
+ */
164
+ public $MessageNameId;
165
+
166
+ /**
167
+ * Whether or not the mandate is accepted by the debtor
168
+ * @var bool
169
+ */
170
+ public $AcceptedResult;
171
+
172
+ /**
173
+ * Original mandate ID
174
+ * @var string
175
+ */
176
+ public $OriginalMandateId;
177
+
178
+ /**
179
+ * Mandate request ID
180
+ * @var string
181
+ */
182
+ public $MandateRequestId;
183
+
184
+ /**
185
+ * SEPA
186
+ * @var string
187
+ */
188
+ public $ServiceLevelCode;
189
+
190
+ /**
191
+ * Core or B2B
192
+ * @var string
193
+ */
194
+ public $LocalInstrumentCode;
195
+
196
+ /**
197
+ * Sequence Type: sequenceType or one-off
198
+ * @var string
199
+ */
200
+ public $SequenceType;
201
+
202
+ /**
203
+ * Maximum amount
204
+ * @var string
205
+ */
206
+ public $MaxAmount;
207
+
208
+ /**
209
+ * Reason for eMandate
210
+ * @var string
211
+ */
212
+ public $eMandateReason;
213
+
214
+ /**
215
+ * Direct Debit ID of the Creditor
216
+ * @var string
217
+ */
218
+ public $CreditorId;
219
+
220
+ /**
221
+ * SEPA
222
+ * @var string
223
+ */
224
+ public $SchemeName;
225
+
226
+ /**
227
+ * Name of the Creditor
228
+ * @var string
229
+ */
230
+ public $CreditorName;
231
+
232
+ /**
233
+ * Country of the postal address of the Creditor
234
+ * @var string
235
+ */
236
+ public $CreditorCountry;
237
+
238
+ /**
239
+ * The Creditor’s address: P.O. Box or street name + building + add-on + Postcode + City.
240
+ * Second Address line only to be used if 70 chars are exceeded in the first line
241
+ * @var array(string)
242
+ */
243
+ public $CreditorAddressLine = array();
244
+
245
+ /**
246
+ * Name of the company (or daughter-company, or label etc.) for which the Creditor is processing eMandates.
247
+ * May only be used when meaningfully different from CreditorName
248
+ * @var string
249
+ */
250
+ public $CreditorTradeName;
251
+
252
+ /**
253
+ * Account holder name of the account that is used for the eMandate
254
+ * @var string
255
+ */
256
+ public $DebtorAccountName;
257
+
258
+ /**
259
+ * Reference ID that identifies the Debtor to the Creditor. Issued by the Creditor
260
+ * @var string
261
+ */
262
+ public $DebtorReference;
263
+
264
+ /**
265
+ * Debtor’s bank account number
266
+ * @var string
267
+ */
268
+ public $DebtorIBAN;
269
+
270
+ /**
271
+ * BIC of the Debtor bank
272
+ * @var string
273
+ */
274
+ public $DebtorBankId;
275
+
276
+ /**
277
+ * Name of the person signing the eMandate. In case of multiple signing, all signer names must be included in this field, separated by commas.
278
+ * If the total would exceed the maximum of 70 characters, the names are cut off at 65 characters and “e.a.” is added after the last name.
279
+ * @var string
280
+ */
281
+ public $DebtorSignerName;
282
+
283
+ /**
284
+ * The response XML
285
+ *
286
+ * @var string
287
+ */
288
+ public $RawMessage;
289
+
290
+ /**
291
+ * Deserializes the data into an AcceptanceReport
292
+ *
293
+ * @param SimpleXMLElement $data
294
+ */
295
+ public function __construct($data) {
296
+ $xpath = new DOMXpath($data);
297
+ $xpath->registerNamespace("p", "urn:iso:std:iso:20022:tech:xsd:pain.012.001.04");
298
+
299
+ $grpHdr = '/p:Document/p:MndtAccptncRpt/p:GrpHdr';
300
+ $accDtls = '/p:Document/p:MndtAccptncRpt/p:UndrlygAccptncDtls';
301
+
302
+ $this->MessageId = (string) $xpath->evaluate($grpHdr . '/p:MsgId')->item(0)->nodeValue;
303
+ $this->DateTime = new DateTime((string) $xpath->evaluate($grpHdr . '/p:CreDtTm')->item(0)->nodeValue );
304
+ $this->ValidationReference = (string) $xpath->evaluate($grpHdr . '/p:Authstn/p:Prtry')->item(0)->nodeValue;
305
+ $this->OriginalMessageId = (string) $xpath->evaluate($accDtls . '/p:OrgnlMsgInf/p:MsgId')->item(0)->nodeValue;
306
+ $this->MessageNameId = (string) $xpath->evaluate($accDtls . '/p:OrgnlMsgInf/p:MsgNmId')->item(0)->nodeValue;
307
+ $this->AcceptedResult = (string) $xpath->evaluate($accDtls . '/p:AccptncRslt/p:Accptd')->item(0)->nodeValue;
308
+
309
+ $origMndt = $accDtls . '/p:OrgnlMndt/p:OrgnlMndt';
310
+
311
+ $this->OriginalMandateId = (string) $xpath->evaluate($origMndt . '/p:MndtId')->item(0)->nodeValue;
312
+ $this->MandateRequestId = (string) $xpath->evaluate($origMndt . '/p:MndtReqId')->item(0)->nodeValue;
313
+ $this->LocalInstrumentCode = (string) $xpath->evaluate($origMndt . '/p:Tp/p:LclInstrm/p:Cd')->item(0)->nodeValue;
314
+ $this->SequenceType = (string) $xpath->evaluate($origMndt . '/p:Ocrncs/p:SeqTp')->item(0)->nodeValue;
315
+ $this->MaxAmount = (int) $xpath->evaluate($origMndt . '/p:MaxAmt/p:Value')->item(0)->nodeValue;
316
+ $this->ServiceLevelCode = (string) $xpath->evaluate($origMndt . '/p:Tp/p:SvcLvl/p:Cd')->item(0)->nodeValue;
317
+ $this->eMandateReason = (string) $xpath->evaluate($origMndt . '/p:Rsn/p:Cd')->item(0)->nodeValue;
318
+ $this->CreditorId = (string) $xpath->evaluate($origMndt . '/p:CdtrSchmeId/p:Id/p:PrvtId/p:Othr/p:Id')->item(0)->nodeValue;
319
+ $this->SchemeName = (string) $xpath->evaluate($origMndt . '/p:CdtrSchmeId/p:Id/p:PrvtId/p:Othr/p:SchmeNm/p:Cd')->item(0)->nodeValue;
320
+ $this->CreditorName = (string) $xpath->evaluate($origMndt . '/p:Cdtr/p:Nm')->item(0)->nodeValue;
321
+ $this->CreditorCountry = (string) $xpath->evaluate($origMndt . '/p:Cdtr/p:PstlAdr/p:Ctry')->item(0)->nodeValue;
322
+ $this->CreditorAddressLine = (string) $xpath->evaluate($origMndt . '/p:Cdtr/p:PstlAdr/p:AdrLine')->item(0)->nodeValue;
323
+ $this->CreditorTradeName = (string) $xpath->evaluate($origMndt . '/p:UltmtCdtr/p:Nm')->item(0)->nodeValue;
324
+ $this->DebtorAccountName = (string) $xpath->evaluate($origMndt . '/p:Dbtr/p:Nm')->item(0)->nodeValue;;
325
+ $this->DebtorReference = (string) $xpath->evaluate($origMndt . '/p:Dbtr/p:Id/p:PrvtId/p:Othr/p:Id')->item(0)->nodeValue;
326
+ $this->DebtorIBAN = (string) $xpath->evaluate($origMndt . '/p:DbtrAcct/p:Id/p:IBAN')->item(0)->nodeValue;
327
+ $this->DebtorBankId = (string) $xpath->evaluate($origMndt . '/p:DbtrAgt/p:FinInstnId/p:BICFI')->item(0)->nodeValue;
328
+ $this->DebtorSignerName = (string) $xpath->evaluate($origMndt . '/p:UltmtDbtr/p:Nm')->item(0)->nodeValue;
329
+
330
+ $this->RawMessage = $data->saveXML();
331
+ }
332
+
333
+ }
lib/Communicator/Entities/AcquirerTrxRequest.php ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * AquirerTrxReq description
5
+ */
6
+ class AcquirerTrxRequest {
7
+
8
+ const XMLNS = "http://www.betaalvereniging.nl/iDx/messages/Merchant-Acquirer/1.0.0";
9
+ const XSD = "http://www.w3.org/2001/XMLSchema";
10
+ const XSI = "http://www.w3.org/2001/XMLSchema-instance";
11
+
12
+ public $productID;
13
+ public $version;
14
+ public $dateTime;
15
+
16
+ /**
17
+ * The merchant object
18
+ * @var AcquirerTrxReqMerchant
19
+ */
20
+ public $merchant;
21
+
22
+ /**
23
+ * The Bank id
24
+ * @var string
25
+ */
26
+ public $issuerID;
27
+
28
+ /**
29
+ *
30
+ * @var AcquirerTrxReqTransaction
31
+ */
32
+ public $Transaction;
33
+
34
+ /**
35
+ * Constructor that highlights the required fields
36
+ *
37
+ * @param string $productID
38
+ * @param string $version
39
+ * @param AcquirerTrxReqMerchant $merchant
40
+ * @param string $issuerID
41
+ * @param AcquirerTrxReqTransaction $Transaction
42
+ */
43
+ public function __construct($productID, $version, AcquirerTrxReqMerchant $merchant, $issuerID, AcquirerTrxReqTransaction $Transaction) {
44
+ $this->productID = $productID;
45
+ $this->version = $version;
46
+ $this->dateTime = date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z');
47
+ $this->merchant = $merchant;
48
+ $this->issuerID = $issuerID;
49
+ $this->Transaction = $Transaction;
50
+ }
51
+
52
+ /**
53
+ * Serializes the object into an AcquirerTrxReq
54
+ *
55
+ * @param string $LocalInstrumentCode
56
+ * @return \DOMDocument
57
+ */
58
+ public function toXml($LocalInstrumentCode) {
59
+ $domtree = new DOMDocument('1.0', 'UTF-8');
60
+
61
+ /* create the root element of the xml tree */
62
+ $AcquirerTrxReq = $domtree->createElementNS(self::XMLNS, 'AcquirerTrxReq');
63
+ $AcquirerTrxReq->setAttribute('xmlns:xsd', self::XSD);
64
+ $AcquirerTrxReq->setAttribute('xmlns:xsi', self::XSI);
65
+
66
+ $AcquirerTrxReq->setAttribute('productID', $this->productID);
67
+ $AcquirerTrxReq->setAttribute('version', $this->version);
68
+ $domtree->appendChild($AcquirerTrxReq);
69
+
70
+ /* create the timetamp */
71
+ $createDateTimestamp = $domtree->createElement('createDateTimestamp', $this->dateTime);
72
+ $AcquirerTrxReq->appendChild($createDateTimestamp);
73
+
74
+ /* create the Issuer */
75
+ $issuer = $domtree->createElement('Issuer'); {
76
+ $issuer->appendChild(new DOMElement('issuerID', $this->issuerID));
77
+ }
78
+ $AcquirerTrxReq->appendChild($issuer);
79
+
80
+ /* create the merchant element and it's sub elements */
81
+ $Merchant = $domtree->createElement('Merchant'); {
82
+ $Merchant->appendChild($domtree->createElement('merchantID', $this->merchant->merchantID));
83
+ $Merchant->appendChild($domtree->createElement('subID', $this->merchant->merchantSubID));
84
+ $Merchant->appendChild($domtree->createElement('merchantReturnURL', $this->merchant->merchantReturnURL));
85
+ }
86
+ $AcquirerTrxReq->appendChild($Merchant);
87
+
88
+ /* create the Transaction elem */
89
+ $AcquirerTrxReq->appendChild($domtree->importNode($this->Transaction->toXML($LocalInstrumentCode), true));
90
+
91
+ return $domtree;
92
+ }
93
+
94
+ }
95
+
96
+ /**
97
+ * Description of Merchant
98
+ */
99
+ class AcquirerTrxReqMerchant {
100
+
101
+ public $merchantID;
102
+ public $merchantSubID;
103
+ public $merchantReturnURL;
104
+
105
+ /**
106
+ * Constructor that highlights the required fields
107
+ *
108
+ * @param string $merchantID
109
+ * @param string $merchantSubID
110
+ * @param string $merchantReturnURL
111
+ */
112
+ public function __construct($merchantID, $merchantSubID, $merchantReturnURL) {
113
+ $this->merchantID = $merchantID;
114
+ $this->merchantSubID = $merchantSubID;
115
+ $this->merchantReturnURL = $merchantReturnURL;
116
+ }
117
+
118
+ }
119
+
120
+ class AcquirerTrxReqTransaction {
121
+
122
+ public $entranceCode;
123
+ public $expirationPeriod;
124
+ public $language;
125
+
126
+ /**
127
+ *
128
+ * @var NewMandateRequest | AmendmentRequest | CancellationRequest
129
+ */
130
+ public $container;
131
+
132
+ /**
133
+ * Constructor that highlights the required fields
134
+ *
135
+ * @param string $entranceCode
136
+ * @param DateInterval $expirationPeriod
137
+ * @param string $language
138
+ * @param NewMandateRequest | AmendmentRequest | CancellationRequest $container
139
+ */
140
+ public function __construct($entranceCode, $expirationPeriod, $language, $container) {
141
+ $this->entranceCode = $entranceCode;
142
+ $this->expirationPeriod = $expirationPeriod;
143
+ $this->language = $language;
144
+ $this->container = $container;
145
+ }
146
+
147
+ /**
148
+ * Serializes the object into a Transaction
149
+ *
150
+ * @param string $LocalInstrumentCode
151
+ * @return DOMElement
152
+ */
153
+ public function toXml($LocalInstrumentCode) {
154
+ $domtree = new DOMDocument('1.0', 'UTF-8');
155
+
156
+ /* create the Transaction elem */
157
+ $Transaction = $domtree->createElement('Transaction');
158
+
159
+ if (!empty($this->expirationPeriod)) {
160
+ $expirationPeriod = $domtree->createElement('expirationPeriod', $this->DateIntervalToStr($this->expirationPeriod));
161
+ $Transaction->appendChild($expirationPeriod);
162
+ }
163
+
164
+ $language = $domtree->createElement('language', $this->language);
165
+ $Transaction->appendChild($language);
166
+
167
+ $entranceCode = $domtree->createElement('entranceCode', $this->entranceCode);
168
+ $Transaction->appendChild($entranceCode);
169
+
170
+ /* create the container element */
171
+ $container = $domtree->createElement('container');
172
+ $container->appendChild($domtree->importNode($this->container->toXML($LocalInstrumentCode), true));
173
+ $Transaction->appendChild($container);
174
+
175
+ return $Transaction;
176
+ }
177
+
178
+ /**
179
+ * Returns the str representation of a DateInterval
180
+ *
181
+ * @param DateInterval $dateInterval
182
+ * @return string
183
+ */
184
+ private function DateIntervalToStr($dateInterval) {
185
+ $interval = 'P';
186
+
187
+ $allowedKeys = array('y', 'm', 'd', 'h', 'i', 's');
188
+ $timeKeys = array('h', 'i', 's');
189
+ $addedTime = false;
190
+
191
+ foreach (get_object_vars($dateInterval) as $key => $value) {
192
+ if (in_array($key, $allowedKeys)) {
193
+ if (in_array($key, $timeKeys) && !$addedTime && !empty($value)) {
194
+ $interval .= 'T';
195
+ $addedTime = true;
196
+ }
197
+ if (!empty($value)) {
198
+ $interval .= $value . ( $key == 'i' ? 'M' : strtoupper($key));
199
+ }
200
+ }
201
+ }
202
+
203
+ return $interval;
204
+ }
205
+
206
+ }
lib/Communicator/Entities/AmendmentRequest.php ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Describes an amendment request
5
+ */
6
+ class AmendmentRequest {
7
+
8
+ const XMLNS = "urn:iso:std:iso:20022:tech:xsd:pain.010.001.04";
9
+ const XSD = "http://www.w3.org/2001/XMLSchema";
10
+ const XSI = "http://www.w3.org/2001/XMLSchema-instance";
11
+ const NOT_PROVIDED = 'NOTPROVIDED';
12
+ const SEPA = 'SEPA';
13
+ const MD16 = 'MD16';
14
+ const CCY = 'EUR';
15
+
16
+ /**
17
+ * An 'authentication identifier' to facilitate continuation of the session between creditor and debtor, even
18
+ * if the existing session has been lost. It enables the creditor to recognise the debtor associated with a (completed) transaction.
19
+ * @var string
20
+ */
21
+ public $EntranceCode;
22
+
23
+ /**
24
+ * This field enables the debtor bank's site to select the debtor's preferred language (e.g. the language selected on the creditor's site),
25
+ * if the debtor bank's site supports this: Dutch = 'nl', English = 'en'
26
+ * @var string
27
+ */
28
+ public $Language;
29
+
30
+ /**
31
+ * Optional: The period of validity of the transaction request as stated by the creditor measured from the receipt by the debtor bank.
32
+ * The debtor must authorise the transaction within this period.
33
+ * @var DateInterval
34
+ */
35
+ public $ExpirationPeriod;
36
+
37
+ /**
38
+ * Message ID for pain message
39
+ * @var string
40
+ */
41
+ public $MessageId;
42
+
43
+ /**
44
+ * ID that identifies the mandate and is issued by the creditor
45
+ * @var string
46
+ */
47
+ public $eMandateId;
48
+
49
+ /**
50
+ * Reason of the mandate
51
+ * @var string
52
+ */
53
+ public $eMandateReason;
54
+
55
+ /**
56
+ * Reference ID that identifies the debtor to creditor, which is issued by the creditor
57
+ * @var string
58
+ */
59
+ public $DebtorReference;
60
+
61
+ /**
62
+ * BIC of the Debtor Bank
63
+ * @var string
64
+ */
65
+ public $DebtorBankId;
66
+
67
+ /**
68
+ * A purchaseID that acts as a reference from eMandate to the purchase-order
69
+ * @var string
70
+ */
71
+ public $PurchaseId;
72
+
73
+ /**
74
+ * Indicates type of eMandate: one-off or sequenceType direct debit.
75
+ * @var string
76
+ */
77
+ public $SequenceType;
78
+
79
+ /**
80
+ * Maximum amount. Not allowed for Core, optional for B2B.
81
+ * @var string
82
+ */
83
+ public $MaxAmount;
84
+
85
+ /**
86
+ * IBAN of the original mandate
87
+ * @var string
88
+ */
89
+ public $OriginalIBAN;
90
+
91
+ /**
92
+ * BankID of the original mandate
93
+ * @var string
94
+ */
95
+ public $OriginalDebtorBankId;
96
+
97
+ /**
98
+ * The object used to log internal messages and the xml files
99
+ *
100
+ * @var Logger
101
+ */
102
+ public $logger;
103
+
104
+ /**
105
+ * Constructor that highlights all required fields for this object
106
+ *
107
+ * @param string $entranceCode
108
+ * @param string $language
109
+ * @param string $eMandateId
110
+ * @param string $eMandateReason
111
+ * @param string $debtorReference
112
+ * @param string $debtorBankId
113
+ * @param string $purchaseId
114
+ * @param string $sequenceType
115
+ * @param string $originalIBAN
116
+ * @param string $originalDebtorBankId
117
+ * @param string $messageId - optional
118
+ * @param string $maxAmount - optional
119
+ * @param DateInterval $expirationPeriod - optional
120
+ */
121
+ public function __construct(
122
+ $entranceCode, $language, $eMandateId, $eMandateReason, $debtorReference, $debtorBankId, $purchaseId, $sequenceType, $originalIBAN, $originalDebtorBankId, $messageId = '', $maxAmount = '', $expirationPeriod = null) {
123
+
124
+ /* setting the required fields */
125
+ $this->EntranceCode = $entranceCode;
126
+ $this->Language = $language;
127
+ $this->eMandateId = $eMandateId;
128
+ $this->eMandateReason = $eMandateReason;
129
+ $this->DebtorReference = $debtorReference;
130
+ $this->DebtorBankId = $debtorBankId;
131
+ $this->PurchaseId = $purchaseId;
132
+ $this->SequenceType = $sequenceType;
133
+ $this->OriginalIBAN = $originalIBAN;
134
+ $this->OriginalDebtorBankId = $originalDebtorBankId;
135
+ $this->MessageId = $messageId;
136
+
137
+ /* setting the optional fields */
138
+ $this->MaxAmount = str_replace(',', '.', $maxAmount);
139
+ $this->ExpirationPeriod = $expirationPeriod;
140
+
141
+ if (empty($this->MessageId)) {
142
+ $this->MessageId = MessageIdGenerator::NewMessageId();
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Serializes the object into a Document
148
+ *
149
+ * @param string $LocalInstrumentCode
150
+ * @return DOMElement
151
+ */
152
+ public function toXml($LocalInstrumentCode) {
153
+ $this->logger->Log("building eMandate");
154
+ $this->validateExpirationPeriodAndMaxAmount();
155
+
156
+ $domtree = new DOMDocument('1.0', 'UTF-8');
157
+
158
+ /* create the Document element with it's namespaces */
159
+ $Document = $domtree->createElement('Document');
160
+ $Document->setAttribute('xmlns', self::XMLNS);
161
+ $Document->setAttribute('xmlns:xsd', self::XSD);
162
+ $Document->setAttribute('xmlns:xsi', self::XSI); {
163
+ /* create the MndtAmdmntReq element */
164
+ $MndtAmdmntReq = $domtree->createElement('MndtAmdmntReq'); {
165
+ /* create the GrpHdr element */
166
+ $GrpHdr = $domtree->createElement('GrpHdr'); {
167
+ $GrpHdr->appendChild(new DOMElement('MsgId', $this->MessageId));
168
+ $GrpHdr->appendChild(new DOMElement('CreDtTm', date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z')));
169
+ }
170
+ $MndtAmdmntReq->appendChild($GrpHdr);
171
+
172
+ /* create the UndrlygAmdmntDtls element */
173
+ $UndrlygAmdmntDtls = $domtree->createElement('UndrlygAmdmntDtls'); {
174
+ /* create the AmdmntRsn element */
175
+ $AmdmntRsn = $domtree->createElement('AmdmntRsn'); {
176
+ /* create the Rsn element */
177
+ $Rsn = $domtree->createElement('Rsn');
178
+ $Rsn->appendChild(new DOMElement('Cd', self::MD16));
179
+ $AmdmntRsn->appendChild($Rsn);
180
+ }
181
+ $UndrlygAmdmntDtls->appendChild($AmdmntRsn);
182
+
183
+ /* create the Mndt element */
184
+ $Mndt = $domtree->createElement('Mndt'); {
185
+ /* create the MndtId element */
186
+ $Mndt->appendChild($domtree->createElement('MndtId', $this->eMandateId));
187
+
188
+ /* create the MndtReqId element */
189
+ $Mndt->appendChild($domtree->createElement('MndtReqId', self::NOT_PROVIDED));
190
+
191
+ /* create Tp element */
192
+ $Tp = $domtree->createElement('Tp'); {
193
+ /* create SvcLvl element */
194
+ $SvcLvl = $domtree->createElement('SvcLvl');
195
+ $SvcLvl->appendChild(new DOMElement('Cd', self::SEPA));
196
+ $Tp->appendChild($SvcLvl);
197
+
198
+ /* create LclInstrm element */
199
+ $LclInstrm = $domtree->createElement('LclInstrm');
200
+ $LclInstrm->appendChild(new DOMElement('Cd', $LocalInstrumentCode));
201
+ $Tp->appendChild($LclInstrm);
202
+ }
203
+ $Mndt->appendChild($Tp);
204
+
205
+ /* create Ocrncs element */
206
+ $Ocrncs = $domtree->createElement('Ocrncs');
207
+ $Ocrncs->appendChild(new DOMElement('SeqTp', $this->SequenceType));
208
+ $Mndt->appendChild($Ocrncs);
209
+
210
+ /* create MaxAmt element */
211
+ if (!empty($this->MaxAmount) && $LocalInstrumentCode == B2BCommunicator::LOCAL_INSTRUMENT) {
212
+ $MaxAmt = $domtree->createElement('MaxAmt', $this->MaxAmount);
213
+ $MaxAmt->setAttribute('Ccy', self::CCY);
214
+ $Mndt->appendChild($MaxAmt);
215
+ }
216
+
217
+ /* create Rsn element */
218
+ if (!empty($this->eMandateReason)) {
219
+ $Rsn1 = $domtree->createElement('Rsn');
220
+ $Rsn1->appendChild(new DOMElement('Prtry', $this->eMandateReason));
221
+ $Mndt->appendChild($Rsn1);
222
+ }
223
+
224
+ /* create Cdtr element */
225
+ $Mndt->appendChild(new DOMElement('Cdtr'));
226
+
227
+ /* create Dbtr element */
228
+ $Dbtr = $domtree->createElement('Dbtr'); {
229
+ if (!empty($this->DebtorReference)) {
230
+ $Id = $domtree->createElement('Id'); {
231
+ $PrvtId = $domtree->createElement('PrvtId'); {
232
+ $Othr = $domtree->createElement('Othr');
233
+ $Othr->appendChild(new DOMElement('Id', $this->DebtorReference));
234
+ $PrvtId->appendChild($Othr);
235
+ }
236
+ }
237
+ $Id->appendChild($PrvtId);
238
+ $Dbtr->appendChild($Id);
239
+ }
240
+ }
241
+ $Mndt->appendChild($Dbtr);
242
+
243
+ /* create the DbtrAgt element */
244
+ $DbtrAgt = $domtree->createElement('DbtrAgt'); {
245
+ $FinInstnId = $domtree->createElement('FinInstnId');
246
+ $FinInstnId->appendChild(new DOMElement('BICFI', $this->DebtorBankId));
247
+ $DbtrAgt->appendChild($FinInstnId);
248
+ }
249
+ $Mndt->appendChild($DbtrAgt);
250
+
251
+ /* create the RfrdDoc element */
252
+ if (!empty($this->PurchaseId)) {
253
+ $RfrdDoc = $domtree->createElement('RfrdDoc'); {
254
+ $Tp = $domtree->createElement('Tp'); {
255
+ $CdOrPrtry = $domtree->createElement('CdOrPrtry');
256
+ $CdOrPrtry->appendChild(new DOMElement('Prtry', $this->PurchaseId));
257
+ $Tp->appendChild($CdOrPrtry);
258
+ }
259
+ $RfrdDoc->appendChild($Tp);
260
+ }
261
+ $Mndt->appendChild($RfrdDoc);
262
+ }
263
+ }
264
+ $UndrlygAmdmntDtls->appendChild($Mndt);
265
+
266
+ /* create the OrgnlMndt element */
267
+ $OrgnlMndt1 = $domtree->createElement('OrgnlMndt');
268
+ $OrgnlMndt = $domtree->createElement('OrgnlMndt'); {
269
+ /* create the MndtId element */
270
+ $OrgnlMndt->appendChild($domtree->createElement('MndtId', $this->eMandateId));
271
+
272
+ /* create Cdtr element */
273
+ $OrgnlMndt->appendChild(new DOMElement('Cdtr'));
274
+
275
+ /* create Dbtr element */
276
+ $Dbtr = $domtree->createElement('Dbtr');
277
+ $OrgnlMndt->appendChild($Dbtr);
278
+
279
+ /* create DbtrAcct element */
280
+ $DbtrAcct = $domtree->createElement('DbtrAcct'); {
281
+ $Id = $domtree->createElement('Id');
282
+ $Id->appendChild(new DOMElement('IBAN', $this->OriginalIBAN));
283
+ $DbtrAcct->appendChild($Id);
284
+ }
285
+ $OrgnlMndt->appendChild($DbtrAcct);
286
+
287
+ /* create the DbtrAgt element */
288
+ $DbtrAgt = $domtree->createElement('DbtrAgt'); {
289
+ $FinInstnId = $domtree->createElement('FinInstnId');
290
+ $FinInstnId->appendChild(new DOMElement('BICFI', $this->OriginalDebtorBankId));
291
+ $DbtrAgt->appendChild($FinInstnId);
292
+ }
293
+ $OrgnlMndt->appendChild($DbtrAgt);
294
+ }
295
+ $OrgnlMndt1->appendChild($OrgnlMndt);
296
+ $UndrlygAmdmntDtls->appendChild($OrgnlMndt1);
297
+ }
298
+ $MndtAmdmntReq->appendChild($UndrlygAmdmntDtls);
299
+ }
300
+ $Document->appendChild($MndtAmdmntReq);
301
+ }
302
+
303
+ $domtree->appendChild($Document);
304
+
305
+ XmlValidator::isValidatXML($domtree->saveXML(), XmlValidator::SCHEMA_PAIN010, $this->logger);
306
+
307
+ return $Document;
308
+ }
309
+
310
+ /**
311
+ * Validates that the ExpirationPeriod is not greater than 7days
312
+ * and that the MaxAmount respects the standard
313
+ * @throws CommunicatorException
314
+ */
315
+ private function validateExpirationPeriodAndMaxAmount(){
316
+
317
+ //EXPIRATION PERIOD
318
+ if(!empty($this->ExpirationPeriod)){
319
+ $max_future = new DateTime();
320
+ $max_future->add(new DateInterval('P7DT1S')); // max plus one second
321
+
322
+ $future = new DateTime();
323
+ $future->add($this->ExpirationPeriod);
324
+
325
+ $check_interval2 = $max_future->diff($future);
326
+
327
+ if($check_interval2->invert == 0){
328
+ throw new CommunicatorException('The Expiration Period should not be greater than 7 days!');
329
+ }
330
+ }
331
+
332
+ //MAX AMOUNT
333
+ if ($this->MaxAmount !== '' && !is_numeric($this->MaxAmount)) {
334
+ throw new CommunicatorException('The MaxAmount should be a number.');
335
+ }
336
+
337
+ if ($this->MaxAmount !== '' && (float) $this->MaxAmount == 0) {
338
+ throw new CommunicatorException('The MaxAmount cannot be 0.');
339
+ }
340
+
341
+ $tempMaxAmount = str_replace('.', '', $this->MaxAmount);
342
+ $pos = strpos($this->MaxAmount, '.');
343
+ $pos = ($pos !== false ? $pos : strlen($this->MaxAmount));
344
+
345
+ $decimals = substr($this->MaxAmount, $pos + 1);
346
+ if (!empty($this->MaxAmount) && (strlen($tempMaxAmount) > 11 || strlen($decimals) > 2)) {
347
+ throw new CommunicatorException('The MaxAmount should have maximum 2 decimals and the total number of digits should be maximum 11.');
348
+ }
349
+ }
350
+
351
+ }
lib/Communicator/Entities/AmendmentResponse.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Represents an amendment response
5
+ */
6
+ class AmendmentResponse {
7
+
8
+ /**
9
+ * true if an error occurred, or false when no errors were encountered
10
+ * @var bool
11
+ */
12
+ public $IsError = false;
13
+
14
+ /**
15
+ * Object that holds the error if one occurs; when there are no errors, this is set to null
16
+ * @var ErrorResponse
17
+ */
18
+ public $Error = null;
19
+
20
+ /**
21
+ * The URL to which to redirect the creditor so they can authorize the transaction
22
+ * @var string
23
+ */
24
+ public $IssuerAuthenticationUrl = null;
25
+
26
+ /**
27
+ * The transaction ID
28
+ * @var string
29
+ */
30
+ public $TransactionId = null;
31
+
32
+ /**
33
+ * DateTime set to when this transaction was created
34
+ * @var DateTime
35
+ */
36
+ public $TransactionCreateDateTimestamp;
37
+
38
+ /**
39
+ * The response XML
40
+ *
41
+ * @var string
42
+ */
43
+ public $RawMessage;
44
+
45
+ /**
46
+ * Deserializes the xml provided into an AmendmentResponse
47
+ *
48
+ * @param string $xml
49
+ * @throws CommunicatorException
50
+ */
51
+ public function __construct($xml, $response_xml = false) {
52
+ $this->RawMessage = (!empty($response_xml) || $response_xml === '' ? $response_xml : $xml);
53
+ $data = XmlUtility::parse($xml);
54
+
55
+ if ($data->getName() == 'AcquirerErrorRes' || $data->getName() == 'Exception') {
56
+ $this->_buildAcquirerErrorRes($data);
57
+ } else if ($data->getName() != 'AcquirerTrxRes') {
58
+ throw new CommunicatorException($data->getName() . ' was not expected.');
59
+ } else {
60
+ $this->_buildAmendmentRes($data);
61
+ }
62
+ }
63
+
64
+ private function _buildAcquirerErrorRes($data) {
65
+ $this->Error = new ErrorResponse($data);
66
+ $this->IsError = true;
67
+ $this->TransactionCreateDateTimestamp = new DateTime((string) $data->createDateTimestamp);
68
+ }
69
+
70
+ private function _buildAmendmentRes($data) {
71
+ $this->IssuerAuthenticationUrl = (string) $data->Issuer->issuerAuthenticationURL;
72
+ $this->TransactionId = (string) $data->Transaction->transactionID;
73
+
74
+ $this->TransactionCreateDateTimestamp = new DateTime((string) $data->Transaction->transactionCreateDateTimestamp);
75
+ }
76
+ }
lib/Communicator/Entities/CancellationRequest.php ADDED
@@ -0,0 +1,318 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Describes a cancellation request
5
+ */
6
+ class CancellationRequest {
7
+
8
+ const XMLNS = "urn:iso:std:iso:20022:tech:xsd:pain.011.001.04";
9
+ const XSD = "http://www.w3.org/2001/XMLSchema";
10
+ const XSI = "http://www.w3.org/2001/XMLSchema-instance";
11
+ const NOT_PROVIDED = 'NOTPROVIDED';
12
+ const SEPA = 'SEPA';
13
+ const MD16 = 'MD16';
14
+ const CCY = 'EUR';
15
+
16
+ /**
17
+ * An 'authentication identifier' to facilitate continuation of the session between creditor and debtor, even
18
+ * if the existing session has been lost. It enables the creditor to recognise the debtor associated with a (completed) transaction.
19
+ * @var string
20
+ */
21
+ public $EntranceCode;
22
+
23
+ /**
24
+ * This field enables the debtor bank's site to select the debtor's preferred language (e.g. the language selected on the creditor's site),
25
+ * if the debtor bank's site supports this: Dutch = 'nl', English = 'en'
26
+ * @var string
27
+ */
28
+ public $Language;
29
+
30
+ /**
31
+ * Optional: The period of validity of the transaction request as stated by the creditor measured from the receipt by the debtor bank.
32
+ * The debtor must authorise the transaction within this period.
33
+ * @var DateInterval
34
+ */
35
+ public $ExpirationPeriod;
36
+
37
+ /**
38
+ * BIC of the Debtor Bank
39
+ * @var string
40
+ */
41
+ public $DebtorBankId;
42
+
43
+ /**
44
+ * Message ID for pain message
45
+ * @var string
46
+ */
47
+ public $MessageId;
48
+
49
+ /**
50
+ * ID that identifies the mandate and is issued by the creditor
51
+ * @var string
52
+ */
53
+ public $eMandateId;
54
+
55
+ /**
56
+ * Indicates type of eMandate: one-off or sequenceType direct debit.
57
+ * @var string
58
+ */
59
+ public $SequenceType;
60
+
61
+ /**
62
+ * Reason of the mandate
63
+ * @var string
64
+ */
65
+ public $eMandateReason;
66
+
67
+ /**
68
+ * Reference ID that identifies the debtor to creditor, which is issued by the creditor
69
+ * @var string
70
+ */
71
+ public $DebtorReference;
72
+
73
+ /**
74
+ * A purchaseID that acts as a reference from eMandate to the purchase-order
75
+ * @var string
76
+ */
77
+ public $PurchaseId;
78
+
79
+ /**
80
+ * IBAN of the original mandate
81
+ * @var string
82
+ */
83
+ public $OriginalIBAN;
84
+
85
+ /**
86
+ * Maximum amount. Not allowed for Core, optional for B2B.
87
+ * @var string
88
+ */
89
+ public $MaxAmount;
90
+
91
+ /**
92
+ * The object used to log internal messages and the xml files
93
+ *
94
+ * @var Logger
95
+ */
96
+ public $logger;
97
+
98
+ /**
99
+ * Constructor that highlights all required fields for this object; use this one to specify your own messageId
100
+ *
101
+ * @param string $entranceCode
102
+ * @param string $language
103
+ * @param string $eMandateId
104
+ * @param string $eMandateReason
105
+ * @param string $debtorReference
106
+ * @param string $debtorBankId
107
+ * @param string $purchaseId
108
+ * @param string $sequenceType
109
+ * @param string $originalIBAN
110
+ * @param string $messageId - optional
111
+ * @param string $maxAmount - optional
112
+ * @param DateInterval $expirationPeriod - optional
113
+ */
114
+ public function __construct($entranceCode, $language, $eMandateId, $eMandateReason, $debtorReference, $debtorBankId, $purchaseId, $sequenceType, $originalIBAN, $messageId = '', $maxAmount = '', $expirationPeriod = null) {
115
+
116
+ $this->EntranceCode = $entranceCode;
117
+ $this->Language = $language;
118
+ $this->eMandateId = $eMandateId;
119
+ $this->eMandateReason = $eMandateReason;
120
+ $this->DebtorReference = $debtorReference;
121
+ $this->DebtorBankId = $debtorBankId;
122
+ $this->PurchaseId = $purchaseId;
123
+ $this->SequenceType = $sequenceType;
124
+ $this->OriginalIBAN = $originalIBAN;
125
+ $this->MessageId = $messageId;
126
+
127
+ /* setting the optional fields */
128
+ $this->MaxAmount = str_replace(',', '.', $maxAmount);
129
+ $this->ExpirationPeriod = $expirationPeriod;
130
+
131
+ if (empty($this->MessageId)) {
132
+ $this->MessageId = MessageIdGenerator::NewMessageId();
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Serializes the object into a Document
138
+ *
139
+ * @param string $LocalInstrumentCode
140
+ * @return DOMElement
141
+ */
142
+ public function toXml($LocalInstrumentCode) {
143
+ $this->logger->Log("building eMandate");
144
+ $this->validateExpirationPeriodAndMaxAmount();
145
+
146
+ $domtree = new DOMDocument('1.0', 'UTF-8');
147
+
148
+ /* create the Document element with it's namespaces */
149
+ $Document = $domtree->createElement('Document');
150
+ $Document->setAttribute('xmlns', self::XMLNS);
151
+ $Document->setAttribute('xmlns:xsd', self::XSD);
152
+ $Document->setAttribute('xmlns:xsi', self::XSI); {
153
+ /* create the MndtCxlReq element */
154
+ $MndtCxlReq = $domtree->createElement('MndtCxlReq'); {
155
+ /* create the GrpHdr element */
156
+ $GrpHdr = $domtree->createElement('GrpHdr'); {
157
+ $GrpHdr->appendChild(new DOMElement('MsgId', $this->MessageId));
158
+ $GrpHdr->appendChild(new DOMElement('CreDtTm', date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z')));
159
+ }
160
+ $MndtCxlReq->appendChild($GrpHdr);
161
+
162
+ /* create the UndrlygCxlDtls element */
163
+ $UndrlygCxlDtls = $domtree->createElement('UndrlygCxlDtls'); {
164
+ /* create the CxlRsn element */
165
+ $CxlRsn = $domtree->createElement('CxlRsn'); {
166
+ /* create the Rsn element */
167
+ $Rsn = $domtree->createElement('Rsn');
168
+ $Rsn->appendChild(new DOMElement('Cd', self::MD16));
169
+ $CxlRsn->appendChild($Rsn);
170
+ }
171
+ $UndrlygCxlDtls->appendChild($CxlRsn);
172
+
173
+ /* create the OrgnlMndt element */
174
+ $OrgnlMndt1 = $domtree->createElement('OrgnlMndt');
175
+ $OrgnlMndt = $domtree->createElement('OrgnlMndt'); {
176
+ /* create the MndtId element */
177
+ $OrgnlMndt->appendChild($domtree->createElement('MndtId', $this->eMandateId));
178
+
179
+ /* create the MndtReqId element */
180
+ $OrgnlMndt->appendChild($domtree->createElement('MndtReqId', self::NOT_PROVIDED));
181
+
182
+ /* create Tp element */
183
+ $Tp = $domtree->createElement('Tp'); {
184
+ /* create SvcLvl element */
185
+ $SvcLvl = $domtree->createElement('SvcLvl');
186
+ $SvcLvl->appendChild(new DOMElement('Cd', self::SEPA));
187
+ $Tp->appendChild($SvcLvl);
188
+
189
+ /* create LclInstrm element */
190
+ $LclInstrm = $domtree->createElement('LclInstrm');
191
+ $LclInstrm->appendChild(new DOMElement('Cd', $LocalInstrumentCode));
192
+ $Tp->appendChild($LclInstrm);
193
+ }
194
+ $OrgnlMndt->appendChild($Tp);
195
+
196
+ /* create Ocrncs element */
197
+ $Ocrncs = $domtree->createElement('Ocrncs');
198
+ $Ocrncs->appendChild(new DOMElement('SeqTp', $this->SequenceType));
199
+ $OrgnlMndt->appendChild($Ocrncs);
200
+
201
+ /* create MaxAmt element */
202
+ if (!empty($this->MaxAmount) && $LocalInstrumentCode == B2BCommunicator::LOCAL_INSTRUMENT) {
203
+ $MaxAmt = $domtree->createElement('MaxAmt', $this->MaxAmount);
204
+ $MaxAmt->setAttribute('Ccy', self::CCY);
205
+ $OrgnlMndt->appendChild($MaxAmt);
206
+ }
207
+ /* create Rsn element */
208
+ if (!empty($this->eMandateReason)) {
209
+ $Rsn1 = $domtree->createElement('Rsn');
210
+ $Rsn1->appendChild(new DOMElement('Prtry', $this->eMandateReason));
211
+ $OrgnlMndt->appendChild($Rsn1);
212
+ }
213
+
214
+ /* create Cdtr element */
215
+ $OrgnlMndt->appendChild(new DOMElement('Cdtr'));
216
+
217
+ /* create Dbtr element */
218
+ $Dbtr = $domtree->createElement('Dbtr'); {
219
+ if (!empty($this->DebtorReference)) {
220
+ $Id = $domtree->createElement('Id'); {
221
+ $PrvtId = $domtree->createElement('PrvtId'); {
222
+ $Othr = $domtree->createElement('Othr');
223
+ $Othr->appendChild(new DOMElement('Id', $this->DebtorReference));
224
+ $PrvtId->appendChild($Othr);
225
+ }
226
+ }
227
+ $Id->appendChild($PrvtId);
228
+ $Dbtr->appendChild($Id);
229
+ }
230
+ }
231
+ $OrgnlMndt->appendChild($Dbtr);
232
+
233
+ /* create DbtrAcct element */
234
+ $DbtrAcct = $domtree->createElement('DbtrAcct'); {
235
+ $Id = $domtree->createElement('Id');
236
+ $Id->appendChild(new DOMElement('IBAN', $this->OriginalIBAN));
237
+ $DbtrAcct->appendChild($Id);
238
+ }
239
+ $OrgnlMndt->appendChild($DbtrAcct);
240
+
241
+ /* create the DbtrAgt element */
242
+ $DbtrAgt = $domtree->createElement('DbtrAgt'); {
243
+ $FinInstnId = $domtree->createElement('FinInstnId');
244
+ $FinInstnId->appendChild(new DOMElement('BICFI', $this->DebtorBankId));
245
+ $DbtrAgt->appendChild($FinInstnId);
246
+ }
247
+ $OrgnlMndt->appendChild($DbtrAgt);
248
+
249
+ /* create the RfrdDoc element */
250
+ if (!empty($this->PurchaseId)) {
251
+ $RfrdDoc = $domtree->createElement('RfrdDoc'); {
252
+ $Tp = $domtree->createElement('Tp'); {
253
+ $CdOrPrtry = $domtree->createElement('CdOrPrtry');
254
+ $CdOrPrtry->appendChild(new DOMElement('Prtry', $this->PurchaseId));
255
+ $Tp->appendChild($CdOrPrtry);
256
+ }
257
+ $RfrdDoc->appendChild($Tp);
258
+ }
259
+ $OrgnlMndt->appendChild($RfrdDoc);
260
+ }
261
+ }
262
+ $OrgnlMndt1->appendChild($OrgnlMndt);
263
+ $UndrlygCxlDtls->appendChild($OrgnlMndt1);
264
+ }
265
+ $MndtCxlReq->appendChild($UndrlygCxlDtls);
266
+ }
267
+ $Document->appendChild($MndtCxlReq);
268
+ }
269
+
270
+ $domtree->appendChild($Document);
271
+
272
+ XmlValidator::isValidatXML($domtree->saveXML(), XmlValidator::SCHEMA_PAIN011, $this->logger);
273
+
274
+ return $Document;
275
+ }
276
+
277
+ /**
278
+ * Validates that the ExpirationPeriod is not greater than 7days
279
+ * and that the MaxAmount respects the standard
280
+ * @throws CommunicatorException
281
+ */
282
+ private function validateExpirationPeriodAndMaxAmount(){
283
+
284
+ //EXPIRATION PERIOD
285
+ if(!empty($this->ExpirationPeriod)){
286
+ $max_future = new DateTime();
287
+ $max_future->add(new DateInterval('P7DT1S')); // max plus one second
288
+
289
+ $future = new DateTime();
290
+ $future->add($this->ExpirationPeriod);
291
+
292
+ $check_interval2 = $max_future->diff($future);
293
+
294
+ if($check_interval2->invert == 0){
295
+ throw new CommunicatorException('The Expiration Period should not be greater than 7 days!');
296
+ }
297
+ }
298
+
299
+ //MAX AMOUNT
300
+ if ($this->MaxAmount !== '' && !is_numeric($this->MaxAmount)) {
301
+ throw new CommunicatorException('The MaxAmount should be a number.');
302
+ }
303
+
304
+ if ($this->MaxAmount !== '' && (float) $this->MaxAmount == 0) {
305
+ throw new CommunicatorException('The MaxAmount cannot be 0.');
306
+ }
307
+
308
+ $tempMaxAmount = str_replace('.', '', $this->MaxAmount);
309
+ $pos = strpos($this->MaxAmount, '.');
310
+ $pos = ($pos !== false ? $pos : strlen($this->MaxAmount));
311
+
312
+ $decimals = substr($this->MaxAmount, $pos + 1);
313
+ if (!empty($this->MaxAmount) && (strlen($tempMaxAmount) > 11 || strlen($decimals) > 2)) {
314
+ throw new CommunicatorException('The MaxAmount should have maximum 2 decimals and the total number of digits should be maximum 11.');
315
+ }
316
+ }
317
+
318
+ }
lib/Communicator/Entities/CancellationResponse.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Represents a cancellation response
5
+ */
6
+ class CancellationResponse {
7
+
8
+ /**
9
+ * true if an error occurred, or false when no errors were encountered
10
+ * @var bool
11
+ */
12
+ public $IsError = false;
13
+
14
+ /**
15
+ * Object that holds the error if one occurs; when there are no errors, this is set to null
16
+ * @var ErrorResponse
17
+ */
18
+ public $Error = null;
19
+
20
+ /**
21
+ * The URL to which to redirect the creditor so they can authorize the transaction
22
+ * @var string
23
+ */
24
+ public $IssuerAuthenticationUrl = null;
25
+
26
+ /**
27
+ * The transaction ID
28
+ * @var string
29
+ */
30
+ public $TransactionId = null;
31
+
32
+ /**
33
+ * DateTime set to when this transaction was created
34
+ * @var DateTime
35
+ */
36
+ public $TransactionCreateDateTimestamp;
37
+
38
+ /**
39
+ * The response XML
40
+ *
41
+ * @var string
42
+ */
43
+ public $RawMessage;
44
+
45
+ /**
46
+ * Deserializes the xml into an CancellationResponse
47
+ *
48
+ * @param string $xml
49
+ * @throws CommunicatorException
50
+ */
51
+ public function __construct($xml, $response_xml = false) {
52
+ $this->RawMessage = (!empty($response_xml) || $response_xml === '' ? $response_xml : $xml);
53
+ $data = XmlUtility::parse($xml);
54
+
55
+ if ($data->getName() == 'AcquirerErrorRes' || $data->getName() == 'Exception') {
56
+ $this->_buildAcquirerErrorRes($data);
57
+ } else if ($data->getName() != 'AcquirerTrxRes') {
58
+ throw new CommunicatorException($data->getName() . ' was not expected.');
59
+ } else {
60
+ $this->_buildCancellationRes($data);
61
+ }
62
+ }
63
+
64
+ private function _buildAcquirerErrorRes($data) {
65
+ $this->Error = new ErrorResponse($data);
66
+ $this->IsError = true;
67
+ $this->TransactionCreateDateTimestamp = new DateTime((string) $data->createDateTimestamp);
68
+ }
69
+
70
+ private function _buildCancellationRes($data) {
71
+ $this->IssuerAuthenticationUrl = (string) $data->Issuer->issuerAuthenticationURL;
72
+ $this->TransactionId = (string) $data->Transaction->transactionID;
73
+
74
+ $this->TransactionCreateDateTimestamp = new DateTime((string) $data->Transaction->transactionCreateDateTimestamp);
75
+ }
76
+ }
lib/Communicator/Entities/DirectoryRequest.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Description of DirectoryRequest
5
+ */
6
+ class DirectoryRequest {
7
+ const XMLNS = "http://www.betaalvereniging.nl/iDx/messages/Merchant-Acquirer/1.0.0";
8
+ const XSD = "http://www.w3.org/2001/XMLSchema";
9
+ const XSI = "http://www.w3.org/2001/XMLSchema-instance";
10
+
11
+ public $productID;
12
+ public $version;
13
+ public $dateTime;
14
+ public $merchant;
15
+
16
+ /**
17
+ * Constructor that highlights the required fields
18
+ *
19
+ * @param string $productID
20
+ * @param string $version
21
+ * @param Merchant $merchant
22
+ */
23
+ public function __construct($productID, $version, Merchant $merchant) {
24
+ $this->productID = $productID;
25
+ $this->version = $version;
26
+ $this->dateTime = date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z');
27
+ $this->merchant = $merchant;
28
+ }
29
+
30
+ /**
31
+ * Serializes the object into a DirectoryReq
32
+ *
33
+ * @return \DOMDocument
34
+ */
35
+ public function toXml() {
36
+ $domtree = new DOMDocument('1.0', 'UTF-8');
37
+
38
+ /* create the root element of the xml tree */
39
+ $DirectoryReq = $domtree->createElementNS(self::XMLNS, 'DirectoryReq');
40
+ $DirectoryReq->setAttribute('xmlns:xsd', self::XSD);
41
+ $DirectoryReq->setAttribute('xmlns:xsi', self::XSI);
42
+
43
+ $DirectoryReq->setAttribute('productID', $this->productID);
44
+ $DirectoryReq->setAttribute('version', $this->version);
45
+ $domtree->appendChild($DirectoryReq);
46
+
47
+ /* create the timetamp */
48
+ $createDateTimestamp = $domtree->createElement('createDateTimestamp', $this->dateTime);
49
+ $DirectoryReq->appendChild($createDateTimestamp);
50
+
51
+ /* create the merchant element and it's sub elements */
52
+ $Merchant = $domtree->createElement('Merchant');
53
+ $Merchant->appendChild($domtree->createElement('merchantID', $this->merchant->merchantID));
54
+ $Merchant->appendChild($domtree->createElement('subID', $this->merchant->merchantSubID));
55
+ $DirectoryReq->appendChild($Merchant);
56
+ //-----[END] Build the XML
57
+
58
+ return $domtree;
59
+ }
60
+
61
+ }
62
+
63
+ /**
64
+ * Description of Merchant
65
+ */
66
+ class Merchant {
67
+
68
+ public $merchantID;
69
+ public $merchantSubID;
70
+
71
+ /**
72
+ * Constructor that highlights the required fields
73
+ *
74
+ * @param string $merchantID
75
+ * @param string $merchantSubID
76
+ */
77
+ public function __construct($merchantID, $merchantSubID) {
78
+ $this->merchantID = $merchantID;
79
+ $this->merchantSubID = $merchantSubID;
80
+ }
81
+
82
+ }
lib/Communicator/Entities/DirectoryResponse.php ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once dirname(__FILE__) . "./ErrorResponse.php";
4
+
5
+ /**
6
+ * Description of DebtorBank
7
+ */
8
+ class DebtorBank {
9
+
10
+ /**
11
+ * Country name
12
+ * @var string
13
+ */
14
+ public $DebtorBankCountry;
15
+
16
+ /**
17
+ * BIC
18
+ * @var string
19
+ */
20
+ public $DebtorBankId;
21
+
22
+ /**
23
+ * Bank name
24
+ * @var string
25
+ */
26
+ public $DebtorBankName;
27
+
28
+ }
29
+
30
+ /**
31
+ * Describes a directory response
32
+ */
33
+ class DirectoryResponse {
34
+
35
+ /**
36
+ * true if an error occurred, or false when no errors were encountered
37
+ * @var bool
38
+ */
39
+ public $IsError = false;
40
+
41
+ /**
42
+ * Object that holds the error if one occurs; when there are no errors, this is set to null
43
+ * @var ErrorResponse
44
+ */
45
+ public $Error = null;
46
+
47
+ /**
48
+ * DateTime set to when this directory was last updated
49
+ * @var DateTime
50
+ */
51
+ public $DirectoryDateTimestamp;
52
+
53
+ /**
54
+ * List of available debtor banks *
55
+ * @var array
56
+ */
57
+ public $DebtorBanks = array();
58
+
59
+ /**
60
+ * The response XML
61
+ *
62
+ * @var string
63
+ */
64
+ public $RawMessage;
65
+
66
+ /**
67
+ * Deserializes the xml into a DirectoryRes
68
+ *
69
+ * @param string $xml
70
+ * @throws CommunicatorException
71
+ */
72
+ public function __construct($xml, $response_xml = false) {
73
+ $this->RawMessage = (!empty($response_xml) || $response_xml === '' ? $response_xml : $xml);
74
+ $data = XmlUtility::parse($xml);
75
+
76
+ if ($data->getName() == 'AcquirerErrorRes' || $data->getName() == 'Exception') {
77
+ $this->_buildAcquirerErrorRes($data);
78
+ } else if ($data->getName() != 'DirectoryRes') {
79
+ throw new CommunicatorException($data->getName() . ' was not expected.');
80
+ } else {
81
+ $this->_buildDirectoryRes($data);
82
+ }
83
+ }
84
+
85
+ private function _buildAcquirerErrorRes($data) {
86
+ $this->Error = new ErrorResponse($data);
87
+ $this->IsError = true;
88
+ $this->DirectoryDateTimestamp = new DateTime((string) $data->createDateTimestamp);
89
+ $this->DebtorBanks = null;
90
+ }
91
+
92
+ private function _buildDirectoryRes($data) {
93
+ $this->DirectoryDateTimestamp = new DateTime((string) $data->Directory->DirectoryDateTimestamp);
94
+
95
+ if (!empty($data->Directory->Country)) {
96
+ foreach ($data->Directory->Country as $countryElem) {
97
+ if (!empty($countryElem->Issuer)) {
98
+ foreach ($countryElem->Issuer as $IssuerElem) {
99
+ $debtor = new DebtorBank();
100
+ $debtor->DebtorBankId = (string) $IssuerElem->issuerID;
101
+ $debtor->DebtorBankName = (string) $IssuerElem->issuerName;
102
+
103
+ $debtor->DebtorBankCountry = (string) $countryElem->countryNames;
104
+
105
+ $this->DebtorBanks[] = $debtor;
106
+ }
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
lib/Communicator/Entities/ErrorResponse.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Describes an error response
5
+ */
6
+ class ErrorResponse {
7
+
8
+ /**
9
+ * Unique identification of the error occurring within the iDx transaction
10
+ * @var string
11
+ */
12
+ public $ErrorCode;
13
+
14
+ /**
15
+ * Descriptive text accompanying Error.errorCode
16
+ * @var string
17
+ */
18
+ public $ErrorMessage;
19
+
20
+ /**
21
+ * Details of the error
22
+ * @var string
23
+ */
24
+ public $ErrorDetails;
25
+
26
+ /**
27
+ * Suggestions aimed at resolving the problem
28
+ * @var string
29
+ */
30
+ public $SuggestedAction;
31
+
32
+ /**
33
+ * A (standardised) message that the merchant should show to the consumer
34
+ * @var string
35
+ */
36
+ public $ConsumerMessage;
37
+
38
+ /**
39
+ * Builds an ErrorResponse from the errRes received
40
+ *
41
+ * @param SimpleXMLElement $errRes
42
+ */
43
+ public function __construct(SimpleXMLElement $errRes) {
44
+
45
+ $this->ErrorCode = (string) $errRes->Error->errorCode;
46
+ $this->ErrorMessage = (string) $errRes->Error->errorMessage;
47
+ $this->ErrorDetails = (string) $errRes->Error->errorDetail;
48
+ $this->SuggestedAction = (string) $errRes->Error->suggestedAction;
49
+ $this->ConsumerMessage = (string) $errRes->Error->consumerMessage;
50
+ }
51
+
52
+ }
lib/Communicator/Entities/NewMandateRequest.php ADDED
@@ -0,0 +1,289 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Description of eMandate
5
+ */
6
+ class NewMandateRequest {
7
+
8
+ const XMLNS = "urn:iso:std:iso:20022:tech:xsd:pain.009.001.04";
9
+ const XSD = "http://www.w3.org/2001/XMLSchema";
10
+ const XSI = "http://www.w3.org/2001/XMLSchema-instance";
11
+ const NOT_PROVIDED = 'NOTPROVIDED';
12
+ const SEPA = 'SEPA';
13
+ const CCY = 'EUR';
14
+
15
+ /**
16
+ * An 'authentication identifier' to facilitate continuation of the session between creditor and debtor, even
17
+ * if the existing session has been lost. It enables the creditor to recognise the debtor associated with a (completed) transaction.
18
+ * @var string
19
+ */
20
+ public $EntranceCode;
21
+
22
+ /**
23
+ * This field enables the debtor bank's site to select the debtor's preferred language (e.g. the language selected on the creditor's site),
24
+ * if the debtor bank's site supports this: Dutch = 'nl', English = 'en'
25
+ * @var string
26
+ */
27
+ public $Language;
28
+
29
+ /**
30
+ * Message ID for pain message
31
+ * @var string
32
+ */
33
+ public $MessageId;
34
+
35
+ /**
36
+ * ID that identifies the mandate and is issued by the creditor
37
+ * @var string
38
+ */
39
+ public $eMandateId;
40
+
41
+ /**
42
+ * Reason of the mandate
43
+ * @var string
44
+ */
45
+ public $eMandateReason;
46
+
47
+ /**
48
+ * Reference ID that identifies the debtor to creditor, which is issued by the creditor
49
+ * @var string
50
+ */
51
+ public $DebtorReference;
52
+
53
+ /**
54
+ * BIC of the Debtor Bank
55
+ * @var string
56
+ */
57
+ public $DebtorBankId;
58
+
59
+ /**
60
+ * A purchaseID that acts as a reference from eMandate to the purchase-order
61
+ * @var string
62
+ */
63
+ public $PurchaseId;
64
+
65
+ /**
66
+ * Indicates type of eMandate: one-off or sequenceType direct debit.
67
+ * @var type
68
+ */
69
+ public $SequenceType;
70
+
71
+ /**
72
+ * Optional: The period of validity of the transaction request as stated by the creditor measured from the receipt by the debtor bank.
73
+ * The debtor must authorise the transaction within this period.
74
+ * @var DateInterval
75
+ */
76
+ public $ExpirationPeriod;
77
+
78
+ /**
79
+ * Maximum amount. Not allowed for Core, optional for B2B.
80
+ * @var string
81
+ */
82
+ public $MaxAmount;
83
+
84
+ /**
85
+ * The object used to log internal messages and the xml files
86
+ *
87
+ * @var Logger
88
+ */
89
+ public $logger;
90
+
91
+ /**
92
+ * Constructor that highlights all required fields for this object
93
+ *
94
+ * @param string $entranceCode
95
+ * @param string $language
96
+ * @param string $messageId
97
+ * @param string $eMandateId
98
+ * @param string $eMandateReason
99
+ * @param string $debtorReference
100
+ * @param string $debtorBankId
101
+ * @param string $purchaseId
102
+ * @param string $sequenceType
103
+ * @param string $maxAmount - optional
104
+ * @param DateInterval $expirationPeriod - optional
105
+ */
106
+ public function __construct($entranceCode, $language, $messageId, $eMandateId, $eMandateReason, $debtorReference, $debtorBankId, $purchaseId, $sequenceType, $maxAmount = '', $expirationPeriod = null) {
107
+
108
+ /* setting the required fields */
109
+ $this->EntranceCode = $entranceCode;
110
+ $this->Language = $language;
111
+ $this->MessageId = $messageId;
112
+ $this->eMandateId = $eMandateId;
113
+ $this->eMandateReason = $eMandateReason;
114
+ $this->DebtorReference = $debtorReference;
115
+ $this->DebtorBankId = $debtorBankId;
116
+ $this->PurchaseId = $purchaseId;
117
+ $this->SequenceType = $sequenceType;
118
+
119
+ /* setting the optional fields */
120
+ $this->MaxAmount = str_replace(',', '.', $maxAmount);
121
+ $this->ExpirationPeriod = $expirationPeriod;
122
+
123
+ if (empty($this->MessageId)) {
124
+ $this->MessageId = MessageIdGenerator::NewMessageId();
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Serializes the object into a Document
130
+ *
131
+ * @param string $LocalInstrumentCode
132
+ * @return DOMElement
133
+ */
134
+ public function toXml($LocalInstrumentCode) {
135
+ $this->logger->Log("building eMandate");
136
+ $this->validateExpirationPeriodAndMaxAmount();
137
+
138
+ $domtree = new DOMDocument('1.0', 'UTF-8');
139
+
140
+ /* create the Document element with it's namespaces */
141
+ $Document = $domtree->createElement('Document');
142
+ $Document->setAttribute('xmlns', self::XMLNS);
143
+ $Document->setAttribute('xmlns:xsd', self::XSD);
144
+ $Document->setAttribute('xmlns:xsi', self::XSI); {
145
+ /* create the MndtInitnReq element */
146
+ $MndtInitnReq = $domtree->createElement('MndtInitnReq'); {
147
+ /* create the GrpHdr element */
148
+ $GrpHdr = $domtree->createElement('GrpHdr'); {
149
+ /* create the MsgId and the CreDtTm elements */
150
+ $GrpHdr->appendChild(new DOMElement('MsgId', $this->MessageId));
151
+ $GrpHdr->appendChild(new DOMElement('CreDtTm', date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z')));
152
+ }
153
+ $MndtInitnReq->appendChild($GrpHdr);
154
+
155
+ /* create the Mndt element */
156
+ $Mndt = $domtree->createElement('Mndt'); {
157
+ /* create MndtId elemnt */
158
+ $Mndt->appendChild(new DOMElement('MndtId', $this->eMandateId));
159
+
160
+ /* create MndtReqId element */
161
+ $Mndt->appendChild(new DOMElement('MndtReqId', self::NOT_PROVIDED));
162
+
163
+ /* create Tp element */
164
+ $Tp = $domtree->createElement('Tp'); {
165
+ /* create SvcLvl element */
166
+ $SvcLvl = $domtree->createElement('SvcLvl');
167
+ $SvcLvl->appendChild(new DOMElement('Cd', self::SEPA));
168
+ $Tp->appendChild($SvcLvl);
169
+
170
+ /* create LclInstrm element */
171
+ $LclInstrm = $domtree->createElement('LclInstrm');
172
+ $LclInstrm->appendChild(new DOMElement('Cd', $LocalInstrumentCode));
173
+ $Tp->appendChild($LclInstrm);
174
+ }
175
+ $Mndt->appendChild($Tp);
176
+
177
+ /* create Ocrncs element */
178
+ $Ocrncs = $domtree->createElement('Ocrncs');
179
+ $Ocrncs->appendChild(new DOMElement('SeqTp', $this->SequenceType));
180
+ $Mndt->appendChild($Ocrncs);
181
+
182
+ /* create MaxAmt element */
183
+ if (!empty($this->MaxAmount) && $LocalInstrumentCode == B2BCommunicator::LOCAL_INSTRUMENT) {
184
+ $MaxAmt = $domtree->createElement('MaxAmt', $this->MaxAmount);
185
+ $MaxAmt->setAttribute('Ccy', self::CCY);
186
+ $Mndt->appendChild($MaxAmt);
187
+ }
188
+
189
+ /* create Rsn element */
190
+ if (!empty($this->eMandateReason)) {
191
+ $Rsn = $domtree->createElement('Rsn');
192
+ $Rsn->appendChild(new DOMElement('Prtry', $this->eMandateReason));
193
+ $Mndt->appendChild($Rsn);
194
+ }
195
+
196
+ /* create Cdtr element */
197
+ $Mndt->appendChild(new DOMElement('Cdtr'));
198
+
199
+ /* create Dbtr element */
200
+ $Dbtr = $domtree->createElement('Dbtr'); {
201
+ if (!empty($this->DebtorReference)) {
202
+ $Id = $domtree->createElement('Id'); {
203
+ $PrvtId = $domtree->createElement('PrvtId'); {
204
+ $Othr = $domtree->createElement('Othr');
205
+ $Othr->appendChild(new DOMElement('Id', $this->DebtorReference));
206
+ $PrvtId->appendChild($Othr);
207
+ }
208
+ }
209
+ $Id->appendChild($PrvtId);
210
+ $Dbtr->appendChild($Id);
211
+ }
212
+ }
213
+ $Mndt->appendChild($Dbtr);
214
+
215
+ /* create DbtrAgt element */
216
+ $DbtrAgt = $domtree->createElement('DbtrAgt'); {
217
+ $FinInstnId = $domtree->createElement('FinInstnId');
218
+ $FinInstnId->appendChild(new DOMElement('BICFI', $this->DebtorBankId));
219
+ $DbtrAgt->appendChild($FinInstnId);
220
+ }
221
+ $Mndt->appendChild($DbtrAgt);
222
+
223
+ /* create RfrdDoc element */
224
+ if (!empty($this->PurchaseId)) {
225
+ $RfrdDoc = $domtree->createElement('RfrdDoc'); {
226
+ $Tp = $domtree->createElement('Tp'); {
227
+ $CdOrPrtry = $domtree->createElement('CdOrPrtry');
228
+ $CdOrPrtry->appendChild(new DOMElement('Prtry', $this->PurchaseId));
229
+ $Tp->appendChild($CdOrPrtry);
230
+ }
231
+ $RfrdDoc->appendChild($Tp);
232
+ }
233
+ $Mndt->appendChild($RfrdDoc);
234
+ }
235
+ }
236
+ $MndtInitnReq->appendChild($Mndt);
237
+ }
238
+ $Document->appendChild($MndtInitnReq);
239
+ }
240
+
241
+ $domtree->appendChild($Document);
242
+
243
+ XmlValidator::isValidatXML($domtree->saveXML(), XmlValidator::SCHEMA_PAIN009, $this->logger);
244
+
245
+ return $Document;
246
+ }
247
+
248
+ /**
249
+ * Validates that the ExpirationPeriod is not greater than 7days
250
+ * and that the MaxAmount respects the standard
251
+ * @throws CommunicatorException
252
+ */
253
+ private function validateExpirationPeriodAndMaxAmount(){
254
+
255
+ //EXPIRATION PERIOD
256
+ if(!empty($this->ExpirationPeriod)){
257
+ $max_future = new DateTime();
258
+ $max_future->add(new DateInterval('P7DT1S')); // max plus one second
259
+
260
+ $future = new DateTime();
261
+ $future->add($this->ExpirationPeriod);
262
+
263
+ $check_interval2 = $max_future->diff($future);
264
+
265
+ if($check_interval2->invert == 0){
266
+ throw new CommunicatorException('The Expiration Period should not be greater than 7 days!');
267
+ }
268
+ }
269
+
270
+ //MAX AMOUNT
271
+ if ($this->MaxAmount !== '' && !is_numeric($this->MaxAmount)) {
272
+ throw new CommunicatorException('The MaxAmount should be a number.');
273
+ }
274
+
275
+ if ($this->MaxAmount !== '' && (float) $this->MaxAmount == 0) {
276
+ throw new CommunicatorException('The MaxAmount cannot be 0.');
277
+ }
278
+
279
+ $tempMaxAmount = str_replace('.', '', $this->MaxAmount);
280
+ $pos = strpos($this->MaxAmount, '.');
281
+ $pos = ($pos !== false ? $pos : strlen($this->MaxAmount));
282
+
283
+ $decimals = substr($this->MaxAmount, $pos + 1);
284
+ if (!empty($this->MaxAmount) && (strlen($tempMaxAmount) > 11 || strlen($decimals) > 2)) {
285
+ throw new CommunicatorException('The MaxAmount should have maximum 2 decimals and the total number of digits should be maximum 11.');
286
+ }
287
+ }
288
+
289
+ }
lib/Communicator/Entities/NewMandateResponse.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Describes a new mandate response
5
+ */
6
+ class NewMandateResponse {
7
+
8
+ /**
9
+ * true if an error occurred, or false when no errors were encountered
10
+ * @var bool
11
+ */
12
+ public $IsError = false;
13
+
14
+ /**
15
+ * Object that holds the error if one occurs; when there are no errors, this is set to null
16
+ * @var ErrorResponse
17
+ */
18
+ public $Error = null;
19
+
20
+ /**
21
+ * The URL to which to redirect the creditor so they can authorize the transaction
22
+ * @var string
23
+ */
24
+ public $IssuerAuthenticationUrl = null;
25
+
26
+ /**
27
+ * The transaction ID
28
+ * @var string
29
+ */
30
+ public $TransactionId = null;
31
+
32
+ /**
33
+ * DateTime set to when this transaction was created
34
+ * @var DateTime
35
+ */
36
+ public $TransactionCreateDateTimestamp;
37
+
38
+ /**
39
+ * The response XML
40
+ *
41
+ * @var string
42
+ */
43
+ public $RawMessage;
44
+
45
+ /**
46
+ * Deserializes the xml into a NewMandateResponse
47
+ *
48
+ * @param string $xml
49
+ * @throws CommunicatorException
50
+ */
51
+ public function __construct($xml, $response_xml = false) {
52
+ $this->RawMessage = (!empty($response_xml) || $response_xml === '' ? $response_xml : $xml);
53
+ $data = XmlUtility::parse($xml);
54
+
55
+ if ($data->getName() == 'AcquirerErrorRes' || $data->getName() == 'Exception') {
56
+ $this->_buildAcquirerErrorRes($data);
57
+ } else if ($data->getName() != 'AcquirerTrxRes') {
58
+ throw new CommunicatorException($data->getName() . ' was not expected.');
59
+ } else {
60
+ $this->_buildNewMandateResponse($data);
61
+ }
62
+ }
63
+
64
+ private function _buildAcquirerErrorRes($data) {
65
+ $this->Error = new ErrorResponse($data);
66
+ $this->IsError = true;
67
+ $this->TransactionCreateDateTimestamp = new DateTime((string) $data->createDateTimestamp);
68
+ }
69
+
70
+ private function _buildNewMandateResponse($data) {
71
+ $this->IssuerAuthenticationUrl = (string) $data->Issuer->issuerAuthenticationURL;
72
+ $this->TransactionId = (string) $data->Transaction->transactionID;
73
+
74
+ $this->TransactionCreateDateTimestamp = new DateTime((string) $data->Transaction->transactionCreateDateTimestamp);
75
+ }
76
+ }
lib/Communicator/Libraries/CommunicatorException.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * To change this license header, choose License Headers in Project Properties.
5
+ * To change this template file, choose Tools | Templates
6
+ * and open the template in the editor.
7
+ */
8
+
9
+ /**
10
+ * Description of CommunicatorException
11
+ */
12
+ class CommunicatorException extends Exception {
13
+
14
+ /**
15
+ * Createst an Exception with custom message so it can be parsed by the ErrorResponse
16
+ *
17
+ * @param string $message
18
+ * @param string | int $code
19
+ */
20
+ public function __construct($message, $code = false) {
21
+ // some code
22
+ $new_message = "
23
+ <Exception>
24
+ <Error>
25
+ <errorCode>$code</errorCode>
26
+ <errorMessage>$message</errorMessage>
27
+ </Error>
28
+ </Exception>
29
+ ";
30
+ // make sure everything is assigned properly
31
+ parent::__construct($new_message, $code);
32
+ }
33
+
34
+ }
lib/Communicator/Libraries/Logger.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Description of Logger
5
+ */
6
+ class Logger {
7
+
8
+ protected $enableXMLLogs;
9
+ protected $logPath;
10
+ protected $folderNamePattern;
11
+ protected $fileNamePrefix;
12
+ protected $enableInternalLogs;
13
+ protected $fileName;
14
+
15
+ public function __construct(Configuration $configuration) {
16
+ $this->enableXMLLogs = $configuration->enableXMLLogs;
17
+ $this->logPath = $configuration->logPath;
18
+ $this->folderNamePattern = $configuration->folderNamePattern;
19
+ $this->fileNamePrefix = $configuration->fileNamePrefix;
20
+ $this->enableInternalLogs = $configuration->enableInternalLogs;
21
+ $this->fileName = $configuration->fileName;
22
+ }
23
+
24
+ /**
25
+ * Logs a trace message to the config['fileName']
26
+ *
27
+ * @param string $message
28
+ */
29
+ public function Log($message) {
30
+ $callers = debug_backtrace();
31
+ $this->Write($callers[1]['function'], $message);
32
+ }
33
+
34
+ /**
35
+ * Saves the desired dom or xml into the logPath folder
36
+ *
37
+ * @param DOMDocument/string $dom
38
+ */
39
+ public function LogXmlMessage($dom, $isXML = false) {
40
+
41
+ if ($this->enableXMLLogs) {
42
+ if ($isXML) {
43
+ $domtree = new DOMDocument();
44
+ $domtree->loadXML($dom);
45
+
46
+ $dom = $domtree;
47
+ }
48
+
49
+ $dirName = $this->logPath . date($this->folderNamePattern);
50
+ if (!file_exists($dirName)) {
51
+ mkdir($dirName, 0777, true);
52
+ }
53
+
54
+ $t = microtime(true);
55
+ $micro = sprintf("%06d", ($t - floor($t)) * 1000000);
56
+ $d = new DateTime(date('Y-m-d H:i:s.' . $micro, $t));
57
+
58
+ $dom->save($dirName . '/' . $d->format($this->fileNamePrefix) . '-' . (!empty($dom->documentElement->localName) ? $dom->documentElement->localName : '') . '.xml');
59
+ }
60
+ }
61
+
62
+ public function Write($function, $message) {
63
+
64
+ if ($this->enableInternalLogs) {
65
+ $dirName = $this->logPath . date($this->folderNamePattern);
66
+ if (!file_exists($dirName)) {
67
+ mkdir($dirName, 0777, true);
68
+ }
69
+
70
+ file_put_contents($dirName . '/' . $this->fileName, date('Y-m-d H:i:s : ') . $function . '() - ' . $message . "\n", FILE_APPEND);
71
+ }
72
+ }
73
+
74
+ }
lib/Communicator/Libraries/MessageIdGenerator.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class that automatically generates MessageId's. You may use this to set the MessageId field manually, or you can use
5
+ * the constructors for NewMandateRequest, AmendmentRequest or CancellationRequest to do it automatically.
6
+ */
7
+ class MessageIdGenerator {
8
+
9
+ /**
10
+ * Returns a string of 16 alphanumeric characters
11
+ * @return string
12
+ */
13
+ public static function NewMessageId() {
14
+ $ok = false;
15
+ while (!$ok) {
16
+ $charid = strtoupper(md5(uniqid(rand(), true)));
17
+ $hyphen = ''; //chr(45); // "-"
18
+ $uuid = ''//chr(123)// "{"
19
+ . substr($charid, 0, 8) . $hyphen
20
+ . substr($charid, 8, 4) . $hyphen
21
+ . substr($charid, 12, 4) . $hyphen
22
+ . substr($charid, 16, 4) . $hyphen
23
+ . substr($charid, 20, 12)
24
+ . ''; //chr(125); // "}"
25
+ $base64 = preg_replace("/[^A-Za-z0-9 ]/", '', base64_encode($uuid));
26
+ $base64 = substr($base64, 0, 16);
27
+
28
+ if (strlen($base64) == 16) {
29
+ $ok = true;
30
+ }
31
+ }
32
+ return $base64;
33
+ }
34
+
35
+ }
lib/Communicator/Libraries/XmlSecurity.php ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once dirname(__FILE__) . './xmlseclibs.php';
4
+ require_once dirname(__FILE__) . './CommunicatorException.php';
5
+
6
+ const BEGIN_CERTIFICATE = '-----BEGIN CERTIFICATE-----';
7
+ const END_CERTIFICATE = '-----END CERTIFICATE-----';
8
+
9
+ class XmlSecurity {
10
+
11
+ private $logger;
12
+
13
+ function __construct($logger) {
14
+ $this->logger = $logger;
15
+ }
16
+
17
+ public function sign(DOMDocument $docTree, $privateCertificatePath, $privateKeyPath, $passphrase) {
18
+ $this->logger->Log("signing xml...");
19
+
20
+ /* The GOOD thing that fixed the xignature */
21
+ $doc = new DOMDocument();
22
+ $doc->loadXML($docTree->saveXML());
23
+
24
+ $signature = new XMLSecurityDSig();
25
+ $signature->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
26
+ $signature->addReference(
27
+ $doc,
28
+ XMLSecurityDSig::SHA256,
29
+ array(
30
+ 'http://www.w3.org/2000/09/xmldsig#enveloped-signature',
31
+ 'http://www.w3.org/2001/10/xml-exc-c14n#'
32
+ ),
33
+ array('force_uri' => true)
34
+ );
35
+
36
+ $key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, array('type' => 'private'));
37
+
38
+ $key->passphrase = $passphrase;
39
+ $key->loadKey($privateKeyPath, TRUE);
40
+
41
+ $signature->sign($key);
42
+
43
+ $fingerprint = $this->getFingerprint($privateCertificatePath);
44
+
45
+ $this->logger->Log("embedding thumbprint: {{$fingerprint}}");
46
+
47
+ $signature->addKeyInfoAndName($fingerprint);
48
+
49
+ $signature->appendSignature($doc->documentElement);
50
+
51
+ $this->logger->Log("finished signing xml");
52
+
53
+ return $doc;
54
+ }
55
+
56
+ private function checkIdxSignature($doc, $certificatePath) {
57
+ $signature = new XMLSecurityDSig();
58
+
59
+ $signature->locateSignature($doc);
60
+ $signature->canonicalizeSignedInfo();
61
+
62
+ try {
63
+ $signature->validateReference();
64
+ } catch (Exception $ex) {
65
+ $this->logger->Log("Reference Validation Failed");
66
+ throw new CommunicatorException('Reference Validation Failed', $ex->getCode());
67
+ }
68
+
69
+ $key = $signature->locateKey();
70
+ if (!$key) {
71
+ $this->logger->Log("Cannot locate the key");
72
+ throw new CommunicatorException('Cannot locate the key.');
73
+ }
74
+
75
+ $key->loadKey($this->normalizeCertificate($certificatePath));
76
+
77
+ if ($signature->verify($key) == 1) {
78
+ $this->logger->Log("signature is valid");
79
+ return true;
80
+ } else {
81
+ $this->logger->Log("The signature could not be verified.");
82
+ throw new CommunicatorException('The signature could not be verified.');
83
+ }
84
+ }
85
+
86
+ public function checkEmandateSignature($emandatedoc) {
87
+ $str = $emandatedoc->saveXML();
88
+ $str = str_replace(' xmlns:default="http://www.w3.org/2000/09/xmldsig#"', '', str_replace('default:', '', $str));
89
+
90
+ $emandatedoc->loadXML($str);
91
+
92
+ $certificate = $emandatedoc->getElementsByTagNameNS('http://www.w3.org/2000/09/xmldsig#', 'X509Certificate')->item(0);
93
+ $cert = $this->normalizeEmbeddedCertificate($certificate->nodeValue);
94
+
95
+ $signature = new XMLSecurityDSig();
96
+
97
+ $signature->locateSignature($emandatedoc);
98
+ $signature->canonicalizeSignedInfo();
99
+
100
+ try {
101
+ $signature->validateReference();
102
+ } catch (Exception $ex) {
103
+ $this->logger->Log("emandate signature: reference validation failed");
104
+ throw new CommunicatorException('emandate signature: reference validation failed', $ex->getCode());
105
+ }
106
+
107
+ $key = $signature->locateKey();
108
+ if (!$key) {
109
+ $this->logger->Log("emandate signature: cannot locate the key");
110
+ throw new CommunicatorException('emandate signature: cannot locate the key.');
111
+ }
112
+
113
+ $key->loadKey($cert);
114
+
115
+ if ($signature->verify($key) == 1) {
116
+ $this->logger->Log("emandate signature: signature is valid");
117
+ return true;
118
+ } else {
119
+ $this->logger->Log("emandate signature: the signature could not be verified.");
120
+ throw new CommunicatorException('emandate signature: the signature could not be verified.');
121
+ }
122
+ }
123
+
124
+ public function verify($xml, $certificatePath) {
125
+ $this->logger->Log("checking signature...");
126
+
127
+ $doc = new DOMDocument();
128
+ $doc->loadXML($xml);
129
+
130
+ $signature = new XMLSecurityDSig();
131
+ if ($signature->signaturesCount($doc) == 2) {
132
+ // TODO: first check emandate signature
133
+ $eMandate = $doc->getElementsByTagNameNS('urn:iso:std:iso:20022:tech:xsd:pain.012.001.04', 'Document')->item(0);
134
+ $newEmandate = $eMandate->cloneNode(TRUE);
135
+ $emandatedoc = new DOMDocument();
136
+ $newEmandate = $emandatedoc->importNode($newEmandate, TRUE);
137
+ $emandatedoc->appendChild($newEmandate);
138
+
139
+ $this->checkEmandateSignature($emandatedoc);
140
+ }
141
+
142
+ return $this->checkIdxSignature($doc, $certificatePath);
143
+ }
144
+
145
+ private function getFingerprint($path) {
146
+ $contents = $this->normalizeCertificate($path);
147
+
148
+ if (is_null($contents) || $contents == false) {
149
+ $this->logger->Log("Empty signing certificate.");
150
+ throw new CommunicatorException('Empty signing certificate.');
151
+ }
152
+
153
+ $contents = str_replace(END_CERTIFICATE, '', str_replace(BEGIN_CERTIFICATE, '', $contents));
154
+ $contents = base64_decode($contents);
155
+ return strtoupper(sha1($contents));
156
+ }
157
+
158
+ private function normalizeCertificate($path) {
159
+ $origcontent = file_get_contents($path);
160
+
161
+ if (is_null($origcontent) || $origcontent == false) {
162
+ $this->logger->Log("Empty acquirer certificate.");
163
+ throw new CommunicatorException('Empty acquirer certificate.');
164
+ }
165
+
166
+ $count = substr_count($origcontent, "\n");
167
+ if ($count > 5) {
168
+ return $origcontent;
169
+ }
170
+
171
+ $contents = str_replace(END_CERTIFICATE, '', str_replace(BEGIN_CERTIFICATE, '', $origcontent));
172
+
173
+ $blocks = array();
174
+ while (strlen($contents) > 0) {
175
+ array_push($blocks, substr($contents, 0, 64));
176
+ $contents = substr($contents, 64);
177
+ $contents = ltrim($contents);
178
+ }
179
+
180
+ $str = BEGIN_CERTIFICATE . "\r\n" . implode("\r\n", $blocks) . "\r\n" . END_CERTIFICATE;
181
+
182
+ return $str;
183
+ }
184
+
185
+ private function normalizeEmbeddedCertificate($text) {
186
+ $blocks = array();
187
+ $contents = $text;
188
+ while (strlen($contents) > 0) {
189
+ array_push($blocks, substr($contents, 0, 64));
190
+ $contents = substr($contents, 64);
191
+ $contents = ltrim($contents);
192
+ }
193
+
194
+ $str = BEGIN_CERTIFICATE . "\r\n" . implode("\r\n", $blocks) . "\r\n" . END_CERTIFICATE;
195
+
196
+ return $str;
197
+ }
198
+ }
lib/Communicator/Libraries/XmlUtility.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Utility class for processing XML documents
5
+ */
6
+ class XmlUtility {
7
+
8
+ public static function parse($xml) {
9
+ $xml = preg_replace("/(<\\/?)[\\w]*?:/m", '$1', $xml);
10
+ $xml = preg_replace("/xmlns:[\\w]*?=\"[^\"]*?\"/m", '', $xml);
11
+
12
+ $element = simplexml_load_string($xml);
13
+ return $element;
14
+ }
15
+ }
lib/Communicator/Libraries/XmlValidator.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Description of XmlValidator
5
+ */
6
+ class XmlValidator {
7
+
8
+ const SCHEMA_IDX = 'SchemaIDX';
9
+ const SCHEMA_PAIN009 = 'SchemaPain009';
10
+ const SCHEMA_PAIN010 = 'SchemaPain010';
11
+ const SCHEMA_PAIN011 = 'SchemaPain011';
12
+ const SCHEMA_PAIN012 = 'SchemaPain012';
13
+
14
+ public $SchemaIDX;
15
+ public $SchemaPain009;
16
+ public $SchemaPain010;
17
+ public $SchemaPain011;
18
+ public $SchemaPain012;
19
+
20
+ function __construct() {
21
+
22
+ $this->SchemaIDX = dirname(__FILE__) . './../schemas/idx.merchant-acquirer.1.0.xsd';
23
+ $this->SchemaPain009 = dirname(__FILE__) . './../schemas/pain.009.001.04.xsd';
24
+ $this->SchemaPain010 = dirname(__FILE__) . './../schemas/pain.010.001.04.xsd';
25
+ $this->SchemaPain011 = dirname(__FILE__) . './../schemas/pain.011.001.04.xsd';
26
+ $this->SchemaPain012 = dirname(__FILE__) . './../schemas/pain.012.001.04.xsd';
27
+ }
28
+
29
+ /**
30
+ * Validates the xml provided against the xsd schema
31
+ *
32
+ * @param string $xml
33
+ * @return boolean
34
+ * @throws Exception
35
+ */
36
+ public static function isValidatXML($xml, $schemaName, $logger) {
37
+ $validator = new self();
38
+
39
+ libxml_use_internal_errors(true);
40
+
41
+ $document = new DOMDocument();
42
+ $document->loadXML($xml);
43
+
44
+ if (!$document->schemaValidate($validator->$schemaName)) {
45
+
46
+ foreach (libxml_get_errors() as $error) {
47
+ $logger->Log("xml schema is not valid: {{$error->message}}");
48
+ throw new CommunicatorException($error->message, $error->code);
49
+ }
50
+ return false;
51
+ }
52
+ $logger->Log("xml schema is valid");
53
+ return true;
54
+ }
55
+
56
+ }
lib/Communicator/Libraries/xmlseclibs.php ADDED
@@ -0,0 +1,1853 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * xmlseclibs.php
4
+ *
5
+ * Copyright (c) 2007-2013, Robert Richards <rrichards@cdatazone.org>.
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without
9
+ * modification, are permitted provided that the following conditions
10
+ * are met:
11
+ *
12
+ * * Redistributions of source code must retain the above copyright
13
+ * notice, this list of conditions and the following disclaimer.
14
+ *
15
+ * * Redistributions in binary form must reproduce the above copyright
16
+ * notice, this list of conditions and the following disclaimer in
17
+ * the documentation and/or other materials provided with the
18
+ * distribution.
19
+ *
20
+ * * Neither the name of Robert Richards nor the names of his
21
+ * contributors may be used to endorse or promote products derived
22
+ * from this software without specific prior written permission.
23
+ *
24
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
+ * POSSIBILITY OF SUCH DAMAGE.
36
+ *
37
+ * @author Robert Richards <rrichards@cdatazone.org>
38
+ * @copyright 2007-2013 Robert Richards <rrichards@cdatazone.org>
39
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
40
+ * @version 1.3.1
41
+ */
42
+
43
+ /*
44
+ Functions to generate simple cases of Exclusive Canonical XML - Callable function is C14NGeneral()
45
+ i.e.: $canonical = C14NGeneral($domelement, TRUE);
46
+ */
47
+
48
+ /* helper function */
49
+ function sortAndAddAttrs($element, $arAtts) {
50
+ $newAtts = array();
51
+ foreach ($arAtts AS $attnode) {
52
+ $newAtts[$attnode->nodeName] = $attnode;
53
+ }
54
+ ksort($newAtts);
55
+ foreach ($newAtts as $attnode) {
56
+ $element->setAttribute($attnode->nodeName, $attnode->nodeValue);
57
+ }
58
+ }
59
+
60
+ /* helper function */
61
+ function canonical($tree, $element, $withcomments) {
62
+ if ($tree->nodeType != XML_DOCUMENT_NODE) {
63
+ $dom = $tree->ownerDocument;
64
+ } else {
65
+ $dom = $tree;
66
+ }
67
+ if ($element->nodeType != XML_ELEMENT_NODE) {
68
+ if ($element->nodeType == XML_DOCUMENT_NODE) {
69
+ foreach ($element->childNodes AS $node) {
70
+ canonical($dom, $node, $withcomments);
71
+ }
72
+ return;
73
+ }
74
+ if ($element->nodeType == XML_COMMENT_NODE && ! $withcomments) {
75
+ return;
76
+ }
77
+ $tree->appendChild($dom->importNode($element, TRUE));
78
+ return;
79
+ }
80
+ $arNS = array();
81
+ if ($element->namespaceURI != "") {
82
+ if ($element->prefix == "") {
83
+ $elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
84
+ } else {
85
+ $prefix = $tree->lookupPrefix($element->namespaceURI);
86
+ if ($prefix == $element->prefix) {
87
+ $elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName);
88
+ } else {
89
+ $elCopy = $dom->createElement($element->nodeName);
90
+ $arNS[$element->namespaceURI] = $element->prefix;
91
+ }
92
+ }
93
+ } else {
94
+ $elCopy = $dom->createElement($element->nodeName);
95
+ }
96
+ $tree->appendChild($elCopy);
97
+
98
+ /* Create DOMXPath based on original document */
99
+ $xPath = new DOMXPath($element->ownerDocument);
100
+
101
+ /* Get namespaced attributes */
102
+ $arAtts = $xPath->query('attribute::*[namespace-uri(.) != ""]', $element);
103
+
104
+ /* Create an array with namespace URIs as keys, and sort them */
105
+ foreach ($arAtts AS $attnode) {
106
+ if (array_key_exists($attnode->namespaceURI, $arNS) &&
107
+ ($arNS[$attnode->namespaceURI] == $attnode->prefix)) {
108
+ continue;
109
+ }
110
+ $prefix = $tree->lookupPrefix($attnode->namespaceURI);
111
+ if ($prefix != $attnode->prefix) {
112
+ $arNS[$attnode->namespaceURI] = $attnode->prefix;
113
+ } else {
114
+ $arNS[$attnode->namespaceURI] = NULL;
115
+ }
116
+ }
117
+ if (count($arNS) > 0) {
118
+ asort($arNS);
119
+ }
120
+
121
+ /* Add namespace nodes */
122
+ foreach ($arNS AS $namespaceURI=>$prefix) {
123
+ if ($prefix != NULL) {
124
+ $elCopy->setAttributeNS("http://www.w3.org/2000/xmlns/",
125
+ "xmlns:".$prefix, $namespaceURI);
126
+ }
127
+ }
128
+ if (count($arNS) > 0) {
129
+ ksort($arNS);
130
+ }
131
+
132
+ /* Get attributes not in a namespace, and then sort and add them */
133
+ $arAtts = $xPath->query('attribute::*[namespace-uri(.) = ""]', $element);
134
+ sortAndAddAttrs($elCopy, $arAtts);
135
+
136
+ /* Loop through the URIs, and then sort and add attributes within that namespace */
137
+ foreach ($arNS as $nsURI=>$prefix) {
138
+ $arAtts = $xPath->query('attribute::*[namespace-uri(.) = "'.$nsURI.'"]', $element);
139
+ sortAndAddAttrs($elCopy, $arAtts);
140
+ }
141
+
142
+ foreach ($element->childNodes AS $node) {
143
+ canonical($elCopy, $node, $withcomments);
144
+ }
145
+ }
146
+
147
+ /*
148
+ $element - DOMElement for which to produce the canonical version of
149
+ $exclusive - boolean to indicate exclusive canonicalization (must pass TRUE)
150
+ $withcomments - boolean indicating wether or not to include comments in canonicalized form
151
+ */
152
+ function C14NGeneral($element, $exclusive=FALSE, $withcomments=FALSE) {
153
+ /* IF PHP 5.2+ then use built in canonical functionality */
154
+ $php_version = explode('.', PHP_VERSION);
155
+ if (($php_version[0] > 5) || ($php_version[0] == 5 && $php_version[1] >= 2) ) {
156
+ return $element->C14N($exclusive, $withcomments);
157
+ }
158
+
159
+ /* Must be element or document */
160
+ if (! $element instanceof DOMElement && ! $element instanceof DOMDocument) {
161
+ return NULL;
162
+ }
163
+ /* Currently only exclusive XML is supported */
164
+ if ($exclusive == FALSE) {
165
+ throw new Exception("Only exclusive canonicalization is supported in this version of PHP");
166
+ }
167
+
168
+ $copyDoc = new DOMDocument();
169
+ canonical($copyDoc, $element, $withcomments);
170
+ return $copyDoc->saveXML($copyDoc->documentElement, LIBXML_NOEMPTYTAG);
171
+ }
172
+
173
+ class XMLSecurityKey {
174
+ const TRIPLEDES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
175
+ const AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
176
+ const AES192_CBC = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
177
+ const AES256_CBC = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
178
+ const RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
179
+ const RSA_OAEP_MGF1P = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
180
+ const DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1';
181
+ const RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
182
+ const RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
183
+ const RSA_SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384';
184
+ const RSA_SHA512 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512';
185
+
186
+ private $cryptParams = array();
187
+ public $type = 0;
188
+ public $key = NULL;
189
+ public $passphrase = "";
190
+ public $iv = NULL;
191
+ public $name = NULL;
192
+ public $keyChain = NULL;
193
+ public $isEncrypted = FALSE;
194
+ public $encryptedCtx = NULL;
195
+ public $guid = NULL;
196
+
197
+ /**
198
+ * This variable contains the certificate as a string if this key represents an X509-certificate.
199
+ * If this key doesn't represent a certificate, this will be NULL.
200
+ */
201
+ private $x509Certificate = NULL;
202
+
203
+ /* This variable contains the certificate thunbprint if we have loaded an X509-certificate. */
204
+ private $X509Thumbprint = NULL;
205
+
206
+ public function __construct($type, $params=NULL) {
207
+ srand();
208
+ switch ($type) {
209
+ case (XMLSecurityKey::TRIPLEDES_CBC):
210
+ $this->cryptParams['library'] = 'mcrypt';
211
+ $this->cryptParams['cipher'] = MCRYPT_TRIPLEDES;
212
+ $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
213
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
214
+ $this->cryptParams['keysize'] = 24;
215
+ break;
216
+ case (XMLSecurityKey::AES128_CBC):
217
+ $this->cryptParams['library'] = 'mcrypt';
218
+ $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
219
+ $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
220
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
221
+ $this->cryptParams['keysize'] = 16;
222
+ break;
223
+ case (XMLSecurityKey::AES192_CBC):
224
+ $this->cryptParams['library'] = 'mcrypt';
225
+ $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
226
+ $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
227
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
228
+ $this->cryptParams['keysize'] = 24;
229
+ break;
230
+ case (XMLSecurityKey::AES256_CBC):
231
+ $this->cryptParams['library'] = 'mcrypt';
232
+ $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128;
233
+ $this->cryptParams['mode'] = MCRYPT_MODE_CBC;
234
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
235
+ $this->cryptParams['keysize'] = 32;
236
+ break;
237
+ case (XMLSecurityKey::RSA_1_5):
238
+ $this->cryptParams['library'] = 'openssl';
239
+ $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
240
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
241
+ if (is_array($params) && ! empty($params['type'])) {
242
+ if ($params['type'] == 'public' || $params['type'] == 'private') {
243
+ $this->cryptParams['type'] = $params['type'];
244
+ break;
245
+ }
246
+ }
247
+ throw new Exception('Certificate "type" (private/public) must be passed via parameters');
248
+ return;
249
+ case (XMLSecurityKey::RSA_OAEP_MGF1P):
250
+ $this->cryptParams['library'] = 'openssl';
251
+ $this->cryptParams['padding'] = OPENSSL_PKCS1_OAEP_PADDING;
252
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
253
+ $this->cryptParams['hash'] = NULL;
254
+ if (is_array($params) && ! empty($params['type'])) {
255
+ if ($params['type'] == 'public' || $params['type'] == 'private') {
256
+ $this->cryptParams['type'] = $params['type'];
257
+ break;
258
+ }
259
+ }
260
+ throw new Exception('Certificate "type" (private/public) must be passed via parameters');
261
+ return;
262
+ case (XMLSecurityKey::RSA_SHA1):
263
+ $this->cryptParams['library'] = 'openssl';
264
+ $this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
265
+ $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
266
+ if (is_array($params) && ! empty($params['type'])) {
267
+ if ($params['type'] == 'public' || $params['type'] == 'private') {
268
+ $this->cryptParams['type'] = $params['type'];
269
+ break;
270
+ }
271
+ }
272
+ throw new Exception('Certificate "type" (private/public) must be passed via parameters');
273
+ break;
274
+ case (XMLSecurityKey::RSA_SHA256):
275
+ $this->cryptParams['library'] = 'openssl';
276
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
277
+ $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
278
+ $this->cryptParams['digest'] = 'SHA256';
279
+ if (is_array($params) && ! empty($params['type'])) {
280
+ if ($params['type'] == 'public' || $params['type'] == 'private') {
281
+ $this->cryptParams['type'] = $params['type'];
282
+ break;
283
+ }
284
+ }
285
+ throw new Exception('Certificate "type" (private/public) must be passed via parameters');
286
+ break;
287
+ case (XMLSecurityKey::RSA_SHA384):
288
+ $this->cryptParams['library'] = 'openssl';
289
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384';
290
+ $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
291
+ $this->cryptParams['digest'] = 'SHA384';
292
+ if (is_array($params) && ! empty($params['type'])) {
293
+ if ($params['type'] == 'public' || $params['type'] == 'private') {
294
+ $this->cryptParams['type'] = $params['type'];
295
+ break;
296
+ }
297
+ }
298
+ case (XMLSecurityKey::RSA_SHA512):
299
+ $this->cryptParams['library'] = 'openssl';
300
+ $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512';
301
+ $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING;
302
+ $this->cryptParams['digest'] = 'SHA512';
303
+ if (is_array($params) && ! empty($params['type'])) {
304
+ if ($params['type'] == 'public' || $params['type'] == 'private') {
305
+ $this->cryptParams['type'] = $params['type'];
306
+ break;
307
+ }
308
+ }
309
+ default:
310
+ throw new Exception('Invalid Key Type');
311
+ return;
312
+ }
313
+ $this->type = $type;
314
+ }
315
+
316
+ /**
317
+ * Retrieve the key size for the symmetric encryption algorithm..
318
+ *
319
+ * If the key size is unknown, or this isn't a symmetric encryption algorithm,
320
+ * NULL is returned.
321
+ *
322
+ * @return int|NULL The number of bytes in the key.
323
+ */
324
+ public function getSymmetricKeySize() {
325
+ if (! isset($this->cryptParams['keysize'])) {
326
+ return NULL;
327
+ }
328
+ return $this->cryptParams['keysize'];
329
+ }
330
+
331
+ public function generateSessionKey() {
332
+ if (!isset($this->cryptParams['keysize'])) {
333
+ throw new Exception('Unknown key size for type "' . $this->type . '".');
334
+ }
335
+ $keysize = $this->cryptParams['keysize'];
336
+
337
+ if (function_exists('openssl_random_pseudo_bytes')) {
338
+ /* We have PHP >= 5.3 - use openssl to generate session key. */
339
+ $key = openssl_random_pseudo_bytes($keysize);
340
+ } else {
341
+ /* Generating random key using iv generation routines */
342
+ $key = mcrypt_create_iv($keysize, MCRYPT_RAND);
343
+ }
344
+
345
+ if ($this->type === XMLSecurityKey::TRIPLEDES_CBC) {
346
+ /* Make sure that the generated key has the proper parity bits set.
347
+ * Mcrypt doesn't care about the parity bits, but others may care.
348
+ */
349
+ for ($i = 0; $i < strlen($key); $i++) {
350
+ $byte = ord($key[$i]) & 0xfe;
351
+ $parity = 1;
352
+ for ($j = 1; $j < 8; $j++) {
353
+ $parity ^= ($byte >> $j) & 1;
354
+ }
355
+ $byte |= $parity;
356
+ $key[$i] = chr($byte);
357
+ }
358
+ }
359
+
360
+ $this->key = $key;
361
+ return $key;
362
+ }
363
+
364
+ public static function getRawThumbprint($cert) {
365
+
366
+ $arCert = explode("\n", $cert);
367
+ $data = '';
368
+ $inData = FALSE;
369
+
370
+ foreach ($arCert AS $curData) {
371
+ if (! $inData) {
372
+ if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
373
+ $inData = TRUE;
374
+ }
375
+ } else {
376
+ if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
377
+ $inData = FALSE;
378
+ break;
379
+ }
380
+ $data .= trim($curData);
381
+ }
382
+ }
383
+
384
+ if (! empty($data)) {
385
+ return strtolower(sha1(base64_decode($data)));
386
+ }
387
+
388
+ return NULL;
389
+ }
390
+
391
+ public function loadKey($key, $isFile=FALSE, $isCert = FALSE) {
392
+ if ($isFile) {
393
+ $this->key = file_get_contents($key);
394
+ } else {
395
+ $this->key = $key;
396
+ }
397
+ if ($isCert) {
398
+ $this->key = openssl_x509_read($this->key);
399
+ openssl_x509_export($this->key, $str_cert);
400
+ $this->x509Certificate = $str_cert;
401
+ $this->key = $str_cert;
402
+ } else {
403
+ $this->x509Certificate = NULL;
404
+ }
405
+ if ($this->cryptParams['library'] == 'openssl') {
406
+ if ($this->cryptParams['type'] == 'public') {
407
+ if ($isCert) {
408
+ /* Load the thumbprint if this is an X509 certificate. */
409
+ $this->X509Thumbprint = self::getRawThumbprint($this->key);
410
+ }
411
+ $this->key = openssl_get_publickey($this->key);
412
+ } else {
413
+ $this->key = openssl_get_privatekey($this->key, $this->passphrase);
414
+ }
415
+ } else if ($this->cryptParams['cipher'] == MCRYPT_RIJNDAEL_128) {
416
+ /* Check key length */
417
+ switch ($this->type) {
418
+ case (XMLSecurityKey::AES256_CBC):
419
+ if (strlen($this->key) < 25) {
420
+ throw new Exception('Key must contain at least 25 characters for this cipher');
421
+ }
422
+ break;
423
+ case (XMLSecurityKey::AES192_CBC):
424
+ if (strlen($this->key) < 17) {
425
+ throw new Exception('Key must contain at least 17 characters for this cipher');
426
+ }
427
+ break;
428
+ }
429
+ }
430
+ }
431
+
432
+ private function encryptMcrypt($data) {
433
+ $td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
434
+ $this->iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
435
+ mcrypt_generic_init($td, $this->key, $this->iv);
436
+ if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
437
+ $bs = mcrypt_enc_get_block_size($td);
438
+ for ($datalen0=$datalen=strlen($data); (($datalen%$bs)!=($bs-1)); $datalen++)
439
+ $data.=chr(rand(1, 127));
440
+ $data.=chr($datalen-$datalen0+1);
441
+ }
442
+ $encrypted_data = $this->iv.mcrypt_generic($td, $data);
443
+ mcrypt_generic_deinit($td);
444
+ mcrypt_module_close($td);
445
+ return $encrypted_data;
446
+ }
447
+
448
+ private function decryptMcrypt($data) {
449
+ $td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], '');
450
+ $iv_length = mcrypt_enc_get_iv_size($td);
451
+
452
+ $this->iv = substr($data, 0, $iv_length);
453
+ $data = substr($data, $iv_length);
454
+
455
+ mcrypt_generic_init($td, $this->key, $this->iv);
456
+ $decrypted_data = mdecrypt_generic($td, $data);
457
+ mcrypt_generic_deinit($td);
458
+ mcrypt_module_close($td);
459
+ if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) {
460
+ $dataLen = strlen($decrypted_data);
461
+ $paddingLength = substr($decrypted_data, $dataLen - 1, 1);
462
+ $decrypted_data = substr($decrypted_data, 0, $dataLen - ord($paddingLength));
463
+ }
464
+ return $decrypted_data;
465
+ }
466
+
467
+ private function encryptOpenSSL($data) {
468
+ if ($this->cryptParams['type'] == 'public') {
469
+ if (! openssl_public_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
470
+ throw new Exception('Failure encrypting Data');
471
+ return;
472
+ }
473
+ } else {
474
+ if (! openssl_private_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) {
475
+ throw new Exception('Failure encrypting Data');
476
+ return;
477
+ }
478
+ }
479
+ return $encrypted_data;
480
+ }
481
+
482
+ private function decryptOpenSSL($data) {
483
+ if ($this->cryptParams['type'] == 'public') {
484
+ if (! openssl_public_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
485
+ throw new Exception('Failure decrypting Data');
486
+ return;
487
+ }
488
+ } else {
489
+ if (! openssl_private_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) {
490
+ throw new Exception('Failure decrypting Data');
491
+ return;
492
+ }
493
+ }
494
+ return $decrypted;
495
+ }
496
+
497
+ private function signOpenSSL($data) {
498
+ $algo = OPENSSL_ALGO_SHA1;
499
+ if (! empty($this->cryptParams['digest'])) {
500
+ $algo = $this->cryptParams['digest'];
501
+ }
502
+ if (! openssl_sign ($data, $signature, $this->key, $algo)) {
503
+ throw new Exception('Failure Signing Data: ' . openssl_error_string() . ' - ' . $algo);
504
+ return;
505
+ }
506
+ return $signature;
507
+ }
508
+
509
+ private function verifyOpenSSL($data, $signature) {
510
+ $algo = OPENSSL_ALGO_SHA1;
511
+ if (! empty($this->cryptParams['digest'])) {
512
+ $algo = $this->cryptParams['digest'];
513
+ }
514
+ return openssl_verify ($data, $signature, $this->key, $algo);
515
+ }
516
+
517
+ public function encryptData($data) {
518
+ switch ($this->cryptParams['library']) {
519
+ case 'mcrypt':
520
+ return $this->encryptMcrypt($data);
521
+ break;
522
+ case 'openssl':
523
+ return $this->encryptOpenSSL($data);
524
+ break;
525
+ }
526
+ }
527
+
528
+ public function decryptData($data) {
529
+ switch ($this->cryptParams['library']) {
530
+ case 'mcrypt':
531
+ return $this->decryptMcrypt($data);
532
+ break;
533
+ case 'openssl':
534
+ return $this->decryptOpenSSL($data);
535
+ break;
536
+ }
537
+ }
538
+
539
+ public function signData($data) {
540
+ switch ($this->cryptParams['library']) {
541
+ case 'openssl':
542
+ return $this->signOpenSSL($data);
543
+ break;
544
+ }
545
+ }
546
+
547
+ public function verifySignature($data, $signature) {
548
+ switch ($this->cryptParams['library']) {
549
+ case 'openssl':
550
+ return $this->verifyOpenSSL($data, $signature);
551
+ break;
552
+ }
553
+ }
554
+
555
+ public function getAlgorith() {
556
+ return $this->cryptParams['method'];
557
+ }
558
+
559
+ static function makeAsnSegment($type, $string) {
560
+ switch ($type){
561
+ case 0x02:
562
+ if (ord($string) > 0x7f)
563
+ $string = chr(0).$string;
564
+ break;
565
+ case 0x03:
566
+ $string = chr(0).$string;
567
+ break;
568
+ }
569
+
570
+ $length = strlen($string);
571
+
572
+ if ($length < 128){
573
+ $output = sprintf("%c%c%s", $type, $length, $string);
574
+ } else if ($length < 0x0100){
575
+ $output = sprintf("%c%c%c%s", $type, 0x81, $length, $string);
576
+ } else if ($length < 0x010000) {
577
+ $output = sprintf("%c%c%c%c%s", $type, 0x82, $length/0x0100, $length%0x0100, $string);
578
+ } else {
579
+ $output = NULL;
580
+ }
581
+ return($output);
582
+ }
583
+
584
+ /* Modulus and Exponent must already be base64 decoded */
585
+ static function convertRSA($modulus, $exponent) {
586
+ /* make an ASN publicKeyInfo */
587
+ $exponentEncoding = XMLSecurityKey::makeAsnSegment(0x02, $exponent);
588
+ $modulusEncoding = XMLSecurityKey::makeAsnSegment(0x02, $modulus);
589
+ $sequenceEncoding = XMLSecurityKey:: makeAsnSegment(0x30, $modulusEncoding.$exponentEncoding);
590
+ $bitstringEncoding = XMLSecurityKey::makeAsnSegment(0x03, $sequenceEncoding);
591
+ $rsaAlgorithmIdentifier = pack("H*", "300D06092A864886F70D0101010500");
592
+ $publicKeyInfo = XMLSecurityKey::makeAsnSegment (0x30, $rsaAlgorithmIdentifier.$bitstringEncoding);
593
+
594
+ /* encode the publicKeyInfo in base64 and add PEM brackets */
595
+ $publicKeyInfoBase64 = base64_encode($publicKeyInfo);
596
+ $encoding = "-----BEGIN PUBLIC KEY-----\n";
597
+ $offset = 0;
598
+ while ($segment=substr($publicKeyInfoBase64, $offset, 64)){
599
+ $encoding = $encoding.$segment."\n";
600
+ $offset += 64;
601
+ }
602
+ return $encoding."-----END PUBLIC KEY-----\n";
603
+ }
604
+
605
+ public function serializeKey($parent) {
606
+
607
+ }
608
+
609
+
610
+
611
+ /**
612
+ * Retrieve the X509 certificate this key represents.
613
+ *
614
+ * Will return the X509 certificate in PEM-format if this key represents
615
+ * an X509 certificate.
616
+ *
617
+ * @return The X509 certificate or NULL if this key doesn't represent an X509-certificate.
618
+ */
619
+ public function getX509Certificate() {
620
+ return $this->x509Certificate;
621
+ }
622
+
623
+ /* Get the thumbprint of this X509 certificate.
624
+ *
625
+ * Returns:
626
+ * The thumbprint as a lowercase 40-character hexadecimal number, or NULL
627
+ * if this isn't a X509 certificate.
628
+ */
629
+ public function getX509Thumbprint() {
630
+ return $this->X509Thumbprint;
631
+ }
632
+
633
+
634
+ /**
635
+ * Create key from an EncryptedKey-element.
636
+ *
637
+ * @param DOMElement $element The EncryptedKey-element.
638
+ * @return XMLSecurityKey The new key.
639
+ */
640
+ public static function fromEncryptedKeyElement(DOMElement $element) {
641
+
642
+ $objenc = new XMLSecEnc();
643
+ $objenc->setNode($element);
644
+ if (! $objKey = $objenc->locateKey()) {
645
+ throw new Exception("Unable to locate algorithm for this Encrypted Key");
646
+ }
647
+ $objKey->isEncrypted = TRUE;
648
+ $objKey->encryptedCtx = $objenc;
649
+ XMLSecEnc::staticLocateKeyInfo($objKey, $element);
650
+ return $objKey;
651
+ }
652
+
653
+ }
654
+
655
+ class XMLSecurityDSig {
656
+ const XMLDSIGNS = 'http://www.w3.org/2000/09/xmldsig#';
657
+ const SHA1 = 'http://www.w3.org/2000/09/xmldsig#sha1';
658
+ const SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256';
659
+ const SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#sha384';
660
+ const SHA512 = 'http://www.w3.org/2001/04/xmlenc#sha512';
661
+ const RIPEMD160 = 'http://www.w3.org/2001/04/xmlenc#ripemd160';
662
+
663
+ const C14N = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
664
+ const C14N_COMMENTS = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments';
665
+ const EXC_C14N = 'http://www.w3.org/2001/10/xml-exc-c14n#';
666
+ const EXC_C14N_COMMENTS = 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments';
667
+
668
+ const template = '<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
669
+ <SignedInfo>
670
+ <SignatureMethod />
671
+ </SignedInfo>
672
+ </Signature>';
673
+
674
+ public $sigNode = NULL;
675
+ public $idKeys = array();
676
+ public $idNS = array();
677
+ private $signedInfo = NULL;
678
+ private $xPathCtx = NULL;
679
+ private $canonicalMethod = NULL;
680
+ private $prefix = NULL;
681
+ private $searchpfx = 'secdsig';
682
+
683
+ /* This variable contains an associative array of validated nodes. */
684
+ private $validatedNodes = NULL;
685
+
686
+ public function __construct() {
687
+ $sigdoc = new DOMDocument();
688
+ $sigdoc->loadXML(XMLSecurityDSig::template);
689
+ $this->sigNode = $sigdoc->documentElement;
690
+ }
691
+
692
+ private function resetXPathObj() {
693
+ $this->xPathCtx = NULL;
694
+ }
695
+
696
+ private function getXPathObj() {
697
+ if (empty($this->xPathCtx) && ! empty($this->sigNode)) {
698
+ $xpath = new DOMXPath($this->sigNode->ownerDocument);
699
+ $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
700
+ $this->xPathCtx = $xpath;
701
+ }
702
+ return $this->xPathCtx;
703
+ }
704
+
705
+ static function generate_GUID($prefix='pfx') {
706
+ $uuid = md5(uniqid(rand(), true));
707
+ $guid = $prefix.substr($uuid,0,8)."-".
708
+ substr($uuid,8,4)."-".
709
+ substr($uuid,12,4)."-".
710
+ substr($uuid,16,4)."-".
711
+ substr($uuid,20,12);
712
+ return $guid;
713
+ }
714
+
715
+ public function signaturesCount($objDoc) {
716
+ if ($objDoc instanceof DOMDocument) {
717
+ $xpath = new DOMXPath($objDoc);
718
+ $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
719
+ $query = ".//secdsig:Signature";
720
+ $nodeset = $xpath->query($query, $objDoc);
721
+ return $nodeset->length;
722
+ }
723
+ return NULL;
724
+ }
725
+
726
+ public function locateSignature($objDoc) {
727
+ if ($objDoc instanceof DOMDocument) {
728
+ $doc = $objDoc;
729
+ } else {
730
+ $doc = $objDoc->ownerDocument;
731
+ }
732
+ if ($doc) {
733
+ $xpath = new DOMXPath($doc);
734
+ $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
735
+ $query = ".//secdsig:Signature";
736
+ $nodeset = $xpath->query($query, $objDoc);
737
+ $count = $nodeset->length;
738
+ $this->sigNode = $nodeset->item($count - 1);
739
+ return $this->sigNode;
740
+ }
741
+ return NULL;
742
+ }
743
+
744
+ public function createNewSignNode($name, $value=NULL) {
745
+ $doc = $this->sigNode->ownerDocument;
746
+ if ($this->prefix != null) {
747
+ $name = $this->prefix . ':' . $name;
748
+ }
749
+ if (!is_null($value)) {
750
+ $node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $name, $value);
751
+ } else {
752
+ $node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $name);
753
+ }
754
+ return $node;
755
+ }
756
+
757
+ public function setCanonicalMethod($method) {
758
+ switch ($method) {
759
+ case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
760
+ case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
761
+ case 'http://www.w3.org/2001/10/xml-exc-c14n#':
762
+ case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
763
+ $this->canonicalMethod = $method;
764
+ break;
765
+ default:
766
+ throw new Exception('Invalid Canonical Method');
767
+ }
768
+ if ($xpath = $this->getXPathObj()) {
769
+ $query = './'.$this->searchpfx.':SignedInfo';
770
+ $nodeset = $xpath->query($query, $this->sigNode);
771
+ if ($sinfo = $nodeset->item(0)) {
772
+ $query = './'.$this->searchpfx.'CanonicalizationMethod';
773
+ $nodeset = $xpath->query($query, $sinfo);
774
+ if (! ($canonNode = $nodeset->item(0))) {
775
+ $canonNode = $this->createNewSignNode('CanonicalizationMethod');
776
+ $sinfo->insertBefore($canonNode, $sinfo->firstChild);
777
+ }
778
+ $canonNode->setAttribute('Algorithm', $this->canonicalMethod);
779
+ }
780
+ }
781
+ }
782
+
783
+ private function canonicalizeData($node, $canonicalmethod, $arXPath=NULL, $prefixList=NULL) {
784
+ $exclusive = FALSE;
785
+ $withComments = FALSE;
786
+ switch ($canonicalmethod) {
787
+ case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
788
+ $exclusive = FALSE;
789
+ $withComments = FALSE;
790
+ break;
791
+ case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
792
+ $withComments = TRUE;
793
+ break;
794
+ case 'http://www.w3.org/2001/10/xml-exc-c14n#':
795
+ $exclusive = TRUE;
796
+ break;
797
+ case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
798
+ $exclusive = TRUE;
799
+ $withComments = TRUE;
800
+ break;
801
+ }
802
+ /* Support PHP versions < 5.2 not containing C14N methods in DOM extension */
803
+ $php_version = explode('.', PHP_VERSION);
804
+ if (($php_version[0] < 5) || ($php_version[0] == 5 && $php_version[1] < 2) ) {
805
+ if (! is_null($arXPath)) {
806
+ throw new Exception("PHP 5.2.0 or higher is required to perform XPath Transformations");
807
+ }
808
+ return C14NGeneral($node, $exclusive, $withComments);
809
+ }
810
+ return $node->C14N($exclusive, $withComments, $arXPath, $prefixList);
811
+ }
812
+
813
+ public function canonicalizeSignedInfo() {
814
+
815
+ $doc = $this->sigNode->ownerDocument;
816
+ $canonicalmethod = NULL;
817
+ if ($doc) {
818
+ $xpath = $this->getXPathObj();
819
+ $query = "./secdsig:SignedInfo";
820
+ $nodeset = $xpath->query($query, $this->sigNode);
821
+ if ($signInfoNode = $nodeset->item(0)) {
822
+ $query = "./secdsig:CanonicalizationMethod";
823
+ $nodeset = $xpath->query($query, $signInfoNode);
824
+ if ($canonNode = $nodeset->item(0)) {
825
+ $canonicalmethod = $canonNode->getAttribute('Algorithm');
826
+ }
827
+ $this->signedInfo = $this->canonicalizeData($signInfoNode, $canonicalmethod);
828
+ return $this->signedInfo;
829
+ }
830
+ }
831
+ return NULL;
832
+ }
833
+
834
+ public function calculateDigest ($digestAlgorithm, $data) {
835
+ switch ($digestAlgorithm) {
836
+ case XMLSecurityDSig::SHA1:
837
+ $alg = 'sha1';
838
+ break;
839
+ case XMLSecurityDSig::SHA256:
840
+ $alg = 'sha256';
841
+ break;
842
+ case XMLSecurityDSig::SHA384:
843
+ $alg = 'sha384';
844
+ break;
845
+ case XMLSecurityDSig::SHA512:
846
+ $alg = 'sha512';
847
+ break;
848
+ case XMLSecurityDSig::RIPEMD160:
849
+ $alg = 'ripemd160';
850
+ break;
851
+ default:
852
+ throw new Exception("Cannot validate digest: Unsupported Algorith <$digestAlgorithm>");
853
+ }
854
+ if (function_exists('hash')) {
855
+ return base64_encode(hash($alg, $data, TRUE));
856
+ } elseif (function_exists('mhash')) {
857
+ $alg = "MHASH_" . strtoupper($alg);
858
+ return base64_encode(mhash(constant($alg), $data));
859
+ } elseif ($alg === 'sha1') {
860
+ return base64_encode(sha1($data, TRUE));
861
+ } else {
862
+ throw new Exception('xmlseclibs is unable to calculate a digest. Maybe you need the mhash library?');
863
+ }
864
+ }
865
+
866
+ public function validateDigest($refNode, $data) {
867
+ $xpath = new DOMXPath($refNode->ownerDocument);
868
+ $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
869
+ $query = 'string(./secdsig:DigestMethod/@Algorithm)';
870
+ $digestAlgorithm = $xpath->evaluate($query, $refNode);
871
+ $digValue = $this->calculateDigest($digestAlgorithm, $data);
872
+ $query = 'string(./secdsig:DigestValue)';
873
+ $digestValue = $xpath->evaluate($query, $refNode);
874
+ return ($digValue == $digestValue);
875
+ }
876
+
877
+ public function processTransforms($refNode, $objData, $includeCommentNodes = TRUE) {
878
+ $data = $objData;
879
+ $xpath = new DOMXPath($refNode->ownerDocument);
880
+ $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
881
+ $query = './secdsig:Transforms/secdsig:Transform';
882
+ $nodelist = $xpath->query($query, $refNode);
883
+ $canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
884
+ $arXPath = NULL;
885
+ $prefixList = NULL;
886
+ foreach ($nodelist AS $transform) {
887
+ $algorithm = $transform->getAttribute("Algorithm");
888
+ switch ($algorithm) {
889
+ case 'http://www.w3.org/2001/10/xml-exc-c14n#':
890
+ case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments':
891
+
892
+ if(!$includeCommentNodes) {
893
+ /* We remove comment nodes by forcing it to use a canonicalization
894
+ * without comments.
895
+ */
896
+ $canonicalMethod = 'http://www.w3.org/2001/10/xml-exc-c14n#';
897
+ } else {
898
+ $canonicalMethod = $algorithm;
899
+ }
900
+
901
+ $node = $transform->firstChild;
902
+ while ($node) {
903
+ if ($node->localName == 'InclusiveNamespaces') {
904
+ if ($pfx = $node->getAttribute('PrefixList')) {
905
+ $arpfx = array();
906
+ $pfxlist = explode(" ", $pfx);
907
+ foreach ($pfxlist AS $pfx) {
908
+ $val = trim($pfx);
909
+ if (! empty($val)) {
910
+ $arpfx[] = $val;
911
+ }
912
+ }
913
+ if (count($arpfx) > 0) {
914
+ $prefixList = $arpfx;
915
+ }
916
+ }
917
+ break;
918
+ }
919
+ $node = $node->nextSibling;
920
+ }
921
+ break;
922
+ case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315':
923
+ case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments':
924
+ if(!$includeCommentNodes) {
925
+ /* We remove comment nodes by forcing it to use a canonicalization
926
+ * without comments.
927
+ */
928
+ $canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315';
929
+ } else {
930
+ $canonicalMethod = $algorithm;
931
+ }
932
+
933
+ break;
934
+ case 'http://www.w3.org/TR/1999/REC-xpath-19991116':
935
+ $node = $transform->firstChild;
936
+ while ($node) {
937
+ if ($node->localName == 'XPath') {
938
+ $arXPath = array();
939
+ $arXPath['query'] = '(.//. | .//@* | .//namespace::*)['.$node->nodeValue.']';
940
+ $arXpath['namespaces'] = array();
941
+ $nslist = $xpath->query('./namespace::*', $node);
942
+ foreach ($nslist AS $nsnode) {
943
+ if ($nsnode->localName != "xml") {
944
+ $arXPath['namespaces'][$nsnode->localName] = $nsnode->nodeValue;
945
+ }
946
+ }
947
+ break;
948
+ }
949
+ $node = $node->nextSibling;
950
+ }
951
+ break;
952
+ }
953
+ }
954
+ if ($data instanceof DOMNode) {
955
+ $data = $this->canonicalizeData($objData, $canonicalMethod, $arXPath, $prefixList);
956
+ }
957
+ return $data;
958
+ }
959
+
960
+ public function processRefNode($refNode) {
961
+ $dataObject = NULL;
962
+
963
+ /*
964
+ * Depending on the URI, we may not want to include comments in the result
965
+ * See: http://www.w3.org/TR/xmldsig-core/#sec-ReferenceProcessingModel
966
+ */
967
+ $includeCommentNodes = TRUE;
968
+
969
+ if ($uri = $refNode->getAttribute("URI")) {
970
+ $arUrl = parse_url($uri);
971
+ if (empty($arUrl['path'])) {
972
+ if ($identifier = $arUrl['fragment']) {
973
+
974
+ /* This reference identifies a node with the given id by using
975
+ * a URI on the form "#identifier". This should not include comments.
976
+ */
977
+ $includeCommentNodes = FALSE;
978
+
979
+ $xPath = new DOMXPath($refNode->ownerDocument);
980
+ if ($this->idNS && is_array($this->idNS)) {
981
+ foreach ($this->idNS AS $nspf=>$ns) {
982
+ $xPath->registerNamespace($nspf, $ns);
983
+ }
984
+ }
985
+ $iDlist = '@Id="'.$identifier.'"';
986
+ if (is_array($this->idKeys)) {
987
+ foreach ($this->idKeys AS $idKey) {
988
+ $iDlist .= " or @$idKey='$identifier'";
989
+ }
990
+ }
991
+ $query = '//*['.$iDlist.']';
992
+ $dataObject = $xPath->query($query)->item(0);
993
+ } else {
994
+ $dataObject = $refNode->ownerDocument;
995
+ }
996
+ } else {
997
+ $dataObject = file_get_contents($arUrl);
998
+ }
999
+ } else {
1000
+ /* This reference identifies the root node with an empty URI. This should
1001
+ * not include comments.
1002
+ */
1003
+ $includeCommentNodes = FALSE;
1004
+
1005
+ $dataObject = $refNode->ownerDocument;
1006
+ }
1007
+ $data = $this->processTransforms($refNode, $dataObject, $includeCommentNodes);
1008
+ if (!$this->validateDigest($refNode, $data)) {
1009
+ return FALSE;
1010
+ }
1011
+
1012
+ if ($dataObject instanceof DOMNode) {
1013
+ /* Add this node to the list of validated nodes. */
1014
+ if(! empty($identifier)) {
1015
+ $this->validatedNodes[$identifier] = $dataObject;
1016
+ } else {
1017
+ $this->validatedNodes[] = $dataObject;
1018
+ }
1019
+ }
1020
+
1021
+ return TRUE;
1022
+ }
1023
+
1024
+ public function getRefNodeID($refNode) {
1025
+ if ($uri = $refNode->getAttribute("URI")) {
1026
+ $arUrl = parse_url($uri);
1027
+ if (empty($arUrl['path'])) {
1028
+ if ($identifier = $arUrl['fragment']) {
1029
+ return $identifier;
1030
+ }
1031
+ }
1032
+ }
1033
+ return null;
1034
+ }
1035
+
1036
+ public function getRefIDs() {
1037
+ $refids = array();
1038
+ $doc = $this->sigNode->ownerDocument;
1039
+
1040
+ $xpath = $this->getXPathObj();
1041
+ $query = "./secdsig:SignedInfo/secdsig:Reference";
1042
+ $nodeset = $xpath->query($query, $this->sigNode);
1043
+ if ($nodeset->length == 0) {
1044
+ throw new Exception("Reference nodes not found");
1045
+ }
1046
+ foreach ($nodeset AS $refNode) {
1047
+ $refids[] = $this->getRefNodeID($refNode);
1048
+ }
1049
+ return $refids;
1050
+ }
1051
+
1052
+ public function validateReference() {
1053
+ $doc = $this->sigNode->ownerDocument;
1054
+ if (! $doc->isSameNode($this->sigNode)) {
1055
+ $this->sigNode->parentNode->removeChild($this->sigNode);
1056
+ }
1057
+ $xpath = $this->getXPathObj();
1058
+ $query = "./secdsig:SignedInfo/secdsig:Reference";
1059
+ $nodeset = $xpath->query($query, $this->sigNode);
1060
+ if ($nodeset->length == 0) {
1061
+ throw new Exception("Reference nodes not found");
1062
+ }
1063
+
1064
+ /* Initialize/reset the list of validated nodes. */
1065
+ $this->validatedNodes = array();
1066
+
1067
+ foreach ($nodeset AS $refNode) {
1068
+ if (! $this->processRefNode($refNode)) {
1069
+ /* Clear the list of validated nodes. */
1070
+ $this->validatedNodes = NULL;
1071
+ throw new Exception("Reference validation failed");
1072
+ }
1073
+ }
1074
+ return TRUE;
1075
+ }
1076
+
1077
+ private function addRefInternal($sinfoNode, $node, $algorithm, $arTransforms=NULL, $options=NULL) {
1078
+ $prefix = NULL;
1079
+ $prefix_ns = NULL;
1080
+ $id_name = 'Id';
1081
+ $overwrite_id = TRUE;
1082
+ $force_uri = FALSE;
1083
+
1084
+ if (is_array($options)) {
1085
+ $prefix = empty($options['prefix'])?NULL:$options['prefix'];
1086
+ $prefix_ns = empty($options['prefix_ns'])?NULL:$options['prefix_ns'];
1087
+ $id_name = empty($options['id_name'])?'Id':$options['id_name'];
1088
+ $overwrite_id = !isset($options['overwrite'])?TRUE:(bool)$options['overwrite'];
1089
+ $force_uri = !isset($options['force_uri'])?FALSE:(bool)$options['force_uri'];
1090
+ }
1091
+
1092
+ $attname = $id_name;
1093
+ if (! empty($prefix)) {
1094
+ $attname = $prefix.':'.$attname;
1095
+ }
1096
+
1097
+ $refNode = $this->createNewSignNode('Reference');
1098
+ $sinfoNode->appendChild($refNode);
1099
+
1100
+ if (! $node instanceof DOMDocument) {
1101
+ $uri = NULL;
1102
+ if (! $overwrite_id) {
1103
+ $uri = $node->getAttributeNS($prefix_ns, $id_name);
1104
+ }
1105
+ if (empty($uri)) {
1106
+ $uri = XMLSecurityDSig::generate_GUID();
1107
+ $node->setAttributeNS($prefix_ns, $attname, $uri);
1108
+ }
1109
+ $refNode->setAttribute("URI", '#'.$uri);
1110
+ } elseif ($force_uri) {
1111
+ $refNode->setAttribute("URI", '');
1112
+ }
1113
+
1114
+ $transNodes = $this->createNewSignNode('Transforms');
1115
+ $refNode->appendChild($transNodes);
1116
+
1117
+ if (is_array($arTransforms)) {
1118
+ foreach ($arTransforms AS $transform) {
1119
+ $transNode = $this->createNewSignNode('Transform');
1120
+ $transNodes->appendChild($transNode);
1121
+ if (is_array($transform) &&
1122
+ (! empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116'])) &&
1123
+ (! empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']))) {
1124
+ $transNode->setAttribute('Algorithm', 'http://www.w3.org/TR/1999/REC-xpath-19991116');
1125
+ $XPathNode = $this->createNewSignNode('XPath', $transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']);
1126
+ $transNode->appendChild($XPathNode);
1127
+ if (! empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'])) {
1128
+ foreach ($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'] AS $prefix => $namespace) {
1129
+ $XPathNode->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:$prefix", $namespace);
1130
+ }
1131
+ }
1132
+ } else {
1133
+ $transNode->setAttribute('Algorithm', $transform);
1134
+ }
1135
+ }
1136
+ } elseif (! empty($this->canonicalMethod)) {
1137
+ $transNode = $this->createNewSignNode('Transform');
1138
+ $transNodes->appendChild($transNode);
1139
+ $transNode->setAttribute('Algorithm', $this->canonicalMethod);
1140
+ }
1141
+
1142
+ $canonicalData = $this->processTransforms($refNode, $node);
1143
+ $digValue = $this->calculateDigest($algorithm, $canonicalData);
1144
+
1145
+ $digestMethod = $this->createNewSignNode('DigestMethod');
1146
+ $refNode->appendChild($digestMethod);
1147
+ $digestMethod->setAttribute('Algorithm', $algorithm);
1148
+
1149
+ $digestValue = $this->createNewSignNode('DigestValue', $digValue);
1150
+ $refNode->appendChild($digestValue);
1151
+ }
1152
+
1153
+ public function addReference($node, $algorithm, $arTransforms=NULL, $options=NULL) {
1154
+ if ($xpath = $this->getXPathObj()) {
1155
+ $query = "./secdsig:SignedInfo";
1156
+ $nodeset = $xpath->query($query, $this->sigNode);
1157
+ if ($sInfo = $nodeset->item(0)) {
1158
+ $this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
1159
+ }
1160
+ }
1161
+ }
1162
+
1163
+ public function addReferenceList($arNodes, $algorithm, $arTransforms=NULL, $options=NULL) {
1164
+ if ($xpath = $this->getXPathObj()) {
1165
+ $query = "./secdsig:SignedInfo";
1166
+ $nodeset = $xpath->query($query, $this->sigNode);
1167
+ if ($sInfo = $nodeset->item(0)) {
1168
+ foreach ($arNodes AS $node) {
1169
+ $this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options);
1170
+ }
1171
+ }
1172
+ }
1173
+ }
1174
+
1175
+ public function addObject($data, $mimetype=NULL, $encoding=NULL) {
1176
+ $objNode = $this->createNewSignNode('Object');
1177
+ $this->sigNode->appendChild($objNode);
1178
+ if (! empty($mimetype)) {
1179
+ $objNode->setAtribute('MimeType', $mimetype);
1180
+ }
1181
+ if (! empty($encoding)) {
1182
+ $objNode->setAttribute('Encoding', $encoding);
1183
+ }
1184
+
1185
+ if ($data instanceof DOMElement) {
1186
+ $newData = $this->sigNode->ownerDocument->importNode($data, TRUE);
1187
+ } else {
1188
+ $newData = $this->sigNode->ownerDocument->createTextNode($data);
1189
+ }
1190
+ $objNode->appendChild($newData);
1191
+
1192
+ return $objNode;
1193
+ }
1194
+
1195
+ public function locateKey($node=NULL) {
1196
+ if (empty($node)) {
1197
+ $node = $this->sigNode;
1198
+ }
1199
+ if (! $node instanceof DOMNode) {
1200
+ return NULL;
1201
+ }
1202
+ if ($doc = $node->ownerDocument) {
1203
+ $xpath = new DOMXPath($doc);
1204
+ $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1205
+ $query = "string(./secdsig:SignedInfo/secdsig:SignatureMethod/@Algorithm)";
1206
+ $algorithm = $xpath->evaluate($query, $node);
1207
+ if ($algorithm) {
1208
+ try {
1209
+ $objKey = new XMLSecurityKey($algorithm, array('type'=>'public'));
1210
+ } catch (Exception $e) {
1211
+ return NULL;
1212
+ }
1213
+ return $objKey;
1214
+ }
1215
+ }
1216
+ return NULL;
1217
+ }
1218
+
1219
+ public function verify($objKey) {
1220
+ $doc = $this->sigNode->ownerDocument;
1221
+ $xpath = new DOMXPath($doc);
1222
+ $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1223
+ $query = "string(./secdsig:SignatureValue)";
1224
+ $sigValue = $xpath->evaluate($query, $this->sigNode);
1225
+ if (empty($sigValue)) {
1226
+ throw new Exception("Unable to locate SignatureValue");
1227
+ }
1228
+ return $objKey->verifySignature($this->signedInfo, base64_decode($sigValue));
1229
+ }
1230
+
1231
+ public function signData($objKey, $data) {
1232
+ return $objKey->signData($data);
1233
+ }
1234
+
1235
+ public function sign($objKey, $appendToNode = NULL) {
1236
+ // If we have a parent node append it now so C14N properly works
1237
+ if ($appendToNode != NULL) {
1238
+ $this->resetXPathObj();
1239
+ $this->appendSignature($appendToNode);
1240
+ $this->sigNode = $appendToNode->lastChild;
1241
+ }
1242
+ if ($xpath = $this->getXPathObj()) {
1243
+ $query = "./secdsig:SignedInfo";
1244
+ $nodeset = $xpath->query($query, $this->sigNode);
1245
+ if ($sInfo = $nodeset->item(0)) {
1246
+ $query = "./secdsig:SignatureMethod";
1247
+ $nodeset = $xpath->query($query, $sInfo);
1248
+ $sMethod = $nodeset->item(0);
1249
+ $sMethod->setAttribute('Algorithm', $objKey->type);
1250
+ $data = $this->canonicalizeData($sInfo, $this->canonicalMethod);
1251
+ $sigValue = base64_encode($this->signData($objKey, $data));
1252
+ $sigValueNode = $this->createNewSignNode('SignatureValue', $sigValue);
1253
+ if ($infoSibling = $sInfo->nextSibling) {
1254
+ $infoSibling->parentNode->insertBefore($sigValueNode, $infoSibling);
1255
+ } else {
1256
+ $this->sigNode->appendChild($sigValueNode);
1257
+ }
1258
+ }
1259
+ }
1260
+ }
1261
+
1262
+ public function appendCert() {
1263
+
1264
+ }
1265
+
1266
+ public function appendKey($objKey, $parent=NULL) {
1267
+ $objKey->serializeKey($parent);
1268
+ }
1269
+
1270
+
1271
+ /**
1272
+ * This function inserts the signature element.
1273
+ *
1274
+ * The signature element will be appended to the element, unless $beforeNode is specified. If $beforeNode
1275
+ * is specified, the signature element will be inserted as the last element before $beforeNode.
1276
+ *
1277
+ * @param $node The node the signature element should be inserted into.
1278
+ * @param $beforeNode The node the signature element should be located before.
1279
+ *
1280
+ * @return DOMNode The signature element node
1281
+ */
1282
+ public function insertSignature($node, $beforeNode = NULL) {
1283
+
1284
+ $document = $node->ownerDocument;
1285
+ $signatureElement = $document->importNode($this->sigNode, TRUE);
1286
+
1287
+ if($beforeNode == NULL) {
1288
+ return $node->insertBefore($signatureElement);
1289
+ } else {
1290
+ return $node->insertBefore($signatureElement, $beforeNode);
1291
+ }
1292
+ }
1293
+
1294
+ public function appendSignature($parentNode, $insertBefore = FALSE) {
1295
+ $beforeNode = $insertBefore ? $parentNode->firstChild : NULL;
1296
+ return $this->insertSignature($parentNode, $beforeNode);
1297
+ }
1298
+
1299
+ static function get509XCert($cert, $isPEMFormat=TRUE) {
1300
+ $certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat);
1301
+ if (! empty($certs)) {
1302
+ return $certs[0];
1303
+ }
1304
+ return '';
1305
+ }
1306
+
1307
+ static function staticGet509XCerts($certs, $isPEMFormat=TRUE) {
1308
+ if ($isPEMFormat) {
1309
+ $data = '';
1310
+ $certlist = array();
1311
+ $arCert = explode("\n", $certs);
1312
+ $inData = FALSE;
1313
+ foreach ($arCert AS $curData) {
1314
+ if (! $inData) {
1315
+ if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) {
1316
+ $inData = TRUE;
1317
+ }
1318
+ } else {
1319
+ if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) {
1320
+ $inData = FALSE;
1321
+ $certlist[] = $data;
1322
+ $data = '';
1323
+ continue;
1324
+ }
1325
+ $data .= trim($curData);
1326
+ }
1327
+ }
1328
+ return $certlist;
1329
+ } else {
1330
+ return array($certs);
1331
+ }
1332
+ }
1333
+
1334
+ static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=TRUE, $isURL=False, $xpath=NULL, $options=NULL) {
1335
+ if ($isURL) {
1336
+ $cert = file_get_contents($cert);
1337
+ }
1338
+ if (! $parentRef instanceof DOMElement) {
1339
+ throw new Exception('Invalid parent Node parameter');
1340
+ }
1341
+ $baseDoc = $parentRef->ownerDocument;
1342
+
1343
+ if (empty($xpath)) {
1344
+ $xpath = new DOMXPath($parentRef->ownerDocument);
1345
+ $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1346
+ }
1347
+
1348
+ $query = "./secdsig:KeyInfo";
1349
+ $nodeset = $xpath->query($query, $parentRef);
1350
+ $keyInfo = $nodeset->item(0);
1351
+ if (! $keyInfo) {
1352
+ $inserted = FALSE;
1353
+ $keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:KeyInfo');
1354
+
1355
+ $query = "./secdsig:Object";
1356
+ $nodeset = $xpath->query($query, $parentRef);
1357
+ if ($sObject = $nodeset->item(0)) {
1358
+ $sObject->parentNode->insertBefore($keyInfo, $sObject);
1359
+ $inserted = TRUE;
1360
+ }
1361
+
1362
+ if (! $inserted) {
1363
+ $parentRef->appendChild($keyInfo);
1364
+ }
1365
+ }
1366
+
1367
+ // Add all certs if there are more than one
1368
+ $certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat);
1369
+
1370
+ // Attach X509 data node
1371
+ $x509DataNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Data');
1372
+ $keyInfo->appendChild($x509DataNode);
1373
+
1374
+ $issuerSerial = FALSE;
1375
+ $subjectName = FALSE;
1376
+ if (is_array($options)) {
1377
+ if (! empty($options['issuerSerial'])) {
1378
+ $issuerSerial = TRUE;
1379
+ }
1380
+ }
1381
+
1382
+ // Attach all certificate nodes and any additional data
1383
+ foreach ($certs as $X509Cert){
1384
+ if ($issuerSerial) {
1385
+ if ($certData = openssl_x509_parse("-----BEGIN CERTIFICATE-----\n".chunk_split($X509Cert, 64, "\n")."-----END CERTIFICATE-----\n")) {
1386
+ if ($issuerSerial && ! empty($certData['issuer']) && ! empty($certData['serialNumber'])) {
1387
+ if (is_array($certData['issuer'])) {
1388
+ $parts = array();
1389
+ foreach ($certData['issuer'] AS $key => $value) {
1390
+ array_unshift($parts, "$key=$value" . $issuer);
1391
+ }
1392
+ $issuerName = implode(',', $parts);
1393
+ } else {
1394
+ $issuerName = $certData['issuer'];
1395
+ }
1396
+
1397
+ $x509IssuerNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509IssuerSerial');
1398
+ $x509DataNode->appendChild($x509IssuerNode);
1399
+
1400
+ $x509Node = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509IssuerName', $issuerName);
1401
+ $x509IssuerNode->appendChild($x509Node);
1402
+ $x509Node = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509SerialNumber', $certData['serialNumber']);
1403
+ $x509IssuerNode->appendChild($x509Node);
1404
+ }
1405
+ }
1406
+
1407
+ }
1408
+ $x509CertNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Certificate', $X509Cert);
1409
+ $x509DataNode->appendChild($x509CertNode);
1410
+ }
1411
+ }
1412
+
1413
+ public function add509Cert($cert, $isPEMFormat=TRUE, $isURL=False, $options=NULL) {
1414
+ if ($xpath = $this->getXPathObj()) {
1415
+ self::staticAdd509Cert($this->sigNode, $cert, $isPEMFormat, $isURL, $xpath, $options);
1416
+ }
1417
+ }
1418
+
1419
+ function addKeyInfoAndName($keyName, $xpath = NULL) {
1420
+
1421
+ $baseDoc = $this->sigNode->ownerDocument;
1422
+
1423
+ if (empty($xpath)) {
1424
+ $xpath = new DOMXPath($baseDoc);
1425
+ $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS);
1426
+ }
1427
+
1428
+ $query = "./secdsig:KeyInfo";
1429
+ $nodeset = $xpath->query($query, $this->sigNode);
1430
+ $keyInfo = $nodeset->item(0);
1431
+ if (!$keyInfo) {
1432
+ $inserted = FALSE;
1433
+ $keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'KeyInfo');
1434
+
1435
+ $query = "./secdsig:Object";
1436
+ $nodeset = $xpath->query($query, $this->sigNode);
1437
+ if ($sObject = $nodeset->item(0)) {
1438
+ $sObject->parentNode->insertBefore($keyInfo, $sObject);
1439
+ $inserted = TRUE;
1440
+ }
1441
+ if (!$inserted) {
1442
+ $this->sigNode->appendChild($keyInfo);
1443
+ }
1444
+ }
1445
+ $keyInfo->appendChild($baseDoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'KeyName', $keyName));
1446
+ }
1447
+
1448
+ /* This function retrieves an associative array of the validated nodes.
1449
+ *
1450
+ * The array will contain the id of the referenced node as the key and the node itself
1451
+ * as the value.
1452
+ *
1453
+ * Returns:
1454
+ * An associative array of validated nodes or NULL if no nodes have been validated.
1455
+ */
1456
+ public function getValidatedNodes() {
1457
+ return $this->validatedNodes;
1458
+ }
1459
+ }
1460
+
1461
+ class XMLSecEnc {
1462
+ const template = "<xenc:EncryptedData xmlns:xenc='http://www.w3.org/2001/04/xmlenc#'>
1463
+ <xenc:CipherData>
1464
+ <xenc:CipherValue></xenc:CipherValue>
1465
+ </xenc:CipherData>
1466
+ </xenc:EncryptedData>";
1467
+
1468
+ const Element = 'http://www.w3.org/2001/04/xmlenc#Element';
1469
+ const Content = 'http://www.w3.org/2001/04/xmlenc#Content';
1470
+ const URI = 3;
1471
+ const XMLENCNS = 'http://www.w3.org/2001/04/xmlenc#';
1472
+
1473
+ private $encdoc = NULL;
1474
+ private $rawNode = NULL;
1475
+ public $type = NULL;
1476
+ public $encKey = NULL;
1477
+ private $references = array();
1478
+
1479
+ public function __construct() {
1480
+ $this->_resetTemplate();
1481
+ }
1482
+
1483
+ private function _resetTemplate(){
1484
+ $this->encdoc = new DOMDocument();
1485
+ $this->encdoc->loadXML(XMLSecEnc::template);
1486
+ }
1487
+
1488
+ public function addReference($name, $node, $type) {
1489
+ if (! $node instanceOf DOMNode) {
1490
+ throw new Exception('$node is not of type DOMNode');
1491
+ }
1492
+ $curencdoc = $this->encdoc;
1493
+ $this->_resetTemplate();
1494
+ $encdoc = $this->encdoc;
1495
+ $this->encdoc = $curencdoc;
1496
+ $refuri = XMLSecurityDSig::generate_GUID();
1497
+ $element = $encdoc->documentElement;
1498
+ $element->setAttribute("Id", $refuri);
1499
+ $this->references[$name] = array("node" => $node, "type" => $type, "encnode" => $encdoc, "refuri" => $refuri);
1500
+ }
1501
+
1502
+ public function setNode($node) {
1503
+ $this->rawNode = $node;
1504
+ }
1505
+
1506
+ /**
1507
+ * Encrypt the selected node with the given key.
1508
+ *
1509
+ * @param XMLSecurityKey $objKey The encryption key and algorithm.
1510
+ * @param bool $replace Whether the encrypted node should be replaced in the original tree. Default is TRUE.
1511
+ * @return DOMElement The <xenc:EncryptedData>-element.
1512
+ */
1513
+ public function encryptNode($objKey, $replace=TRUE) {
1514
+ $data = '';
1515
+ if (empty($this->rawNode)) {
1516
+ throw new Exception('Node to encrypt has not been set');
1517
+ }
1518
+ if (! $objKey instanceof XMLSecurityKey) {
1519
+ throw new Exception('Invalid Key');
1520
+ }
1521
+ $doc = $this->rawNode->ownerDocument;
1522
+ $xPath = new DOMXPath($this->encdoc);
1523
+ $objList = $xPath->query('/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue');
1524
+ $cipherValue = $objList->item(0);
1525
+ if ($cipherValue == NULL) {
1526
+ throw new Exception('Error locating CipherValue element within template');
1527
+ }
1528
+ switch ($this->type) {
1529
+ case (XMLSecEnc::Element):
1530
+ $data = $doc->saveXML($this->rawNode);
1531
+ $this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Element);
1532
+ break;
1533
+ case (XMLSecEnc::Content):
1534
+ $children = $this->rawNode->childNodes;
1535
+ foreach ($children AS $child) {
1536
+ $data .= $doc->saveXML($child);
1537
+ }
1538
+ $this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Content);
1539
+ break;
1540
+ default:
1541
+ throw new Exception('Type is currently not supported');
1542
+ return;
1543
+ }
1544
+
1545
+ $encMethod = $this->encdoc->documentElement->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
1546
+ $encMethod->setAttribute('Algorithm', $objKey->getAlgorith());
1547
+ $cipherValue->parentNode->parentNode->insertBefore($encMethod, $cipherValue->parentNode->parentNode->firstChild);
1548
+
1549
+ $strEncrypt = base64_encode($objKey->encryptData($data));
1550
+ $value = $this->encdoc->createTextNode($strEncrypt);
1551
+ $cipherValue->appendChild($value);
1552
+
1553
+ if ($replace) {
1554
+ switch ($this->type) {
1555
+ case (XMLSecEnc::Element):
1556
+ if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
1557
+ return $this->encdoc;
1558
+ }
1559
+ $importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
1560
+ $this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
1561
+ return $importEnc;
1562
+ break;
1563
+ case (XMLSecEnc::Content):
1564
+ $importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE);
1565
+ while($this->rawNode->firstChild) {
1566
+ $this->rawNode->removeChild($this->rawNode->firstChild);
1567
+ }
1568
+ $this->rawNode->appendChild($importEnc);
1569
+ return $importEnc;
1570
+ break;
1571
+ }
1572
+ } else {
1573
+ return $this->encdoc->documentElement;
1574
+ }
1575
+ }
1576
+
1577
+ public function encryptReferences($objKey) {
1578
+ $curRawNode = $this->rawNode;
1579
+ $curType = $this->type;
1580
+ foreach ($this->references AS $name=>$reference) {
1581
+ $this->encdoc = $reference["encnode"];
1582
+ $this->rawNode = $reference["node"];
1583
+ $this->type = $reference["type"];
1584
+ try {
1585
+ $encNode = $this->encryptNode($objKey);
1586
+ $this->references[$name]["encnode"] = $encNode;
1587
+ } catch (Exception $e) {
1588
+ $this->rawNode = $curRawNode;
1589
+ $this->type = $curType;
1590
+ throw $e;
1591
+ }
1592
+ }
1593
+ $this->rawNode = $curRawNode;
1594
+ $this->type = $curType;
1595
+ }
1596
+
1597
+ /**
1598
+ * Retrieve the CipherValue text from this encrypted node.
1599
+ *
1600
+ * @return string|NULL The Ciphervalue text, or NULL if no CipherValue is found.
1601
+ */
1602
+ public function getCipherValue() {
1603
+ if (empty($this->rawNode)) {
1604
+ throw new Exception('Node to decrypt has not been set');
1605
+ }
1606
+
1607
+ $doc = $this->rawNode->ownerDocument;
1608
+ $xPath = new DOMXPath($doc);
1609
+ $xPath->registerNamespace('xmlencr', XMLSecEnc::XMLENCNS);
1610
+ /* Only handles embedded content right now and not a reference */
1611
+ $query = "./xmlencr:CipherData/xmlencr:CipherValue";
1612
+ $nodeset = $xPath->query($query, $this->rawNode);
1613
+ $node = $nodeset->item(0);
1614
+
1615
+ if (!$node) {
1616
+ return NULL;
1617
+ }
1618
+
1619
+ return base64_decode($node->nodeValue);
1620
+ }
1621
+
1622
+ /**
1623
+ * Decrypt this encrypted node.
1624
+ *
1625
+ * The behaviour of this function depends on the value of $replace.
1626
+ * If $replace is FALSE, we will return the decrypted data as a string.
1627
+ * If $replace is TRUE, we will insert the decrypted element(s) into the
1628
+ * document, and return the decrypted element(s).
1629
+ *
1630
+ * @params XMLSecurityKey $objKey The decryption key that should be used when decrypting the node.
1631
+ * @params boolean $replace Whether we should replace the encrypted node in the XML document with the decrypted data. The default is TRUE.
1632
+ * @return string|DOMElement The decrypted data.
1633
+ */
1634
+ public function decryptNode($objKey, $replace=TRUE) {
1635
+ if (! $objKey instanceof XMLSecurityKey) {
1636
+ throw new Exception('Invalid Key');
1637
+ }
1638
+
1639
+ $encryptedData = $this->getCipherValue();
1640
+ if ($encryptedData) {
1641
+ $decrypted = $objKey->decryptData($encryptedData);
1642
+ if ($replace) {
1643
+ switch ($this->type) {
1644
+ case (XMLSecEnc::Element):
1645
+ $newdoc = new DOMDocument();
1646
+ $newdoc->loadXML($decrypted);
1647
+ if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
1648
+ return $newdoc;
1649
+ }
1650
+ $importEnc = $this->rawNode->ownerDocument->importNode($newdoc->documentElement, TRUE);
1651
+ $this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode);
1652
+ return $importEnc;
1653
+ break;
1654
+ case (XMLSecEnc::Content):
1655
+ if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) {
1656
+ $doc = $this->rawNode;
1657
+ } else {
1658
+ $doc = $this->rawNode->ownerDocument;
1659
+ }
1660
+ $newFrag = $doc->createDocumentFragment();
1661
+ $newFrag->appendXML($decrypted);
1662
+ $parent = $this->rawNode->parentNode;
1663
+ $parent->replaceChild($newFrag, $this->rawNode);
1664
+ return $parent;
1665
+ break;
1666
+ default:
1667
+ return $decrypted;
1668
+ }
1669
+ } else {
1670
+ return $decrypted;
1671
+ }
1672
+ } else {
1673
+ throw new Exception("Cannot locate encrypted data");
1674
+ }
1675
+ }
1676
+
1677
+ public function encryptKey($srcKey, $rawKey, $append=TRUE) {
1678
+ if ((! $srcKey instanceof XMLSecurityKey) || (! $rawKey instanceof XMLSecurityKey)) {
1679
+ throw new Exception('Invalid Key');
1680
+ }
1681
+ $strEncKey = base64_encode($srcKey->encryptData($rawKey->key));
1682
+ $root = $this->encdoc->documentElement;
1683
+ $encKey = $this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptedKey');
1684
+ if ($append) {
1685
+ $keyInfo = $root->insertBefore($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'), $root->firstChild);
1686
+ $keyInfo->appendChild($encKey);
1687
+ } else {
1688
+ $this->encKey = $encKey;
1689
+ }
1690
+ $encMethod = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod'));
1691
+ $encMethod->setAttribute('Algorithm', $srcKey->getAlgorith());
1692
+ if (! empty($srcKey->name)) {
1693
+ $keyInfo = $encKey->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'));
1694
+ $keyInfo->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyName', $srcKey->name));
1695
+ }
1696
+ $cipherData = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherData'));
1697
+ $cipherData->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherValue', $strEncKey));
1698
+ if (is_array($this->references) && count($this->references) > 0) {
1699
+ $refList = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:ReferenceList'));
1700
+ foreach ($this->references AS $name=>$reference) {
1701
+ $refuri = $reference["refuri"];
1702
+ $dataRef = $refList->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:DataReference'));
1703
+ $dataRef->setAttribute("URI", '#' . $refuri);
1704
+ }
1705
+ }
1706
+ return;
1707
+ }
1708
+
1709
+ public function decryptKey($encKey) {
1710
+ if (! $encKey->isEncrypted) {
1711
+ throw new Exception("Key is not Encrypted");
1712
+ }
1713
+ if (empty($encKey->key)) {
1714
+ throw new Exception("Key is missing data to perform the decryption");
1715
+ }
1716
+ return $this->decryptNode($encKey, FALSE);
1717
+ }
1718
+
1719
+ public function locateEncryptedData($element) {
1720
+ if ($element instanceof DOMDocument) {
1721
+ $doc = $element;
1722
+ } else {
1723
+ $doc = $element->ownerDocument;
1724
+ }
1725
+ if ($doc) {
1726
+ $xpath = new DOMXPath($doc);
1727
+ $query = "//*[local-name()='EncryptedData' and namespace-uri()='".XMLSecEnc::XMLENCNS."']";
1728
+ $nodeset = $xpath->query($query);
1729
+ return $nodeset->item(0);
1730
+ }
1731
+ return NULL;
1732
+ }
1733
+
1734
+ public function locateKey($node=NULL) {
1735
+ if (empty($node)) {
1736
+ $node = $this->rawNode;
1737
+ }
1738
+ if (! $node instanceof DOMNode) {
1739
+ return NULL;
1740
+ }
1741
+ if ($doc = $node->ownerDocument) {
1742
+ $xpath = new DOMXPath($doc);
1743
+ $xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
1744
+ $query = ".//xmlsecenc:EncryptionMethod";
1745
+ $nodeset = $xpath->query($query, $node);
1746
+ if ($encmeth = $nodeset->item(0)) {
1747
+ $attrAlgorithm = $encmeth->getAttribute("Algorithm");
1748
+ try {
1749
+ $objKey = new XMLSecurityKey($attrAlgorithm, array('type'=>'private'));
1750
+ } catch (Exception $e) {
1751
+ return NULL;
1752
+ }
1753
+ return $objKey;
1754
+ }
1755
+ }
1756
+ return NULL;
1757
+ }
1758
+
1759
+ static function staticLocateKeyInfo($objBaseKey=NULL, $node=NULL) {
1760
+ if (empty($node) || (! $node instanceof DOMNode)) {
1761
+ return NULL;
1762
+ }
1763
+ $doc = $node->ownerDocument;
1764
+ if (!$doc) {
1765
+ return NULL;
1766
+ }
1767
+
1768
+ $xpath = new DOMXPath($doc);
1769
+ $xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS);
1770
+ $xpath->registerNamespace('xmlsecdsig', XMLSecurityDSig::XMLDSIGNS);
1771
+ $query = "./xmlsecdsig:KeyInfo";
1772
+ $nodeset = $xpath->query($query, $node);
1773
+ $encmeth = $nodeset->item(0);
1774
+ if (!$encmeth) {
1775
+ /* No KeyInfo in EncryptedData / EncryptedKey. */
1776
+ return $objBaseKey;
1777
+ }
1778
+
1779
+ foreach ($encmeth->childNodes AS $child) {
1780
+ switch ($child->localName) {
1781
+ case 'KeyName':
1782
+ if (! empty($objBaseKey)) {
1783
+ $objBaseKey->name = $child->nodeValue;
1784
+ }
1785
+ break;
1786
+ case 'KeyValue':
1787
+ foreach ($child->childNodes AS $keyval) {
1788
+ switch ($keyval->localName) {
1789
+ case 'DSAKeyValue':
1790
+ throw new Exception("DSAKeyValue currently not supported");
1791
+ break;
1792
+ case 'RSAKeyValue':
1793
+ $modulus = NULL;
1794
+ $exponent = NULL;
1795
+ if ($modulusNode = $keyval->getElementsByTagName('Modulus')->item(0)) {
1796
+ $modulus = base64_decode($modulusNode->nodeValue);
1797
+ }
1798
+ if ($exponentNode = $keyval->getElementsByTagName('Exponent')->item(0)) {
1799
+ $exponent = base64_decode($exponentNode->nodeValue);
1800
+ }
1801
+ if (empty($modulus) || empty($exponent)) {
1802
+ throw new Exception("Missing Modulus or Exponent");
1803
+ }
1804
+ $publicKey = XMLSecurityKey::convertRSA($modulus, $exponent);
1805
+ $objBaseKey->loadKey($publicKey);
1806
+ break;
1807
+ }
1808
+ }
1809
+ break;
1810
+ case 'RetrievalMethod':
1811
+ $type = $child->getAttribute('Type');
1812
+ if ($type !== 'http://www.w3.org/2001/04/xmlenc#EncryptedKey') {
1813
+ /* Unsupported key type. */
1814
+ break;
1815
+ }
1816
+ $uri = $child->getAttribute('URI');
1817
+ if ($uri[0] !== '#') {
1818
+ /* URI not a reference - unsupported. */
1819
+ break;
1820
+ }
1821
+ $id = substr($uri, 1);
1822
+
1823
+ $query = "//xmlsecenc:EncryptedKey[@Id='$id']";
1824
+ $keyElement = $xpath->query($query)->item(0);
1825
+ if (!$keyElement) {
1826
+ throw new Exception("Unable to locate EncryptedKey with @Id='$id'.");
1827
+ }
1828
+
1829
+ return XMLSecurityKey::fromEncryptedKeyElement($keyElement);
1830
+ case 'EncryptedKey':
1831
+ return XMLSecurityKey::fromEncryptedKeyElement($child);
1832
+ case 'X509Data':
1833
+ if ($x509certNodes = $child->getElementsByTagName('X509Certificate')) {
1834
+ if ($x509certNodes->length > 0) {
1835
+ $x509cert = $x509certNodes->item(0)->textContent;
1836
+ $x509cert = str_replace(array("\r", "\n"), "", $x509cert);
1837
+ $x509cert = "-----BEGIN CERTIFICATE-----\n".chunk_split($x509cert, 64, "\n")."-----END CERTIFICATE-----\n";
1838
+ $objBaseKey->loadKey($x509cert, FALSE, TRUE);
1839
+ }
1840
+ }
1841
+ break;
1842
+ }
1843
+ }
1844
+ return $objBaseKey;
1845
+ }
1846
+
1847
+ public function locateKeyInfo($objBaseKey=NULL, $node=NULL) {
1848
+ if (empty($node)) {
1849
+ $node = $this->rawNode;
1850
+ }
1851
+ return XMLSecEnc::staticLocateKeyInfo($objBaseKey, $node);
1852
+ }
1853
+ }
lib/Communicator/schemas/idx.merchant-acquirer.1.0.xsd ADDED
@@ -0,0 +1,369 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!-- iDx Messages version 1.0.0: interface Merchant/Acquirer -->
3
+ <!-- Copyright © Betaalvereniging -->
4
+ <xs:schema xmlns="http://www.betaalvereniging.nl/iDx/messages/Merchant-Acquirer/1.0.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" targetNamespace="http://www.betaalvereniging.nl/iDx/messages/Merchant-Acquirer/1.0.0" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.0.0">
5
+ <xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsig-core-schema.xsd"/>
6
+ <xs:annotation>
7
+ <xs:documentation>elements defined</xs:documentation>
8
+ </xs:annotation>
9
+ <xs:element name="DirectoryReq">
10
+ <xs:annotation>
11
+ <xs:documentation>Directory Request (A)</xs:documentation>
12
+ </xs:annotation>
13
+ <xs:complexType>
14
+ <xs:sequence>
15
+ <xs:element name="createDateTimestamp" type="dateTime"/>
16
+ <xs:element name="Merchant">
17
+ <xs:complexType>
18
+ <xs:sequence>
19
+ <xs:element name="merchantID" type="Merchant.merchantID"/>
20
+ <xs:element name="subID" type="Merchant.subID"/>
21
+ </xs:sequence>
22
+ </xs:complexType>
23
+ </xs:element>
24
+ <xs:element ref="ds:Signature"/>
25
+ </xs:sequence>
26
+ <xs:attributeGroup ref="MessageAttributes"/>
27
+ </xs:complexType>
28
+ </xs:element>
29
+ <xs:element name="DirectoryRes">
30
+ <xs:annotation>
31
+ <xs:documentation>Directory Response (A')</xs:documentation>
32
+ </xs:annotation>
33
+ <xs:complexType>
34
+ <xs:sequence>
35
+ <xs:element name="createDateTimestamp" type="dateTime"/>
36
+ <xs:element name="Acquirer">
37
+ <xs:complexType>
38
+ <xs:sequence>
39
+ <xs:element name="acquirerID" type="Acquirer.acquirerID"/>
40
+ </xs:sequence>
41
+ </xs:complexType>
42
+ </xs:element>
43
+ <xs:element name="Directory">
44
+ <xs:complexType>
45
+ <xs:sequence>
46
+ <xs:element name="directoryDateTimestamp" type="dateTime"/>
47
+ <xs:element name="Country" maxOccurs="unbounded">
48
+ <xs:complexType>
49
+ <xs:sequence>
50
+ <xs:element name="countryNames" type="Country.countryNames"/>
51
+ <xs:element name="Issuer" maxOccurs="unbounded">
52
+ <xs:complexType>
53
+ <xs:sequence>
54
+ <xs:element name="issuerID" type="Issuer.issuerID"/>
55
+ <xs:element name="issuerName" type="Issuer.issuerName"/>
56
+ </xs:sequence>
57
+ </xs:complexType>
58
+ </xs:element>
59
+ </xs:sequence>
60
+ </xs:complexType>
61
+ </xs:element>
62
+ </xs:sequence>
63
+ </xs:complexType>
64
+ </xs:element>
65
+ <xs:element ref="ds:Signature"/>
66
+ </xs:sequence>
67
+ <xs:attributeGroup ref="MessageAttributes"/>
68
+ </xs:complexType>
69
+ </xs:element>
70
+ <xs:element name="AcquirerTrxReq">
71
+ <xs:annotation>
72
+ <xs:documentation>Acquirer Transaction Request (B)</xs:documentation>
73
+ </xs:annotation>
74
+ <xs:complexType>
75
+ <xs:sequence>
76
+ <xs:element name="createDateTimestamp" type="dateTime"/>
77
+ <xs:element name="Issuer">
78
+ <xs:complexType>
79
+ <xs:sequence>
80
+ <xs:element name="issuerID" type="Issuer.issuerID"/>
81
+ </xs:sequence>
82
+ </xs:complexType>
83
+ </xs:element>
84
+ <xs:element name="Merchant">
85
+ <xs:complexType>
86
+ <xs:sequence>
87
+ <xs:element name="merchantID" type="Merchant.merchantID"/>
88
+ <xs:element name="subID" type="Merchant.subID"/>
89
+ <xs:element name="merchantReturnURL" type="url"/>
90
+ </xs:sequence>
91
+ </xs:complexType>
92
+ </xs:element>
93
+ <xs:element name="Transaction">
94
+ <xs:complexType>
95
+ <xs:sequence>
96
+ <xs:element name="expirationPeriod" type="Transaction.expirationPeriod" minOccurs="0"/>
97
+ <xs:element name="language" type="Transaction.language"/>
98
+ <xs:element name="entranceCode" type="Transaction.entranceCode"/>
99
+ <xs:element name="container" type="Transaction.container"/>
100
+ </xs:sequence>
101
+ </xs:complexType>
102
+ </xs:element>
103
+ <xs:element ref="ds:Signature"/>
104
+ </xs:sequence>
105
+ <xs:attributeGroup ref="MessageAttributes"/>
106
+ </xs:complexType>
107
+ </xs:element>
108
+ <xs:element name="AcquirerTrxRes">
109
+ <xs:annotation>
110
+ <xs:documentation>Acquirer Transaction Response (B')</xs:documentation>
111
+ </xs:annotation>
112
+ <xs:complexType>
113
+ <xs:sequence>
114
+ <xs:element name="createDateTimestamp" type="dateTime"/>
115
+ <xs:element name="Acquirer">
116
+ <xs:complexType>
117
+ <xs:sequence>
118
+ <xs:element name="acquirerID" type="Acquirer.acquirerID"/>
119
+ </xs:sequence>
120
+ </xs:complexType>
121
+ </xs:element>
122
+ <xs:element name="Issuer">
123
+ <xs:complexType>
124
+ <xs:sequence>
125
+ <xs:element name="issuerAuthenticationURL" type="Issuer.issuerAuthenticationURL"/>
126
+ </xs:sequence>
127
+ </xs:complexType>
128
+ </xs:element>
129
+ <xs:element name="Transaction">
130
+ <xs:complexType>
131
+ <xs:sequence>
132
+ <xs:element name="transactionID" type="Transaction.transactionID"/>
133
+ <xs:element name="transactionCreateDateTimestamp" type="dateTime"/>
134
+ </xs:sequence>
135
+ </xs:complexType>
136
+ </xs:element>
137
+ <xs:element ref="ds:Signature"/>
138
+ </xs:sequence>
139
+ <xs:attributeGroup ref="MessageAttributes"/>
140
+ </xs:complexType>
141
+ </xs:element>
142
+ <xs:element name="AcquirerStatusReq">
143
+ <xs:annotation>
144
+ <xs:documentation>Acquirer Status Request (F)</xs:documentation>
145
+ </xs:annotation>
146
+ <xs:complexType>
147
+ <xs:sequence>
148
+ <xs:element name="createDateTimestamp" type="dateTime"/>
149
+ <xs:element name="Merchant">
150
+ <xs:complexType>
151
+ <xs:sequence>
152
+ <xs:element name="merchantID" type="Merchant.merchantID"/>
153
+ <xs:element name="subID" type="Merchant.subID"/>
154
+ </xs:sequence>
155
+ </xs:complexType>
156
+ </xs:element>
157
+ <xs:element name="Transaction">
158
+ <xs:complexType>
159
+ <xs:sequence>
160
+ <xs:element name="transactionID" type="Transaction.transactionID"/>
161
+ </xs:sequence>
162
+ </xs:complexType>
163
+ </xs:element>
164
+ <xs:element ref="ds:Signature"/>
165
+ </xs:sequence>
166
+ <xs:attributeGroup ref="MessageAttributes"/>
167
+ </xs:complexType>
168
+ </xs:element>
169
+ <xs:element name="AcquirerStatusRes">
170
+ <xs:annotation>
171
+ <xs:documentation>Acquirer Status Response (F')</xs:documentation>
172
+ </xs:annotation>
173
+ <xs:complexType>
174
+ <xs:sequence>
175
+ <xs:element name="createDateTimestamp" type="dateTime"/>
176
+ <xs:element name="Acquirer">
177
+ <xs:complexType>
178
+ <xs:sequence>
179
+ <xs:element name="acquirerID" type="Acquirer.acquirerID"/>
180
+ </xs:sequence>
181
+ </xs:complexType>
182
+ </xs:element>
183
+ <xs:element name="Transaction">
184
+ <xs:complexType>
185
+ <xs:sequence>
186
+ <xs:element name="transactionID" type="Transaction.transactionID"/>
187
+ <xs:element name="status" type="Transaction.status"/>
188
+ <xs:element name="statusDateTimestamp" type="dateTime" minOccurs="0"/>
189
+ <xs:element name="container" type="Transaction.container" minOccurs="0"/>
190
+ </xs:sequence>
191
+ </xs:complexType>
192
+ </xs:element>
193
+ <xs:element ref="ds:Signature"/>
194
+ </xs:sequence>
195
+ <xs:attributeGroup ref="MessageAttributes"/>
196
+ </xs:complexType>
197
+ </xs:element>
198
+ <xs:element name="AcquirerErrorRes">
199
+ <xs:annotation>
200
+ <xs:documentation>Acquirer Error Response (X')</xs:documentation>
201
+ </xs:annotation>
202
+ <xs:complexType>
203
+ <xs:sequence>
204
+ <xs:element name="createDateTimestamp" type="dateTime"/>
205
+ <xs:element name="Error">
206
+ <xs:complexType>
207
+ <xs:sequence>
208
+ <xs:element name="errorCode" type="Error.errorCode"/>
209
+ <xs:element name="errorMessage" type="Error.errorMessage"/>
210
+ <xs:element name="errorDetail" type="Error.errorDetail" minOccurs="0"/>
211
+ <xs:element name="suggestedAction" type="Error.suggestedAction" minOccurs="0"/>
212
+ <xs:element name="consumerMessage" type="Error.consumerMessage" minOccurs="0"/>
213
+ <xs:element name="container" type="Transaction.container" minOccurs="0"/>
214
+ </xs:sequence>
215
+ </xs:complexType>
216
+ </xs:element>
217
+ <xs:element ref="ds:Signature"/>
218
+ </xs:sequence>
219
+ <xs:attributeGroup ref="MessageAttributes"/>
220
+ </xs:complexType>
221
+ </xs:element>
222
+ <xs:annotation>
223
+ <xs:documentation>simpleTypes defined</xs:documentation>
224
+ </xs:annotation>
225
+ <xs:simpleType name="Acquirer.acquirerID">
226
+ <xs:restriction base="xs:token">
227
+ <xs:length value="4" fixed="true"/>
228
+ <xs:pattern value="[0-9]+"/>
229
+ </xs:restriction>
230
+ </xs:simpleType>
231
+ <xs:simpleType name="Country.countryNames">
232
+ <xs:restriction base="xs:token">
233
+ <xs:minLength value="1"/>
234
+ <xs:maxLength value="128"/>
235
+ </xs:restriction>
236
+ </xs:simpleType>
237
+ <xs:simpleType name="Error.consumerMessage">
238
+ <xs:restriction base="xs:string">
239
+ <xs:maxLength value="512" fixed="true"/>
240
+ <xs:minLength value="1" fixed="true"/>
241
+ </xs:restriction>
242
+ </xs:simpleType>
243
+ <xs:simpleType name="Error.errorCode">
244
+ <xs:restriction base="xs:token">
245
+ <xs:length value="6" fixed="true"/>
246
+ <xs:pattern value="[A-Z]{2}[0-9]{4}"/>
247
+ </xs:restriction>
248
+ </xs:simpleType>
249
+ <xs:simpleType name="Error.errorDetail">
250
+ <xs:restriction base="xs:string">
251
+ <xs:maxLength value="256" fixed="true"/>
252
+ <xs:minLength value="1" fixed="true"/>
253
+ </xs:restriction>
254
+ </xs:simpleType>
255
+ <xs:simpleType name="Error.errorMessage">
256
+ <xs:restriction base="xs:string">
257
+ <xs:minLength value="1"/>
258
+ <xs:maxLength value="128"/>
259
+ </xs:restriction>
260
+ </xs:simpleType>
261
+ <xs:simpleType name="Error.suggestedAction">
262
+ <xs:restriction base="xs:string">
263
+ <xs:maxLength value="512" fixed="true"/>
264
+ <xs:minLength value="1" fixed="true"/>
265
+ </xs:restriction>
266
+ </xs:simpleType>
267
+ <xs:simpleType name="Issuer.issuerAuthenticationURL">
268
+ <xs:restriction base="url"/>
269
+ </xs:simpleType>
270
+ <xs:simpleType name="Issuer.issuerID">
271
+ <xs:restriction base="BIC"/>
272
+ </xs:simpleType>
273
+ <xs:simpleType name="Issuer.issuerName">
274
+ <xs:restriction base="xs:token">
275
+ <xs:maxLength value="35" fixed="true"/>
276
+ <xs:minLength value="1" fixed="true"/>
277
+ </xs:restriction>
278
+ </xs:simpleType>
279
+ <xs:simpleType name="Merchant.merchantID">
280
+ <xs:restriction base="xs:token">
281
+ <xs:length value="10" fixed="true"/>
282
+ <xs:pattern value="[0-9]+"/>
283
+ </xs:restriction>
284
+ </xs:simpleType>
285
+ <xs:simpleType name="Merchant.merchantReturnURL">
286
+ <xs:restriction base="url"/>
287
+ </xs:simpleType>
288
+ <xs:simpleType name="Merchant.subID">
289
+ <xs:restriction base="xs:nonNegativeInteger">
290
+ <xs:maxInclusive value="999999" fixed="true"/>
291
+ </xs:restriction>
292
+ </xs:simpleType>
293
+ <xs:simpleType name="Transaction.entranceCode">
294
+ <xs:restriction base="xs:token">
295
+ <xs:minLength value="1" fixed="true"/>
296
+ <xs:maxLength value="40" fixed="true"/>
297
+ <xs:pattern value="[a-zA-Z0-9]+"/>
298
+ </xs:restriction>
299
+ </xs:simpleType>
300
+ <xs:simpleType name="Transaction.expirationPeriod">
301
+ <xs:restriction base="xs:duration">
302
+ <xs:minInclusive value="PT1M" fixed="true"/>
303
+ </xs:restriction>
304
+ </xs:simpleType>
305
+ <xs:simpleType name="Transaction.language">
306
+ <xs:restriction base="language"/>
307
+ </xs:simpleType>
308
+ <xs:simpleType name="Transaction.status">
309
+ <xs:restriction base="xs:token">
310
+ <xs:pattern value="Open|Success|Failure|Expired|Cancelled|Pending"/>
311
+ </xs:restriction>
312
+ </xs:simpleType>
313
+ <xs:simpleType name="Transaction.transactionID">
314
+ <xs:restriction base="xs:token">
315
+ <xs:length value="16" fixed="true"/>
316
+ <xs:pattern value="[0-9]+"/>
317
+ </xs:restriction>
318
+ </xs:simpleType>
319
+ <xs:annotation>
320
+ <xs:documentation>basic simpleTypes defined</xs:documentation>
321
+ </xs:annotation>
322
+ <xs:simpleType name="BIC">
323
+ <xs:restriction base="xs:token">
324
+ <xs:pattern value="[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}"/>
325
+ </xs:restriction>
326
+ </xs:simpleType>
327
+ <xs:simpleType name="dateTime">
328
+ <xs:restriction base="xs:dateTime">
329
+ <xs:pattern value=".+Z"/>
330
+ </xs:restriction>
331
+ </xs:simpleType>
332
+ <xs:simpleType name="language">
333
+ <xs:restriction base="xs:token">
334
+ <xs:length value="2" fixed="true"/>
335
+ <xs:pattern value="[a-z]+"/>
336
+ </xs:restriction>
337
+ </xs:simpleType>
338
+ <xs:simpleType name="productID">
339
+ <xs:restriction base="xs:string"/>
340
+ </xs:simpleType>
341
+ <xs:simpleType name="url">
342
+ <xs:restriction base="xs:anyURI">
343
+ <xs:maxLength value="512"/>
344
+ </xs:restriction>
345
+ </xs:simpleType>
346
+ <xs:simpleType name="version">
347
+ <xs:restriction base="xs:string">
348
+ <xs:pattern value="1\.0\.0"/>
349
+ </xs:restriction>
350
+ </xs:simpleType>
351
+ <xs:annotation>
352
+ <xs:documentation>complexTypes defined</xs:documentation>
353
+ </xs:annotation>
354
+ <xs:complexType name="Transaction.container">
355
+ <xs:sequence>
356
+ <xs:any namespace="##any" maxOccurs="unbounded" processContents="lax"/>
357
+ </xs:sequence>
358
+ </xs:complexType>
359
+ <xs:annotation>
360
+ <xs:documentation>attributeGroups defined</xs:documentation>
361
+ </xs:annotation>
362
+ <xs:attributeGroup name="MessageAttributes">
363
+ <xs:annotation>
364
+ <xs:documentation>attributes of each message</xs:documentation>
365
+ </xs:annotation>
366
+ <xs:attribute name="version" type="version" use="required"/>
367
+ <xs:attribute name="productID" type="productID" use="required"/>
368
+ </xs:attributeGroup>
369
+ </xs:schema>
lib/Communicator/schemas/pain.009.001.04.xsd ADDED
@@ -0,0 +1,534 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--Generated by Standards Editor (build:R1.6.2.2) on 2014 Oct 24 13:58:14, ISO 20022 version : 2013-->
3
+ <xs:schema xmlns="urn:iso:std:iso:20022:tech:xsd:pain.009.001.04" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:iso:std:iso:20022:tech:xsd:pain.009.001.04">
4
+ <xs:element name="Document" type="Document"/>
5
+ <xs:complexType name="AccountIdentification4Choice">
6
+ <xs:choice>
7
+ <xs:element name="IBAN" type="IBAN2007Identifier"/>
8
+ <xs:element name="Othr" type="GenericAccountIdentification1"/>
9
+ </xs:choice>
10
+ </xs:complexType>
11
+ <xs:complexType name="AccountSchemeName1Choice">
12
+ <xs:choice>
13
+ <xs:element name="Cd" type="ExternalAccountIdentification1Code"/>
14
+ <xs:element name="Prtry" type="Max35Text"/>
15
+ </xs:choice>
16
+ </xs:complexType>
17
+ <xs:simpleType name="ActiveCurrencyAndAmount_SimpleType">
18
+ <xs:restriction base="xs:decimal">
19
+ <xs:fractionDigits value="2"/>
20
+ <xs:totalDigits value="18"/>
21
+ <xs:minInclusive value="0"/>
22
+ </xs:restriction>
23
+ </xs:simpleType>
24
+ <xs:complexType name="ActiveCurrencyAndAmount">
25
+ <xs:simpleContent>
26
+ <xs:extension base="ActiveCurrencyAndAmount_SimpleType">
27
+ <xs:attribute name="Ccy" type="ActiveCurrencyCode" use="required"/>
28
+ </xs:extension>
29
+ </xs:simpleContent>
30
+ </xs:complexType>
31
+ <xs:simpleType name="ActiveCurrencyCode">
32
+ <xs:restriction base="xs:string">
33
+ <xs:pattern value="[A-Z]{3,3}"/>
34
+ </xs:restriction>
35
+ </xs:simpleType>
36
+ <xs:simpleType name="ActiveOrHistoricCurrencyCode">
37
+ <xs:restriction base="xs:string">
38
+ <xs:pattern value="[A-Z]{3,3}"/>
39
+ </xs:restriction>
40
+ </xs:simpleType>
41
+ <xs:simpleType name="AddressType2Code">
42
+ <xs:restriction base="xs:string">
43
+ <xs:enumeration value="ADDR"/>
44
+ <xs:enumeration value="PBOX"/>
45
+ <xs:enumeration value="HOME"/>
46
+ <xs:enumeration value="BIZZ"/>
47
+ <xs:enumeration value="MLTO"/>
48
+ <xs:enumeration value="DLVY"/>
49
+ </xs:restriction>
50
+ </xs:simpleType>
51
+ <xs:simpleType name="AnyBICIdentifier">
52
+ <xs:restriction base="xs:string">
53
+ <xs:pattern value="[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}"/>
54
+ </xs:restriction>
55
+ </xs:simpleType>
56
+ <xs:complexType name="Authorisation1Choice">
57
+ <xs:choice>
58
+ <xs:element name="Cd" type="Authorisation1Code"/>
59
+ <xs:element name="Prtry" type="Max128Text"/>
60
+ </xs:choice>
61
+ </xs:complexType>
62
+ <xs:simpleType name="Authorisation1Code">
63
+ <xs:restriction base="xs:string">
64
+ <xs:enumeration value="AUTH"/>
65
+ <xs:enumeration value="FDET"/>
66
+ <xs:enumeration value="FSUM"/>
67
+ <xs:enumeration value="ILEV"/>
68
+ </xs:restriction>
69
+ </xs:simpleType>
70
+ <xs:simpleType name="BICFIIdentifier">
71
+ <xs:restriction base="xs:string">
72
+ <xs:pattern value="[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}"/>
73
+ </xs:restriction>
74
+ </xs:simpleType>
75
+ <xs:complexType name="BranchAndFinancialInstitutionIdentification5">
76
+ <xs:sequence>
77
+ <xs:element name="FinInstnId" type="FinancialInstitutionIdentification8"/>
78
+ <xs:element maxOccurs="1" minOccurs="0" name="BrnchId" type="BranchData2"/>
79
+ </xs:sequence>
80
+ </xs:complexType>
81
+ <xs:complexType name="BranchData2">
82
+ <xs:sequence>
83
+ <xs:element maxOccurs="1" minOccurs="0" name="Id" type="Max35Text"/>
84
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
85
+ <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/>
86
+ </xs:sequence>
87
+ </xs:complexType>
88
+ <xs:complexType name="CashAccount24">
89
+ <xs:sequence>
90
+ <xs:element name="Id" type="AccountIdentification4Choice"/>
91
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="CashAccountType2Choice"/>
92
+ <xs:element maxOccurs="1" minOccurs="0" name="Ccy" type="ActiveOrHistoricCurrencyCode"/>
93
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max70Text"/>
94
+ </xs:sequence>
95
+ </xs:complexType>
96
+ <xs:complexType name="CashAccountType2Choice">
97
+ <xs:choice>
98
+ <xs:element name="Cd" type="ExternalCashAccountType1Code"/>
99
+ <xs:element name="Prtry" type="Max35Text"/>
100
+ </xs:choice>
101
+ </xs:complexType>
102
+ <xs:complexType name="ClearingSystemIdentification2Choice">
103
+ <xs:choice>
104
+ <xs:element name="Cd" type="ExternalClearingSystemIdentification1Code"/>
105
+ <xs:element name="Prtry" type="Max35Text"/>
106
+ </xs:choice>
107
+ </xs:complexType>
108
+ <xs:complexType name="ClearingSystemMemberIdentification2">
109
+ <xs:sequence>
110
+ <xs:element maxOccurs="1" minOccurs="0" name="ClrSysId" type="ClearingSystemIdentification2Choice"/>
111
+ <xs:element name="MmbId" type="Max35Text"/>
112
+ </xs:sequence>
113
+ </xs:complexType>
114
+ <xs:complexType name="ContactDetails2">
115
+ <xs:sequence>
116
+ <xs:element maxOccurs="1" minOccurs="0" name="NmPrfx" type="NamePrefix1Code"/>
117
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
118
+ <xs:element maxOccurs="1" minOccurs="0" name="PhneNb" type="PhoneNumber"/>
119
+ <xs:element maxOccurs="1" minOccurs="0" name="MobNb" type="PhoneNumber"/>
120
+ <xs:element maxOccurs="1" minOccurs="0" name="FaxNb" type="PhoneNumber"/>
121
+ <xs:element maxOccurs="1" minOccurs="0" name="EmailAdr" type="Max2048Text"/>
122
+ <xs:element maxOccurs="1" minOccurs="0" name="Othr" type="Max35Text"/>
123
+ </xs:sequence>
124
+ </xs:complexType>
125
+ <xs:simpleType name="CountryCode">
126
+ <xs:restriction base="xs:string">
127
+ <xs:pattern value="[A-Z]{2,2}"/>
128
+ </xs:restriction>
129
+ </xs:simpleType>
130
+ <xs:complexType name="DateAndPlaceOfBirth">
131
+ <xs:sequence>
132
+ <xs:element name="BirthDt" type="ISODate"/>
133
+ <xs:element maxOccurs="1" minOccurs="0" name="PrvcOfBirth" type="Max35Text"/>
134
+ <xs:element name="CityOfBirth" type="Max35Text"/>
135
+ <xs:element name="CtryOfBirth" type="CountryCode"/>
136
+ </xs:sequence>
137
+ </xs:complexType>
138
+ <xs:complexType name="DatePeriodDetails1">
139
+ <xs:sequence>
140
+ <xs:element name="FrDt" type="ISODate"/>
141
+ <xs:element maxOccurs="1" minOccurs="0" name="ToDt" type="ISODate"/>
142
+ </xs:sequence>
143
+ </xs:complexType>
144
+ <xs:simpleType name="DecimalNumber">
145
+ <xs:restriction base="xs:decimal">
146
+ <xs:fractionDigits value="17"/>
147
+ <xs:totalDigits value="18"/>
148
+ </xs:restriction>
149
+ </xs:simpleType>
150
+ <xs:complexType name="Document">
151
+ <xs:sequence>
152
+ <xs:element name="MndtInitnReq" type="MandateInitiationRequestV04"/>
153
+ </xs:sequence>
154
+ </xs:complexType>
155
+ <xs:simpleType name="DocumentType6Code">
156
+ <xs:restriction base="xs:string">
157
+ <xs:enumeration value="MSIN"/>
158
+ <xs:enumeration value="CNFA"/>
159
+ <xs:enumeration value="DNFA"/>
160
+ <xs:enumeration value="CINV"/>
161
+ <xs:enumeration value="CREN"/>
162
+ <xs:enumeration value="DEBN"/>
163
+ <xs:enumeration value="HIRI"/>
164
+ <xs:enumeration value="SBIN"/>
165
+ <xs:enumeration value="CMCN"/>
166
+ <xs:enumeration value="SOAC"/>
167
+ <xs:enumeration value="DISP"/>
168
+ <xs:enumeration value="BOLD"/>
169
+ <xs:enumeration value="VCHR"/>
170
+ <xs:enumeration value="AROI"/>
171
+ <xs:enumeration value="TSUT"/>
172
+ <xs:enumeration value="PUOR"/>
173
+ </xs:restriction>
174
+ </xs:simpleType>
175
+ <xs:simpleType name="ExternalAccountIdentification1Code">
176
+ <xs:restriction base="xs:string">
177
+ <xs:minLength value="1"/>
178
+ <xs:maxLength value="4"/>
179
+ </xs:restriction>
180
+ </xs:simpleType>
181
+ <xs:simpleType name="ExternalCashAccountType1Code">
182
+ <xs:restriction base="xs:string">
183
+ <xs:minLength value="1"/>
184
+ <xs:maxLength value="4"/>
185
+ </xs:restriction>
186
+ </xs:simpleType>
187
+ <xs:simpleType name="ExternalClearingSystemIdentification1Code">
188
+ <xs:restriction base="xs:string">
189
+ <xs:minLength value="1"/>
190
+ <xs:maxLength value="5"/>
191
+ </xs:restriction>
192
+ </xs:simpleType>
193
+ <xs:simpleType name="ExternalFinancialInstitutionIdentification1Code">
194
+ <xs:restriction base="xs:string">
195
+ <xs:minLength value="1"/>
196
+ <xs:maxLength value="4"/>
197
+ </xs:restriction>
198
+ </xs:simpleType>
199
+ <xs:simpleType name="ExternalLocalInstrument1Code">
200
+ <xs:restriction base="xs:string">
201
+ <xs:minLength value="1"/>
202
+ <xs:maxLength value="35"/>
203
+ </xs:restriction>
204
+ </xs:simpleType>
205
+ <xs:simpleType name="ExternalMandateSetupReason1Code">
206
+ <xs:restriction base="xs:string">
207
+ <xs:minLength value="1"/>
208
+ <xs:maxLength value="4"/>
209
+ </xs:restriction>
210
+ </xs:simpleType>
211
+ <xs:simpleType name="ExternalOrganisationIdentification1Code">
212
+ <xs:restriction base="xs:string">
213
+ <xs:minLength value="1"/>
214
+ <xs:maxLength value="4"/>
215
+ </xs:restriction>
216
+ </xs:simpleType>
217
+ <xs:simpleType name="ExternalPersonIdentification1Code">
218
+ <xs:restriction base="xs:string">
219
+ <xs:minLength value="1"/>
220
+ <xs:maxLength value="4"/>
221
+ </xs:restriction>
222
+ </xs:simpleType>
223
+ <xs:simpleType name="ExternalServiceLevel1Code">
224
+ <xs:restriction base="xs:string">
225
+ <xs:minLength value="1"/>
226
+ <xs:maxLength value="4"/>
227
+ </xs:restriction>
228
+ </xs:simpleType>
229
+ <xs:complexType name="FinancialIdentificationSchemeName1Choice">
230
+ <xs:choice>
231
+ <xs:element name="Cd" type="ExternalFinancialInstitutionIdentification1Code"/>
232
+ <xs:element name="Prtry" type="Max35Text"/>
233
+ </xs:choice>
234
+ </xs:complexType>
235
+ <xs:complexType name="FinancialInstitutionIdentification8">
236
+ <xs:sequence>
237
+ <!-- Made BICFI mandatory, previously this line was: -->
238
+ <!-- <xs:element maxOccurs="1" minOccurs="0" name="BICFI" type="BICFIIdentifier"/> -->
239
+ <xs:element name="BICFI" type="BICFIIdentifier"/>
240
+ <xs:element maxOccurs="1" minOccurs="0" name="ClrSysMmbId" type="ClearingSystemMemberIdentification2"/>
241
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
242
+ <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/>
243
+ <xs:element maxOccurs="1" minOccurs="0" name="Othr" type="GenericFinancialIdentification1"/>
244
+ </xs:sequence>
245
+ </xs:complexType>
246
+ <xs:complexType name="Frequency21Choice">
247
+ <xs:choice>
248
+ <xs:element name="Tp" type="Frequency6Code"/>
249
+ <xs:element name="Prd" type="FrequencyPeriod1"/>
250
+ </xs:choice>
251
+ </xs:complexType>
252
+ <xs:simpleType name="Frequency6Code">
253
+ <xs:restriction base="xs:string">
254
+ <xs:enumeration value="YEAR"/>
255
+ <xs:enumeration value="MNTH"/>
256
+ <xs:enumeration value="QURT"/>
257
+ <xs:enumeration value="MIAN"/>
258
+ <xs:enumeration value="WEEK"/>
259
+ <xs:enumeration value="DAIL"/>
260
+ <xs:enumeration value="ADHO"/>
261
+ <xs:enumeration value="INDA"/>
262
+ <xs:enumeration value="FRTN"/>
263
+ </xs:restriction>
264
+ </xs:simpleType>
265
+ <xs:complexType name="FrequencyPeriod1">
266
+ <xs:sequence>
267
+ <xs:element name="Tp" type="Frequency6Code"/>
268
+ <xs:element name="CntPerPrd" type="DecimalNumber"/>
269
+ </xs:sequence>
270
+ </xs:complexType>
271
+ <xs:complexType name="GenericAccountIdentification1">
272
+ <xs:sequence>
273
+ <xs:element name="Id" type="Max34Text"/>
274
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="AccountSchemeName1Choice"/>
275
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
276
+ </xs:sequence>
277
+ </xs:complexType>
278
+ <xs:complexType name="GenericFinancialIdentification1">
279
+ <xs:sequence>
280
+ <xs:element name="Id" type="Max35Text"/>
281
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="FinancialIdentificationSchemeName1Choice"/>
282
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
283
+ </xs:sequence>
284
+ </xs:complexType>
285
+ <xs:complexType name="GenericOrganisationIdentification1">
286
+ <xs:sequence>
287
+ <xs:element name="Id" type="Max35Text"/>
288
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="OrganisationIdentificationSchemeName1Choice"/>
289
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
290
+ </xs:sequence>
291
+ </xs:complexType>
292
+ <xs:complexType name="GenericPersonIdentification1">
293
+ <xs:sequence>
294
+ <xs:element name="Id" type="Max35Text"/>
295
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="PersonIdentificationSchemeName1Choice"/>
296
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
297
+ </xs:sequence>
298
+ </xs:complexType>
299
+ <xs:complexType name="GroupHeader47">
300
+ <xs:sequence>
301
+ <xs:element name="MsgId" type="Max35Text"/>
302
+ <xs:element name="CreDtTm" type="ISODateTime"/>
303
+ <xs:element maxOccurs="2" minOccurs="0" name="Authstn" type="Authorisation1Choice"/>
304
+ <xs:element maxOccurs="1" minOccurs="0" name="InitgPty" type="PartyIdentification43"/>
305
+ <xs:element maxOccurs="1" minOccurs="0" name="InstgAgt" type="BranchAndFinancialInstitutionIdentification5"/>
306
+ <xs:element maxOccurs="1" minOccurs="0" name="InstdAgt" type="BranchAndFinancialInstitutionIdentification5"/>
307
+ </xs:sequence>
308
+ </xs:complexType>
309
+ <xs:simpleType name="IBAN2007Identifier">
310
+ <xs:restriction base="xs:string">
311
+ <xs:pattern value="[A-Z]{2,2}[0-9]{2,2}[a-zA-Z0-9]{1,30}"/>
312
+ </xs:restriction>
313
+ </xs:simpleType>
314
+ <xs:simpleType name="ISODate">
315
+ <xs:restriction base="xs:date"/>
316
+ </xs:simpleType>
317
+ <xs:simpleType name="ISODateTime">
318
+ <xs:restriction base="xs:dateTime"/>
319
+ </xs:simpleType>
320
+ <xs:complexType name="LocalInstrument2Choice">
321
+ <xs:choice>
322
+ <xs:element name="Cd" type="ExternalLocalInstrument1Code"/>
323
+ <xs:element name="Prtry" type="Max35Text"/>
324
+ </xs:choice>
325
+ </xs:complexType>
326
+ <xs:complexType name="Mandate7">
327
+ <xs:sequence>
328
+ <!-- Made MndtId mandatory and only able to be specified once, previously this line was: -->
329
+ <!-- <xs:element maxOccurs="unbounded" minOccurs="0" name="MndtId" type="Max35Text"/> -->
330
+ <xs:element name="MndtId" type="Max35Text"/>
331
+ <xs:element name="MndtReqId" type="Max35Text"/>
332
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="MandateTypeInformation1"/>
333
+ <xs:element maxOccurs="1" minOccurs="0" name="Ocrncs" type="MandateOccurrences3"/>
334
+ <xs:element maxOccurs="1" minOccurs="0" name="ColltnAmt" type="ActiveCurrencyAndAmount"/>
335
+ <xs:element maxOccurs="1" minOccurs="0" name="MaxAmt" type="ActiveCurrencyAndAmount"/>
336
+ <xs:element maxOccurs="1" minOccurs="0" name="Rsn" type="MandateSetupReason1Choice"/>
337
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrSchmeId" type="PartyIdentification43"/>
338
+ <xs:element name="Cdtr" type="PartyIdentification43"/>
339
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrAcct" type="CashAccount24"/>
340
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrAgt" type="BranchAndFinancialInstitutionIdentification5"/>
341
+ <xs:element maxOccurs="1" minOccurs="0" name="UltmtCdtr" type="PartyIdentification43"/>
342
+ <xs:element name="Dbtr" type="PartyIdentification43"/>
343
+ <xs:element maxOccurs="1" minOccurs="0" name="DbtrAcct" type="CashAccount24"/>
344
+ <xs:element name="DbtrAgt" type="BranchAndFinancialInstitutionIdentification5"/>
345
+ <xs:element maxOccurs="1" minOccurs="0" name="UltmtDbtr" type="PartyIdentification43"/>
346
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="RfrdDoc" type="ReferredDocumentInformation6"/>
347
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="SplmtryData" type="SupplementaryData1"/>
348
+ </xs:sequence>
349
+ </xs:complexType>
350
+ <xs:complexType name="MandateInitiationRequestV04">
351
+ <xs:sequence>
352
+ <xs:element name="GrpHdr" type="GroupHeader47"/>
353
+ <xs:element maxOccurs="unbounded" minOccurs="1" name="Mndt" type="Mandate7"/>
354
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="SplmtryData" type="SupplementaryData1"/>
355
+ </xs:sequence>
356
+ </xs:complexType>
357
+ <xs:complexType name="MandateOccurrences3">
358
+ <xs:sequence>
359
+ <xs:element name="SeqTp" type="SequenceType2Code"/>
360
+ <xs:element maxOccurs="1" minOccurs="0" name="Frqcy" type="Frequency21Choice"/>
361
+ <xs:element maxOccurs="1" minOccurs="0" name="Drtn" type="DatePeriodDetails1"/>
362
+ <xs:element maxOccurs="1" minOccurs="0" name="FrstColltnDt" type="ISODate"/>
363
+ <xs:element maxOccurs="1" minOccurs="0" name="FnlColltnDt" type="ISODate"/>
364
+ </xs:sequence>
365
+ </xs:complexType>
366
+ <xs:complexType name="MandateSetupReason1Choice">
367
+ <xs:choice>
368
+ <xs:element name="Cd" type="ExternalMandateSetupReason1Code"/>
369
+ <xs:element name="Prtry" type="Max70Text"/>
370
+ </xs:choice>
371
+ </xs:complexType>
372
+ <xs:complexType name="MandateTypeInformation1">
373
+ <xs:sequence>
374
+ <xs:element maxOccurs="1" minOccurs="0" name="SvcLvl" type="ServiceLevel8Choice"/>
375
+ <xs:element maxOccurs="1" minOccurs="0" name="LclInstrm" type="LocalInstrument2Choice"/>
376
+ </xs:sequence>
377
+ </xs:complexType>
378
+ <xs:simpleType name="Max128Text">
379
+ <xs:restriction base="xs:string">
380
+ <xs:minLength value="1"/>
381
+ <xs:maxLength value="128"/>
382
+ </xs:restriction>
383
+ </xs:simpleType>
384
+ <xs:simpleType name="Max140Text">
385
+ <xs:restriction base="xs:string">
386
+ <xs:minLength value="1"/>
387
+ <xs:maxLength value="140"/>
388
+ </xs:restriction>
389
+ </xs:simpleType>
390
+ <xs:simpleType name="Max16Text">
391
+ <xs:restriction base="xs:string">
392
+ <xs:minLength value="1"/>
393
+ <xs:maxLength value="16"/>
394
+ </xs:restriction>
395
+ </xs:simpleType>
396
+ <xs:simpleType name="Max2048Text">
397
+ <xs:restriction base="xs:string">
398
+ <xs:minLength value="1"/>
399
+ <xs:maxLength value="2048"/>
400
+ </xs:restriction>
401
+ </xs:simpleType>
402
+ <xs:simpleType name="Max34Text">
403
+ <xs:restriction base="xs:string">
404
+ <xs:minLength value="1"/>
405
+ <xs:maxLength value="34"/>
406
+ </xs:restriction>
407
+ </xs:simpleType>
408
+ <xs:simpleType name="Max350Text">
409
+ <xs:restriction base="xs:string">
410
+ <xs:minLength value="1"/>
411
+ <xs:maxLength value="350"/>
412
+ </xs:restriction>
413
+ </xs:simpleType>
414
+ <xs:simpleType name="Max35Text">
415
+ <xs:restriction base="xs:string">
416
+ <xs:minLength value="1"/>
417
+ <xs:maxLength value="35"/>
418
+ </xs:restriction>
419
+ </xs:simpleType>
420
+ <xs:simpleType name="Max70Text">
421
+ <xs:restriction base="xs:string">
422
+ <xs:minLength value="1"/>
423
+ <xs:maxLength value="70"/>
424
+ </xs:restriction>
425
+ </xs:simpleType>
426
+ <xs:simpleType name="NamePrefix1Code">
427
+ <xs:restriction base="xs:string">
428
+ <xs:enumeration value="DOCT"/>
429
+ <xs:enumeration value="MIST"/>
430
+ <xs:enumeration value="MISS"/>
431
+ <xs:enumeration value="MADM"/>
432
+ </xs:restriction>
433
+ </xs:simpleType>
434
+ <xs:complexType name="OrganisationIdentification8">
435
+ <xs:sequence>
436
+ <xs:element maxOccurs="1" minOccurs="0" name="AnyBIC" type="AnyBICIdentifier"/>
437
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Othr" type="GenericOrganisationIdentification1"/>
438
+ </xs:sequence>
439
+ </xs:complexType>
440
+ <xs:complexType name="OrganisationIdentificationSchemeName1Choice">
441
+ <xs:choice>
442
+ <xs:element name="Cd" type="ExternalOrganisationIdentification1Code"/>
443
+ <xs:element name="Prtry" type="Max35Text"/>
444
+ </xs:choice>
445
+ </xs:complexType>
446
+ <xs:complexType name="Party11Choice">
447
+ <xs:choice>
448
+ <xs:element name="OrgId" type="OrganisationIdentification8"/>
449
+ <xs:element name="PrvtId" type="PersonIdentification5"/>
450
+ </xs:choice>
451
+ </xs:complexType>
452
+ <xs:complexType name="PartyIdentification43">
453
+ <xs:sequence>
454
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
455
+ <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/>
456
+ <xs:element maxOccurs="1" minOccurs="0" name="Id" type="Party11Choice"/>
457
+ <xs:element maxOccurs="1" minOccurs="0" name="CtryOfRes" type="CountryCode"/>
458
+ <xs:element maxOccurs="1" minOccurs="0" name="CtctDtls" type="ContactDetails2"/>
459
+ </xs:sequence>
460
+ </xs:complexType>
461
+ <xs:complexType name="PersonIdentification5">
462
+ <xs:sequence>
463
+ <xs:element maxOccurs="1" minOccurs="0" name="DtAndPlcOfBirth" type="DateAndPlaceOfBirth"/>
464
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Othr" type="GenericPersonIdentification1"/>
465
+ </xs:sequence>
466
+ </xs:complexType>
467
+ <xs:complexType name="PersonIdentificationSchemeName1Choice">
468
+ <xs:choice>
469
+ <xs:element name="Cd" type="ExternalPersonIdentification1Code"/>
470
+ <xs:element name="Prtry" type="Max35Text"/>
471
+ </xs:choice>
472
+ </xs:complexType>
473
+ <xs:simpleType name="PhoneNumber">
474
+ <xs:restriction base="xs:string">
475
+ <xs:pattern value="\+[0-9]{1,3}-[0-9()+\-]{1,30}"/>
476
+ </xs:restriction>
477
+ </xs:simpleType>
478
+ <xs:complexType name="PostalAddress6">
479
+ <xs:sequence>
480
+ <xs:element maxOccurs="1" minOccurs="0" name="AdrTp" type="AddressType2Code"/>
481
+ <xs:element maxOccurs="1" minOccurs="0" name="Dept" type="Max70Text"/>
482
+ <xs:element maxOccurs="1" minOccurs="0" name="SubDept" type="Max70Text"/>
483
+ <xs:element maxOccurs="1" minOccurs="0" name="StrtNm" type="Max70Text"/>
484
+ <xs:element maxOccurs="1" minOccurs="0" name="BldgNb" type="Max16Text"/>
485
+ <xs:element maxOccurs="1" minOccurs="0" name="PstCd" type="Max16Text"/>
486
+ <xs:element maxOccurs="1" minOccurs="0" name="TwnNm" type="Max35Text"/>
487
+ <xs:element maxOccurs="1" minOccurs="0" name="CtrySubDvsn" type="Max35Text"/>
488
+ <xs:element maxOccurs="1" minOccurs="0" name="Ctry" type="CountryCode"/>
489
+ <xs:element maxOccurs="7" minOccurs="0" name="AdrLine" type="Max70Text"/>
490
+ </xs:sequence>
491
+ </xs:complexType>
492
+ <xs:complexType name="ReferredDocumentInformation6">
493
+ <xs:sequence>
494
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="ReferredDocumentType4"/>
495
+ <xs:element maxOccurs="1" minOccurs="0" name="Nb" type="Max35Text"/>
496
+ <xs:element maxOccurs="1" minOccurs="0" name="RltdDt" type="ISODate"/>
497
+ </xs:sequence>
498
+ </xs:complexType>
499
+ <xs:complexType name="ReferredDocumentType3Choice">
500
+ <xs:choice>
501
+ <xs:element name="Cd" type="DocumentType6Code"/>
502
+ <xs:element name="Prtry" type="Max35Text"/>
503
+ </xs:choice>
504
+ </xs:complexType>
505
+ <xs:complexType name="ReferredDocumentType4">
506
+ <xs:sequence>
507
+ <xs:element name="CdOrPrtry" type="ReferredDocumentType3Choice"/>
508
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
509
+ </xs:sequence>
510
+ </xs:complexType>
511
+ <xs:simpleType name="SequenceType2Code">
512
+ <xs:restriction base="xs:string">
513
+ <xs:enumeration value="RCUR"/>
514
+ <xs:enumeration value="OOFF"/>
515
+ </xs:restriction>
516
+ </xs:simpleType>
517
+ <xs:complexType name="ServiceLevel8Choice">
518
+ <xs:choice>
519
+ <xs:element name="Cd" type="ExternalServiceLevel1Code"/>
520
+ <xs:element name="Prtry" type="Max35Text"/>
521
+ </xs:choice>
522
+ </xs:complexType>
523
+ <xs:complexType name="SupplementaryData1">
524
+ <xs:sequence>
525
+ <xs:element maxOccurs="1" minOccurs="0" name="PlcAndNm" type="Max350Text"/>
526
+ <xs:element name="Envlp" type="SupplementaryDataEnvelope1"/>
527
+ </xs:sequence>
528
+ </xs:complexType>
529
+ <xs:complexType name="SupplementaryDataEnvelope1">
530
+ <xs:sequence>
531
+ <xs:any namespace="##any" processContents="lax"/>
532
+ </xs:sequence>
533
+ </xs:complexType>
534
+ </xs:schema>
lib/Communicator/schemas/pain.010.001.04.xsd ADDED
@@ -0,0 +1,615 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--Generated by Standards Editor (build:R1.6.2.2) on 2014 Oct 24 13:58:14, ISO 20022 version : 2013-->
3
+ <xs:schema xmlns="urn:iso:std:iso:20022:tech:xsd:pain.010.001.04" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:iso:std:iso:20022:tech:xsd:pain.010.001.04">
4
+ <xs:element name="Document" type="Document"/>
5
+ <xs:complexType name="AccountIdentification4Choice">
6
+ <xs:choice>
7
+ <xs:element name="IBAN" type="IBAN2007Identifier"/>
8
+ <xs:element name="Othr" type="GenericAccountIdentification1"/>
9
+ </xs:choice>
10
+ </xs:complexType>
11
+ <xs:complexType name="AccountSchemeName1Choice">
12
+ <xs:choice>
13
+ <xs:element name="Cd" type="ExternalAccountIdentification1Code"/>
14
+ <xs:element name="Prtry" type="Max35Text"/>
15
+ </xs:choice>
16
+ </xs:complexType>
17
+ <xs:simpleType name="ActiveCurrencyAndAmount_SimpleType">
18
+ <xs:restriction base="xs:decimal">
19
+ <xs:fractionDigits value="2"/>
20
+ <xs:totalDigits value="18"/>
21
+ <xs:minInclusive value="0"/>
22
+ </xs:restriction>
23
+ </xs:simpleType>
24
+ <xs:complexType name="ActiveCurrencyAndAmount">
25
+ <xs:simpleContent>
26
+ <xs:extension base="ActiveCurrencyAndAmount_SimpleType">
27
+ <xs:attribute name="Ccy" type="ActiveCurrencyCode" use="required"/>
28
+ </xs:extension>
29
+ </xs:simpleContent>
30
+ </xs:complexType>
31
+ <xs:simpleType name="ActiveCurrencyCode">
32
+ <xs:restriction base="xs:string">
33
+ <xs:pattern value="[A-Z]{3,3}"/>
34
+ </xs:restriction>
35
+ </xs:simpleType>
36
+ <xs:simpleType name="ActiveOrHistoricCurrencyAndAmount_SimpleType">
37
+ <xs:restriction base="xs:decimal">
38
+ <xs:fractionDigits value="2"/>
39
+ <xs:totalDigits value="18"/>
40
+ <xs:minInclusive value="0"/>
41
+ </xs:restriction>
42
+ </xs:simpleType>
43
+ <xs:complexType name="ActiveOrHistoricCurrencyAndAmount">
44
+ <xs:simpleContent>
45
+ <xs:extension base="ActiveOrHistoricCurrencyAndAmount_SimpleType">
46
+ <xs:attribute name="Ccy" type="ActiveOrHistoricCurrencyCode" use="required"/>
47
+ </xs:extension>
48
+ </xs:simpleContent>
49
+ </xs:complexType>
50
+ <xs:simpleType name="ActiveOrHistoricCurrencyCode">
51
+ <xs:restriction base="xs:string">
52
+ <xs:pattern value="[A-Z]{3,3}"/>
53
+ </xs:restriction>
54
+ </xs:simpleType>
55
+ <xs:simpleType name="AddressType2Code">
56
+ <xs:restriction base="xs:string">
57
+ <xs:enumeration value="ADDR"/>
58
+ <xs:enumeration value="PBOX"/>
59
+ <xs:enumeration value="HOME"/>
60
+ <xs:enumeration value="BIZZ"/>
61
+ <xs:enumeration value="MLTO"/>
62
+ <xs:enumeration value="DLVY"/>
63
+ </xs:restriction>
64
+ </xs:simpleType>
65
+ <xs:simpleType name="AnyBICIdentifier">
66
+ <xs:restriction base="xs:string">
67
+ <xs:pattern value="[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}"/>
68
+ </xs:restriction>
69
+ </xs:simpleType>
70
+ <xs:complexType name="Authorisation1Choice">
71
+ <xs:choice>
72
+ <xs:element name="Cd" type="Authorisation1Code"/>
73
+ <xs:element name="Prtry" type="Max128Text"/>
74
+ </xs:choice>
75
+ </xs:complexType>
76
+ <xs:simpleType name="Authorisation1Code">
77
+ <xs:restriction base="xs:string">
78
+ <xs:enumeration value="AUTH"/>
79
+ <xs:enumeration value="FDET"/>
80
+ <xs:enumeration value="FSUM"/>
81
+ <xs:enumeration value="ILEV"/>
82
+ </xs:restriction>
83
+ </xs:simpleType>
84
+ <xs:simpleType name="BICFIIdentifier">
85
+ <xs:restriction base="xs:string">
86
+ <xs:pattern value="[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}"/>
87
+ </xs:restriction>
88
+ </xs:simpleType>
89
+ <xs:complexType name="BranchAndFinancialInstitutionIdentification5">
90
+ <xs:sequence>
91
+ <xs:element name="FinInstnId" type="FinancialInstitutionIdentification8"/>
92
+ <xs:element maxOccurs="1" minOccurs="0" name="BrnchId" type="BranchData2"/>
93
+ </xs:sequence>
94
+ </xs:complexType>
95
+ <xs:complexType name="BranchData2">
96
+ <xs:sequence>
97
+ <xs:element maxOccurs="1" minOccurs="0" name="Id" type="Max35Text"/>
98
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
99
+ <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/>
100
+ </xs:sequence>
101
+ </xs:complexType>
102
+ <xs:complexType name="CashAccount24">
103
+ <xs:sequence>
104
+ <xs:element name="Id" type="AccountIdentification4Choice"/>
105
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="CashAccountType2Choice"/>
106
+ <xs:element maxOccurs="1" minOccurs="0" name="Ccy" type="ActiveOrHistoricCurrencyCode"/>
107
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max70Text"/>
108
+ </xs:sequence>
109
+ </xs:complexType>
110
+ <xs:complexType name="CashAccountType2Choice">
111
+ <xs:choice>
112
+ <xs:element name="Cd" type="ExternalCashAccountType1Code"/>
113
+ <xs:element name="Prtry" type="Max35Text"/>
114
+ </xs:choice>
115
+ </xs:complexType>
116
+ <xs:complexType name="ClearingSystemIdentification2Choice">
117
+ <xs:choice>
118
+ <xs:element name="Cd" type="ExternalClearingSystemIdentification1Code"/>
119
+ <xs:element name="Prtry" type="Max35Text"/>
120
+ </xs:choice>
121
+ </xs:complexType>
122
+ <xs:complexType name="ClearingSystemMemberIdentification2">
123
+ <xs:sequence>
124
+ <xs:element maxOccurs="1" minOccurs="0" name="ClrSysId" type="ClearingSystemIdentification2Choice"/>
125
+ <xs:element name="MmbId" type="Max35Text"/>
126
+ </xs:sequence>
127
+ </xs:complexType>
128
+ <xs:complexType name="ContactDetails2">
129
+ <xs:sequence>
130
+ <xs:element maxOccurs="1" minOccurs="0" name="NmPrfx" type="NamePrefix1Code"/>
131
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
132
+ <xs:element maxOccurs="1" minOccurs="0" name="PhneNb" type="PhoneNumber"/>
133
+ <xs:element maxOccurs="1" minOccurs="0" name="MobNb" type="PhoneNumber"/>
134
+ <xs:element maxOccurs="1" minOccurs="0" name="FaxNb" type="PhoneNumber"/>
135
+ <xs:element maxOccurs="1" minOccurs="0" name="EmailAdr" type="Max2048Text"/>
136
+ <xs:element maxOccurs="1" minOccurs="0" name="Othr" type="Max35Text"/>
137
+ </xs:sequence>
138
+ </xs:complexType>
139
+ <xs:simpleType name="CountryCode">
140
+ <xs:restriction base="xs:string">
141
+ <xs:pattern value="[A-Z]{2,2}"/>
142
+ </xs:restriction>
143
+ </xs:simpleType>
144
+ <xs:complexType name="DateAndPlaceOfBirth">
145
+ <xs:sequence>
146
+ <xs:element name="BirthDt" type="ISODate"/>
147
+ <xs:element maxOccurs="1" minOccurs="0" name="PrvcOfBirth" type="Max35Text"/>
148
+ <xs:element name="CityOfBirth" type="Max35Text"/>
149
+ <xs:element name="CtryOfBirth" type="CountryCode"/>
150
+ </xs:sequence>
151
+ </xs:complexType>
152
+ <xs:complexType name="DatePeriodDetails1">
153
+ <xs:sequence>
154
+ <xs:element name="FrDt" type="ISODate"/>
155
+ <xs:element maxOccurs="1" minOccurs="0" name="ToDt" type="ISODate"/>
156
+ </xs:sequence>
157
+ </xs:complexType>
158
+ <xs:simpleType name="DecimalNumber">
159
+ <xs:restriction base="xs:decimal">
160
+ <xs:fractionDigits value="17"/>
161
+ <xs:totalDigits value="18"/>
162
+ </xs:restriction>
163
+ </xs:simpleType>
164
+ <xs:complexType name="Document">
165
+ <xs:sequence>
166
+ <xs:element name="MndtAmdmntReq" type="MandateAmendmentRequestV04"/>
167
+ </xs:sequence>
168
+ </xs:complexType>
169
+ <xs:simpleType name="DocumentType6Code">
170
+ <xs:restriction base="xs:string">
171
+ <xs:enumeration value="MSIN"/>
172
+ <xs:enumeration value="CNFA"/>
173
+ <xs:enumeration value="DNFA"/>
174
+ <xs:enumeration value="CINV"/>
175
+ <xs:enumeration value="CREN"/>
176
+ <xs:enumeration value="DEBN"/>
177
+ <xs:enumeration value="HIRI"/>
178
+ <xs:enumeration value="SBIN"/>
179
+ <xs:enumeration value="CMCN"/>
180
+ <xs:enumeration value="SOAC"/>
181
+ <xs:enumeration value="DISP"/>
182
+ <xs:enumeration value="BOLD"/>
183
+ <xs:enumeration value="VCHR"/>
184
+ <xs:enumeration value="AROI"/>
185
+ <xs:enumeration value="TSUT"/>
186
+ <xs:enumeration value="PUOR"/>
187
+ </xs:restriction>
188
+ </xs:simpleType>
189
+ <xs:simpleType name="ExternalAccountIdentification1Code">
190
+ <xs:restriction base="xs:string">
191
+ <xs:minLength value="1"/>
192
+ <xs:maxLength value="4"/>
193
+ </xs:restriction>
194
+ </xs:simpleType>
195
+ <xs:simpleType name="ExternalCashAccountType1Code">
196
+ <xs:restriction base="xs:string">
197
+ <xs:minLength value="1"/>
198
+ <xs:maxLength value="4"/>
199
+ </xs:restriction>
200
+ </xs:simpleType>
201
+ <xs:simpleType name="ExternalClearingSystemIdentification1Code">
202
+ <xs:restriction base="xs:string">
203
+ <xs:minLength value="1"/>
204
+ <xs:maxLength value="5"/>
205
+ </xs:restriction>
206
+ </xs:simpleType>
207
+ <xs:simpleType name="ExternalFinancialInstitutionIdentification1Code">
208
+ <xs:restriction base="xs:string">
209
+ <xs:minLength value="1"/>
210
+ <xs:maxLength value="4"/>
211
+ </xs:restriction>
212
+ </xs:simpleType>
213
+ <xs:simpleType name="ExternalLocalInstrument1Code">
214
+ <xs:restriction base="xs:string">
215
+ <xs:minLength value="1"/>
216
+ <xs:maxLength value="35"/>
217
+ </xs:restriction>
218
+ </xs:simpleType>
219
+ <xs:simpleType name="ExternalMandateReason1Code">
220
+ <xs:restriction base="xs:string">
221
+ <xs:minLength value="1"/>
222
+ <xs:maxLength value="4"/>
223
+ </xs:restriction>
224
+ </xs:simpleType>
225
+ <xs:simpleType name="ExternalMandateSetupReason1Code">
226
+ <xs:restriction base="xs:string">
227
+ <xs:minLength value="1"/>
228
+ <xs:maxLength value="4"/>
229
+ </xs:restriction>
230
+ </xs:simpleType>
231
+ <xs:simpleType name="ExternalOrganisationIdentification1Code">
232
+ <xs:restriction base="xs:string">
233
+ <xs:minLength value="1"/>
234
+ <xs:maxLength value="4"/>
235
+ </xs:restriction>
236
+ </xs:simpleType>
237
+ <xs:simpleType name="ExternalPersonIdentification1Code">
238
+ <xs:restriction base="xs:string">
239
+ <xs:minLength value="1"/>
240
+ <xs:maxLength value="4"/>
241
+ </xs:restriction>
242
+ </xs:simpleType>
243
+ <xs:simpleType name="ExternalServiceLevel1Code">
244
+ <xs:restriction base="xs:string">
245
+ <xs:minLength value="1"/>
246
+ <xs:maxLength value="4"/>
247
+ </xs:restriction>
248
+ </xs:simpleType>
249
+ <xs:complexType name="FinancialIdentificationSchemeName1Choice">
250
+ <xs:choice>
251
+ <xs:element name="Cd" type="ExternalFinancialInstitutionIdentification1Code"/>
252
+ <xs:element name="Prtry" type="Max35Text"/>
253
+ </xs:choice>
254
+ </xs:complexType>
255
+ <xs:complexType name="FinancialInstitutionIdentification8">
256
+ <xs:sequence>
257
+ <!-- Made BICFI mandatory, previously this line was: -->
258
+ <!-- <xs:element maxOccurs="1" minOccurs="0" name="BICFI" type="BICFIIdentifier"/> -->
259
+ <xs:element name="BICFI" type="BICFIIdentifier"/>
260
+ <xs:element maxOccurs="1" minOccurs="0" name="ClrSysMmbId" type="ClearingSystemMemberIdentification2"/>
261
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
262
+ <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/>
263
+ <xs:element maxOccurs="1" minOccurs="0" name="Othr" type="GenericFinancialIdentification1"/>
264
+ </xs:sequence>
265
+ </xs:complexType>
266
+ <xs:complexType name="Frequency21Choice">
267
+ <xs:choice>
268
+ <xs:element name="Tp" type="Frequency6Code"/>
269
+ <xs:element name="Prd" type="FrequencyPeriod1"/>
270
+ </xs:choice>
271
+ </xs:complexType>
272
+ <xs:simpleType name="Frequency6Code">
273
+ <xs:restriction base="xs:string">
274
+ <xs:enumeration value="YEAR"/>
275
+ <xs:enumeration value="MNTH"/>
276
+ <xs:enumeration value="QURT"/>
277
+ <xs:enumeration value="MIAN"/>
278
+ <xs:enumeration value="WEEK"/>
279
+ <xs:enumeration value="DAIL"/>
280
+ <xs:enumeration value="ADHO"/>
281
+ <xs:enumeration value="INDA"/>
282
+ <xs:enumeration value="FRTN"/>
283
+ </xs:restriction>
284
+ </xs:simpleType>
285
+ <xs:complexType name="FrequencyPeriod1">
286
+ <xs:sequence>
287
+ <xs:element name="Tp" type="Frequency6Code"/>
288
+ <xs:element name="CntPerPrd" type="DecimalNumber"/>
289
+ </xs:sequence>
290
+ </xs:complexType>
291
+ <xs:complexType name="GenericAccountIdentification1">
292
+ <xs:sequence>
293
+ <xs:element name="Id" type="Max34Text"/>
294
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="AccountSchemeName1Choice"/>
295
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
296
+ </xs:sequence>
297
+ </xs:complexType>
298
+ <xs:complexType name="GenericFinancialIdentification1">
299
+ <xs:sequence>
300
+ <xs:element name="Id" type="Max35Text"/>
301
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="FinancialIdentificationSchemeName1Choice"/>
302
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
303
+ </xs:sequence>
304
+ </xs:complexType>
305
+ <xs:complexType name="GenericOrganisationIdentification1">
306
+ <xs:sequence>
307
+ <xs:element name="Id" type="Max35Text"/>
308
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="OrganisationIdentificationSchemeName1Choice"/>
309
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
310
+ </xs:sequence>
311
+ </xs:complexType>
312
+ <xs:complexType name="GenericPersonIdentification1">
313
+ <xs:sequence>
314
+ <xs:element name="Id" type="Max35Text"/>
315
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="PersonIdentificationSchemeName1Choice"/>
316
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
317
+ </xs:sequence>
318
+ </xs:complexType>
319
+ <xs:complexType name="GroupHeader47">
320
+ <xs:sequence>
321
+ <xs:element name="MsgId" type="Max35Text"/>
322
+ <xs:element name="CreDtTm" type="ISODateTime"/>
323
+ <xs:element maxOccurs="2" minOccurs="0" name="Authstn" type="Authorisation1Choice"/>
324
+ <xs:element maxOccurs="1" minOccurs="0" name="InitgPty" type="PartyIdentification43"/>
325
+ <xs:element maxOccurs="1" minOccurs="0" name="InstgAgt" type="BranchAndFinancialInstitutionIdentification5"/>
326
+ <xs:element maxOccurs="1" minOccurs="0" name="InstdAgt" type="BranchAndFinancialInstitutionIdentification5"/>
327
+ </xs:sequence>
328
+ </xs:complexType>
329
+ <xs:simpleType name="IBAN2007Identifier">
330
+ <xs:restriction base="xs:string">
331
+ <xs:pattern value="[A-Z]{2,2}[0-9]{2,2}[a-zA-Z0-9]{1,30}"/>
332
+ </xs:restriction>
333
+ </xs:simpleType>
334
+ <xs:simpleType name="ISODate">
335
+ <xs:restriction base="xs:date"/>
336
+ </xs:simpleType>
337
+ <xs:simpleType name="ISODateTime">
338
+ <xs:restriction base="xs:dateTime"/>
339
+ </xs:simpleType>
340
+ <xs:complexType name="LocalInstrument2Choice">
341
+ <xs:choice>
342
+ <xs:element name="Cd" type="ExternalLocalInstrument1Code"/>
343
+ <xs:element name="Prtry" type="Max35Text"/>
344
+ </xs:choice>
345
+ </xs:complexType>
346
+ <xs:complexType name="Mandate5">
347
+ <xs:sequence>
348
+ <xs:element name="MndtId" type="Max35Text"/>
349
+ <xs:element maxOccurs="1" minOccurs="0" name="MndtReqId" type="Max35Text"/>
350
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="MandateTypeInformation1"/>
351
+ <xs:element maxOccurs="1" minOccurs="0" name="Ocrncs" type="MandateOccurrences3"/>
352
+ <xs:element maxOccurs="1" minOccurs="0" name="ColltnAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
353
+ <xs:element maxOccurs="1" minOccurs="0" name="MaxAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
354
+ <xs:element maxOccurs="1" minOccurs="0" name="Rsn" type="MandateSetupReason1Choice"/>
355
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrSchmeId" type="PartyIdentification43"/>
356
+ <xs:element name="Cdtr" type="PartyIdentification43"/>
357
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrAcct" type="CashAccount24"/>
358
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrAgt" type="BranchAndFinancialInstitutionIdentification5"/>
359
+ <xs:element maxOccurs="1" minOccurs="0" name="UltmtCdtr" type="PartyIdentification43"/>
360
+ <xs:element name="Dbtr" type="PartyIdentification43"/>
361
+ <!-- Made DbtrAcct mandatory, previously this line was: -->
362
+ <!-- <xs:element maxOccurs="1" minOccurs="0" name="DbtrAcct" type="CashAccount24"/> -->
363
+ <xs:element name="DbtrAcct" type="CashAccount24"/>
364
+ <xs:element name="DbtrAgt" type="BranchAndFinancialInstitutionIdentification5"/>
365
+ <xs:element maxOccurs="1" minOccurs="0" name="UltmtDbtr" type="PartyIdentification43"/>
366
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="RfrdDoc" type="ReferredDocumentInformation6"/>
367
+ </xs:sequence>
368
+ </xs:complexType>
369
+ <xs:complexType name="Mandate6">
370
+ <xs:sequence>
371
+ <xs:element name="MndtId" type="Max35Text"/>
372
+ <xs:element maxOccurs="1" minOccurs="0" name="MndtReqId" type="Max35Text"/>
373
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="MandateTypeInformation1"/>
374
+ <xs:element maxOccurs="1" minOccurs="0" name="Ocrncs" type="MandateOccurrences3"/>
375
+ <xs:element maxOccurs="1" minOccurs="0" name="ColltnAmt" type="ActiveCurrencyAndAmount"/>
376
+ <xs:element maxOccurs="1" minOccurs="0" name="MaxAmt" type="ActiveCurrencyAndAmount"/>
377
+ <xs:element maxOccurs="1" minOccurs="0" name="Rsn" type="MandateSetupReason1Choice"/>
378
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrSchmeId" type="PartyIdentification43"/>
379
+ <xs:element maxOccurs="1" minOccurs="0" name="Cdtr" type="PartyIdentification43"/>
380
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrAcct" type="CashAccount24"/>
381
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrAgt" type="BranchAndFinancialInstitutionIdentification5"/>
382
+ <xs:element maxOccurs="1" minOccurs="0" name="UltmtCdtr" type="PartyIdentification43"/>
383
+ <xs:element maxOccurs="1" minOccurs="0" name="Dbtr" type="PartyIdentification43"/>
384
+ <xs:element maxOccurs="1" minOccurs="0" name="DbtrAcct" type="CashAccount24"/>
385
+ <xs:element maxOccurs="1" minOccurs="0" name="DbtrAgt" type="BranchAndFinancialInstitutionIdentification5"/>
386
+ <xs:element maxOccurs="1" minOccurs="0" name="UltmtDbtr" type="PartyIdentification43"/>
387
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="RfrdDoc" type="ReferredDocumentInformation6"/>
388
+ </xs:sequence>
389
+ </xs:complexType>
390
+ <xs:complexType name="MandateAmendment4">
391
+ <xs:sequence>
392
+ <xs:element maxOccurs="1" minOccurs="0" name="OrgnlMsgInf" type="OriginalMessageInformation1"/>
393
+ <xs:element name="AmdmntRsn" type="MandateAmendmentReason1"/>
394
+ <xs:element name="Mndt" type="Mandate6"/>
395
+ <xs:element name="OrgnlMndt" type="OriginalMandate3Choice"/>
396
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="SplmtryData" type="SupplementaryData1"/>
397
+ </xs:sequence>
398
+ </xs:complexType>
399
+ <xs:complexType name="MandateAmendmentReason1">
400
+ <xs:sequence>
401
+ <xs:element maxOccurs="1" minOccurs="0" name="Orgtr" type="PartyIdentification43"/>
402
+ <xs:element name="Rsn" type="MandateReason1Choice"/>
403
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="AddtlInf" type="Max105Text"/>
404
+ </xs:sequence>
405
+ </xs:complexType>
406
+ <xs:complexType name="MandateAmendmentRequestV04">
407
+ <xs:sequence>
408
+ <xs:element name="GrpHdr" type="GroupHeader47"/>
409
+ <xs:element maxOccurs="unbounded" minOccurs="1" name="UndrlygAmdmntDtls" type="MandateAmendment4"/>
410
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="SplmtryData" type="SupplementaryData1"/>
411
+ </xs:sequence>
412
+ </xs:complexType>
413
+ <xs:complexType name="MandateOccurrences3">
414
+ <xs:sequence>
415
+ <xs:element name="SeqTp" type="SequenceType2Code"/>
416
+ <xs:element maxOccurs="1" minOccurs="0" name="Frqcy" type="Frequency21Choice"/>
417
+ <xs:element maxOccurs="1" minOccurs="0" name="Drtn" type="DatePeriodDetails1"/>
418
+ <xs:element maxOccurs="1" minOccurs="0" name="FrstColltnDt" type="ISODate"/>
419
+ <xs:element maxOccurs="1" minOccurs="0" name="FnlColltnDt" type="ISODate"/>
420
+ </xs:sequence>
421
+ </xs:complexType>
422
+ <xs:complexType name="MandateReason1Choice">
423
+ <xs:choice>
424
+ <xs:element name="Cd" type="ExternalMandateReason1Code"/>
425
+ <xs:element name="Prtry" type="Max35Text"/>
426
+ </xs:choice>
427
+ </xs:complexType>
428
+ <xs:complexType name="MandateSetupReason1Choice">
429
+ <xs:choice>
430
+ <xs:element name="Cd" type="ExternalMandateSetupReason1Code"/>
431
+ <xs:element name="Prtry" type="Max70Text"/>
432
+ </xs:choice>
433
+ </xs:complexType>
434
+ <xs:complexType name="MandateTypeInformation1">
435
+ <xs:sequence>
436
+ <xs:element maxOccurs="1" minOccurs="0" name="SvcLvl" type="ServiceLevel8Choice"/>
437
+ <xs:element maxOccurs="1" minOccurs="0" name="LclInstrm" type="LocalInstrument2Choice"/>
438
+ </xs:sequence>
439
+ </xs:complexType>
440
+ <xs:simpleType name="Max105Text">
441
+ <xs:restriction base="xs:string">
442
+ <xs:minLength value="1"/>
443
+ <xs:maxLength value="105"/>
444
+ </xs:restriction>
445
+ </xs:simpleType>
446
+ <xs:simpleType name="Max128Text">
447
+ <xs:restriction base="xs:string">
448
+ <xs:minLength value="1"/>
449
+ <xs:maxLength value="128"/>
450
+ </xs:restriction>
451
+ </xs:simpleType>
452
+ <xs:simpleType name="Max140Text">
453
+ <xs:restriction base="xs:string">
454
+ <xs:minLength value="1"/>
455
+ <xs:maxLength value="140"/>
456
+ </xs:restriction>
457
+ </xs:simpleType>
458
+ <xs:simpleType name="Max16Text">
459
+ <xs:restriction base="xs:string">
460
+ <xs:minLength value="1"/>
461
+ <xs:maxLength value="16"/>
462
+ </xs:restriction>
463
+ </xs:simpleType>
464
+ <xs:simpleType name="Max2048Text">
465
+ <xs:restriction base="xs:string">
466
+ <xs:minLength value="1"/>
467
+ <xs:maxLength value="2048"/>
468
+ </xs:restriction>
469
+ </xs:simpleType>
470
+ <xs:simpleType name="Max34Text">
471
+ <xs:restriction base="xs:string">
472
+ <xs:minLength value="1"/>
473
+ <xs:maxLength value="34"/>
474
+ </xs:restriction>
475
+ </xs:simpleType>
476
+ <xs:simpleType name="Max350Text">
477
+ <xs:restriction base="xs:string">
478
+ <xs:minLength value="1"/>
479
+ <xs:maxLength value="350"/>
480
+ </xs:restriction>
481
+ </xs:simpleType>
482
+ <xs:simpleType name="Max35Text">
483
+ <xs:restriction base="xs:string">
484
+ <xs:minLength value="1"/>
485
+ <xs:maxLength value="35"/>
486
+ </xs:restriction>
487
+ </xs:simpleType>
488
+ <xs:simpleType name="Max70Text">
489
+ <xs:restriction base="xs:string">
490
+ <xs:minLength value="1"/>
491
+ <xs:maxLength value="70"/>
492
+ </xs:restriction>
493
+ </xs:simpleType>
494
+ <xs:simpleType name="NamePrefix1Code">
495
+ <xs:restriction base="xs:string">
496
+ <xs:enumeration value="DOCT"/>
497
+ <xs:enumeration value="MIST"/>
498
+ <xs:enumeration value="MISS"/>
499
+ <xs:enumeration value="MADM"/>
500
+ </xs:restriction>
501
+ </xs:simpleType>
502
+ <xs:complexType name="OrganisationIdentification8">
503
+ <xs:sequence>
504
+ <xs:element maxOccurs="1" minOccurs="0" name="AnyBIC" type="AnyBICIdentifier"/>
505
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Othr" type="GenericOrganisationIdentification1"/>
506
+ </xs:sequence>
507
+ </xs:complexType>
508
+ <xs:complexType name="OrganisationIdentificationSchemeName1Choice">
509
+ <xs:choice>
510
+ <xs:element name="Cd" type="ExternalOrganisationIdentification1Code"/>
511
+ <xs:element name="Prtry" type="Max35Text"/>
512
+ </xs:choice>
513
+ </xs:complexType>
514
+ <xs:complexType name="OriginalMandate3Choice">
515
+ <xs:choice>
516
+ <xs:element name="OrgnlMndtId" type="Max35Text"/>
517
+ <xs:element name="OrgnlMndt" type="Mandate5"/>
518
+ </xs:choice>
519
+ </xs:complexType>
520
+ <xs:complexType name="OriginalMessageInformation1">
521
+ <xs:sequence>
522
+ <xs:element name="MsgId" type="Max35Text"/>
523
+ <xs:element name="MsgNmId" type="Max35Text"/>
524
+ <xs:element maxOccurs="1" minOccurs="0" name="CreDtTm" type="ISODateTime"/>
525
+ </xs:sequence>
526
+ </xs:complexType>
527
+ <xs:complexType name="Party11Choice">
528
+ <xs:choice>
529
+ <xs:element name="OrgId" type="OrganisationIdentification8"/>
530
+ <xs:element name="PrvtId" type="PersonIdentification5"/>
531
+ </xs:choice>
532
+ </xs:complexType>
533
+ <xs:complexType name="PartyIdentification43">
534
+ <xs:sequence>
535
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
536
+ <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/>
537
+ <xs:element maxOccurs="1" minOccurs="0" name="Id" type="Party11Choice"/>
538
+ <xs:element maxOccurs="1" minOccurs="0" name="CtryOfRes" type="CountryCode"/>
539
+ <xs:element maxOccurs="1" minOccurs="0" name="CtctDtls" type="ContactDetails2"/>
540
+ </xs:sequence>
541
+ </xs:complexType>
542
+ <xs:complexType name="PersonIdentification5">
543
+ <xs:sequence>
544
+ <xs:element maxOccurs="1" minOccurs="0" name="DtAndPlcOfBirth" type="DateAndPlaceOfBirth"/>
545
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Othr" type="GenericPersonIdentification1"/>
546
+ </xs:sequence>
547
+ </xs:complexType>
548
+ <xs:complexType name="PersonIdentificationSchemeName1Choice">
549
+ <xs:choice>
550
+ <xs:element name="Cd" type="ExternalPersonIdentification1Code"/>
551
+ <xs:element name="Prtry" type="Max35Text"/>
552
+ </xs:choice>
553
+ </xs:complexType>
554
+ <xs:simpleType name="PhoneNumber">
555
+ <xs:restriction base="xs:string">
556
+ <xs:pattern value="\+[0-9]{1,3}-[0-9()+\-]{1,30}"/>
557
+ </xs:restriction>
558
+ </xs:simpleType>
559
+ <xs:complexType name="PostalAddress6">
560
+ <xs:sequence>
561
+ <xs:element maxOccurs="1" minOccurs="0" name="AdrTp" type="AddressType2Code"/>
562
+ <xs:element maxOccurs="1" minOccurs="0" name="Dept" type="Max70Text"/>
563
+ <xs:element maxOccurs="1" minOccurs="0" name="SubDept" type="Max70Text"/>
564
+ <xs:element maxOccurs="1" minOccurs="0" name="StrtNm" type="Max70Text"/>
565
+ <xs:element maxOccurs="1" minOccurs="0" name="BldgNb" type="Max16Text"/>
566
+ <xs:element maxOccurs="1" minOccurs="0" name="PstCd" type="Max16Text"/>
567
+ <xs:element maxOccurs="1" minOccurs="0" name="TwnNm" type="Max35Text"/>
568
+ <xs:element maxOccurs="1" minOccurs="0" name="CtrySubDvsn" type="Max35Text"/>
569
+ <xs:element maxOccurs="1" minOccurs="0" name="Ctry" type="CountryCode"/>
570
+ <xs:element maxOccurs="7" minOccurs="0" name="AdrLine" type="Max70Text"/>
571
+ </xs:sequence>
572
+ </xs:complexType>
573
+ <xs:complexType name="ReferredDocumentInformation6">
574
+ <xs:sequence>
575
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="ReferredDocumentType4"/>
576
+ <xs:element maxOccurs="1" minOccurs="0" name="Nb" type="Max35Text"/>
577
+ <xs:element maxOccurs="1" minOccurs="0" name="RltdDt" type="ISODate"/>
578
+ </xs:sequence>
579
+ </xs:complexType>
580
+ <xs:complexType name="ReferredDocumentType3Choice">
581
+ <xs:choice>
582
+ <xs:element name="Cd" type="DocumentType6Code"/>
583
+ <xs:element name="Prtry" type="Max35Text"/>
584
+ </xs:choice>
585
+ </xs:complexType>
586
+ <xs:complexType name="ReferredDocumentType4">
587
+ <xs:sequence>
588
+ <xs:element name="CdOrPrtry" type="ReferredDocumentType3Choice"/>
589
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
590
+ </xs:sequence>
591
+ </xs:complexType>
592
+ <xs:simpleType name="SequenceType2Code">
593
+ <xs:restriction base="xs:string">
594
+ <xs:enumeration value="RCUR"/>
595
+ <xs:enumeration value="OOFF"/>
596
+ </xs:restriction>
597
+ </xs:simpleType>
598
+ <xs:complexType name="ServiceLevel8Choice">
599
+ <xs:choice>
600
+ <xs:element name="Cd" type="ExternalServiceLevel1Code"/>
601
+ <xs:element name="Prtry" type="Max35Text"/>
602
+ </xs:choice>
603
+ </xs:complexType>
604
+ <xs:complexType name="SupplementaryData1">
605
+ <xs:sequence>
606
+ <xs:element maxOccurs="1" minOccurs="0" name="PlcAndNm" type="Max350Text"/>
607
+ <xs:element name="Envlp" type="SupplementaryDataEnvelope1"/>
608
+ </xs:sequence>
609
+ </xs:complexType>
610
+ <xs:complexType name="SupplementaryDataEnvelope1">
611
+ <xs:sequence>
612
+ <xs:any namespace="##any" processContents="lax"/>
613
+ </xs:sequence>
614
+ </xs:complexType>
615
+ </xs:schema>
lib/Communicator/schemas/pain.011.001.04.xsd ADDED
@@ -0,0 +1,574 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--Generated by Standards Editor (build:R1.6.2.2) on 2014 Oct 24 13:58:14, ISO 20022 version : 2013-->
3
+ <xs:schema xmlns="urn:iso:std:iso:20022:tech:xsd:pain.011.001.04" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:iso:std:iso:20022:tech:xsd:pain.011.001.04">
4
+ <xs:element name="Document" type="Document"/>
5
+ <xs:complexType name="AccountIdentification4Choice">
6
+ <xs:choice>
7
+ <xs:element name="IBAN" type="IBAN2007Identifier"/>
8
+ <xs:element name="Othr" type="GenericAccountIdentification1"/>
9
+ </xs:choice>
10
+ </xs:complexType>
11
+ <xs:complexType name="AccountSchemeName1Choice">
12
+ <xs:choice>
13
+ <xs:element name="Cd" type="ExternalAccountIdentification1Code"/>
14
+ <xs:element name="Prtry" type="Max35Text"/>
15
+ </xs:choice>
16
+ </xs:complexType>
17
+ <xs:simpleType name="ActiveOrHistoricCurrencyAndAmount_SimpleType">
18
+ <xs:restriction base="xs:decimal">
19
+ <xs:fractionDigits value="2"/>
20
+ <xs:totalDigits value="18"/>
21
+ <xs:minInclusive value="0"/>
22
+ </xs:restriction>
23
+ </xs:simpleType>
24
+ <xs:complexType name="ActiveOrHistoricCurrencyAndAmount">
25
+ <xs:simpleContent>
26
+ <xs:extension base="ActiveOrHistoricCurrencyAndAmount_SimpleType">
27
+ <xs:attribute name="Ccy" type="ActiveOrHistoricCurrencyCode" use="required"/>
28
+ </xs:extension>
29
+ </xs:simpleContent>
30
+ </xs:complexType>
31
+ <xs:simpleType name="ActiveOrHistoricCurrencyCode">
32
+ <xs:restriction base="xs:string">
33
+ <xs:pattern value="[A-Z]{3,3}"/>
34
+ </xs:restriction>
35
+ </xs:simpleType>
36
+ <xs:simpleType name="AddressType2Code">
37
+ <xs:restriction base="xs:string">
38
+ <xs:enumeration value="ADDR"/>
39
+ <xs:enumeration value="PBOX"/>
40
+ <xs:enumeration value="HOME"/>
41
+ <xs:enumeration value="BIZZ"/>
42
+ <xs:enumeration value="MLTO"/>
43
+ <xs:enumeration value="DLVY"/>
44
+ </xs:restriction>
45
+ </xs:simpleType>
46
+ <xs:simpleType name="AnyBICIdentifier">
47
+ <xs:restriction base="xs:string">
48
+ <xs:pattern value="[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}"/>
49
+ </xs:restriction>
50
+ </xs:simpleType>
51
+ <xs:complexType name="Authorisation1Choice">
52
+ <xs:choice>
53
+ <xs:element name="Cd" type="Authorisation1Code"/>
54
+ <xs:element name="Prtry" type="Max128Text"/>
55
+ </xs:choice>
56
+ </xs:complexType>
57
+ <xs:simpleType name="Authorisation1Code">
58
+ <xs:restriction base="xs:string">
59
+ <xs:enumeration value="AUTH"/>
60
+ <xs:enumeration value="FDET"/>
61
+ <xs:enumeration value="FSUM"/>
62
+ <xs:enumeration value="ILEV"/>
63
+ </xs:restriction>
64
+ </xs:simpleType>
65
+ <xs:simpleType name="BICFIIdentifier">
66
+ <xs:restriction base="xs:string">
67
+ <xs:pattern value="[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}"/>
68
+ </xs:restriction>
69
+ </xs:simpleType>
70
+ <xs:complexType name="BranchAndFinancialInstitutionIdentification5">
71
+ <xs:sequence>
72
+ <xs:element name="FinInstnId" type="FinancialInstitutionIdentification8"/>
73
+ <xs:element maxOccurs="1" minOccurs="0" name="BrnchId" type="BranchData2"/>
74
+ </xs:sequence>
75
+ </xs:complexType>
76
+ <xs:complexType name="BranchData2">
77
+ <xs:sequence>
78
+ <xs:element maxOccurs="1" minOccurs="0" name="Id" type="Max35Text"/>
79
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
80
+ <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/>
81
+ </xs:sequence>
82
+ </xs:complexType>
83
+ <xs:complexType name="CashAccount24">
84
+ <xs:sequence>
85
+ <xs:element name="Id" type="AccountIdentification4Choice"/>
86
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="CashAccountType2Choice"/>
87
+ <xs:element maxOccurs="1" minOccurs="0" name="Ccy" type="ActiveOrHistoricCurrencyCode"/>
88
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max70Text"/>
89
+ </xs:sequence>
90
+ </xs:complexType>
91
+ <xs:complexType name="CashAccountType2Choice">
92
+ <xs:choice>
93
+ <xs:element name="Cd" type="ExternalCashAccountType1Code"/>
94
+ <xs:element name="Prtry" type="Max35Text"/>
95
+ </xs:choice>
96
+ </xs:complexType>
97
+ <xs:complexType name="ClearingSystemIdentification2Choice">
98
+ <xs:choice>
99
+ <xs:element name="Cd" type="ExternalClearingSystemIdentification1Code"/>
100
+ <xs:element name="Prtry" type="Max35Text"/>
101
+ </xs:choice>
102
+ </xs:complexType>
103
+ <xs:complexType name="ClearingSystemMemberIdentification2">
104
+ <xs:sequence>
105
+ <xs:element maxOccurs="1" minOccurs="0" name="ClrSysId" type="ClearingSystemIdentification2Choice"/>
106
+ <xs:element name="MmbId" type="Max35Text"/>
107
+ </xs:sequence>
108
+ </xs:complexType>
109
+ <xs:complexType name="ContactDetails2">
110
+ <xs:sequence>
111
+ <xs:element maxOccurs="1" minOccurs="0" name="NmPrfx" type="NamePrefix1Code"/>
112
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
113
+ <xs:element maxOccurs="1" minOccurs="0" name="PhneNb" type="PhoneNumber"/>
114
+ <xs:element maxOccurs="1" minOccurs="0" name="MobNb" type="PhoneNumber"/>
115
+ <xs:element maxOccurs="1" minOccurs="0" name="FaxNb" type="PhoneNumber"/>
116
+ <xs:element maxOccurs="1" minOccurs="0" name="EmailAdr" type="Max2048Text"/>
117
+ <xs:element maxOccurs="1" minOccurs="0" name="Othr" type="Max35Text"/>
118
+ </xs:sequence>
119
+ </xs:complexType>
120
+ <xs:simpleType name="CountryCode">
121
+ <xs:restriction base="xs:string">
122
+ <xs:pattern value="[A-Z]{2,2}"/>
123
+ </xs:restriction>
124
+ </xs:simpleType>
125
+ <xs:complexType name="DateAndPlaceOfBirth">
126
+ <xs:sequence>
127
+ <xs:element name="BirthDt" type="ISODate"/>
128
+ <xs:element maxOccurs="1" minOccurs="0" name="PrvcOfBirth" type="Max35Text"/>
129
+ <xs:element name="CityOfBirth" type="Max35Text"/>
130
+ <xs:element name="CtryOfBirth" type="CountryCode"/>
131
+ </xs:sequence>
132
+ </xs:complexType>
133
+ <xs:complexType name="DatePeriodDetails1">
134
+ <xs:sequence>
135
+ <xs:element name="FrDt" type="ISODate"/>
136
+ <xs:element maxOccurs="1" minOccurs="0" name="ToDt" type="ISODate"/>
137
+ </xs:sequence>
138
+ </xs:complexType>
139
+ <xs:simpleType name="DecimalNumber">
140
+ <xs:restriction base="xs:decimal">
141
+ <xs:fractionDigits value="17"/>
142
+ <xs:totalDigits value="18"/>
143
+ </xs:restriction>
144
+ </xs:simpleType>
145
+ <xs:complexType name="Document">
146
+ <xs:sequence>
147
+ <xs:element name="MndtCxlReq" type="MandateCancellationRequestV04"/>
148
+ </xs:sequence>
149
+ </xs:complexType>
150
+ <xs:simpleType name="DocumentType6Code">
151
+ <xs:restriction base="xs:string">
152
+ <xs:enumeration value="MSIN"/>
153
+ <xs:enumeration value="CNFA"/>
154
+ <xs:enumeration value="DNFA"/>
155
+ <xs:enumeration value="CINV"/>
156
+ <xs:enumeration value="CREN"/>
157
+ <xs:enumeration value="DEBN"/>
158
+ <xs:enumeration value="HIRI"/>
159
+ <xs:enumeration value="SBIN"/>
160
+ <xs:enumeration value="CMCN"/>
161
+ <xs:enumeration value="SOAC"/>
162
+ <xs:enumeration value="DISP"/>
163
+ <xs:enumeration value="BOLD"/>
164
+ <xs:enumeration value="VCHR"/>
165
+ <xs:enumeration value="AROI"/>
166
+ <xs:enumeration value="TSUT"/>
167
+ <xs:enumeration value="PUOR"/>
168
+ </xs:restriction>
169
+ </xs:simpleType>
170
+ <xs:simpleType name="ExternalAccountIdentification1Code">
171
+ <xs:restriction base="xs:string">
172
+ <xs:minLength value="1"/>
173
+ <xs:maxLength value="4"/>
174
+ </xs:restriction>
175
+ </xs:simpleType>
176
+ <xs:simpleType name="ExternalCashAccountType1Code">
177
+ <xs:restriction base="xs:string">
178
+ <xs:minLength value="1"/>
179
+ <xs:maxLength value="4"/>
180
+ </xs:restriction>
181
+ </xs:simpleType>
182
+ <xs:simpleType name="ExternalClearingSystemIdentification1Code">
183
+ <xs:restriction base="xs:string">
184
+ <xs:minLength value="1"/>
185
+ <xs:maxLength value="5"/>
186
+ </xs:restriction>
187
+ </xs:simpleType>
188
+ <xs:simpleType name="ExternalFinancialInstitutionIdentification1Code">
189
+ <xs:restriction base="xs:string">
190
+ <xs:minLength value="1"/>
191
+ <xs:maxLength value="4"/>
192
+ </xs:restriction>
193
+ </xs:simpleType>
194
+ <xs:simpleType name="ExternalLocalInstrument1Code">
195
+ <xs:restriction base="xs:string">
196
+ <xs:minLength value="1"/>
197
+ <xs:maxLength value="35"/>
198
+ </xs:restriction>
199
+ </xs:simpleType>
200
+ <xs:simpleType name="ExternalMandateReason1Code">
201
+ <xs:restriction base="xs:string">
202
+ <xs:minLength value="1"/>
203
+ <xs:maxLength value="4"/>
204
+ </xs:restriction>
205
+ </xs:simpleType>
206
+ <xs:simpleType name="ExternalMandateSetupReason1Code">
207
+ <xs:restriction base="xs:string">
208
+ <xs:minLength value="1"/>
209
+ <xs:maxLength value="4"/>
210
+ </xs:restriction>
211
+ </xs:simpleType>
212
+ <xs:simpleType name="ExternalOrganisationIdentification1Code">
213
+ <xs:restriction base="xs:string">
214
+ <xs:minLength value="1"/>
215
+ <xs:maxLength value="4"/>
216
+ </xs:restriction>
217
+ </xs:simpleType>
218
+ <xs:simpleType name="ExternalPersonIdentification1Code">
219
+ <xs:restriction base="xs:string">
220
+ <xs:minLength value="1"/>
221
+ <xs:maxLength value="4"/>
222
+ </xs:restriction>
223
+ </xs:simpleType>
224
+ <xs:simpleType name="ExternalServiceLevel1Code">
225
+ <xs:restriction base="xs:string">
226
+ <xs:minLength value="1"/>
227
+ <xs:maxLength value="4"/>
228
+ </xs:restriction>
229
+ </xs:simpleType>
230
+ <xs:complexType name="FinancialIdentificationSchemeName1Choice">
231
+ <xs:choice>
232
+ <xs:element name="Cd" type="ExternalFinancialInstitutionIdentification1Code"/>
233
+ <xs:element name="Prtry" type="Max35Text"/>
234
+ </xs:choice>
235
+ </xs:complexType>
236
+ <xs:complexType name="FinancialInstitutionIdentification8">
237
+ <xs:sequence>
238
+ <!-- Made BICFI mandatory, previously this line was: -->
239
+ <!-- <xs:element maxOccurs="1" minOccurs="0" name="BICFI" type="BICFIIdentifier"/> -->
240
+ <xs:element name="BICFI" type="BICFIIdentifier"/>
241
+ <xs:element maxOccurs="1" minOccurs="0" name="ClrSysMmbId" type="ClearingSystemMemberIdentification2"/>
242
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
243
+ <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/>
244
+ <xs:element maxOccurs="1" minOccurs="0" name="Othr" type="GenericFinancialIdentification1"/>
245
+ </xs:sequence>
246
+ </xs:complexType>
247
+ <xs:complexType name="Frequency21Choice">
248
+ <xs:choice>
249
+ <xs:element name="Tp" type="Frequency6Code"/>
250
+ <xs:element name="Prd" type="FrequencyPeriod1"/>
251
+ </xs:choice>
252
+ </xs:complexType>
253
+ <xs:simpleType name="Frequency6Code">
254
+ <xs:restriction base="xs:string">
255
+ <xs:enumeration value="YEAR"/>
256
+ <xs:enumeration value="MNTH"/>
257
+ <xs:enumeration value="QURT"/>
258
+ <xs:enumeration value="MIAN"/>
259
+ <xs:enumeration value="WEEK"/>
260
+ <xs:enumeration value="DAIL"/>
261
+ <xs:enumeration value="ADHO"/>
262
+ <xs:enumeration value="INDA"/>
263
+ <xs:enumeration value="FRTN"/>
264
+ </xs:restriction>
265
+ </xs:simpleType>
266
+ <xs:complexType name="FrequencyPeriod1">
267
+ <xs:sequence>
268
+ <xs:element name="Tp" type="Frequency6Code"/>
269
+ <xs:element name="CntPerPrd" type="DecimalNumber"/>
270
+ </xs:sequence>
271
+ </xs:complexType>
272
+ <xs:complexType name="GenericAccountIdentification1">
273
+ <xs:sequence>
274
+ <xs:element name="Id" type="Max34Text"/>
275
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="AccountSchemeName1Choice"/>
276
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
277
+ </xs:sequence>
278
+ </xs:complexType>
279
+ <xs:complexType name="GenericFinancialIdentification1">
280
+ <xs:sequence>
281
+ <xs:element name="Id" type="Max35Text"/>
282
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="FinancialIdentificationSchemeName1Choice"/>
283
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
284
+ </xs:sequence>
285
+ </xs:complexType>
286
+ <xs:complexType name="GenericOrganisationIdentification1">
287
+ <xs:sequence>
288
+ <xs:element name="Id" type="Max35Text"/>
289
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="OrganisationIdentificationSchemeName1Choice"/>
290
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
291
+ </xs:sequence>
292
+ </xs:complexType>
293
+ <xs:complexType name="GenericPersonIdentification1">
294
+ <xs:sequence>
295
+ <xs:element name="Id" type="Max35Text"/>
296
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="PersonIdentificationSchemeName1Choice"/>
297
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
298
+ </xs:sequence>
299
+ </xs:complexType>
300
+ <xs:complexType name="GroupHeader47">
301
+ <xs:sequence>
302
+ <xs:element name="MsgId" type="Max35Text"/>
303
+ <xs:element name="CreDtTm" type="ISODateTime"/>
304
+ <xs:element maxOccurs="2" minOccurs="0" name="Authstn" type="Authorisation1Choice"/>
305
+ <xs:element maxOccurs="1" minOccurs="0" name="InitgPty" type="PartyIdentification43"/>
306
+ <xs:element maxOccurs="1" minOccurs="0" name="InstgAgt" type="BranchAndFinancialInstitutionIdentification5"/>
307
+ <xs:element maxOccurs="1" minOccurs="0" name="InstdAgt" type="BranchAndFinancialInstitutionIdentification5"/>
308
+ </xs:sequence>
309
+ </xs:complexType>
310
+ <xs:simpleType name="IBAN2007Identifier">
311
+ <xs:restriction base="xs:string">
312
+ <xs:pattern value="[A-Z]{2,2}[0-9]{2,2}[a-zA-Z0-9]{1,30}"/>
313
+ </xs:restriction>
314
+ </xs:simpleType>
315
+ <xs:simpleType name="ISODate">
316
+ <xs:restriction base="xs:date"/>
317
+ </xs:simpleType>
318
+ <xs:simpleType name="ISODateTime">
319
+ <xs:restriction base="xs:dateTime"/>
320
+ </xs:simpleType>
321
+ <xs:complexType name="LocalInstrument2Choice">
322
+ <xs:choice>
323
+ <xs:element name="Cd" type="ExternalLocalInstrument1Code"/>
324
+ <xs:element name="Prtry" type="Max35Text"/>
325
+ </xs:choice>
326
+ </xs:complexType>
327
+ <xs:complexType name="Mandate5">
328
+ <xs:sequence>
329
+ <xs:element name="MndtId" type="Max35Text"/>
330
+ <xs:element maxOccurs="1" minOccurs="0" name="MndtReqId" type="Max35Text"/>
331
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="MandateTypeInformation1"/>
332
+ <xs:element maxOccurs="1" minOccurs="0" name="Ocrncs" type="MandateOccurrences3"/>
333
+ <xs:element maxOccurs="1" minOccurs="0" name="ColltnAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
334
+ <xs:element maxOccurs="1" minOccurs="0" name="MaxAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
335
+ <xs:element maxOccurs="1" minOccurs="0" name="Rsn" type="MandateSetupReason1Choice"/>
336
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrSchmeId" type="PartyIdentification43"/>
337
+ <xs:element name="Cdtr" type="PartyIdentification43"/>
338
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrAcct" type="CashAccount24"/>
339
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrAgt" type="BranchAndFinancialInstitutionIdentification5"/>
340
+ <xs:element maxOccurs="1" minOccurs="0" name="UltmtCdtr" type="PartyIdentification43"/>
341
+ <xs:element name="Dbtr" type="PartyIdentification43"/>
342
+ <!-- Made DbtrAcct mandatory, previously this line was: -->
343
+ <!-- <xs:element maxOccurs="1" minOccurs="0" name="DbtrAcct" type="CashAccount24"/> -->
344
+ <xs:element name="DbtrAcct" type="CashAccount24"/>
345
+ <xs:element name="DbtrAgt" type="BranchAndFinancialInstitutionIdentification5"/>
346
+ <xs:element maxOccurs="1" minOccurs="0" name="UltmtDbtr" type="PartyIdentification43"/>
347
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="RfrdDoc" type="ReferredDocumentInformation6"/>
348
+ </xs:sequence>
349
+ </xs:complexType>
350
+ <xs:complexType name="MandateCancellation4">
351
+ <xs:sequence>
352
+ <xs:element maxOccurs="1" minOccurs="0" name="OrgnlMsgInf" type="OriginalMessageInformation1"/>
353
+ <xs:element name="CxlRsn" type="PaymentCancellationReason1"/>
354
+ <xs:element name="OrgnlMndt" type="OriginalMandate3Choice"/>
355
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="SplmtryData" type="SupplementaryData1"/>
356
+ </xs:sequence>
357
+ </xs:complexType>
358
+ <xs:complexType name="MandateCancellationRequestV04">
359
+ <xs:sequence>
360
+ <xs:element name="GrpHdr" type="GroupHeader47"/>
361
+ <xs:element maxOccurs="unbounded" minOccurs="1" name="UndrlygCxlDtls" type="MandateCancellation4"/>
362
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="SplmtryData" type="SupplementaryData1"/>
363
+ </xs:sequence>
364
+ </xs:complexType>
365
+ <xs:complexType name="MandateOccurrences3">
366
+ <xs:sequence>
367
+ <xs:element name="SeqTp" type="SequenceType2Code"/>
368
+ <xs:element maxOccurs="1" minOccurs="0" name="Frqcy" type="Frequency21Choice"/>
369
+ <xs:element maxOccurs="1" minOccurs="0" name="Drtn" type="DatePeriodDetails1"/>
370
+ <xs:element maxOccurs="1" minOccurs="0" name="FrstColltnDt" type="ISODate"/>
371
+ <xs:element maxOccurs="1" minOccurs="0" name="FnlColltnDt" type="ISODate"/>
372
+ </xs:sequence>
373
+ </xs:complexType>
374
+ <xs:complexType name="MandateReason1Choice">
375
+ <xs:choice>
376
+ <xs:element name="Cd" type="ExternalMandateReason1Code"/>
377
+ <xs:element name="Prtry" type="Max35Text"/>
378
+ </xs:choice>
379
+ </xs:complexType>
380
+ <xs:complexType name="MandateSetupReason1Choice">
381
+ <xs:choice>
382
+ <xs:element name="Cd" type="ExternalMandateSetupReason1Code"/>
383
+ <xs:element name="Prtry" type="Max70Text"/>
384
+ </xs:choice>
385
+ </xs:complexType>
386
+ <xs:complexType name="MandateTypeInformation1">
387
+ <xs:sequence>
388
+ <xs:element maxOccurs="1" minOccurs="0" name="SvcLvl" type="ServiceLevel8Choice"/>
389
+ <xs:element maxOccurs="1" minOccurs="0" name="LclInstrm" type="LocalInstrument2Choice"/>
390
+ </xs:sequence>
391
+ </xs:complexType>
392
+ <xs:simpleType name="Max105Text">
393
+ <xs:restriction base="xs:string">
394
+ <xs:minLength value="1"/>
395
+ <xs:maxLength value="105"/>
396
+ </xs:restriction>
397
+ </xs:simpleType>
398
+ <xs:simpleType name="Max128Text">
399
+ <xs:restriction base="xs:string">
400
+ <xs:minLength value="1"/>
401
+ <xs:maxLength value="128"/>
402
+ </xs:restriction>
403
+ </xs:simpleType>
404
+ <xs:simpleType name="Max140Text">
405
+ <xs:restriction base="xs:string">
406
+ <xs:minLength value="1"/>
407
+ <xs:maxLength value="140"/>
408
+ </xs:restriction>
409
+ </xs:simpleType>
410
+ <xs:simpleType name="Max16Text">
411
+ <xs:restriction base="xs:string">
412
+ <xs:minLength value="1"/>
413
+ <xs:maxLength value="16"/>
414
+ </xs:restriction>
415
+ </xs:simpleType>
416
+ <xs:simpleType name="Max2048Text">
417
+ <xs:restriction base="xs:string">
418
+ <xs:minLength value="1"/>
419
+ <xs:maxLength value="2048"/>
420
+ </xs:restriction>
421
+ </xs:simpleType>
422
+ <xs:simpleType name="Max34Text">
423
+ <xs:restriction base="xs:string">
424
+ <xs:minLength value="1"/>
425
+ <xs:maxLength value="34"/>
426
+ </xs:restriction>
427
+ </xs:simpleType>
428
+ <xs:simpleType name="Max350Text">
429
+ <xs:restriction base="xs:string">
430
+ <xs:minLength value="1"/>
431
+ <xs:maxLength value="350"/>
432
+ </xs:restriction>
433
+ </xs:simpleType>
434
+ <xs:simpleType name="Max35Text">
435
+ <xs:restriction base="xs:string">
436
+ <xs:minLength value="1"/>
437
+ <xs:maxLength value="35"/>
438
+ </xs:restriction>
439
+ </xs:simpleType>
440
+ <xs:simpleType name="Max70Text">
441
+ <xs:restriction base="xs:string">
442
+ <xs:minLength value="1"/>
443
+ <xs:maxLength value="70"/>
444
+ </xs:restriction>
445
+ </xs:simpleType>
446
+ <xs:simpleType name="NamePrefix1Code">
447
+ <xs:restriction base="xs:string">
448
+ <xs:enumeration value="DOCT"/>
449
+ <xs:enumeration value="MIST"/>
450
+ <xs:enumeration value="MISS"/>
451
+ <xs:enumeration value="MADM"/>
452
+ </xs:restriction>
453
+ </xs:simpleType>
454
+ <xs:complexType name="OrganisationIdentification8">
455
+ <xs:sequence>
456
+ <xs:element maxOccurs="1" minOccurs="0" name="AnyBIC" type="AnyBICIdentifier"/>
457
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Othr" type="GenericOrganisationIdentification1"/>
458
+ </xs:sequence>
459
+ </xs:complexType>
460
+ <xs:complexType name="OrganisationIdentificationSchemeName1Choice">
461
+ <xs:choice>
462
+ <xs:element name="Cd" type="ExternalOrganisationIdentification1Code"/>
463
+ <xs:element name="Prtry" type="Max35Text"/>
464
+ </xs:choice>
465
+ </xs:complexType>
466
+ <xs:complexType name="OriginalMandate3Choice">
467
+ <xs:choice>
468
+ <xs:element name="OrgnlMndtId" type="Max35Text"/>
469
+ <xs:element name="OrgnlMndt" type="Mandate5"/>
470
+ </xs:choice>
471
+ </xs:complexType>
472
+ <xs:complexType name="OriginalMessageInformation1">
473
+ <xs:sequence>
474
+ <xs:element name="MsgId" type="Max35Text"/>
475
+ <xs:element name="MsgNmId" type="Max35Text"/>
476
+ <xs:element maxOccurs="1" minOccurs="0" name="CreDtTm" type="ISODateTime"/>
477
+ </xs:sequence>
478
+ </xs:complexType>
479
+ <xs:complexType name="Party11Choice">
480
+ <xs:choice>
481
+ <xs:element name="OrgId" type="OrganisationIdentification8"/>
482
+ <xs:element name="PrvtId" type="PersonIdentification5"/>
483
+ </xs:choice>
484
+ </xs:complexType>
485
+ <xs:complexType name="PartyIdentification43">
486
+ <xs:sequence>
487
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
488
+ <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/>
489
+ <xs:element maxOccurs="1" minOccurs="0" name="Id" type="Party11Choice"/>
490
+ <xs:element maxOccurs="1" minOccurs="0" name="CtryOfRes" type="CountryCode"/>
491
+ <xs:element maxOccurs="1" minOccurs="0" name="CtctDtls" type="ContactDetails2"/>
492
+ </xs:sequence>
493
+ </xs:complexType>
494
+ <xs:complexType name="PaymentCancellationReason1">
495
+ <xs:sequence>
496
+ <xs:element maxOccurs="1" minOccurs="0" name="Orgtr" type="PartyIdentification43"/>
497
+ <xs:element name="Rsn" type="MandateReason1Choice"/>
498
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="AddtlInf" type="Max105Text"/>
499
+ </xs:sequence>
500
+ </xs:complexType>
501
+ <xs:complexType name="PersonIdentification5">
502
+ <xs:sequence>
503
+ <xs:element maxOccurs="1" minOccurs="0" name="DtAndPlcOfBirth" type="DateAndPlaceOfBirth"/>
504
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Othr" type="GenericPersonIdentification1"/>
505
+ </xs:sequence>
506
+ </xs:complexType>
507
+ <xs:complexType name="PersonIdentificationSchemeName1Choice">
508
+ <xs:choice>
509
+ <xs:element name="Cd" type="ExternalPersonIdentification1Code"/>
510
+ <xs:element name="Prtry" type="Max35Text"/>
511
+ </xs:choice>
512
+ </xs:complexType>
513
+ <xs:simpleType name="PhoneNumber">
514
+ <xs:restriction base="xs:string">
515
+ <xs:pattern value="\+[0-9]{1,3}-[0-9()+\-]{1,30}"/>
516
+ </xs:restriction>
517
+ </xs:simpleType>
518
+ <xs:complexType name="PostalAddress6">
519
+ <xs:sequence>
520
+ <xs:element maxOccurs="1" minOccurs="0" name="AdrTp" type="AddressType2Code"/>
521
+ <xs:element maxOccurs="1" minOccurs="0" name="Dept" type="Max70Text"/>
522
+ <xs:element maxOccurs="1" minOccurs="0" name="SubDept" type="Max70Text"/>
523
+ <xs:element maxOccurs="1" minOccurs="0" name="StrtNm" type="Max70Text"/>
524
+ <xs:element maxOccurs="1" minOccurs="0" name="BldgNb" type="Max16Text"/>
525
+ <xs:element maxOccurs="1" minOccurs="0" name="PstCd" type="Max16Text"/>
526
+ <xs:element maxOccurs="1" minOccurs="0" name="TwnNm" type="Max35Text"/>
527
+ <xs:element maxOccurs="1" minOccurs="0" name="CtrySubDvsn" type="Max35Text"/>
528
+ <xs:element maxOccurs="1" minOccurs="0" name="Ctry" type="CountryCode"/>
529
+ <xs:element maxOccurs="7" minOccurs="0" name="AdrLine" type="Max70Text"/>
530
+ </xs:sequence>
531
+ </xs:complexType>
532
+ <xs:complexType name="ReferredDocumentInformation6">
533
+ <xs:sequence>
534
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="ReferredDocumentType4"/>
535
+ <xs:element maxOccurs="1" minOccurs="0" name="Nb" type="Max35Text"/>
536
+ <xs:element maxOccurs="1" minOccurs="0" name="RltdDt" type="ISODate"/>
537
+ </xs:sequence>
538
+ </xs:complexType>
539
+ <xs:complexType name="ReferredDocumentType3Choice">
540
+ <xs:choice>
541
+ <xs:element name="Cd" type="DocumentType6Code"/>
542
+ <xs:element name="Prtry" type="Max35Text"/>
543
+ </xs:choice>
544
+ </xs:complexType>
545
+ <xs:complexType name="ReferredDocumentType4">
546
+ <xs:sequence>
547
+ <xs:element name="CdOrPrtry" type="ReferredDocumentType3Choice"/>
548
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
549
+ </xs:sequence>
550
+ </xs:complexType>
551
+ <xs:simpleType name="SequenceType2Code">
552
+ <xs:restriction base="xs:string">
553
+ <xs:enumeration value="RCUR"/>
554
+ <xs:enumeration value="OOFF"/>
555
+ </xs:restriction>
556
+ </xs:simpleType>
557
+ <xs:complexType name="ServiceLevel8Choice">
558
+ <xs:choice>
559
+ <xs:element name="Cd" type="ExternalServiceLevel1Code"/>
560
+ <xs:element name="Prtry" type="Max35Text"/>
561
+ </xs:choice>
562
+ </xs:complexType>
563
+ <xs:complexType name="SupplementaryData1">
564
+ <xs:sequence>
565
+ <xs:element maxOccurs="1" minOccurs="0" name="PlcAndNm" type="Max350Text"/>
566
+ <xs:element name="Envlp" type="SupplementaryDataEnvelope1"/>
567
+ </xs:sequence>
568
+ </xs:complexType>
569
+ <xs:complexType name="SupplementaryDataEnvelope1">
570
+ <xs:sequence>
571
+ <xs:any namespace="##any" processContents="lax"/>
572
+ </xs:sequence>
573
+ </xs:complexType>
574
+ </xs:schema>
lib/Communicator/schemas/pain.012.001.04.xsd ADDED
@@ -0,0 +1,573 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--Generated by Standards Editor (build:R1.6.2.2) on 2014 Oct 24 13:58:13, ISO 20022 version : 2013-->
3
+ <xs:schema xmlns="urn:iso:std:iso:20022:tech:xsd:pain.012.001.04" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:iso:std:iso:20022:tech:xsd:pain.012.001.04">
4
+ <xs:element name="Document" type="Document"/>
5
+ <xs:complexType name="AcceptanceResult6">
6
+ <xs:sequence>
7
+ <xs:element name="Accptd" type="YesNoIndicator"/>
8
+ <xs:element maxOccurs="1" minOccurs="0" name="RjctRsn" type="MandateReason1Choice"/>
9
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="AddtlRjctRsnInf" type="Max105Text"/>
10
+ </xs:sequence>
11
+ </xs:complexType>
12
+ <xs:complexType name="AccountIdentification4Choice">
13
+ <xs:choice>
14
+ <xs:element name="IBAN" type="IBAN2007Identifier"/>
15
+ <xs:element name="Othr" type="GenericAccountIdentification1"/>
16
+ </xs:choice>
17
+ </xs:complexType>
18
+ <xs:complexType name="AccountSchemeName1Choice">
19
+ <xs:choice>
20
+ <xs:element name="Cd" type="ExternalAccountIdentification1Code"/>
21
+ <xs:element name="Prtry" type="Max35Text"/>
22
+ </xs:choice>
23
+ </xs:complexType>
24
+ <xs:simpleType name="ActiveOrHistoricCurrencyAndAmount_SimpleType">
25
+ <xs:restriction base="xs:decimal">
26
+ <xs:fractionDigits value="5"/>
27
+ <xs:totalDigits value="18"/>
28
+ <xs:minInclusive value="0"/>
29
+ </xs:restriction>
30
+ </xs:simpleType>
31
+ <xs:complexType name="ActiveOrHistoricCurrencyAndAmount">
32
+ <xs:simpleContent>
33
+ <xs:extension base="ActiveOrHistoricCurrencyAndAmount_SimpleType">
34
+ <xs:attribute name="Ccy" type="ActiveOrHistoricCurrencyCode" use="required"/>
35
+ </xs:extension>
36
+ </xs:simpleContent>
37
+ </xs:complexType>
38
+ <xs:simpleType name="ActiveOrHistoricCurrencyCode">
39
+ <xs:restriction base="xs:string">
40
+ <xs:pattern value="[A-Z]{3,3}"/>
41
+ </xs:restriction>
42
+ </xs:simpleType>
43
+ <xs:simpleType name="AddressType2Code">
44
+ <xs:restriction base="xs:string">
45
+ <xs:enumeration value="ADDR"/>
46
+ <xs:enumeration value="PBOX"/>
47
+ <xs:enumeration value="HOME"/>
48
+ <xs:enumeration value="BIZZ"/>
49
+ <xs:enumeration value="MLTO"/>
50
+ <xs:enumeration value="DLVY"/>
51
+ </xs:restriction>
52
+ </xs:simpleType>
53
+ <xs:simpleType name="AnyBICIdentifier">
54
+ <xs:restriction base="xs:string">
55
+ <xs:pattern value="[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}"/>
56
+ </xs:restriction>
57
+ </xs:simpleType>
58
+ <xs:complexType name="Authorisation1Choice">
59
+ <xs:choice>
60
+ <xs:element name="Cd" type="Authorisation1Code"/>
61
+ <xs:element name="Prtry" type="Max128Text"/>
62
+ </xs:choice>
63
+ </xs:complexType>
64
+ <xs:simpleType name="Authorisation1Code">
65
+ <xs:restriction base="xs:string">
66
+ <xs:enumeration value="AUTH"/>
67
+ <xs:enumeration value="FDET"/>
68
+ <xs:enumeration value="FSUM"/>
69
+ <xs:enumeration value="ILEV"/>
70
+ </xs:restriction>
71
+ </xs:simpleType>
72
+ <xs:simpleType name="BICFIIdentifier">
73
+ <xs:restriction base="xs:string">
74
+ <xs:pattern value="[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}"/>
75
+ </xs:restriction>
76
+ </xs:simpleType>
77
+ <xs:complexType name="BranchAndFinancialInstitutionIdentification5">
78
+ <xs:sequence>
79
+ <xs:element name="FinInstnId" type="FinancialInstitutionIdentification8"/>
80
+ <xs:element maxOccurs="1" minOccurs="0" name="BrnchId" type="BranchData2"/>
81
+ </xs:sequence>
82
+ </xs:complexType>
83
+ <xs:complexType name="BranchData2">
84
+ <xs:sequence>
85
+ <xs:element maxOccurs="1" minOccurs="0" name="Id" type="Max35Text"/>
86
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
87
+ <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/>
88
+ </xs:sequence>
89
+ </xs:complexType>
90
+ <xs:complexType name="CashAccount24">
91
+ <xs:sequence>
92
+ <xs:element name="Id" type="AccountIdentification4Choice"/>
93
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="CashAccountType2Choice"/>
94
+ <xs:element maxOccurs="1" minOccurs="0" name="Ccy" type="ActiveOrHistoricCurrencyCode"/>
95
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max70Text"/>
96
+ </xs:sequence>
97
+ </xs:complexType>
98
+ <xs:complexType name="CashAccountType2Choice">
99
+ <xs:choice>
100
+ <xs:element name="Cd" type="ExternalCashAccountType1Code"/>
101
+ <xs:element name="Prtry" type="Max35Text"/>
102
+ </xs:choice>
103
+ </xs:complexType>
104
+ <xs:complexType name="ClearingSystemIdentification2Choice">
105
+ <xs:choice>
106
+ <xs:element name="Cd" type="ExternalClearingSystemIdentification1Code"/>
107
+ <xs:element name="Prtry" type="Max35Text"/>
108
+ </xs:choice>
109
+ </xs:complexType>
110
+ <xs:complexType name="ClearingSystemMemberIdentification2">
111
+ <xs:sequence>
112
+ <xs:element maxOccurs="1" minOccurs="0" name="ClrSysId" type="ClearingSystemIdentification2Choice"/>
113
+ <xs:element name="MmbId" type="Max35Text"/>
114
+ </xs:sequence>
115
+ </xs:complexType>
116
+ <xs:complexType name="ContactDetails2">
117
+ <xs:sequence>
118
+ <xs:element maxOccurs="1" minOccurs="0" name="NmPrfx" type="NamePrefix1Code"/>
119
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
120
+ <xs:element maxOccurs="1" minOccurs="0" name="PhneNb" type="PhoneNumber"/>
121
+ <xs:element maxOccurs="1" minOccurs="0" name="MobNb" type="PhoneNumber"/>
122
+ <xs:element maxOccurs="1" minOccurs="0" name="FaxNb" type="PhoneNumber"/>
123
+ <xs:element maxOccurs="1" minOccurs="0" name="EmailAdr" type="Max2048Text"/>
124
+ <xs:element maxOccurs="1" minOccurs="0" name="Othr" type="Max35Text"/>
125
+ </xs:sequence>
126
+ </xs:complexType>
127
+ <xs:simpleType name="CountryCode">
128
+ <xs:restriction base="xs:string">
129
+ <xs:pattern value="[A-Z]{2,2}"/>
130
+ </xs:restriction>
131
+ </xs:simpleType>
132
+ <xs:complexType name="DateAndPlaceOfBirth">
133
+ <xs:sequence>
134
+ <xs:element name="BirthDt" type="ISODate"/>
135
+ <xs:element maxOccurs="1" minOccurs="0" name="PrvcOfBirth" type="Max35Text"/>
136
+ <xs:element name="CityOfBirth" type="Max35Text"/>
137
+ <xs:element name="CtryOfBirth" type="CountryCode"/>
138
+ </xs:sequence>
139
+ </xs:complexType>
140
+ <xs:complexType name="DatePeriodDetails1">
141
+ <xs:sequence>
142
+ <xs:element name="FrDt" type="ISODate"/>
143
+ <xs:element maxOccurs="1" minOccurs="0" name="ToDt" type="ISODate"/>
144
+ </xs:sequence>
145
+ </xs:complexType>
146
+ <xs:simpleType name="DecimalNumber">
147
+ <xs:restriction base="xs:decimal">
148
+ <xs:fractionDigits value="17"/>
149
+ <xs:totalDigits value="18"/>
150
+ </xs:restriction>
151
+ </xs:simpleType>
152
+ <xs:complexType name="Document">
153
+ <xs:sequence>
154
+ <xs:element name="MndtAccptncRpt" type="MandateAcceptanceReportV04"/>
155
+ </xs:sequence>
156
+ </xs:complexType>
157
+ <xs:simpleType name="DocumentType6Code">
158
+ <xs:restriction base="xs:string">
159
+ <xs:enumeration value="MSIN"/>
160
+ <xs:enumeration value="CNFA"/>
161
+ <xs:enumeration value="DNFA"/>
162
+ <xs:enumeration value="CINV"/>
163
+ <xs:enumeration value="CREN"/>
164
+ <xs:enumeration value="DEBN"/>
165
+ <xs:enumeration value="HIRI"/>
166
+ <xs:enumeration value="SBIN"/>
167
+ <xs:enumeration value="CMCN"/>
168
+ <xs:enumeration value="SOAC"/>
169
+ <xs:enumeration value="DISP"/>
170
+ <xs:enumeration value="BOLD"/>
171
+ <xs:enumeration value="VCHR"/>
172
+ <xs:enumeration value="AROI"/>
173
+ <xs:enumeration value="TSUT"/>
174
+ <xs:enumeration value="PUOR"/>
175
+ </xs:restriction>
176
+ </xs:simpleType>
177
+ <xs:simpleType name="ExternalAccountIdentification1Code">
178
+ <xs:restriction base="xs:string">
179
+ <xs:minLength value="1"/>
180
+ <xs:maxLength value="4"/>
181
+ </xs:restriction>
182
+ </xs:simpleType>
183
+ <xs:simpleType name="ExternalCashAccountType1Code">
184
+ <xs:restriction base="xs:string">
185
+ <xs:minLength value="1"/>
186
+ <xs:maxLength value="4"/>
187
+ </xs:restriction>
188
+ </xs:simpleType>
189
+ <xs:simpleType name="ExternalClearingSystemIdentification1Code">
190
+ <xs:restriction base="xs:string">
191
+ <xs:minLength value="1"/>
192
+ <xs:maxLength value="5"/>
193
+ </xs:restriction>
194
+ </xs:simpleType>
195
+ <xs:simpleType name="ExternalFinancialInstitutionIdentification1Code">
196
+ <xs:restriction base="xs:string">
197
+ <xs:minLength value="1"/>
198
+ <xs:maxLength value="4"/>
199
+ </xs:restriction>
200
+ </xs:simpleType>
201
+ <xs:simpleType name="ExternalLocalInstrument1Code">
202
+ <xs:restriction base="xs:string">
203
+ <xs:minLength value="1"/>
204
+ <xs:maxLength value="35"/>
205
+ </xs:restriction>
206
+ </xs:simpleType>
207
+ <xs:simpleType name="ExternalMandateReason1Code">
208
+ <xs:restriction base="xs:string">
209
+ <xs:minLength value="1"/>
210
+ <xs:maxLength value="4"/>
211
+ </xs:restriction>
212
+ </xs:simpleType>
213
+ <xs:simpleType name="ExternalMandateSetupReason1Code">
214
+ <xs:restriction base="xs:string">
215
+ <xs:minLength value="1"/>
216
+ <xs:maxLength value="4"/>
217
+ </xs:restriction>
218
+ </xs:simpleType>
219
+ <xs:simpleType name="ExternalOrganisationIdentification1Code">
220
+ <xs:restriction base="xs:string">
221
+ <xs:minLength value="1"/>
222
+ <xs:maxLength value="4"/>
223
+ </xs:restriction>
224
+ </xs:simpleType>
225
+ <xs:simpleType name="ExternalPersonIdentification1Code">
226
+ <xs:restriction base="xs:string">
227
+ <xs:minLength value="1"/>
228
+ <xs:maxLength value="4"/>
229
+ </xs:restriction>
230
+ </xs:simpleType>
231
+ <xs:simpleType name="ExternalServiceLevel1Code">
232
+ <xs:restriction base="xs:string">
233
+ <xs:minLength value="1"/>
234
+ <xs:maxLength value="4"/>
235
+ </xs:restriction>
236
+ </xs:simpleType>
237
+ <xs:complexType name="FinancialIdentificationSchemeName1Choice">
238
+ <xs:choice>
239
+ <xs:element name="Cd" type="ExternalFinancialInstitutionIdentification1Code"/>
240
+ <xs:element name="Prtry" type="Max35Text"/>
241
+ </xs:choice>
242
+ </xs:complexType>
243
+ <xs:complexType name="FinancialInstitutionIdentification8">
244
+ <xs:sequence>
245
+ <xs:element maxOccurs="1" minOccurs="0" name="BICFI" type="BICFIIdentifier"/>
246
+ <xs:element maxOccurs="1" minOccurs="0" name="ClrSysMmbId" type="ClearingSystemMemberIdentification2"/>
247
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
248
+ <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/>
249
+ <xs:element maxOccurs="1" minOccurs="0" name="Othr" type="GenericFinancialIdentification1"/>
250
+ </xs:sequence>
251
+ </xs:complexType>
252
+ <xs:complexType name="Frequency21Choice">
253
+ <xs:choice>
254
+ <xs:element name="Tp" type="Frequency6Code"/>
255
+ <xs:element name="Prd" type="FrequencyPeriod1"/>
256
+ </xs:choice>
257
+ </xs:complexType>
258
+ <xs:simpleType name="Frequency6Code">
259
+ <xs:restriction base="xs:string">
260
+ <xs:enumeration value="YEAR"/>
261
+ <xs:enumeration value="MNTH"/>
262
+ <xs:enumeration value="QURT"/>
263
+ <xs:enumeration value="MIAN"/>
264
+ <xs:enumeration value="WEEK"/>
265
+ <xs:enumeration value="DAIL"/>
266
+ <xs:enumeration value="ADHO"/>
267
+ <xs:enumeration value="INDA"/>
268
+ <xs:enumeration value="FRTN"/>
269
+ </xs:restriction>
270
+ </xs:simpleType>
271
+ <xs:complexType name="FrequencyPeriod1">
272
+ <xs:sequence>
273
+ <xs:element name="Tp" type="Frequency6Code"/>
274
+ <xs:element name="CntPerPrd" type="DecimalNumber"/>
275
+ </xs:sequence>
276
+ </xs:complexType>
277
+ <xs:complexType name="GenericAccountIdentification1">
278
+ <xs:sequence>
279
+ <xs:element name="Id" type="Max34Text"/>
280
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="AccountSchemeName1Choice"/>
281
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
282
+ </xs:sequence>
283
+ </xs:complexType>
284
+ <xs:complexType name="GenericFinancialIdentification1">
285
+ <xs:sequence>
286
+ <xs:element name="Id" type="Max35Text"/>
287
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="FinancialIdentificationSchemeName1Choice"/>
288
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
289
+ </xs:sequence>
290
+ </xs:complexType>
291
+ <xs:complexType name="GenericOrganisationIdentification1">
292
+ <xs:sequence>
293
+ <xs:element name="Id" type="Max35Text"/>
294
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="OrganisationIdentificationSchemeName1Choice"/>
295
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
296
+ </xs:sequence>
297
+ </xs:complexType>
298
+ <xs:complexType name="GenericPersonIdentification1">
299
+ <xs:sequence>
300
+ <xs:element name="Id" type="Max35Text"/>
301
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="PersonIdentificationSchemeName1Choice"/>
302
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
303
+ </xs:sequence>
304
+ </xs:complexType>
305
+ <xs:complexType name="GroupHeader47">
306
+ <xs:sequence>
307
+ <xs:element name="MsgId" type="Max35Text"/>
308
+ <xs:element name="CreDtTm" type="ISODateTime"/>
309
+ <xs:element maxOccurs="2" minOccurs="0" name="Authstn" type="Authorisation1Choice"/>
310
+ <xs:element maxOccurs="1" minOccurs="0" name="InitgPty" type="PartyIdentification43"/>
311
+ <xs:element maxOccurs="1" minOccurs="0" name="InstgAgt" type="BranchAndFinancialInstitutionIdentification5"/>
312
+ <xs:element maxOccurs="1" minOccurs="0" name="InstdAgt" type="BranchAndFinancialInstitutionIdentification5"/>
313
+ </xs:sequence>
314
+ </xs:complexType>
315
+ <xs:simpleType name="IBAN2007Identifier">
316
+ <xs:restriction base="xs:string">
317
+ <xs:pattern value="[A-Z]{2,2}[0-9]{2,2}[a-zA-Z0-9]{1,30}"/>
318
+ </xs:restriction>
319
+ </xs:simpleType>
320
+ <xs:simpleType name="ISODate">
321
+ <xs:restriction base="xs:date"/>
322
+ </xs:simpleType>
323
+ <xs:simpleType name="ISODateTime">
324
+ <xs:restriction base="xs:dateTime"/>
325
+ </xs:simpleType>
326
+ <xs:complexType name="LocalInstrument2Choice">
327
+ <xs:choice>
328
+ <xs:element name="Cd" type="ExternalLocalInstrument1Code"/>
329
+ <xs:element name="Prtry" type="Max35Text"/>
330
+ </xs:choice>
331
+ </xs:complexType>
332
+ <xs:complexType name="Mandate5">
333
+ <xs:sequence>
334
+ <xs:element name="MndtId" type="Max35Text"/>
335
+ <xs:element maxOccurs="1" minOccurs="0" name="MndtReqId" type="Max35Text"/>
336
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="MandateTypeInformation1"/>
337
+ <xs:element maxOccurs="1" minOccurs="0" name="Ocrncs" type="MandateOccurrences3"/>
338
+ <xs:element maxOccurs="1" minOccurs="0" name="ColltnAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
339
+ <xs:element maxOccurs="1" minOccurs="0" name="MaxAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
340
+ <xs:element maxOccurs="1" minOccurs="0" name="Rsn" type="MandateSetupReason1Choice"/>
341
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrSchmeId" type="PartyIdentification43"/>
342
+ <xs:element name="Cdtr" type="PartyIdentification43"/>
343
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrAcct" type="CashAccount24"/>
344
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrAgt" type="BranchAndFinancialInstitutionIdentification5"/>
345
+ <xs:element maxOccurs="1" minOccurs="0" name="UltmtCdtr" type="PartyIdentification43"/>
346
+ <xs:element name="Dbtr" type="PartyIdentification43"/>
347
+ <xs:element maxOccurs="1" minOccurs="0" name="DbtrAcct" type="CashAccount24"/>
348
+ <xs:element name="DbtrAgt" type="BranchAndFinancialInstitutionIdentification5"/>
349
+ <xs:element maxOccurs="1" minOccurs="0" name="UltmtDbtr" type="PartyIdentification43"/>
350
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="RfrdDoc" type="ReferredDocumentInformation6"/>
351
+ </xs:sequence>
352
+ </xs:complexType>
353
+ <xs:complexType name="MandateAcceptance4">
354
+ <xs:sequence>
355
+ <xs:element maxOccurs="1" minOccurs="0" name="OrgnlMsgInf" type="OriginalMessageInformation1"/>
356
+ <xs:element name="AccptncRslt" type="AcceptanceResult6"/>
357
+ <xs:element name="OrgnlMndt" type="OriginalMandate3Choice"/>
358
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="SplmtryData" type="SupplementaryData1"/>
359
+ </xs:sequence>
360
+ </xs:complexType>
361
+ <xs:complexType name="MandateAcceptanceReportV04">
362
+ <xs:sequence>
363
+ <xs:element name="GrpHdr" type="GroupHeader47"/>
364
+ <xs:element maxOccurs="unbounded" minOccurs="1" name="UndrlygAccptncDtls" type="MandateAcceptance4"/>
365
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="SplmtryData" type="SupplementaryData1"/>
366
+ </xs:sequence>
367
+ </xs:complexType>
368
+ <xs:complexType name="MandateOccurrences3">
369
+ <xs:sequence>
370
+ <xs:element name="SeqTp" type="SequenceType2Code"/>
371
+ <xs:element maxOccurs="1" minOccurs="0" name="Frqcy" type="Frequency21Choice"/>
372
+ <xs:element maxOccurs="1" minOccurs="0" name="Drtn" type="DatePeriodDetails1"/>
373
+ <xs:element maxOccurs="1" minOccurs="0" name="FrstColltnDt" type="ISODate"/>
374
+ <xs:element maxOccurs="1" minOccurs="0" name="FnlColltnDt" type="ISODate"/>
375
+ </xs:sequence>
376
+ </xs:complexType>
377
+ <xs:complexType name="MandateReason1Choice">
378
+ <xs:choice>
379
+ <xs:element name="Cd" type="ExternalMandateReason1Code"/>
380
+ <xs:element name="Prtry" type="Max35Text"/>
381
+ </xs:choice>
382
+ </xs:complexType>
383
+ <xs:complexType name="MandateSetupReason1Choice">
384
+ <xs:choice>
385
+ <xs:element name="Cd" type="ExternalMandateSetupReason1Code"/>
386
+ <xs:element name="Prtry" type="Max70Text"/>
387
+ </xs:choice>
388
+ </xs:complexType>
389
+ <xs:complexType name="MandateTypeInformation1">
390
+ <xs:sequence>
391
+ <xs:element maxOccurs="1" minOccurs="0" name="SvcLvl" type="ServiceLevel8Choice"/>
392
+ <xs:element maxOccurs="1" minOccurs="0" name="LclInstrm" type="LocalInstrument2Choice"/>
393
+ </xs:sequence>
394
+ </xs:complexType>
395
+ <xs:simpleType name="Max105Text">
396
+ <xs:restriction base="xs:string">
397
+ <xs:minLength value="1"/>
398
+ <xs:maxLength value="105"/>
399
+ </xs:restriction>
400
+ </xs:simpleType>
401
+ <xs:simpleType name="Max128Text">
402
+ <xs:restriction base="xs:string">
403
+ <xs:minLength value="1"/>
404
+ <xs:maxLength value="128"/>
405
+ </xs:restriction>
406
+ </xs:simpleType>
407
+ <xs:simpleType name="Max140Text">
408
+ <xs:restriction base="xs:string">
409
+ <xs:minLength value="1"/>
410
+ <xs:maxLength value="140"/>
411
+ </xs:restriction>
412
+ </xs:simpleType>
413
+ <xs:simpleType name="Max16Text">
414
+ <xs:restriction base="xs:string">
415
+ <xs:minLength value="1"/>
416
+ <xs:maxLength value="16"/>
417
+ </xs:restriction>
418
+ </xs:simpleType>
419
+ <xs:simpleType name="Max2048Text">
420
+ <xs:restriction base="xs:string">
421
+ <xs:minLength value="1"/>
422
+ <xs:maxLength value="2048"/>
423
+ </xs:restriction>
424
+ </xs:simpleType>
425
+ <xs:simpleType name="Max34Text">
426
+ <xs:restriction base="xs:string">
427
+ <xs:minLength value="1"/>
428
+ <xs:maxLength value="34"/>
429
+ </xs:restriction>
430
+ </xs:simpleType>
431
+ <xs:simpleType name="Max350Text">
432
+ <xs:restriction base="xs:string">
433
+ <xs:minLength value="1"/>
434
+ <xs:maxLength value="350"/>
435
+ </xs:restriction>
436
+ </xs:simpleType>
437
+ <xs:simpleType name="Max35Text">
438
+ <xs:restriction base="xs:string">
439
+ <xs:minLength value="1"/>
440
+ <xs:maxLength value="35"/>
441
+ </xs:restriction>
442
+ </xs:simpleType>
443
+ <xs:simpleType name="Max70Text">
444
+ <xs:restriction base="xs:string">
445
+ <xs:minLength value="1"/>
446
+ <xs:maxLength value="70"/>
447
+ </xs:restriction>
448
+ </xs:simpleType>
449
+ <xs:simpleType name="NamePrefix1Code">
450
+ <xs:restriction base="xs:string">
451
+ <xs:enumeration value="DOCT"/>
452
+ <xs:enumeration value="MIST"/>
453
+ <xs:enumeration value="MISS"/>
454
+ <xs:enumeration value="MADM"/>
455
+ </xs:restriction>
456
+ </xs:simpleType>
457
+ <xs:complexType name="OrganisationIdentification8">
458
+ <xs:sequence>
459
+ <xs:element maxOccurs="1" minOccurs="0" name="AnyBIC" type="AnyBICIdentifier"/>
460
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Othr" type="GenericOrganisationIdentification1"/>
461
+ </xs:sequence>
462
+ </xs:complexType>
463
+ <xs:complexType name="OrganisationIdentificationSchemeName1Choice">
464
+ <xs:choice>
465
+ <xs:element name="Cd" type="ExternalOrganisationIdentification1Code"/>
466
+ <xs:element name="Prtry" type="Max35Text"/>
467
+ </xs:choice>
468
+ </xs:complexType>
469
+ <xs:complexType name="OriginalMandate3Choice">
470
+ <xs:choice>
471
+ <xs:element name="OrgnlMndtId" type="Max35Text"/>
472
+ <xs:element name="OrgnlMndt" type="Mandate5"/>
473
+ </xs:choice>
474
+ </xs:complexType>
475
+ <xs:complexType name="OriginalMessageInformation1">
476
+ <xs:sequence>
477
+ <xs:element name="MsgId" type="Max35Text"/>
478
+ <xs:element name="MsgNmId" type="Max35Text"/>
479
+ <xs:element maxOccurs="1" minOccurs="0" name="CreDtTm" type="ISODateTime"/>
480
+ </xs:sequence>
481
+ </xs:complexType>
482
+ <xs:complexType name="Party11Choice">
483
+ <xs:choice>
484
+ <xs:element name="OrgId" type="OrganisationIdentification8"/>
485
+ <xs:element name="PrvtId" type="PersonIdentification5"/>
486
+ </xs:choice>
487
+ </xs:complexType>
488
+ <xs:complexType name="PartyIdentification43">
489
+ <xs:sequence>
490
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
491
+ <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/>
492
+ <xs:element maxOccurs="1" minOccurs="0" name="Id" type="Party11Choice"/>
493
+ <xs:element maxOccurs="1" minOccurs="0" name="CtryOfRes" type="CountryCode"/>
494
+ <xs:element maxOccurs="1" minOccurs="0" name="CtctDtls" type="ContactDetails2"/>
495
+ </xs:sequence>
496
+ </xs:complexType>
497
+ <xs:complexType name="PersonIdentification5">
498
+ <xs:sequence>
499
+ <xs:element maxOccurs="1" minOccurs="0" name="DtAndPlcOfBirth" type="DateAndPlaceOfBirth"/>
500
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Othr" type="GenericPersonIdentification1"/>
501
+ </xs:sequence>
502
+ </xs:complexType>
503
+ <xs:complexType name="PersonIdentificationSchemeName1Choice">
504
+ <xs:choice>
505
+ <xs:element name="Cd" type="ExternalPersonIdentification1Code"/>
506
+ <xs:element name="Prtry" type="Max35Text"/>
507
+ </xs:choice>
508
+ </xs:complexType>
509
+ <xs:simpleType name="PhoneNumber">
510
+ <xs:restriction base="xs:string">
511
+ <xs:pattern value="\+[0-9]{1,3}-[0-9()+\-]{1,30}"/>
512
+ </xs:restriction>
513
+ </xs:simpleType>
514
+ <xs:complexType name="PostalAddress6">
515
+ <xs:sequence>
516
+ <xs:element maxOccurs="1" minOccurs="0" name="AdrTp" type="AddressType2Code"/>
517
+ <xs:element maxOccurs="1" minOccurs="0" name="Dept" type="Max70Text"/>
518
+ <xs:element maxOccurs="1" minOccurs="0" name="SubDept" type="Max70Text"/>
519
+ <xs:element maxOccurs="1" minOccurs="0" name="StrtNm" type="Max70Text"/>
520
+ <xs:element maxOccurs="1" minOccurs="0" name="BldgNb" type="Max16Text"/>
521
+ <xs:element maxOccurs="1" minOccurs="0" name="PstCd" type="Max16Text"/>
522
+ <xs:element maxOccurs="1" minOccurs="0" name="TwnNm" type="Max35Text"/>
523
+ <xs:element maxOccurs="1" minOccurs="0" name="CtrySubDvsn" type="Max35Text"/>
524
+ <xs:element maxOccurs="1" minOccurs="0" name="Ctry" type="CountryCode"/>
525
+ <xs:element maxOccurs="7" minOccurs="0" name="AdrLine" type="Max70Text"/>
526
+ </xs:sequence>
527
+ </xs:complexType>
528
+ <xs:complexType name="ReferredDocumentInformation6">
529
+ <xs:sequence>
530
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="ReferredDocumentType4"/>
531
+ <xs:element maxOccurs="1" minOccurs="0" name="Nb" type="Max35Text"/>
532
+ <xs:element maxOccurs="1" minOccurs="0" name="RltdDt" type="ISODate"/>
533
+ </xs:sequence>
534
+ </xs:complexType>
535
+ <xs:complexType name="ReferredDocumentType3Choice">
536
+ <xs:choice>
537
+ <xs:element name="Cd" type="DocumentType6Code"/>
538
+ <xs:element name="Prtry" type="Max35Text"/>
539
+ </xs:choice>
540
+ </xs:complexType>
541
+ <xs:complexType name="ReferredDocumentType4">
542
+ <xs:sequence>
543
+ <xs:element name="CdOrPrtry" type="ReferredDocumentType3Choice"/>
544
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
545
+ </xs:sequence>
546
+ </xs:complexType>
547
+ <xs:simpleType name="SequenceType2Code">
548
+ <xs:restriction base="xs:string">
549
+ <xs:enumeration value="RCUR"/>
550
+ <xs:enumeration value="OOFF"/>
551
+ </xs:restriction>
552
+ </xs:simpleType>
553
+ <xs:complexType name="ServiceLevel8Choice">
554
+ <xs:choice>
555
+ <xs:element name="Cd" type="ExternalServiceLevel1Code"/>
556
+ <xs:element name="Prtry" type="Max35Text"/>
557
+ </xs:choice>
558
+ </xs:complexType>
559
+ <xs:complexType name="SupplementaryData1">
560
+ <xs:sequence>
561
+ <xs:element maxOccurs="1" minOccurs="0" name="PlcAndNm" type="Max350Text"/>
562
+ <xs:element name="Envlp" type="SupplementaryDataEnvelope1"/>
563
+ </xs:sequence>
564
+ </xs:complexType>
565
+ <xs:complexType name="SupplementaryDataEnvelope1">
566
+ <xs:sequence>
567
+ <xs:any namespace="##any" processContents="lax"/>
568
+ </xs:sequence>
569
+ </xs:complexType>
570
+ <xs:simpleType name="YesNoIndicator">
571
+ <xs:restriction base="xs:boolean"/>
572
+ </xs:simpleType>
573
+ </xs:schema>
lib/Communicator/schemas/xmldsig-core-schema.xsd ADDED
@@ -0,0 +1,309 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Removed DTD, otherwise xsd2code.exe had problems -->
3
+ <!-- Schema for XML Signatures
4
+ http://www.w3.org/2000/09/xmldsig#
5
+ $Revision: 1.1 $ on $Date: 2002/02/08 20:32:26 $ by $Author: reagle $
6
+
7
+ Copyright 2001 The Internet Society and W3C (Massachusetts Institute
8
+ of Technology, Institut National de Recherche en Informatique et en
9
+ Automatique, Keio University). All Rights Reserved.
10
+ http://www.w3.org/Consortium/Legal/
11
+
12
+ This document is governed by the W3C Software License [1] as described
13
+ in the FAQ [2].
14
+
15
+ [1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
16
+ [2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
17
+ -->
18
+
19
+
20
+ <schema xmlns="http://www.w3.org/2001/XMLSchema"
21
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
22
+ targetNamespace="http://www.w3.org/2000/09/xmldsig#"
23
+ version="0.1" elementFormDefault="qualified">
24
+
25
+ <!-- Basic Types Defined for Signatures -->
26
+
27
+ <simpleType name="CryptoBinary">
28
+ <restriction base="base64Binary">
29
+ </restriction>
30
+ </simpleType>
31
+
32
+ <!-- Start Signature -->
33
+
34
+ <element name="Signature" type="ds:SignatureType"/>
35
+ <complexType name="SignatureType">
36
+ <sequence>
37
+ <element ref="ds:SignedInfo"/>
38
+ <element ref="ds:SignatureValue"/>
39
+ <element ref="ds:KeyInfo" minOccurs="0"/>
40
+ <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/>
41
+ </sequence>
42
+ <attribute name="Id" type="ID" use="optional"/>
43
+ </complexType>
44
+
45
+ <element name="SignatureValue" type="ds:SignatureValueType"/>
46
+ <complexType name="SignatureValueType">
47
+ <simpleContent>
48
+ <extension base="base64Binary">
49
+ <attribute name="Id" type="ID" use="optional"/>
50
+ </extension>
51
+ </simpleContent>
52
+ </complexType>
53
+
54
+ <!-- Start SignedInfo -->
55
+
56
+ <element name="SignedInfo" type="ds:SignedInfoType"/>
57
+ <complexType name="SignedInfoType">
58
+ <sequence>
59
+ <element ref="ds:CanonicalizationMethod"/>
60
+ <element ref="ds:SignatureMethod"/>
61
+ <element ref="ds:Reference" maxOccurs="unbounded"/>
62
+ </sequence>
63
+ <attribute name="Id" type="ID" use="optional"/>
64
+ </complexType>
65
+
66
+ <element name="CanonicalizationMethod" type="ds:CanonicalizationMethodType"/>
67
+ <complexType name="CanonicalizationMethodType" mixed="true">
68
+ <sequence>
69
+ <any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>
70
+ <!-- (0,unbounded) elements from (1,1) namespace -->
71
+ </sequence>
72
+ <attribute name="Algorithm" type="anyURI" use="required"/>
73
+ </complexType>
74
+
75
+ <element name="SignatureMethod" type="ds:SignatureMethodType"/>
76
+ <complexType name="SignatureMethodType" mixed="true">
77
+ <sequence>
78
+ <element name="HMACOutputLength" minOccurs="0" type="ds:HMACOutputLengthType"/>
79
+ <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
80
+ <!-- (0,unbounded) elements from (1,1) external namespace -->
81
+ </sequence>
82
+ <attribute name="Algorithm" type="anyURI" use="required"/>
83
+ </complexType>
84
+
85
+ <!-- Start Reference -->
86
+
87
+ <element name="Reference" type="ds:ReferenceType"/>
88
+ <complexType name="ReferenceType">
89
+ <sequence>
90
+ <element ref="ds:Transforms" minOccurs="0"/>
91
+ <element ref="ds:DigestMethod"/>
92
+ <element ref="ds:DigestValue"/>
93
+ </sequence>
94
+ <attribute name="Id" type="ID" use="optional"/>
95
+ <attribute name="URI" type="anyURI" use="optional"/>
96
+ <attribute name="Type" type="anyURI" use="optional"/>
97
+ </complexType>
98
+
99
+ <element name="Transforms" type="ds:TransformsType"/>
100
+ <complexType name="TransformsType">
101
+ <sequence>
102
+ <element ref="ds:Transform" maxOccurs="unbounded"/>
103
+ </sequence>
104
+ </complexType>
105
+
106
+ <element name="Transform" type="ds:TransformType"/>
107
+ <complexType name="TransformType" mixed="true">
108
+ <choice minOccurs="0" maxOccurs="unbounded">
109
+ <any namespace="##other" processContents="lax"/>
110
+ <!-- (1,1) elements from (0,unbounded) namespaces -->
111
+ <element name="XPath" type="string"/>
112
+ </choice>
113
+ <attribute name="Algorithm" type="anyURI" use="required"/>
114
+ </complexType>
115
+
116
+ <!-- End Reference -->
117
+
118
+ <element name="DigestMethod" type="ds:DigestMethodType"/>
119
+ <complexType name="DigestMethodType" mixed="true">
120
+ <sequence>
121
+ <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
122
+ </sequence>
123
+ <attribute name="Algorithm" type="anyURI" use="required"/>
124
+ </complexType>
125
+
126
+ <element name="DigestValue" type="ds:DigestValueType"/>
127
+ <simpleType name="DigestValueType">
128
+ <restriction base="base64Binary"/>
129
+ </simpleType>
130
+
131
+ <!-- End SignedInfo -->
132
+
133
+ <!-- Start KeyInfo -->
134
+
135
+ <element name="KeyInfo" type="ds:KeyInfoType"/>
136
+ <complexType name="KeyInfoType" mixed="true">
137
+ <choice maxOccurs="unbounded">
138
+ <element ref="ds:KeyName"/>
139
+ <element ref="ds:KeyValue"/>
140
+ <element ref="ds:RetrievalMethod"/>
141
+ <element ref="ds:X509Data"/>
142
+ <element ref="ds:PGPData"/>
143
+ <element ref="ds:SPKIData"/>
144
+ <element ref="ds:MgmtData"/>
145
+ <any processContents="lax" namespace="##other"/>
146
+ <!-- (1,1) elements from (0,unbounded) namespaces -->
147
+ </choice>
148
+ <attribute name="Id" type="ID" use="optional"/>
149
+ </complexType>
150
+
151
+ <element name="KeyName" type="string"/>
152
+ <element name="MgmtData" type="string"/>
153
+
154
+ <element name="KeyValue" type="ds:KeyValueType"/>
155
+ <complexType name="KeyValueType" mixed="true">
156
+ <choice>
157
+ <element ref="ds:DSAKeyValue"/>
158
+ <element ref="ds:RSAKeyValue"/>
159
+ <any namespace="##other" processContents="lax"/>
160
+ </choice>
161
+ </complexType>
162
+
163
+ <element name="RetrievalMethod" type="ds:RetrievalMethodType"/>
164
+ <complexType name="RetrievalMethodType">
165
+ <sequence>
166
+ <element ref="ds:Transforms" minOccurs="0"/>
167
+ </sequence>
168
+ <attribute name="URI" type="anyURI"/>
169
+ <attribute name="Type" type="anyURI" use="optional"/>
170
+ </complexType>
171
+
172
+ <!-- Start X509Data -->
173
+
174
+ <element name="X509Data" type="ds:X509DataType"/>
175
+ <complexType name="X509DataType">
176
+ <sequence maxOccurs="unbounded">
177
+ <choice>
178
+ <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/>
179
+ <element name="X509SKI" type="base64Binary"/>
180
+ <element name="X509SubjectName" type="string"/>
181
+ <element name="X509Certificate" type="base64Binary"/>
182
+ <element name="X509CRL" type="base64Binary"/>
183
+ <any namespace="##other" processContents="lax"/>
184
+ </choice>
185
+ </sequence>
186
+ </complexType>
187
+
188
+ <complexType name="X509IssuerSerialType">
189
+ <sequence>
190
+ <element name="X509IssuerName" type="string"/>
191
+ <element name="X509SerialNumber" type="integer"/>
192
+ </sequence>
193
+ </complexType>
194
+
195
+ <!-- End X509Data -->
196
+
197
+ <!-- Begin PGPData -->
198
+
199
+ <element name="PGPData" type="ds:PGPDataType"/>
200
+ <complexType name="PGPDataType">
201
+ <choice>
202
+ <sequence>
203
+ <element name="PGPKeyID" type="base64Binary"/>
204
+ <element name="PGPKeyPacket" type="base64Binary" minOccurs="0"/>
205
+ <any namespace="##other" processContents="lax" minOccurs="0"
206
+ maxOccurs="unbounded"/>
207
+ </sequence>
208
+ <sequence>
209
+ <element name="PGPKeyPacket" type="base64Binary"/>
210
+ <any namespace="##other" processContents="lax" minOccurs="0"
211
+ maxOccurs="unbounded"/>
212
+ </sequence>
213
+ </choice>
214
+ </complexType>
215
+
216
+ <!-- End PGPData -->
217
+
218
+ <!-- Begin SPKIData -->
219
+
220
+ <element name="SPKIData" type="ds:SPKIDataType"/>
221
+ <complexType name="SPKIDataType">
222
+ <sequence maxOccurs="unbounded">
223
+ <element name="SPKISexp" type="base64Binary"/>
224
+ <any namespace="##other" processContents="lax" minOccurs="0"/>
225
+ </sequence>
226
+ </complexType>
227
+
228
+ <!-- End SPKIData -->
229
+
230
+ <!-- End KeyInfo -->
231
+
232
+ <!-- Start Object (Manifest, SignatureProperty) -->
233
+
234
+ <element name="Object" type="ds:ObjectType"/>
235
+ <complexType name="ObjectType" mixed="true">
236
+ <sequence minOccurs="0" maxOccurs="unbounded">
237
+ <any namespace="##any" processContents="lax"/>
238
+ </sequence>
239
+ <attribute name="Id" type="ID" use="optional"/>
240
+ <attribute name="MimeType" type="string" use="optional"/> <!-- add a grep facet -->
241
+ <attribute name="Encoding" type="anyURI" use="optional"/>
242
+ </complexType>
243
+
244
+ <element name="Manifest" type="ds:ManifestType"/>
245
+ <complexType name="ManifestType">
246
+ <sequence>
247
+ <element ref="ds:Reference" maxOccurs="unbounded"/>
248
+ </sequence>
249
+ <attribute name="Id" type="ID" use="optional"/>
250
+ </complexType>
251
+
252
+ <element name="SignatureProperties" type="ds:SignaturePropertiesType"/>
253
+ <complexType name="SignaturePropertiesType">
254
+ <sequence>
255
+ <element ref="ds:SignatureProperty" maxOccurs="unbounded"/>
256
+ </sequence>
257
+ <attribute name="Id" type="ID" use="optional"/>
258
+ </complexType>
259
+
260
+ <element name="SignatureProperty" type="ds:SignaturePropertyType"/>
261
+ <complexType name="SignaturePropertyType" mixed="true">
262
+ <choice maxOccurs="unbounded">
263
+ <any namespace="##other" processContents="lax"/>
264
+ <!-- (1,1) elements from (1,unbounded) namespaces -->
265
+ </choice>
266
+ <attribute name="Target" type="anyURI" use="required"/>
267
+ <attribute name="Id" type="ID" use="optional"/>
268
+ </complexType>
269
+
270
+ <!-- End Object (Manifest, SignatureProperty) -->
271
+
272
+ <!-- Start Algorithm Parameters -->
273
+
274
+ <simpleType name="HMACOutputLengthType">
275
+ <restriction base="integer"/>
276
+ </simpleType>
277
+
278
+ <!-- Start KeyValue Element-types -->
279
+
280
+ <element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
281
+ <complexType name="DSAKeyValueType">
282
+ <sequence>
283
+ <sequence minOccurs="0">
284
+ <element name="P" type="ds:CryptoBinary"/>
285
+ <element name="Q" type="ds:CryptoBinary"/>
286
+ </sequence>
287
+ <element name="G" type="ds:CryptoBinary" minOccurs="0"/>
288
+ <element name="Y" type="ds:CryptoBinary"/>
289
+ <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
290
+ <sequence minOccurs="0">
291
+ <element name="Seed" type="ds:CryptoBinary"/>
292
+ <element name="PgenCounter" type="ds:CryptoBinary"/>
293
+ </sequence>
294
+ </sequence>
295
+ </complexType>
296
+
297
+ <element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
298
+ <complexType name="RSAKeyValueType">
299
+ <sequence>
300
+ <element name="Modulus" type="ds:CryptoBinary"/>
301
+ <element name="Exponent" type="ds:CryptoBinary"/>
302
+ </sequence>
303
+ </complexType>
304
+
305
+ <!-- End KeyValue Element-types -->
306
+
307
+ <!-- End Signature -->
308
+
309
+ </schema>
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>XREC_DIM</name>
4
+ <version>1.0.1</version>
5
+ <stability>Stable</stability>
6
+ <license>paid</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Digitaal Incassomachtigen</summary>
10
+ <description>ING digitaal Incassomachtigen voor online betalen</description>
11
+ <notes>First Release</notes>
12
+ <authors><author><name>xrec.nl</name><user>yasarkunduz</user><email>info@xrec.nl</email></author></authors>
13
+ <date>2015-06-28</date>
14
+ <time>17:34:05</time>
15
+ <contents><target name="magecommunity"><dir name="Xrec"><dir name="Dim"><dir name="Block"><dir name="Payment"><dir name="Dim"><file name="Fail.php" hash="c02269203e5671651cfcf2f73a46f7b6"/><file name="Form.php" hash="e7d830877f011e967b7f46fbcffd31fe"/><file name="Info.php" hash="343c4a38e6314d370bb39ff1c93ef2d9"/></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="ef41ad5f43178e0ac59d99d2583ecdee"/><file name="Dim.php" hash="92e526ffb3e995710b242240041174b0"/></dir><dir name="Model"><file name="Dim.php" hash="165579ff6573d173bf24bab363d582e7"/></dir><dir name="controllers"><file name="DimController.php" hash="74c3986327c4a16fff873c815da8e9a0"/></dir><dir name="etc"><file name="config.xml" hash="fb8066f1b903991dc83f020aded1d487"/><file name="system.xml" hash="8be4c1a04aa031db9a25e1b145eda137"/></dir><dir name="sql"><dir name="dim_setup"><file name="mysql4-install-1.0.0.php" hash="b2007ad1be0ce4b81fc8c96f318e471c"/><file name="mysql4-uninstall-1.0.0.php" hash="343db23ebd3447bdec9fde2ad9f458ee"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="dim.xml" hash="3bc2c7454e08a67af66a9747121f5a06"/></dir><dir name="template"><dir name="xrec"><dir name="form"><file name="dim.phtml" hash="f702661da3aaf1c79c8c7645c4ddee73"/></dir><dir name="page"><file name="exception.phtml" hash="5696fc484250a35a6a4d4b796c3d0b12"/><file name="fail.phtml" hash="c970bed0050919a585c18ae2b89f9c15"/></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Xrec_Dim.xml" hash="a5a264a4e2ef950c283b9b81c0117098"/></dir></target><target name="magelib"><dir name="Communicator"><file name="B2BCommunicator.php" hash="94fd8863facaaaa598f5f92f134f92c9"/><dir name="Configuration"><file name="Configuration.php" hash="2141e5e7e95465e4b81afdddcd8c3621"/></dir><file name="CoreCommunicator.php" hash="ed81ce17539167a7dfab5d273a6a2810"/><dir name="Entities"><file name="AcquirerStatusRequest.php" hash="dd7308d59634e3efbd985a51e372c494"/><file name="AcquirerStatusResponse.php" hash="782857adb7fff0a36811ffbe2d5149f0"/><file name="AcquirerTrxRequest.php" hash="8111238cbfcad8ee7ac84325819b14d8"/><file name="AmendmentRequest.php" hash="3e83bf8031edcf9ff8b60e60aae6b7f0"/><file name="AmendmentResponse.php" hash="3f18c193fadbce4f65e5bf6d9648a290"/><file name="CancellationRequest.php" hash="40889429b6bff27060566db4c247acfb"/><file name="CancellationResponse.php" hash="40ed6e02dc87973da7547c052cdab3aa"/><file name="DirectoryRequest.php" hash="534bcdbde8bc375921dc7f97cc9c0d6d"/><file name="DirectoryResponse.php" hash="1abd26b8a57dc2c03734d5f5ac8e6211"/><file name="ErrorResponse.php" hash="27c734ddd2d2549e0b52d8db402e9f51"/><file name="NewMandateRequest.php" hash="1252a8a08b427ea9e7382fb5eef8069d"/><file name="NewMandateResponse.php" hash="a8e3b56452e0ff3abb51d72c3b578700"/></dir><dir name="Libraries"><file name="CommunicatorException.php" hash="ae3087f21c3d988048f77db241eb8f2e"/><file name="Logger.php" hash="ec84b8fcde853923b0301aa1361032e8"/><file name="MessageIdGenerator.php" hash="29f189dd41e544871b9545fc3d0a78d5"/><file name="XmlSecurity.php" hash="98a217e1829effdce2b003982f98c9ac"/><file name="XmlValidator.php" hash="65187ed0300108c76951567a839ddbe4"/><file name="xmlseclibs.php" hash="75aa5adc6bd69318bc83f9ca4948f578"/></dir><dir name="schemas"><file name="idx.merchant-acquirer.1.0.xsd" hash="5090a394336fa5691b391e9ca613147f"/><file name="pain.009.001.04.xsd" hash="341c5cc848c4e396c80f087bb5dc1b02"/><file name="pain.010.001.04.xsd" hash="336d47dee264e6600e60d508748a0302"/><file name="pain.011.001.04.xsd" hash="22d4bf175016b944ca6b3538801797b3"/><file name="pain.012.001.04.xsd" hash="3bc9a3bc6d9ddd5885518b0cce45f2c4"/><file name="xmldsig-core-schema.xsd" hash="ec096c98bec8ca421e284af9443546c5"/></dir><file name=".DS_Store" hash="6b79706ed0b8c42eadd16a8fc35be1b7"/></dir></target><target name="mage"><dir><dir name="var"><dir name="xrec"><dir name="dim"><dir name="cer"><file name=".DS_Store" hash="194577a7e20bdcc7afbb718f502c134c"/></dir><file name=".DS_Store" hash="b59dd545b407bbd35442197809059cc2"/></dir><file name=".DS_Store" hash="493d87106d63b713d90e5dec20b455a4"/><file name=".htaccess" hash="72617d60821288133a367f70bf39ad93"/></dir></dir></dir></target><target name="magelocale"><dir name="."><file name="Xrec_Dim.csv" hash=""/></dir></target><target name="mageskin"><dir name="frontend"><dir name="dim"><dir name="css"><file name="style.css" hash="0d98e5fa0f90cb613509f90b64b83129"/></dir><dir name="images"><file name="dim.jpg" hash="f90083a65649212e13c7b407c75ce0a7"/></dir><file name=".DS_Store" hash="144c2056ff80e19faa3722eedcf87c25"/></dir></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
18
+ </package>
skin/frontend/dim/.DS_Store ADDED
Binary file
skin/frontend/dim/css/style.css ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ #p_method_dim + label:before {
2
+ display: inline-block;
3
+ content:"icon";
4
+ text-indent:-999em;
5
+ width: 25px;
6
+ height: 20px;
7
+ margin-top: -3px;
8
+ background: transparent url('../images/dim.jpg') no-repeat;
9
+ }
skin/frontend/dim/images/dim.jpg ADDED
Binary file
var/xrec/.DS_Store ADDED
Binary file
var/xrec/.htaccess ADDED
@@ -0,0 +1,2 @@
 
 
1
+ Order deny,allow
2
+ Deny from all
var/xrec/dim/.DS_Store ADDED
Binary file
var/xrec/dim/cer/.DS_Store ADDED
Binary file