├── .gitignore
├── .travis.yml
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── composer.json
├── phpunit.xml.dist
├── src
├── Gateway.php
├── Message
│ ├── AbstractRequest.php
│ ├── AbstractResponse.php
│ ├── CompletePurchaseRequest.php
│ ├── CompletePurchaseResponse.php
│ ├── FetchIssuersRequest.php
│ ├── FetchIssuersResponse.php
│ ├── FetchPaymentMethodsRequest.php
│ ├── FetchPaymentMethodsResponse.php
│ ├── PurchaseRequest.php
│ ├── PurchaseResponse.php
│ ├── RestAbstractRequest.php
│ ├── RestAbstractResponse.php
│ ├── RestCompletePurchaseRequest.php
│ ├── RestCompletePurchaseResponse.php
│ ├── RestFetchIssuersRequest.php
│ ├── RestFetchIssuersResponse.php
│ ├── RestFetchPaymentMethodsRequest.php
│ ├── RestFetchPaymentMethodsResponse.php
│ ├── RestFetchTransactionRequest.php
│ ├── RestFetchTransactionResponse.php
│ ├── RestPurchaseRequest.php
│ ├── RestPurchaseResponse.php
│ ├── RestRefundRequest.php
│ └── RestRefundResponse.php
├── RestGateway.php
└── XmlGateway.php
└── tests
├── Message
├── RestFetchIssuersRequestTest.php
├── RestFetchPaymentMethodsRequestTest.php
├── RestPurchaseRequestTest.php
├── XmlAbstractRequestTest.php
├── XmlCompletePurchaseRequestTest.php
├── XmlFetchIssuersRequestTest.php
├── XmlFetchPaymentMethodsRequestTest.php
└── XmlPurchaseRequestTest.php
├── Mock
├── RestFetchIssuersFailure.txt
├── RestFetchIssuersSuccess.txt
├── RestFetchPaymentMethodsSuccess.txt
├── RestInvalidApiKeyFailure.txt
├── RestPurchaseInvalidAmount.txt
├── RestPurchaseSuccess.txt
├── XmlCompletePurchaseFailure.txt
├── XmlCompletePurchaseSuccess.txt
├── XmlFetchIssuersFailure.txt
├── XmlFetchIssuersSuccess.txt
├── XmlFetchPaymentMethodsFailure.txt
├── XmlFetchPaymentMethodsSuccess.txt
├── XmlPurchaseFailure.txt
└── XmlPurchaseSuccess.txt
├── RestGatewayTest.php
└── XmlGatewayTest.php
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | composer.lock
3 | composer.phar
4 | phpunit.xml
5 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.6
5 | - 7.0
6 | - 7.1
7 | - 7.2
8 |
9 | # This triggers builds to run on the new TravisCI infrastructure.
10 | # See: http://docs.travis-ci.com/user/workers/container-based-infrastructure/
11 | sudo: false
12 |
13 | ## Cache composer
14 | cache:
15 | directories:
16 | - $HOME/.composer/cache
17 |
18 | env:
19 | global:
20 | - setup=basic
21 |
22 | matrix:
23 | include:
24 | - php: 5.6
25 | env: setup=lowest
26 |
27 | install:
28 | - if [[ $setup = 'basic' ]]; then travis_retry composer install --prefer-dist --no-interaction; fi
29 | - if [[ $setup = 'lowest' ]]; then travis_retry composer update --prefer-dist --no-interaction --prefer-lowest --prefer-stable; fi
30 |
31 | script: vendor/bin/phpcs --standard=PSR2 src && vendor/bin/phpunit --coverage-text
32 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | * Fork the project.
4 | * Make your feature addition or bug fix.
5 | * Add tests for it. This is important so I don't break it in a future version unintentionally.
6 | * Commit just the modifications, do not mess with the composer.json or CHANGELOG.md files.
7 | * Ensure your code is nicely formatted in the [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
8 | style and that all tests pass.
9 | * Send the pull request.
10 | * Check that the Travis CI build passed. If not, rinse and repeat.
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012-2013 Adrian Macneil
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Omnipay: MultiSafepay
2 |
3 | **MultiSafepay driver for the Omnipay PHP payment processing library**
4 |
5 | [](https://travis-ci.org/thephpleague/omnipay-multisafepay)
6 | [](https://packagist.org/packages/omnipay/multisafepay)
7 | [](https://packagist.org/packages/omnipay/multisafepay)
8 |
9 | [Omnipay](https://github.com/thephpleague/omnipay) is a framework agnostic, multi-gateway payment
10 | processing library for PHP 5.3+. This package implements MultiSafepay support for Omnipay.
11 |
12 | ## Installation
13 |
14 | Omnipay is installed via [Composer](http://getcomposer.org/). To install, simply add it
15 | to your `composer.json` file:
16 |
17 | ```json
18 | {
19 | "require": {
20 | "omnipay/multisafepay": "~2.0"
21 | }
22 | }
23 | ```
24 |
25 | And run composer to update your dependencies:
26 |
27 | $ curl -s http://getcomposer.org/installer | php
28 | $ php composer.phar update
29 |
30 | ## Basic Usage
31 |
32 | The following gateways are provided by this package:
33 |
34 | * MultiSafepay_Rest
35 | * MultiSafepay_Xml (Deprecated)
36 |
37 | For general usage instructions, please see the main [Omnipay](https://github.com/thephpleague/omnipay)
38 | repository.
39 |
40 | ## Support
41 |
42 | If you are having general issues with Omnipay, we suggest posting on
43 | [Stack Overflow](http://stackoverflow.com/). Be sure to add the
44 | [omnipay tag](http://stackoverflow.com/questions/tagged/omnipay) so it can be easily found.
45 |
46 | If you want to keep up to date with release anouncements, discuss ideas for the project,
47 | or ask more detailed questions, there is also a [mailing list](https://groups.google.com/forum/#!forum/omnipay) which
48 | you can subscribe to.
49 |
50 | If you believe you have found a bug, please report it using the [GitHub issue tracker](https://github.com/thephpleague/omnipay-multisafepay/issues),
51 | or better yet, fork the library and submit a pull request.
52 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "omnipay/multisafepay",
3 | "type": "library",
4 | "description": "MultiSafepay driver for the Omnipay payment processing library",
5 | "keywords": [
6 | "gateway",
7 | "merchant",
8 | "multi safepay",
9 | "multisafepay",
10 | "omnipay",
11 | "pay",
12 | "payment"
13 | ],
14 | "homepage": "https://github.com/thephpleague/omnipay-multisafepay",
15 | "license": "MIT",
16 | "authors": [
17 | {
18 | "name": "Adrian Macneil",
19 | "email": "adrian@adrianmacneil.com"
20 | },
21 | {
22 | "name": "Omnipay Contributors",
23 | "homepage": "https://github.com/thephpleague/omnipay-multisafepay/contributors"
24 | }
25 | ],
26 | "autoload": {
27 | "psr-4": { "Omnipay\\MultiSafepay\\" : "src/" }
28 | },
29 | "require": {
30 | "omnipay/common": "^3"
31 | },
32 | "require-dev": {
33 | "omnipay/tests": "^3",
34 | "squizlabs/php_codesniffer": "^3"
35 | },
36 | "extra": {
37 | "branch-alias": {
38 | "dev-master": "3.0.x-dev"
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
52 | * $request = $gateway->purchase();
53 | *
54 | * $request->setAmount('20.00');
55 | * $request->setTransactionId('TEST-TRANSACTION');
56 | * $request->setDescription('Test transaction');
57 | *
58 | * $request->setCurrency('EUR');
59 | * $request->setType('redirect');
60 | *
61 | * $response = $request->send();
62 | * var_dump($response->getData());
63 | *
64 | *
65 | * ### Initialize a "direct" payment.
66 | *
67 | * The merchant website need to collect the payment details, so
68 | * the user can stay at the merchant website.
69 | *
70 | *
71 | * $request = $gateway->purchase();
72 | *
73 | * $request->setAmount('20.00');
74 | * $request->setTransactionId('TEST-TRANSACTION');
75 | * $request->setDescription('Test transaction');
76 | *
77 | * $request->setCurrency('EUR');
78 | * $request->setType('direct');
79 | * $request->setCard($card);
80 | *
81 | * $request->setGateway('IDEAL');
82 | * $request->setIssuer('ISSUER-ID'); // This ID can be found, with the RestFetchIssuersRequest.
83 | *
84 | * $response = $request->send();
85 | * var_dump($response->getData());
86 | *
87 | */
88 | class RestPurchaseRequest extends RestAbstractRequest
89 | {
90 | /**
91 | * Get payment type.
92 | *
93 | * Specifies the payment flow for the checkout process.
94 | *
95 | * @return string
96 | */
97 | public function getType()
98 | {
99 | return $this->getParameter('type');
100 | }
101 |
102 | /**
103 | * Set payment type.
104 | *
105 | * Specifies the payment flow for the checkout process.
106 | * Possible values are 'redirect', 'direct'
107 | *
108 | * @param $value
109 | * @return \Omnipay\Common\Message\AbstractRequest
110 | */
111 | public function setType($value)
112 | {
113 | return $this->setParameter('type', $value);
114 | }
115 |
116 | /**
117 | * Get recurring Payment Id
118 | *
119 | * A previously stored identifier referring to a
120 | * payment method to be charged again.
121 | *
122 | * @return int|null
123 | */
124 | public function getRecurringId()
125 | {
126 | return $this->getParameter('recurring_id');
127 | }
128 |
129 | /**
130 | * Set recurring Payment Id
131 | *
132 | * A previously stored identifier referring to a
133 | * payment method to be charged again.
134 | *
135 | * @param $value
136 | * @return \Omnipay\Common\Message\AbstractRequest
137 | */
138 | public function setRecurringId($value)
139 | {
140 | return $this->setParameter('recurring_id', $value);
141 | }
142 |
143 | /**
144 | * Get the gateway.
145 | *
146 | * The unique gateway id to immediately direct the customer to the payment method.
147 | * You retrieve these gateways using a gateway request.
148 | *
149 | * @return mixed
150 | */
151 | public function getGateway()
152 | {
153 | return $this->getParameter('gateway');
154 | }
155 |
156 | /**
157 | * Set the gateway.
158 | *
159 | * The unique gateway id to immediately direct the customer to the payment method.
160 | * You retrieve these gateways using a gateway request.
161 | *
162 | * @param $value
163 | * @return \Omnipay\Common\Message\AbstractRequest
164 | */
165 | public function setGateway($value)
166 | {
167 | return $this->setParameter('gateway', $value);
168 | }
169 |
170 | /**
171 | * Get value of var1.
172 | *
173 | * A free variable for custom data to be stored and persisted.
174 | *
175 | * @return string|null
176 | */
177 | public function getVar1()
178 | {
179 | return $this->getParameter('var1');
180 | }
181 |
182 | /**
183 | * Set var1.
184 | *
185 | * A free optional variable for custom data to be stored and persisted.
186 | *
187 | * @param $value
188 | * @return \Omnipay\Common\Message\AbstractRequest
189 | */
190 | public function setVar1($value)
191 | {
192 | return $this->setParameter('var1', $value);
193 | }
194 |
195 | /**
196 | * Get var2.
197 | *
198 | * A free variable for custom data to be stored and persisted.
199 | *
200 | * @return string|null
201 | */
202 | public function getVar2()
203 | {
204 | return $this->getParameter('var2');
205 | }
206 |
207 | /**
208 | * Set var2.
209 | *
210 | * A free variable for custom data to be stored and persisted.
211 | *
212 | * @param $value
213 | * @return \Omnipay\Common\Message\AbstractRequest
214 | */
215 | public function setVar2($value)
216 | {
217 | return $this->setParameter('var2', $value);
218 | }
219 |
220 | /**
221 | * Get var3.
222 | *
223 | * A free variable for custom data to be stored and persisted.
224 | *
225 | * @return string|null
226 | */
227 | public function getVar3()
228 | {
229 | return $this->getParameter('var3');
230 | }
231 |
232 | /**
233 | * Set var3.
234 | *
235 | * A free variable for custom data to be stored and persisted.
236 | *
237 | * @param $value
238 | * @return \Omnipay\Common\Message\AbstractRequest
239 | */
240 | public function setVar3($value)
241 | {
242 | return $this->setParameter('var3', $value);
243 | }
244 |
245 | /**
246 | * Get manual.
247 | *
248 | * If true this forces a credit card transaction to require manual
249 | * acceptance regardless of the outcome from fraud checks.
250 | * It is possible that a high risk transaction is still declined.
251 | *
252 | * @return boolean|null
253 | */
254 | public function getManual()
255 | {
256 | return $this->getParameter('manual');
257 | }
258 |
259 | /**
260 | * Set manual.
261 | *
262 | * If true this forces a credit card transaction to require manual
263 | * acceptance regardless of the outcome from fraud checks.
264 | * It is possible that a high risk transaction is still declined.
265 | *
266 | * @param $value
267 | * @return \Omnipay\Common\Message\AbstractRequest
268 | */
269 | public function setManual($value)
270 | {
271 | return $this->setParameter('manual', $value);
272 | }
273 |
274 | /**
275 | * Get days active.
276 | *
277 | * The number of days the payment link will be active for.
278 | * When not specified the default will be 30 days.
279 | *
280 | * @return int|null
281 | */
282 | public function getDaysActive()
283 | {
284 | return $this->getParameter('days_active');
285 | }
286 |
287 | /**
288 | * Set days active.
289 | *
290 | * The number of days the payment link will be active for.
291 | * When not specified the default will be 30 days.
292 | *
293 | * @param $value
294 | * @return \Omnipay\Common\Message\AbstractRequest
295 | */
296 | public function setDaysActive($value)
297 | {
298 | return $this->setParameter('days_active', $value);
299 | }
300 |
301 | /**
302 | * Get close window.
303 | *
304 | * Set to true if you will display the MultiSafepay payment
305 | * page in a new window and want it to close automatically
306 | * after the payment process has been completed.
307 | *
308 | * @return boolean|null
309 | */
310 | public function getCloseWindow()
311 | {
312 | return $this->getParameter('close_window');
313 | }
314 |
315 | /**
316 | * Set close window.
317 | *
318 | * Set to true if you will display the MultiSafepay payment
319 | * page in a new window and want it to close automatically
320 | * after the payment process has been completed.
321 | *
322 | * @param $value
323 | * @return \Omnipay\Common\Message\AbstractRequest
324 | */
325 | public function setCloseWindow($value)
326 | {
327 | return $this->setParameter('close_window', $value);
328 | }
329 |
330 | /**
331 | * Send mail.
332 | *
333 | * True if you will send your own bank transfer payment instructions to
334 | * consumers and do not want MultiSafepay to do this.
335 | *
336 | * @return boolean
337 | */
338 | public function getSendMail()
339 | {
340 | return $this->getParameter('disable_send_mail');
341 | }
342 |
343 | /**
344 | * Send mail.
345 | *
346 | * True if you will send your own bank transfer payment instructions to
347 | * consumers and do not want MultiSafepay to do this.
348 | *
349 | * @param $value
350 | * @return \Omnipay\Common\Message\AbstractRequest
351 | */
352 | public function setSendMail($value)
353 | {
354 | return $this->setParameter('disable_send_mail', $value);
355 | }
356 |
357 | /**
358 | * Google analytics code.
359 | *
360 | * Your Google Analytics Site Id.
361 | * This will be injected into the payment pages
362 | * so you can trigger custom events and track payment metrics.
363 | *
364 | * @return string|null
365 | */
366 | public function getGoogleAnalyticsCode()
367 | {
368 | return $this->getParameter('google_analytics');
369 | }
370 |
371 | /**
372 | * Google analytics code.
373 | *
374 | * Your Google Analytics Site Id.
375 | * This will be injected into the payment pages
376 | * so you can trigger custom events and track payment metrics.
377 | *
378 | * @param $value
379 | * @return \Omnipay\Common\Message\AbstractRequest
380 | */
381 | public function setGoogleAnalyticsCode($value)
382 | {
383 | return $this->setParameter('google_analytics', $value);
384 | }
385 |
386 | /**
387 | * Get items HTML
388 | *
389 | * @return string
390 | */
391 | public function setItemsHtml($itemsHtml)
392 | {
393 | $this->setParameter('itemsHtml', $itemsHtml);
394 | }
395 |
396 | /**
397 | * Get items HTML
398 | *
399 | * @return string
400 | */
401 | public function getItemsHtml()
402 | {
403 | return $this->getParameter('itemsHtml');
404 | }
405 |
406 | /**
407 | * Get the payment options.
408 | *
409 | * @return array
410 | */
411 | protected function getPaymentData()
412 | {
413 | $data = array(
414 | 'cancel_url' => $this->getCancelUrl(),
415 | 'close_window' => $this->getCloseWindow(),
416 | 'notification_url' => $this->getNotifyUrl(),
417 | 'redirect_url' => $this->getReturnUrl(),
418 | );
419 |
420 | return array_filter($data);
421 | }
422 |
423 | /**
424 | * Customer information.
425 | *
426 | * This function returns all the provided
427 | * client related parameters.
428 | *
429 | * @return array
430 | */
431 | public function getCustomerData()
432 | {
433 | $data = array(
434 | 'disable_send_mail' => $this->getSendMail(),
435 | 'locale' => $this->getLocale(),
436 | );
437 |
438 | if (is_null($this->getCard())) {
439 | return array_filter($data);
440 | }
441 |
442 | $cardData = array(
443 | 'address1' => $this->getCard()->getAddress1(),
444 | 'address2' => $this->getCard()->getAddress2(),
445 | 'city' => $this->getCard()->getCity(),
446 | 'country' => $this->getCard()->getCountry(),
447 | 'email' => $this->getCard()->getEmail(),
448 | 'first_name' => $this->getCard()->getFirstName(),
449 | 'house_number' => $this->getVar1(),
450 | 'last_name' => $this->getCard()->getLastName(),
451 | 'phone' => $this->getCard()->getPhone(),
452 | 'state' => $this->getCard()->getState(),
453 | 'zip_code' => $this->getCard()->getPostcode(),
454 | );
455 |
456 | return array_filter(
457 | array_merge($data, $cardData)
458 | );
459 | }
460 |
461 | /**
462 | * Get gateway data.
463 | *
464 | * @return array
465 | */
466 | protected function getGatewayData()
467 | {
468 | $data = array(
469 | 'issuer_id' => $this->getIssuer(),
470 | );
471 |
472 | return array_filter($data);
473 | }
474 |
475 | /**
476 | * Get itembag data.
477 | *
478 | * @return array
479 | */
480 | protected function getItemBagData()
481 | {
482 | $items = array();
483 | $itemBag = $this->getItems();
484 | if (! empty($itemBag)) {
485 | foreach ($itemBag->all() as $item) {
486 | $items[] = array(
487 | 'name' => $item->getName(),
488 | 'description' => $item->getDescription(),
489 | 'quantity' => $item->getQuantity(),
490 | 'unit_price' => $item->getPrice(),
491 | );
492 | }
493 | }
494 |
495 | return $items;
496 | }
497 |
498 | /**
499 | * Get the raw data array for this message. The format of this varies from gateway to
500 | * gateway, but will usually be either an associative array, or a SimpleXMLElement.
501 | *
502 | * @return array
503 | * @throws \Omnipay\Common\Exception\InvalidRequestException
504 | */
505 | public function getData()
506 | {
507 | parent::getData();
508 |
509 | $this->validate(
510 | 'amount',
511 | 'currency',
512 | 'description',
513 | 'transactionId',
514 | 'type'
515 | );
516 |
517 | // Direct order.
518 | if ($this->getType() === 'direct') {
519 | $this->validate('gateway');
520 | }
521 |
522 | // When the gateway is set to IDEAL,
523 | // the issuer parameter is required.
524 | if ($this->getType() == 'direct' && $this->getGateway() == 'IDEAL') {
525 | $this->validate('issuer');
526 | }
527 |
528 | $data = array(
529 | 'amount' => $this->getAmountInteger(),
530 | 'currency' => $this->getCurrency(),
531 | 'days_active' => $this->getDaysActive(),
532 | 'description' => $this->getDescription(),
533 | 'gateway' => $this->getGateway(),
534 | 'google_analytics' => $this->getGoogleAnalyticsCode(),
535 | 'items' => $this->getItemsHtml(),
536 | 'manual' => $this->getManual(),
537 | 'order_id' => $this->getTransactionId(),
538 | 'recurring_id' => $this->getRecurringId(),
539 | 'type' => $this->getType(),
540 | 'var1' => $this->getVar1(),
541 | 'var2' => $this->getVar2(),
542 | 'var3' => $this->getVar3(),
543 | );
544 |
545 | $paymentData = $this->getPaymentData();
546 |
547 | if (! empty($paymentData)) {
548 | $data['payment_options'] = $paymentData;
549 | }
550 |
551 | $customerData = $this->getCustomerData();
552 |
553 | if (! empty($customerData)) {
554 | $data['customer'] = $customerData;
555 | }
556 |
557 | $gatewayData = $this->getGatewayData();
558 |
559 | if (! empty($gatewayData)) {
560 | $data['gateway_info'] = $gatewayData;
561 | }
562 |
563 | $getItemBagData = $this->getItemBagData();
564 |
565 | if (! empty($getItemBagData)) {
566 | $data['shopping_cart']['items'] = $getItemBagData;
567 | }
568 |
569 | return array_filter($data);
570 | }
571 |
572 | /**
573 | * Send the request with specified data
574 | *
575 | * @param mixed $data
576 | * @return RestPurchaseResponse
577 | */
578 | public function sendData($data)
579 | {
580 | $httpResponse = $this->sendRequest('POST', '/orders', json_encode($data));
581 |
582 | $this->response = new RestPurchaseResponse(
583 | $this,
584 | json_decode($httpResponse->getBody()->getContents(), true)
585 | );
586 |
587 | return $this->response;
588 | }
589 | }
590 |
--------------------------------------------------------------------------------
/src/Message/RestPurchaseResponse.php:
--------------------------------------------------------------------------------
1 |
31 | * // Create a credit card object
32 | * $card = new CreditCard(array(
33 | * 'firstName' => 'Example',
34 | * 'lastName' => 'Customer',
35 | * 'number' => '4222222222222222',
36 | * 'expiryMonth' => '01',
37 | * 'expiryYear' => '2020',
38 | * 'cvv' => '123',
39 | * 'email' => 'customer@example.com',
40 | * 'address1' => '1 Scrubby Creek Road',
41 | * 'country' => 'AU',
42 | * 'city' => 'Scrubby Creek',
43 | * 'postalcode' => '4999',
44 | * 'state' => 'QLD',
45 | * ));
46 | *
47 | *
48 | * ### Initialize a "redirect" payment.
49 | *
50 | * The customer will be redirected to the MultiSafepay website
51 | * where they need to enter their payment details.
52 | *
53 | *
54 | * $request = $gateway->purchase();
55 | *
56 | * $request->setAmount('20.00');
57 | * $request->setTransactionId('TEST-TRANSACTION');
58 | * $request->setDescription('Test transaction');
59 | *
60 | * $request->setCurrency('EUR');
61 | * $request->setType('redirect');
62 | *
63 | * $response = $request->send();
64 | * var_dump($response->getData());
65 | *
66 | *
67 | * ### Initialize a "direct" payment.
68 | *
69 | * The merchant website need to collect the payment details, so
70 | * the user can stay at the merchant website.
71 | *
72 | *
73 | * $request = $gateway->purchase();
74 | *
75 | * $request->setAmount('20.00');
76 | * $request->setTransactionId('TEST-TRANSACTION');
77 | * $request->setDescription('Test transaction');
78 | *
79 | * $request->setCurrency('EUR');
80 | * $request->setType('direct');
81 | * $request->setCard($card);
82 | *
83 | * $request->setGateway('IDEAL');
84 | * $request->setIssuer('ISSUER-ID'); // This ID can be found, with the RestFetchIssuersRequest.
85 | *
86 | * $response = $request->send();
87 | * var_dump($response->getData());
88 | *
89 | */
90 | class RestPurchaseResponse extends RestAbstractResponse implements RedirectResponseInterface
91 | {
92 | /**
93 | * Is the response successful?
94 | *
95 | * @return bool
96 | */
97 | public function isSuccessful()
98 | {
99 | if ($this->isRedirect()) {
100 | return false;
101 | }
102 |
103 | return parent::isSuccessful();
104 | }
105 |
106 | /**
107 | * {@inheritdoc}
108 | */
109 | public function isRedirect()
110 | {
111 | return isset($this->data['data']['payment_url']);
112 | }
113 |
114 | /**
115 | * {@inheritdoc}
116 | */
117 | public function getRedirectUrl()
118 | {
119 | if (!$this->isRedirect()) {
120 | return;
121 | }
122 |
123 | return $this->data['data']['payment_url'];
124 | }
125 |
126 | /**
127 | * {@inheritdoc}
128 | */
129 | public function getRedirectMethod()
130 | {
131 | return 'GET';
132 | }
133 |
134 | /**
135 | * {@inheritdoc}
136 | */
137 | public function getRedirectData()
138 | {
139 | return;
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/Message/RestRefundRequest.php:
--------------------------------------------------------------------------------
1 |
25 | * $request = $this->gateway->refund();
26 | *
27 | * $request->setTransactionId('test-transaction');
28 | * $request->setAmount('10.00');
29 | * $request->setCurrency('eur');
30 | * $request->setDescription('Test Refund');
31 | *
32 | * $response = $request->send();
33 | * var_dump($response->isSuccessful());
34 | *
35 | */
36 | class RestRefundRequest extends RestAbstractRequest
37 | {
38 | /**
39 | * Get the required data for the API request.
40 | *
41 | * @return array
42 | * @throws \Omnipay\Common\Exception\InvalidRequestException
43 | */
44 | public function getData()
45 | {
46 | parent::getData();
47 |
48 | $this->validate('amount', 'currency', 'description', 'transactionId');
49 |
50 | return array(
51 | 'amount' => $this->getAmountInteger(),
52 | 'currency' => $this->getCurrency(),
53 | 'description' => $this->getDescription(),
54 | 'id' => $this->getTransactionId(),
55 | 'type' => 'refund',
56 | );
57 | }
58 |
59 | /**
60 | * Send the request with specified data
61 | *
62 | * @param mixed $data
63 | * @return RestRefundResponse
64 | */
65 | public function sendData($data)
66 | {
67 | $httpResponse = $this->sendRequest(
68 | 'POST',
69 | '/orders/' . $data['id'] . '/refunds',
70 | json_encode($data)
71 | );
72 |
73 | $this->response = new RestRefundResponse(
74 | $this,
75 | json_decode($httpResponse->getBody()->getContents(), true)
76 | );
77 |
78 | return $this->response;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/Message/RestRefundResponse.php:
--------------------------------------------------------------------------------
1 |
24 | * $request = $this->gateway->refund();
25 | *
26 | * $request->setTransactionId('test-transaction');
27 | * $request->setAmount('10.00');
28 | * $request->setCurrency('eur');
29 | * $request->setDescription('Test Refund');
30 | *
31 | * $response = $request->send();
32 | * var_dump($response->isSuccessful());
33 | *
34 | */
35 | class RestRefundResponse extends RestAbstractResponse
36 | {
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/RestGateway.php:
--------------------------------------------------------------------------------
1 |
58 | * // Create the gateway
59 | * $gateway = Omnipay::create('MultiSafepay_Rest');
60 | *
61 | * // Initialise the gateway
62 | * $gateway->initialize(array(
63 | * 'apiKey' => 'API-KEY',
64 | * 'locale' => 'en',
65 | * 'testMode' => true, // Or false, when you want to use the production environment
66 | * ));
67 | *
68 | *
69 | * ### Retrieve Payment Methods
70 | *
71 | *
72 | * $request = $gateway->fetchPaymentMethods();
73 | * $response = $request->send();
74 | * $paymentMethods = $response->getPaymentMethods();
75 | *
76 | *
77 | * @link https://github.com/MultiSafepay/PHP
78 | * @link https://www.multisafepay.com/docs/getting-started/
79 | * @link https://www.multisafepay.com/documentation/doc/API-Reference/
80 | * @link https://www.multisafepay.com/documentation/doc/Step-by-Step/
81 | * @link https://www.multisafepay.com/signup/
82 | */
83 | class RestGateway extends AbstractGateway
84 | {
85 | /**
86 | * @{inheritdoc}
87 | */
88 | public function getName()
89 | {
90 | return 'MultiSafepay REST';
91 | }
92 |
93 | /**
94 | * Get the gateway parameters
95 | *
96 | * @return array
97 | */
98 | public function getDefaultParameters()
99 | {
100 | return array(
101 | 'apiKey' => '',
102 | 'locale' => 'en',
103 | 'testMode' => false,
104 | );
105 | }
106 |
107 | /**
108 | * Get the locale.
109 | *
110 | * Optional ISO 639-1 language code which is used to specify a
111 | * a language used to display gateway information and other
112 | * messages in the responses.
113 | *
114 | * The default language is English.
115 | *
116 | * @return string
117 | */
118 | public function getLocale()
119 | {
120 | return $this->getParameter('locale');
121 | }
122 |
123 | /**
124 | * Set the locale.
125 | *
126 | * Optional ISO 639-1 language code which is used to specify a
127 | * a language used to display gateway information and other
128 | * messages in the responses.
129 | *
130 | * The default language is English.
131 | *
132 | * @param $value
133 | * @return \Omnipay\Common\Message\AbstractRequest
134 | */
135 | public function setLocale($value)
136 | {
137 | return $this->setParameter('locale', $value);
138 | }
139 |
140 | /**
141 | * Get the gateway API Key
142 | *
143 | * Authentication is by means of a single secret API key set as
144 | * the apiKey parameter when creating the gateway object.
145 | *
146 | * @return string
147 | */
148 | public function getApiKey()
149 | {
150 | return $this->getParameter('apiKey');
151 | }
152 |
153 | /**
154 | * Set the gateway API Key
155 | *
156 | * Authentication is by means of a single secret API key set as
157 | * the apiKey parameter when creating the gateway object.
158 | *
159 | * @param string $value
160 | * @return RestGateway provides a fluent interface.
161 | */
162 | public function setApiKey($value)
163 | {
164 | return $this->setParameter('apiKey', $value);
165 | }
166 |
167 | /**
168 | * Retrieve payment methods active on the given MultiSafepay
169 | * account.
170 | *
171 | * @param array $parameters
172 | *
173 | * @return \Omnipay\MultiSafepay\Message\RestFetchPaymentMethodsRequest
174 | */
175 | public function fetchPaymentMethods(array $parameters = array())
176 | {
177 | return $this->createRequest(
178 | 'Omnipay\MultiSafepay\Message\RestFetchPaymentMethodsRequest',
179 | $parameters
180 | );
181 | }
182 |
183 | /**
184 | * Retrieve issuers for gateway.
185 | *
186 | * @param array $parameters
187 | *
188 | * @return \Omnipay\MultiSafepay\Message\RestFetchIssuersRequest
189 | */
190 | public function fetchIssuers(array $parameters = array())
191 | {
192 | return $this->createRequest(
193 | 'Omnipay\MultiSafepay\Message\RestFetchIssuersRequest',
194 | $parameters
195 | );
196 | }
197 |
198 | /**
199 | * Retrieve transaction by the given identifier.
200 | *
201 | * @param array $parameters
202 | * @return \Omnipay\MultiSafepay\Message\RestFetchTransactionRequest
203 | */
204 | public function fetchTransaction(array $parameters = array())
205 | {
206 | return $this->createRequest(
207 | 'Omnipay\MultiSafepay\Message\RestFetchTransactionRequest',
208 | $parameters
209 | );
210 | }
211 |
212 | /**
213 | * Create a refund.
214 | *
215 | * @param array $parameters
216 | * @return \Omnipay\MultiSafepay\Message\RestRefundRequest
217 | */
218 | public function refund(array $parameters = array())
219 | {
220 | return $this->createRequest(
221 | 'Omnipay\MultiSafepay\Message\RestRefundRequest',
222 | $parameters
223 | );
224 | }
225 |
226 | /**
227 | * Create a purchase request.
228 | *
229 | * MultisafePay support different types of transactions,
230 | * such as iDEAL, Paypal and CreditCard payments.
231 | *
232 | * @param array $parameters
233 | *
234 | * @return \Omnipay\MultiSafepay\Message\RestPurchaseRequest
235 | */
236 | public function purchase(array $parameters = array())
237 | {
238 | return $this->createRequest(
239 | 'Omnipay\MultiSafepay\Message\RestPurchaseRequest',
240 | $parameters
241 | );
242 | }
243 |
244 | /**
245 | * Complete a payment request.
246 | *
247 | * @param array $parameters
248 | *
249 | * @return \Omnipay\MultiSafepay\Message\RestCompletePurchaseRequest
250 | */
251 | public function completePurchase(array $parameters = array())
252 | {
253 | return $this->createRequest(
254 | 'Omnipay\MultiSafepay\Message\RestCompletePurchaseRequest',
255 | $parameters
256 | );
257 | }
258 | }
259 |
--------------------------------------------------------------------------------
/src/XmlGateway.php:
--------------------------------------------------------------------------------
1 |
19 | * // Create the gateway
20 | * $gateway = Omnipay::create('MultiSafepay_Xml');
21 | *
22 | * // Initialise the gateway
23 | * $gateway->initialize(array(
24 | * 'apiKey' => 'API-KEY',
25 | * 'locale' => 'en',
26 | * 'testMode' => true, // Or false, when you want to use the production environment
27 | * ));
28 | *
29 | *
30 | * @link https://www.multisafepay.com/downloads/handleidingen/Handleiding_connect(ENG).pdf
31 | */
32 | class XmlGateway extends AbstractGateway
33 | {
34 | /**
35 | * {@inheritdoc}
36 | */
37 | public function getName()
38 | {
39 | return 'MultiSafepay XML';
40 | }
41 |
42 | /**
43 | * {@inheritdoc}
44 | */
45 | public function getDefaultParameters()
46 | {
47 | return array(
48 | 'accountId' => '',
49 | 'siteId' => '',
50 | 'siteCode' => '',
51 | 'testMode' => false,
52 | );
53 | }
54 |
55 | /**
56 | * Get the account identifier.
57 | *
58 | * @return mixed
59 | */
60 | public function getAccountId()
61 | {
62 | return $this->getParameter('accountId');
63 | }
64 |
65 | /**
66 | * Set the account identifier.
67 | *
68 | * @param $value
69 | * @return $this
70 | */
71 | public function setAccountId($value)
72 | {
73 | return $this->setParameter('accountId', $value);
74 | }
75 |
76 | /**
77 | * Get the site identifier.
78 | *
79 | * @return mixed
80 | */
81 | public function getSiteId()
82 | {
83 | return $this->getParameter('siteId');
84 | }
85 |
86 | /**
87 | * Set the site identifier.
88 | *
89 | * @param $value
90 | * @return $this
91 | */
92 | public function setSiteId($value)
93 | {
94 | return $this->setParameter('siteId', $value);
95 | }
96 |
97 | /**
98 | * Get the site code.
99 | *
100 | * @return mixed
101 | */
102 | public function getSiteCode()
103 | {
104 | return $this->getParameter('siteCode');
105 | }
106 |
107 | /**
108 | * Set the site code.
109 | *
110 | * @param $value
111 | * @return $this
112 | */
113 | public function setSiteCode($value)
114 | {
115 | return $this->setParameter('siteCode', $value);
116 | }
117 |
118 | /**
119 | * Retrieve payment methods active on the given MultiSafepay
120 | * account.
121 | *
122 | * @param array $parameters
123 | *
124 | * @return \Omnipay\MultiSafepay\Message\FetchPaymentMethodsRequest
125 | */
126 | public function fetchPaymentMethods(array $parameters = array())
127 | {
128 | return $this->createRequest(
129 | '\Omnipay\MultiSafepay\Message\FetchPaymentMethodsRequest',
130 | $parameters
131 | );
132 | }
133 |
134 | /**
135 | * Retrieve iDEAL issuers.
136 | *
137 | * @param array $parameters
138 | *
139 | * @return \Omnipay\MultiSafepay\Message\FetchIssuersRequest
140 | */
141 | public function fetchIssuers(array $parameters = array())
142 | {
143 | return $this->createRequest(
144 | '\Omnipay\MultiSafepay\Message\FetchIssuersRequest',
145 | $parameters
146 | );
147 | }
148 |
149 | /**
150 | * Create Purchase request.
151 | *
152 | * @param array $parameters
153 | *
154 | * @return \Omnipay\MultiSafepay\Message\PurchaseRequest
155 | */
156 | public function purchase(array $parameters = array())
157 | {
158 | return $this->createRequest(
159 | '\Omnipay\MultiSafepay\Message\PurchaseRequest',
160 | $parameters
161 | );
162 | }
163 |
164 | /**
165 | * Complete purchase request.
166 | *
167 | * @param array $parameters
168 | *
169 | * @return \Omnipay\MultiSafepay\Message\CompletePurchaseRequest
170 | */
171 | public function completePurchase(array $parameters = array())
172 | {
173 | return $this->createRequest(
174 | '\Omnipay\MultiSafepay\Message\CompletePurchaseRequest',
175 | $parameters
176 | );
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/tests/Message/RestFetchIssuersRequestTest.php:
--------------------------------------------------------------------------------
1 | request = new RestFetchIssuersRequest(
15 | $this->getHttpClient(),
16 | $this->getHttpRequest()
17 | );
18 |
19 | $this->request->initialize(
20 | array(
21 | 'api_key' => '123456789',
22 | 'paymentMethod' => 'IDEAL'
23 | )
24 | );
25 | }
26 |
27 | public function testSendSuccess()
28 | {
29 | $this->setMockHttpResponse('RestFetchIssuersSuccess.txt');
30 |
31 | $response = $this->request->send();
32 |
33 | $issuers = $response->getIssuers();
34 |
35 | $this->assertContainsOnlyInstancesOf('Omnipay\Common\Issuer', $issuers);
36 | $this->assertFalse($response->isRedirect());
37 | $this->assertInstanceOf('Omnipay\MultiSafepay\Message\RestFetchIssuersResponse', $response);
38 | $this->assertInternalType('array', $issuers);
39 |
40 | $this->assertNull($response->getTransactionReference());
41 | $this->assertTrue($response->isSuccessful());
42 | }
43 |
44 | public function testIssuerNotFound()
45 | {
46 | $this->setMockHttpResponse('RestFetchIssuersFailure.txt');
47 |
48 | $response = $this->request->send();
49 |
50 | $this->assertEquals('Not found', $response->getMessage());
51 | $this->assertEquals(404, $response->getCode());
52 | $this->assertFalse($response->isRedirect());
53 |
54 | $this->assertFalse($response->isSuccessful());
55 | $this->assertInstanceOf('Omnipay\MultiSafepay\Message\RestFetchIssuersResponse', $response);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/tests/Message/RestFetchPaymentMethodsRequestTest.php:
--------------------------------------------------------------------------------
1 | request = new RestFetchPaymentMethodsRequest(
15 | $this->getHttpClient(),
16 | $this->getHttpRequest()
17 | );
18 |
19 | $this->request->initialize(
20 | array(
21 | 'api_key' => '123456789',
22 | 'country' => 'NL'
23 | )
24 | );
25 | }
26 |
27 | public function testSendSuccess()
28 | {
29 | $this->setMockHttpResponse('RestFetchPaymentMethodsSuccess.txt');
30 |
31 | $response = $this->request->send();
32 |
33 | $paymentMethods = $response->getPaymentMethods();
34 |
35 | $this->assertTrue($response->isSuccessful());
36 | $this->assertFalse($response->isRedirect());
37 | $this->assertNull($response->getTransactionReference());
38 |
39 | $this->assertInternalType('array', $paymentMethods);
40 | $this->assertContainsOnlyInstancesOf('Omnipay\Common\PaymentMethod', $paymentMethods);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/tests/Message/RestPurchaseRequestTest.php:
--------------------------------------------------------------------------------
1 | request = new RestPurchaseRequest(
15 | $this->getHttpClient(),
16 | $this->getHttpRequest()
17 | );
18 |
19 | $this->request->initialize(
20 | array(
21 | 'apiKey' => '123456789',
22 | 'amount' => 10.00,
23 | 'currency' => 'eur',
24 | 'description' => 'Test transaction',
25 | 'cancel_url' => 'http://localhost/cancel',
26 | 'notify_url' => 'http://localhost/notify',
27 | 'return_url' => 'http://localhost/return',
28 | 'close_window' => false,
29 | 'days_active' => 3,
30 | 'send_mail' => true,
31 | 'gateway' => 'IDEAL',
32 | 'google_analytics_code' => '123456789',
33 | 'manual' => false,
34 | 'transactionId' => 'TEST-TRANS-1',
35 | 'type' => 'redirect',
36 | 'var1' => 'extra data 1',
37 | 'var2' => 'extra data 2',
38 | 'var3' => 'extra data 3',
39 | )
40 | );
41 | }
42 |
43 | public function testSendSuccess()
44 | {
45 | $this->setMockHttpResponse('RestPurchaseSuccess.txt');
46 |
47 | $response = $this->request->send();
48 |
49 | $this->assertFalse($response->isSuccessful());
50 | $this->assertTrue($response->isRedirect());
51 |
52 | $this->assertEquals(
53 | 'https://testpay.multisafepay.com/pay/?order_id=TEST-TRANS-1',
54 | $response->getRedirectUrl()
55 | );
56 |
57 | $this->assertEquals('TEST-TRANS-1', $response->getTransactionId());
58 | }
59 |
60 | public function testInvalidAmount()
61 | {
62 | $this->setMockHttpResponse('RestPurchaseInvalidAmount.txt');
63 |
64 | $response = $this->request->send();
65 |
66 | $this->assertFalse($response->isSuccessful());
67 | $this->assertEquals('Invalid amount', $response->getMessage());
68 | $this->assertEquals(1001, $response->getCode());
69 | }
70 |
71 | public function testDataIntegrity()
72 | {
73 | $this->assertEquals('123456789', $this->request->getGoogleAnalyticsCode());
74 | $this->assertEquals('EUR', $this->request->getCurrency());
75 | $this->assertEquals('extra data 1', $this->request->getVar1());
76 | $this->assertEquals('extra data 2', $this->request->getVar2());
77 | $this->assertEquals('extra data 3', $this->request->getVar3());
78 | $this->assertEquals('http://localhost/cancel', $this->request->getCancelUrl());
79 | $this->assertEquals('http://localhost/notify', $this->request->getNotifyUrl());
80 | $this->assertEquals('http://localhost/return', $this->request->getReturnUrl());
81 | $this->assertEquals('IDEAL', $this->request->getGateway());
82 | $this->assertEquals('redirect', $this->request->getType());
83 | $this->assertEquals('Test transaction', $this->request->getDescription());
84 | $this->assertEquals('TEST-TRANS-1', $this->request->getTransactionId());
85 | $this->assertEquals(10.00, $this->request->getAmount());
86 | $this->assertEquals(3, $this->request->getDaysActive());
87 | $this->assertFalse($this->request->getCloseWindow());
88 | $this->assertFalse($this->request->getManual());
89 | $this->assertTrue($this->request->getSendMail());
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/tests/Message/XmlAbstractRequestTest.php:
--------------------------------------------------------------------------------
1 | request = m::mock('\Omnipay\MultiSafepay\Message\AbstractRequest')->makePartial();
19 | }
20 |
21 | /**
22 | * @covers \Omnipay\MultiSafepay\Message\AbstractRequest::getHeaders()
23 | */
24 | public function testUserAgentHeaderMustNotBeSet()
25 | {
26 | $method = new ReflectionMethod('\Omnipay\MultiSafepay\Message\AbstractRequest', 'getHeaders');
27 | $method->setAccessible(true);
28 |
29 | $headers = $method->invoke($this->request);
30 | $this->assertArrayHasKey(
31 | 'User-Agent',
32 | $headers,
33 | 'Omitting User-Agent header not allowed because then Guzzle will set it and cause 403 Forbidden on the gateway'
34 | );
35 | $this->assertEquals('Omnipay', $headers['User-Agent'], 'User-Agent header set');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tests/Message/XmlCompletePurchaseRequestTest.php:
--------------------------------------------------------------------------------
1 | request = new CompletePurchaseRequest(
17 | $this->getHttpClient(),
18 | $this->getHttpRequest()
19 | );
20 |
21 | $this->request->initialize(array(
22 | 'accountId' => '111111',
23 | 'siteId' => '222222',
24 | 'siteCode' => '333333',
25 | 'notifyUrl' => 'http://localhost/notify',
26 | 'cancelUrl' => 'http://localhost/cancel',
27 | 'returnUrl' => 'http://localhost/return',
28 | 'gateway' => 'IDEAL',
29 | 'issuer' => 'issuer',
30 | 'transactionId' => '123456',
31 | 'currency' => 'EUR',
32 | 'amount' => '100.00',
33 | 'description' => 'desc',
34 | 'extraData1' => 'extra 1',
35 | 'extraData2' => 'extra 2',
36 | 'extraData3' => 'extra 3',
37 | 'language' => 'a language',
38 | 'clientIp' => '127.0.0.1',
39 | 'googleAnalyticsCode' => 'analytics code',
40 | 'card' => array(
41 | 'email' => 'something@example.com',
42 | 'firstName' => 'first name',
43 | 'lastName' => 'last name',
44 | 'address1' => 'address 1',
45 | 'address2' => 'address 2',
46 | 'postcode' => '1000',
47 | 'city' => 'a city',
48 | 'country' => 'a country',
49 | 'phone' => 'phone number',
50 | )
51 | ));
52 | }
53 |
54 | public function testSendSuccess()
55 | {
56 | $this->setMockHttpResponse('XmlCompletePurchaseSuccess.txt');
57 |
58 | $response = $this->request->send();
59 |
60 | $this->assertTrue($response->isSuccessful());
61 | $this->assertEquals('123456', $response->getTransactionReference());
62 | }
63 |
64 | public function testSendFailure()
65 | {
66 | $this->setMockHttpResponse('XmlCompletePurchaseFailure.txt');
67 |
68 | $response = $this->request->send();
69 |
70 | $this->assertFalse($response->isSuccessful());
71 | $this->assertEquals('Back-end: missing data', $response->getMessage());
72 | $this->assertEquals(1016, $response->getCode());
73 | }
74 |
75 | /**
76 | * @dataProvider dataProvider
77 | */
78 | public function testGetData($xml)
79 | {
80 | $data = $this->request->getData();
81 | $this->assertInstanceOf('SimpleXMLElement', $data);
82 |
83 | // Just so the provider remains readable...
84 | $dom = dom_import_simplexml($data)->ownerDocument;
85 | $dom->formatOutput = true;
86 | $this->assertEquals($xml, $dom->saveXML());
87 | }
88 |
89 | public function dataProvider()
90 | {
91 | $xml = <<1016
1005
0031
0751
0721
0021
0091
0761
0771
0511
0161
0801
1005
1001