├── .gitignore ├── tests ├── Mock │ ├── SecureXMLAuthorizeRequestFailure.txt │ ├── SecureXMLAuthorizeRequestInsufficientFundsFailure.txt │ ├── SecureXMLAuthorizeRequestInvalidMerchantIDFailure.txt │ ├── SecureXMLAuthorizeRequestInvalidMerchantFailure.txt │ ├── SecureXMLEchoTestRequestSuccess.txt │ ├── SecureXMLPurchaseRequestSendFailure.txt │ ├── SecureXMLPurchaseRequestInsufficientFundsFailure.txt │ ├── SecureXMLAuthorizeRequestSuccess.txt │ └── SecureXMLPurchaseRequestSendSuccess.txt ├── Message │ ├── SecureXMLEchoTestRequestTest.php │ ├── DirectPostPurchaseRequestTest.php │ ├── DirectPostAuthorizeRequestTest.php │ ├── SecureXMLPurchaseRequestTest.php │ ├── DirectPostCompletePurchaseRequestTest.php │ └── SecureXMLAuthorizeRequestTest.php ├── SecureXMLGatewayTest.php └── DirectPostGatewayTest.php ├── src ├── Message │ ├── DirectPostPurchaseRequest.php │ ├── DirectPostAbstractRequest.php │ ├── SecureXMLPurchaseRequest.php │ ├── SecureXMLEchoTestRequest.php │ ├── SecureXMLAuthorizeRequest.php │ ├── SecureXMLRefundRequest.php │ ├── DirectPostCompletePurchaseResponse.php │ ├── AbstractRequest.php │ ├── DirectPostAuthorizeResponse.php │ ├── DirectPostCompletePurchaseRequest.php │ ├── SecureXMLCaptureRequest.php │ ├── DirectPostAuthorizeRequest.php │ ├── SecureXMLResponse.php │ └── SecureXMLAbstractRequest.php ├── DirectPostGateway.php └── SecureXMLGateway.php ├── grumphp.yml ├── CONTRIBUTING.md ├── .travis.yml ├── phpunit.xml.dist ├── LICENSE ├── composer.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.lock 3 | composer.phar 4 | phpunit.xml 5 | -------------------------------------------------------------------------------- /tests/Mock/SecureXMLAuthorizeRequestFailure.txt: -------------------------------------------------------------------------------- 1 | SecureXMLPurchaseRequestSendFailure.txt -------------------------------------------------------------------------------- /tests/Mock/SecureXMLAuthorizeRequestInsufficientFundsFailure.txt: -------------------------------------------------------------------------------- 1 | SecureXMLPurchaseRequestInsufficientFundsFailure.txt -------------------------------------------------------------------------------- /src/Message/DirectPostPurchaseRequest.php: -------------------------------------------------------------------------------- 1 | 504Invalid merchant ID 9 | -------------------------------------------------------------------------------- /src/Message/SecureXMLPurchaseRequest.php: -------------------------------------------------------------------------------- 1 | getBasePaymentXMLWithCard(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Message/SecureXMLEchoTestRequest.php: -------------------------------------------------------------------------------- 1 | getBaseXML(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.6 5 | - 7.0 6 | - 7.1 7 | - 7.2 8 | 9 | env: 10 | global: 11 | - setup=basic 12 | 13 | matrix: 14 | include: 15 | - php: 5.6 16 | env: setup=lowest 17 | 18 | sudo: false 19 | 20 | before_install: 21 | - travis_retry composer self-update 22 | 23 | install: 24 | - if [[ $setup = 'basic' ]]; then travis_retry composer install --no-interaction --prefer-dist; fi 25 | - if [[ $setup = 'lowest' ]]; then travis_retry composer update --prefer-dist --no-interaction --prefer-lowest --prefer-stable; fi 26 | 27 | script: vendor/bin/phpcs --standard=PSR2 src && vendor/bin/phpunit --coverage-text 28 | -------------------------------------------------------------------------------- /src/Message/SecureXMLAuthorizeRequest.php: -------------------------------------------------------------------------------- 1 | getBasePaymentXMLWithCard(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/Mock/SecureXMLAuthorizeRequestInvalidMerchantFailure.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Date: Fri, 17 Apr 2015 02:05:53 GMT 3 | Server: Apache 4 | Content-Type: text/xml;charset=ISO-8859-1 5 | Content-Length: 506 6 | Connection: close 7 | 8 | 5ef083567a7fe09111ecf709761f9d20151704120553321000+600xml-4.2PaymentABC0030504Invalid merchant ABC0030 9 | -------------------------------------------------------------------------------- /tests/Mock/SecureXMLEchoTestRequestSuccess.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 100 Continue 2 | Server: Microsoft-IIS/5.0 3 | Date: Mon, 19 Apr 2004 06:19:48 GMT 4 | HTTP/1.1 200 OK 5 | Server: Microsoft-IIS/5.0 6 | Date: Mon, 19 Apr 2004 06:20:01 GMT 7 | Content-Type: text/xml;charset=ISO-8859-1 8 | Content-Length: 929 9 | 10 | 11 | 12 | 13 | 8af793f9af34bea0cf40f5fb79f383 14 | 20042403095956732000+660 15 | xml-4.2 16 | 17 | Echo 18 | 19 | 000 20 | Normal 21 | 22 | 23 | -------------------------------------------------------------------------------- /tests/Mock/SecureXMLPurchaseRequestSendFailure.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 100 Continue 2 | Server: Microsoft-IIS/5.0 3 | Date: Mon, 19 Apr 2004 06:19:48 GMT 4 | HTTP/1.1 200 OK 5 | Server: Microsoft-IIS/5.0 6 | Date: Mon, 19 Apr 2004 06:20:01 GMT 7 | Content-Type: text/xml;charset=ISO-8859-1 8 | Content-Length: 929 9 | 10 | 11 | 8af793f9af34bea0cf40f5fc011e0c20041904161959849000+600xml-4.2PaymentABC0001510Unable To Connect To Server 12 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | ./tests/ 15 | 16 | 17 | 18 | 19 | ./src 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /tests/Mock/SecureXMLPurchaseRequestInsufficientFundsFailure.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 100 Continue 2 | Server: Microsoft-IIS/5.0 3 | Date: Mon, 19 Apr 2004 06:19:48 GMT 4 | HTTP/1.1 200 OK 5 | Server: Microsoft-IIS/5.0 6 | Date: Mon, 19 Apr 2004 06:20:01 GMT 7 | Content-Type: text/xml;charset=ISO-8859-1 8 | Content-Length: 929 9 | 10 | 11 | 8af793f9af34bea0cf40f5fc011e0c20041904161959849000+600xml-4.2PaymentABC000151Insufficient Funds 12 | -------------------------------------------------------------------------------- /src/Message/SecureXMLRefundRequest.php: -------------------------------------------------------------------------------- 1 | getBasePaymentXML(); 21 | $xml->Payment->TxnList->Txn->addChild('txnID', $this->getTransactionReference()); 22 | 23 | return $xml; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Message/DirectPostCompletePurchaseResponse.php: -------------------------------------------------------------------------------- 1 | data['summarycode']) && $this->data['summarycode'] == 1; 15 | } 16 | 17 | public function getMessage() 18 | { 19 | if (isset($this->data['restext'])) { 20 | return $this->data['restext']; 21 | } 22 | } 23 | 24 | public function getCode() 25 | { 26 | if (isset($this->data['rescode'])) { 27 | return $this->data['rescode']; 28 | } 29 | } 30 | 31 | public function getTransactionReference() 32 | { 33 | if (isset($this->data['txnid'])) { 34 | return $this->data['txnid']; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Message/AbstractRequest.php: -------------------------------------------------------------------------------- 1 | getParameter('merchantId'); 16 | } 17 | 18 | public function setMerchantId($value) 19 | { 20 | return $this->setParameter('merchantId', $value); 21 | } 22 | 23 | public function getTransactionPassword() 24 | { 25 | return $this->getParameter('transactionPassword'); 26 | } 27 | 28 | public function setTransactionPassword($value) 29 | { 30 | return $this->setParameter('transactionPassword', $value); 31 | } 32 | 33 | public function getEndpoint() 34 | { 35 | return $this->getTestMode() ? $this->testEndpoint : $this->liveEndpoint; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/Message/SecureXMLEchoTestRequestTest.php: -------------------------------------------------------------------------------- 1 | request = new SecureXMLEchoTestRequest($this->getHttpClient(), $this->getHttpRequest()); 12 | 13 | $this->request->initialize([ 14 | 'merchantId' => 'ABC0030', 15 | 'transactionPassword' => 'abc123', 16 | ]); 17 | } 18 | 19 | public function testSuccess() 20 | { 21 | $this->setMockHttpResponse('SecureXMLEchoTestRequestSuccess.txt'); 22 | $response = $this->request->send(); 23 | $data = $response->getData(); 24 | 25 | $this->assertInstanceOf('Omnipay\\SecurePay\\Message\\SecureXMLResponse', $response); 26 | 27 | $this->assertTrue($response->isSuccessful()); 28 | $this->assertFalse($response->isRedirect()); 29 | $this->assertSame('000', $response->getCode()); 30 | $this->assertSame('Normal', $response->getMessage()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2018 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 | -------------------------------------------------------------------------------- /src/Message/DirectPostAuthorizeResponse.php: -------------------------------------------------------------------------------- 1 | request = $request; 19 | $this->data = $data; 20 | $this->redirectUrl = $redirectUrl; 21 | } 22 | 23 | public function isSuccessful() 24 | { 25 | return false; 26 | } 27 | 28 | public function isRedirect() 29 | { 30 | return true; 31 | } 32 | 33 | public function getRedirectUrl() 34 | { 35 | return $this->redirectUrl; 36 | } 37 | 38 | public function getRedirectMethod() 39 | { 40 | return 'POST'; 41 | } 42 | 43 | public function getRedirectData() 44 | { 45 | return $this->getData(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/Mock/SecureXMLAuthorizeRequestSuccess.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 100 Continue 2 | Server: Microsoft-IIS/5.0 3 | Date: Mon, 19 Apr 2004 06:19:48 GMT 4 | HTTP/1.1 200 OK 5 | Server: Microsoft-IIS/5.0 6 | Date: Mon, 19 Apr 2004 06:20:01 GMT 7 | Content-Type: text/xml;charset=ISO-8859-1 8 | Content-Length: 929 9 | 10 | 11 | 8af793f9af34bea0cf40f5fc011e0c20041904161959849000+600xml-4.2PaymentABC0001000Normal1023200AUDtestYes00Approved20040419009729424242...24207/066Visa 12 | -------------------------------------------------------------------------------- /tests/Mock/SecureXMLPurchaseRequestSendSuccess.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 100 Continue 2 | Server: Microsoft-IIS/5.0 3 | Date: Mon, 19 Apr 2004 06:19:48 GMT 4 | HTTP/1.1 200 OK 5 | Server: Microsoft-IIS/5.0 6 | Date: Mon, 19 Apr 2004 06:20:01 GMT 7 | Content-Type: text/xml;charset=ISO-8859-1 8 | Content-Length: 929 9 | 10 | 11 | 8af793f9af34bea0cf40f5fc011e0c20041904161959849000+600xml-4.2PaymentABC0001000Normal023200AUDtestorder123Yes00Approved20040419009729424242...24207/066Visa 12 | -------------------------------------------------------------------------------- /src/Message/DirectPostCompletePurchaseRequest.php: -------------------------------------------------------------------------------- 1 | httpRequest->query->all(); 15 | 16 | if ($this->generateResponseFingerprint($data) !== $this->httpRequest->query->get('fingerprint')) { 17 | throw new InvalidRequestException('Invalid fingerprint'); 18 | } 19 | 20 | return $data; 21 | } 22 | 23 | public function generateResponseFingerprint($data) 24 | { 25 | $fields = implode('|', [ 26 | $data['merchant'], 27 | $this->getTransactionPassword(), 28 | $data['refid'], 29 | $this->getAmount(), 30 | $data['timestamp'], 31 | $data['summarycode'], 32 | ]); 33 | 34 | return sha1($fields); 35 | } 36 | 37 | public function sendData($data) 38 | { 39 | return $this->response = new DirectPostCompletePurchaseResponse($this, $data); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Message/SecureXMLCaptureRequest.php: -------------------------------------------------------------------------------- 1 | getBasePaymentXML(); 22 | 23 | $xml->Payment->TxnList->Txn->addChild('preauthID', $this->getPreauthId()); 24 | 25 | return $xml; 26 | } 27 | 28 | /** 29 | * Set the preauthId that was returned as part of the original authorize 30 | * request. 31 | */ 32 | public function setPreauthId($value) 33 | { 34 | return $this->setParameter('preauthId', $value); 35 | } 36 | 37 | /** 38 | * @return string The preauthId from the authorize request that this 39 | * capture matches. 40 | */ 41 | public function getPreauthId() 42 | { 43 | return $this->getParameter('preauthId'); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "omnipay/securepay", 3 | "type": "library", 4 | "description": "SecurePay driver for the Omnipay payment processing library", 5 | "keywords": [ 6 | "gateway", 7 | "merchant", 8 | "omnipay", 9 | "pay", 10 | "payment", 11 | "securepay" 12 | ], 13 | "homepage": "https://github.com/thephpleague/omnipay-securepay", 14 | "license": "MIT", 15 | "authors": [ 16 | { 17 | "name": "Adrian Macneil", 18 | "email": "adrian@adrianmacneil.com" 19 | }, 20 | { 21 | "name": "Omnipay Contributors", 22 | "homepage": "https://github.com/thephpleague/omnipay-securepay/contributors" 23 | } 24 | ], 25 | "autoload": { 26 | "psr-4": { "Omnipay\\SecurePay\\" : "src/" } 27 | }, 28 | "require": { 29 | "omnipay/common": "^3" 30 | }, 31 | "require-dev": { 32 | "omnipay/tests": "^3", 33 | "squizlabs/php_codesniffer": "^3", 34 | "phpro/grumphp": "^0.14.0" 35 | }, 36 | "extra": { 37 | "branch-alias": { 38 | "dev-master": "3.0.x-dev" 39 | } 40 | }, 41 | "scripts": { 42 | "test": "vendor/bin/phpunit", 43 | "check-style": "phpcs -p --standard=PSR2 src/", 44 | "fix-style": "phpcbf -p --standard=PSR2 src/" 45 | }, 46 | "prefer-stable": true 47 | } 48 | -------------------------------------------------------------------------------- /tests/SecureXMLGatewayTest.php: -------------------------------------------------------------------------------- 1 | gateway = new SecureXMLGateway($this->getHttpClient(), $this->getHttpRequest()); 14 | $this->gateway->setMerchantId('ABC0001'); 15 | } 16 | 17 | public function testAuthorize() 18 | { 19 | $request = $this->gateway->authorize(['amount' => '10.00']); 20 | 21 | $this->assertInstanceOf('\Omnipay\SecurePay\Message\SecureXMLAuthorizeRequest', $request); 22 | $this->assertSame('10.00', $request->getAmount()); 23 | } 24 | 25 | public function testPurchase() 26 | { 27 | $request = $this->gateway->purchase(['amount' => '10.00']); 28 | 29 | $this->assertInstanceOf('\Omnipay\SecurePay\Message\SecureXMLPurchaseRequest', $request); 30 | $this->assertSame('10.00', $request->getAmount()); 31 | } 32 | 33 | public function testRefund() 34 | { 35 | $request = $this->gateway->refund(['amount' => '10.00', 'transactionId' => 'order12345']); 36 | 37 | $this->assertInstanceOf('\Omnipay\SecurePay\Message\SecureXMLRefundRequest', $request); 38 | $this->assertSame('10.00', $request->getAmount()); 39 | $this->assertSame('order12345', $request->getTransactionId()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/DirectPostGatewayTest.php: -------------------------------------------------------------------------------- 1 | gateway = new DirectPostGateway($this->getHttpClient(), $this->getHttpRequest()); 14 | $this->gateway->setMerchantId('abc123'); 15 | } 16 | 17 | public function testAuthorize() 18 | { 19 | $request = $this->gateway->authorize(['amount' => '10.00']); 20 | 21 | $this->assertInstanceOf('\Omnipay\SecurePay\Message\DirectPostAuthorizeRequest', $request); 22 | $this->assertSame('10.00', $request->getAmount()); 23 | } 24 | 25 | public function testCompleteAuthorize() 26 | { 27 | $request = $this->gateway->completeAuthorize(['amount' => '10.00']); 28 | 29 | $this->assertInstanceOf('\Omnipay\SecurePay\Message\DirectPostCompletePurchaseRequest', $request); 30 | $this->assertSame('10.00', $request->getAmount()); 31 | } 32 | 33 | public function testPurchase() 34 | { 35 | $request = $this->gateway->purchase(['amount' => '10.00']); 36 | 37 | $this->assertInstanceOf('\Omnipay\SecurePay\Message\DirectPostPurchaseRequest', $request); 38 | $this->assertSame('10.00', $request->getAmount()); 39 | } 40 | 41 | public function testCompletePurchase() 42 | { 43 | $request = $this->gateway->completePurchase(['amount' => '10.00']); 44 | 45 | $this->assertInstanceOf('\Omnipay\SecurePay\Message\DirectPostCompletePurchaseRequest', $request); 46 | $this->assertSame('10.00', $request->getAmount()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Omnipay: SecurePay 2 | 3 | **SecurePay driver for the Omnipay PHP payment processing library** 4 | 5 | [![Build Status](https://travis-ci.org/thephpleague/omnipay-securepay.png?branch=master)](https://travis-ci.org/thephpleague/omnipay-securepay) 6 | [![Latest Stable Version](https://poser.pugx.org/omnipay/securepay/version.png)](https://packagist.org/packages/omnipay/securepay) 7 | [![Total Downloads](https://poser.pugx.org/omnipay/securepay/d/total.png)](https://packagist.org/packages/omnipay/securepay) 8 | 9 | [Omnipay](https://github.com/thephpleague/omnipay) is a framework agnostic, multi-gateway payment 10 | processing library for PHP. This package implements SecurePay support for Omnipay. 11 | 12 | ## Installation 13 | 14 | Omnipay is installed via [Composer](http://getcomposer.org/). To install, simply require `league/omnipay` and `omnipay/securepay` with Composer: 15 | 16 | ``` 17 | composer require league/omnipay omnipay/securepay 18 | ``` 19 | 20 | ## Basic Usage 21 | 22 | The following gateways are provided by this package: 23 | 24 | * SecurePay 25 | 26 | For general usage instructions, please see the main [Omnipay](https://github.com/thephpleague/omnipay) 27 | repository. 28 | 29 | ## Support 30 | 31 | If you are having general issues with Omnipay, we suggest posting on 32 | [Stack Overflow](http://stackoverflow.com/). Be sure to add the 33 | [omnipay tag](http://stackoverflow.com/questions/tagged/omnipay) so it can be easily found. 34 | 35 | If you want to keep up to date with release anouncements, discuss ideas for the project, 36 | or ask more detailed questions, there is also a [mailing list](https://groups.google.com/forum/#!forum/omnipay) which 37 | you can subscribe to. 38 | 39 | If you believe you have found a bug, please report it using the [GitHub issue tracker](https://github.com/thephpleague/omnipay-securepay/issues), 40 | or better yet, fork the library and submit a pull request. 41 | -------------------------------------------------------------------------------- /tests/Message/DirectPostPurchaseRequestTest.php: -------------------------------------------------------------------------------- 1 | request = new DirectPostPurchaseRequest($this->getHttpClient(), $this->getHttpRequest()); 12 | 13 | $this->request->initialize([ 14 | 'merchantId' => 'foo', 15 | 'transactionPassword' => 'bar', 16 | 'amount' => '12.00', 17 | 'returnUrl' => 'https://www.example.com/return', 18 | 'card' => [ 19 | 'number' => '4444333322221111', 20 | 'expiryMonth' => '12', 21 | 'expiryYear' => date('Y'), 22 | 'cvv' => '123', 23 | ], 24 | ]); 25 | } 26 | 27 | public function testFingerprint() 28 | { 29 | // force timestamp for testing 30 | $data = $this->request->getData(); 31 | $data['EPS_TIMESTAMP'] = '20130416123332'; 32 | 33 | $this->assertSame('652856e75b04c5916a41082e04c9390961497f65', $this->request->generateFingerprint($data)); 34 | } 35 | 36 | public function testSend() 37 | { 38 | $response = $this->request->send(); 39 | 40 | $this->assertInstanceOf('Omnipay\SecurePay\Message\DirectPostAuthorizeResponse', $response); 41 | $this->assertFalse($response->isSuccessful()); 42 | $this->assertTrue($response->isRedirect()); 43 | $this->assertNull($response->getTransactionReference()); 44 | $this->assertNull($response->getMessage()); 45 | $this->assertNull($response->getCode()); 46 | 47 | $this->assertSame('https://api.securepay.com.au/directpost/authorise', $response->getRedirectUrl()); 48 | $this->assertSame('POST', $response->getRedirectMethod()); 49 | 50 | $data = $response->getData(); 51 | $this->assertArrayHasKey('EPS_FINGERPRINT', $data); 52 | $this->assertSame('0', $data['EPS_TXNTYPE']); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tests/Message/DirectPostAuthorizeRequestTest.php: -------------------------------------------------------------------------------- 1 | request = new DirectPostAuthorizeRequest($this->getHttpClient(), $this->getHttpRequest()); 12 | 13 | $this->request->initialize([ 14 | 'merchantId' => 'foo', 15 | 'transactionPassword' => 'bar', 16 | 'amount' => '12.00', 17 | 'returnUrl' => 'https://www.example.com/return', 18 | 'card' => [ 19 | 'number' => '4444333322221111', 20 | 'expiryMonth' => '12', 21 | 'expiryYear' => date('Y'), 22 | 'cvv' => '123', 23 | ], 24 | ]); 25 | } 26 | 27 | public function testFingerprint() 28 | { 29 | // force timestamp for testing 30 | $data = $this->request->getData(); 31 | $data['EPS_TIMESTAMP'] = '20130416123332'; 32 | 33 | $this->assertSame('46b6a59173c9fea66f71b8679558837895f0bce8', $this->request->generateFingerprint($data)); 34 | } 35 | 36 | public function testSend() 37 | { 38 | $response = $this->request->send(); 39 | 40 | $this->assertInstanceOf('Omnipay\SecurePay\Message\DirectPostAuthorizeResponse', $response); 41 | $this->assertFalse($response->isSuccessful()); 42 | $this->assertTrue($response->isRedirect()); 43 | $this->assertNull($response->getTransactionReference()); 44 | $this->assertNull($response->getMessage()); 45 | $this->assertNull($response->getCode()); 46 | 47 | $this->assertSame('https://api.securepay.com.au/directpost/authorise', $response->getRedirectUrl()); 48 | $this->assertSame('POST', $response->getRedirectMethod()); 49 | 50 | $data = $response->getData(); 51 | $this->assertArrayHasKey('EPS_FINGERPRINT', $data); 52 | $this->assertSame('1', $data['EPS_TXNTYPE']); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/DirectPostGateway.php: -------------------------------------------------------------------------------- 1 | '', 25 | 'transactionPassword' => '', 26 | 'testMode' => false, 27 | ]; 28 | } 29 | 30 | public function getMerchantId() 31 | { 32 | return $this->getParameter('merchantId'); 33 | } 34 | 35 | public function setMerchantId($value) 36 | { 37 | return $this->setParameter('merchantId', $value); 38 | } 39 | 40 | public function getTransactionPassword() 41 | { 42 | return $this->getParameter('transactionPassword'); 43 | } 44 | 45 | public function setTransactionPassword($value) 46 | { 47 | return $this->setParameter('transactionPassword', $value); 48 | } 49 | 50 | public function authorize(array $parameters = array()) 51 | { 52 | return $this->createRequest('\Omnipay\SecurePay\Message\DirectPostAuthorizeRequest', $parameters); 53 | } 54 | 55 | public function completeAuthorize(array $parameters = array()) 56 | { 57 | return $this->createRequest('\Omnipay\SecurePay\Message\DirectPostCompletePurchaseRequest', $parameters); 58 | } 59 | 60 | public function purchase(array $parameters = array()) 61 | { 62 | return $this->createRequest('\Omnipay\SecurePay\Message\DirectPostPurchaseRequest', $parameters); 63 | } 64 | 65 | public function completePurchase(array $parameters = array()) 66 | { 67 | return $this->createRequest('\Omnipay\SecurePay\Message\DirectPostCompletePurchaseRequest', $parameters); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Message/DirectPostAuthorizeRequest.php: -------------------------------------------------------------------------------- 1 | validate('amount', 'returnUrl', 'card'); 15 | 16 | $data = []; 17 | $data['EPS_MERCHANT'] = $this->getMerchantId(); 18 | $data['EPS_TXNTYPE'] = $this->txnType; 19 | $data['EPS_IP'] = $this->getClientIp(); 20 | $data['EPS_AMOUNT'] = $this->getAmount(); 21 | $data['EPS_REFERENCEID'] = $this->getTransactionId(); 22 | $data['EPS_TIMESTAMP'] = gmdate('YmdHis'); 23 | $data['EPS_FINGERPRINT'] = $this->generateFingerprint($data); 24 | $data['EPS_RESULTURL'] = $this->getReturnUrl(); 25 | $data['EPS_CALLBACKURL'] = $this->getNotifyUrl() ?: $this->getReturnUrl(); 26 | $data['EPS_REDIRECT'] = 'TRUE'; 27 | $data['EPS_CURRENCY'] = $this->getCurrency(); 28 | 29 | $data = array_replace($data, $this->getCardData()); 30 | 31 | return $data; 32 | } 33 | 34 | public function generateFingerprint(array $data) 35 | { 36 | $hash = implode('|', [ 37 | $data['EPS_MERCHANT'], 38 | $this->getTransactionPassword(), 39 | $data['EPS_TXNTYPE'], 40 | $data['EPS_REFERENCEID'], 41 | $data['EPS_AMOUNT'], 42 | $data['EPS_TIMESTAMP'], 43 | ]); 44 | 45 | return sha1($hash); 46 | } 47 | 48 | public function sendData($data) 49 | { 50 | return $this->response = new DirectPostAuthorizeResponse($this, $data, $this->getEndpoint()); 51 | } 52 | 53 | protected function getCardData() 54 | { 55 | $this->getCard()->validate(); 56 | 57 | $data = []; 58 | $data['EPS_CARDNUMBER'] = $this->getCard()->getNumber(); 59 | $data['EPS_EXPIRYMONTH'] = $this->getCard()->getExpiryMonth(); 60 | $data['EPS_EXPIRYYEAR'] = $this->getCard()->getExpiryYear(); 61 | $data['EPS_CCV'] = $this->getCard()->getCvv(); 62 | 63 | return $data; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /tests/Message/SecureXMLPurchaseRequestTest.php: -------------------------------------------------------------------------------- 1 | request = new SecureXMLPurchaseRequest($this->getHttpClient(), $this->getHttpRequest()); 12 | 13 | $this->request->initialize([ 14 | 'merchantId' => 'ABC0030', 15 | 'transactionPassword' => 'abc123', 16 | 'amount' => '12.00', 17 | 'transactionId' => '1234', 18 | 'card' => [ 19 | 'number' => '4444333322221111', 20 | 'expiryMonth' => '12', 21 | 'expiryYear' => date('Y'), 22 | 'cvv' => '123', 23 | ], 24 | ]); 25 | } 26 | 27 | public function testSendSuccess() 28 | { 29 | $this->setMockHttpResponse('SecureXMLPurchaseRequestSendSuccess.txt'); 30 | $response = $this->request->send(); 31 | $data = $response->getData(); 32 | 33 | $this->assertInstanceOf('Omnipay\\SecurePay\\Message\\SecureXMLResponse', $response); 34 | 35 | $this->assertTrue($response->isSuccessful()); 36 | $this->assertFalse($response->isRedirect()); 37 | $this->assertSame('0', (string) $data->Payment->TxnList->Txn->txnType); 38 | $this->assertSame('009729', $response->getTransactionReference()); 39 | $this->assertSame('00', $response->getCode()); 40 | $this->assertSame('Approved', $response->getMessage()); 41 | } 42 | 43 | public function testSendFailure() 44 | { 45 | $this->setMockHttpResponse('SecureXMLPurchaseRequestSendFailure.txt'); 46 | $response = $this->request->send(); 47 | 48 | $this->assertInstanceOf('Omnipay\\SecurePay\\Message\\SecureXMLResponse', $response); 49 | 50 | $this->assertFalse($response->isSuccessful()); 51 | $this->assertFalse($response->isRedirect()); 52 | $this->assertNull($response->getTransactionReference()); 53 | $this->assertSame('510', $response->getCode()); 54 | $this->assertSame('Unable To Connect To Server', $response->getMessage()); 55 | } 56 | 57 | public function testInsufficientFundsFailure() 58 | { 59 | $this->setMockHttpResponse('SecureXMLPurchaseRequestInsufficientFundsFailure.txt'); 60 | $response = $this->request->send(); 61 | 62 | $this->assertInstanceOf('Omnipay\\SecurePay\\Message\\SecureXMLResponse', $response); 63 | 64 | $this->assertFalse($response->isSuccessful()); 65 | $this->assertFalse($response->isRedirect()); 66 | $this->assertNull($response->getTransactionReference()); 67 | $this->assertSame('51', $response->getCode()); 68 | $this->assertSame('Insufficient Funds', $response->getMessage()); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Message/SecureXMLResponse.php: -------------------------------------------------------------------------------- 1 | data->Status->statusCode !== '000' 21 | || ($this->hasTransaction() 22 | && (string) $this->data->Payment->TxnList->Txn->approved !== 'Yes')) { 23 | return false; 24 | } 25 | 26 | return true; 27 | } 28 | 29 | /** 30 | * Determine if we have had payment information returned. 31 | * 32 | * @note For certain errors a Payment element is returned but has an empty 33 | * TxnList so this will tell us if we actually have a transaction to check. 34 | * 35 | * @return bool True if we have a transaction. 36 | */ 37 | protected function hasTransaction() 38 | { 39 | return isset($this->data->Payment->TxnList->Txn); 40 | } 41 | 42 | /** 43 | * @link https://www.securepay.com.au/_uploads/files/SecurePay_Response_Codes.pdf 44 | * 45 | * @return string Gateway failure code or transaction code if available. 46 | */ 47 | public function getCode() 48 | { 49 | return $this->hasTransaction() 50 | ? (string) $this->data->Payment->TxnList->Txn->responseCode 51 | : (string) $this->data->Status->statusCode; 52 | } 53 | 54 | /** 55 | * @return string Gateway failure message or transaction message if 56 | * available. 57 | */ 58 | public function getMessage() 59 | { 60 | return $this->hasTransaction() 61 | ? (string) $this->data->Payment->TxnList->Txn->responseText 62 | : (string) $this->data->Status->statusDescription; 63 | } 64 | 65 | /** 66 | * @return string Unique SecurePay bank transaction reference. 67 | */ 68 | public function getTransactionReference() 69 | { 70 | return $this->hasTransaction() 71 | ? (string) $this->data->Payment->TxnList->Txn->txnID 72 | : null; 73 | } 74 | 75 | /** 76 | * @return string|null Settlement date when the funds will be settled into the 77 | * merchants account. 78 | */ 79 | public function getSettlementDate() 80 | { 81 | return $this->hasTransaction() 82 | ? (string) $this->data->Payment->TxnList->Txn->settlementDate 83 | : null; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/SecureXMLGateway.php: -------------------------------------------------------------------------------- 1 | 13 | * // Initialise the test gateway 14 | * $gateway = \Omnipay\Omnipay::create('SecurePay_SecureXML'); 15 | * $gateway->setMerchantId('ABC0001'); 16 | * $gateway->setTransactionPassword('abc123'); 17 | * $gateway->setTestMode(true); 18 | * 19 | * // Create a credit card object 20 | * $card = new \Omnipay\Common\CreditCard( 21 | * [ 22 | * 'number' => '4444333322221111', 23 | * 'expiryMonth' => '6', 24 | * 'expiryYear' => '2020', 25 | * 'cvv' => '123', 26 | * ] 27 | * ); 28 | * 29 | * // Perform a purchase test 30 | * $transaction = $gateway->purchase( 31 | * [ 32 | * 'amount' => '10.00', 33 | * 'currency' => 'AUD', 34 | * 'transactionId' => 'invoice_12345', 35 | * 'card' => $card, 36 | * ] 37 | * ); 38 | * 39 | * $response = $transaction->send(); 40 | * 41 | * if ($response->isSuccessful()) { 42 | * echo sprintf('Transaction %s was successful!', $response->getTransactionReference()); 43 | * } else { 44 | * echo sprintf('Transaction %s failed: %s', $response->getTransactionReference(), $response->getMessage()); 45 | * } 46 | * 47 | * 48 | * @link https://www.securepay.com.au/_uploads/files/Secure_XML_API_Integration_Guide.pdf 49 | */ 50 | class SecureXMLGateway extends AbstractGateway 51 | { 52 | public function getName() 53 | { 54 | return 'SecurePay SecureXML'; 55 | } 56 | 57 | public function getDefaultParameters() 58 | { 59 | return [ 60 | 'merchantId' => '', 61 | 'transactionPassword' => '', 62 | 'testMode' => false, 63 | ]; 64 | } 65 | 66 | public function getMerchantId() 67 | { 68 | return $this->getParameter('merchantId'); 69 | } 70 | 71 | public function setMerchantId($value) 72 | { 73 | return $this->setParameter('merchantId', $value); 74 | } 75 | 76 | public function getTransactionPassword() 77 | { 78 | return $this->getParameter('transactionPassword'); 79 | } 80 | 81 | public function setTransactionPassword($value) 82 | { 83 | return $this->setParameter('transactionPassword', $value); 84 | } 85 | 86 | public function authorize(array $parameters = array()) 87 | { 88 | return $this->createRequest('\Omnipay\SecurePay\Message\SecureXMLAuthorizeRequest', $parameters); 89 | } 90 | 91 | public function capture(array $parameters = array()) 92 | { 93 | return $this->createRequest('\Omnipay\SecurePay\Message\SecureXMLCaptureRequest', $parameters); 94 | } 95 | 96 | public function purchase(array $parameters = array()) 97 | { 98 | return $this->createRequest('\Omnipay\SecurePay\Message\SecureXMLPurchaseRequest', $parameters); 99 | } 100 | 101 | public function refund(array $parameters = array()) 102 | { 103 | return $this->createRequest('\Omnipay\SecurePay\Message\SecureXMLRefundRequest', $parameters); 104 | } 105 | 106 | public function echoTest(array $parameters = array()) 107 | { 108 | return $this->createRequest('\Omnipay\SecurePay\Message\SecureXMLEchoTestRequest', $parameters); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /tests/Message/DirectPostCompletePurchaseRequestTest.php: -------------------------------------------------------------------------------- 1 | request = new DirectPostCompletePurchaseRequest($this->getHttpClient(), $this->getHttpRequest()); 12 | } 13 | 14 | public function testGenerateResponseFingerprint() 15 | { 16 | $this->request->initialize([ 17 | 'amount' => '465.18', 18 | 'transactionPassword' => 'abc123', 19 | ]); 20 | 21 | $data = [ 22 | 'timestamp' => '20130602102927', 23 | 'merchant' => 'ABC0030', 24 | 'refid' => '222', 25 | 'summarycode' => '2', 26 | ]; 27 | 28 | $this->assertSame('0516a31bf96ad89c354266afb9bd4be43aaf853f', $this->request->generateResponseFingerprint($data)); 29 | } 30 | 31 | public function testSuccess() 32 | { 33 | $this->request->initialize([ 34 | 'amount' => '355.00', 35 | 'transactionPassword' => 'abc123', 36 | ]); 37 | 38 | $this->getHttpRequest()->query->replace([ 39 | 'timestamp' => '20130602112954', 40 | 'callback_status_code' => '', 41 | 'fingerprint' => 'd9b40fc6f841f41ef3475220fe6316406a5256ce', 42 | 'txnid' => '205861', 43 | 'merchant' => 'ABC0030', 44 | 'restext' => 'Approved', 45 | 'rescode' => '00', 46 | 'expirydate' => '032016', 47 | 'settdate' => '20130602', 48 | 'refid' => '226', 49 | 'pan' => '444433...111', 50 | 'summarycode' => '1', 51 | ]); 52 | 53 | $response = $this->request->send(); 54 | 55 | $this->assertInstanceOf('Omnipay\\SecurePay\\Message\\DirectPostCompletePurchaseResponse', $response); 56 | 57 | $this->assertTrue($response->isSuccessful()); 58 | $this->assertFalse($response->isRedirect()); 59 | $this->assertSame('205861', $response->getTransactionReference()); 60 | $this->assertSame('Approved', $response->getMessage()); 61 | $this->assertSame('00', $response->getCode()); 62 | } 63 | 64 | public function testFailure() 65 | { 66 | $this->request->initialize([ 67 | 'amount' => '465.18', 68 | 'transactionPassword' => 'abc123', 69 | ]); 70 | 71 | $this->getHttpRequest()->query->replace([ 72 | 'timestamp' => '20130602102927', 73 | 'callback_status_code' => '', 74 | 'fingerprint' => '0516a31bf96ad89c354266afb9bd4be43aaf853f', 75 | 'txnid' => '205833', 76 | 'merchant' => 'ABC0030', 77 | 'restext' => 'Customer Dispute', 78 | 'rescode' => '18', 79 | 'expirydate' => '052016', 80 | 'settdate' => '20130602', 81 | 'refid' => '222', 82 | 'pan' => '444433...111', 83 | 'summarycode' => '2', 84 | ]); 85 | 86 | $response = $this->request->send(); 87 | 88 | $this->assertInstanceOf('Omnipay\\SecurePay\\Message\\DirectPostCompletePurchaseResponse', $response); 89 | 90 | $this->assertFalse($response->isSuccessful()); 91 | $this->assertFalse($response->isRedirect()); 92 | $this->assertSame('205833', $response->getTransactionReference()); 93 | $this->assertSame('Customer Dispute', $response->getMessage()); 94 | $this->assertSame('18', $response->getCode()); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /tests/Message/SecureXMLAuthorizeRequestTest.php: -------------------------------------------------------------------------------- 1 | request = new SecureXMLAuthorizeRequest($this->getHttpClient(), $this->getHttpRequest()); 12 | 13 | $this->request->initialize([ 14 | 'merchantId' => 'ABC0030', 15 | 'transactionPassword' => 'abc123', 16 | 'amount' => '12.00', 17 | 'transactionId' => '1234', 18 | 'card' => [ 19 | 'number' => '4444333322221111', 20 | 'expiryMonth' => '12', 21 | 'expiryYear' => date('Y'), 22 | 'cvv' => '123', 23 | ], 24 | ]); 25 | } 26 | 27 | public function testSendSuccess() 28 | { 29 | $this->setMockHttpResponse('SecureXMLAuthorizeRequestSuccess.txt'); 30 | $response = $this->request->send(); 31 | $data = $response->getData(); 32 | 33 | $this->assertInstanceOf('Omnipay\\SecurePay\\Message\\SecureXMLResponse', $response); 34 | 35 | $this->assertTrue($response->isSuccessful()); 36 | $this->assertFalse($response->isRedirect()); 37 | $this->assertSame('009729', $response->getTransactionReference()); 38 | $this->assertSame('00', $response->getCode()); 39 | $this->assertSame('Approved', $response->getMessage()); 40 | $this->assertSame('10', (string) $data->Payment->TxnList->Txn->txnType); 41 | } 42 | 43 | public function testSendFailure() 44 | { 45 | $this->setMockHttpResponse('SecureXMLAuthorizeRequestFailure.txt'); 46 | $response = $this->request->send(); 47 | 48 | $this->assertInstanceOf('Omnipay\\SecurePay\\Message\\SecureXMLResponse', $response); 49 | 50 | $this->assertFalse($response->isSuccessful()); 51 | $this->assertFalse($response->isRedirect()); 52 | $this->assertSame('510', $response->getCode()); 53 | $this->assertSame('Unable To Connect To Server', $response->getMessage()); 54 | } 55 | 56 | public function testInsufficientFundsFailure() 57 | { 58 | $this->setMockHttpResponse('SecureXMLAuthorizeRequestInsufficientFundsFailure.txt'); 59 | $response = $this->request->send(); 60 | 61 | $this->assertInstanceOf('Omnipay\\SecurePay\\Message\\SecureXMLResponse', $response); 62 | 63 | $this->assertFalse($response->isSuccessful()); 64 | $this->assertFalse($response->isRedirect()); 65 | $this->assertNull($response->getTransactionReference()); 66 | $this->assertSame('51', $response->getCode()); 67 | $this->assertSame('Insufficient Funds', $response->getMessage()); 68 | } 69 | 70 | public function testInvalidMerchantFailure() 71 | { 72 | $this->setMockHttpResponse('SecureXMLAuthorizeRequestInvalidMerchantFailure.txt'); 73 | $response = $this->request->send(); 74 | 75 | $this->assertInstanceOf('Omnipay\\SecurePay\\Message\\SecureXMLResponse', $response); 76 | 77 | $this->assertFalse($response->isSuccessful()); 78 | $this->assertFalse($response->isRedirect()); 79 | $this->assertNull($response->getTransactionReference()); 80 | $this->assertSame('504', $response->getCode()); 81 | $this->assertSame('Invalid merchant ABC0030', $response->getMessage()); 82 | } 83 | 84 | public function testInvalidMerchantIDFailure() 85 | { 86 | $this->setMockHttpResponse('SecureXMLAuthorizeRequestInvalidMerchantIDFailure.txt'); 87 | $response = $this->request->send(); 88 | 89 | $this->assertInstanceOf('Omnipay\\SecurePay\\Message\\SecureXMLResponse', $response); 90 | 91 | $this->assertFalse($response->isSuccessful()); 92 | $this->assertFalse($response->isRedirect()); 93 | $this->assertNull($response->getTransactionReference()); 94 | $this->assertSame('504', $response->getCode()); 95 | $this->assertSame('Invalid merchant ID', $response->getMessage()); 96 | } 97 | 98 | public function testSetMessageId() 99 | { 100 | $this->request->setMessageId('message_identifier_here'); 101 | $this->assertSame('message_identifier_here', $this->request->getMessageId()); 102 | } 103 | 104 | public function testAutogeneratedMessageId() 105 | { 106 | $this->assertNotNull($this->request->getMessageId()); 107 | $this->assertSame(30, strlen($this->request->getMessageId())); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/Message/SecureXMLAbstractRequest.php: -------------------------------------------------------------------------------- 1 | setParameter('messageId', $value); 39 | } 40 | 41 | /** 42 | * Get the messageID for the request. 43 | * 44 | * @return string User-supplied messageID or generated one based on 45 | * timestamp. 46 | */ 47 | public function getMessageId() 48 | { 49 | $messageId = $this->getParameter('messageId'); 50 | 51 | if (empty($messageId)) { 52 | $this->setMessageId(substr(md5(microtime()), 0, 30)); 53 | } 54 | 55 | return $this->getParameter('messageId'); 56 | } 57 | 58 | public function sendData($data) 59 | { 60 | $httpResponse = $this->httpClient->request('POST', $this->getEndpoint(), [], $data->asXML()); 61 | 62 | $xml = new \SimpleXMLElement($httpResponse->getBody()->getContents()); 63 | 64 | return $this->response = new SecureXMLResponse($this, $xml); 65 | } 66 | 67 | /** 68 | * XML Template of a SecurePayMessage. 69 | * 70 | * As per section 5.1 of the documentation, these elements are common to 71 | * all requests. 72 | * 73 | * @return \SimpleXMLElement SecurePayMessage template. 74 | */ 75 | protected function getBaseXML() 76 | { 77 | foreach ($this->requiredFields as $field) { 78 | $this->validate($field); 79 | } 80 | 81 | $xml = new \SimpleXMLElement(''); 82 | 83 | $messageInfo = $xml->addChild('MessageInfo'); 84 | $messageInfo->messageID = $this->getMessageId(); 85 | $messageInfo->addChild('messageTimestamp', $this->generateTimestamp()); 86 | $messageInfo->addChild('timeoutValue', 60); 87 | $messageInfo->addChild('apiVersion', 'xml-4.2'); 88 | 89 | $merchantInfo = $xml->addChild('MerchantInfo'); 90 | $merchantInfo->addChild('merchantID', $this->getMerchantId()); 91 | $merchantInfo->addChild('password', $this->getTransactionPassword()); 92 | 93 | $xml->addChild('RequestType', $this->requestType); // Not related to the transaction type 94 | 95 | return $xml; 96 | } 97 | 98 | /** 99 | * XML template of a SecurePayMessage Payment. 100 | * 101 | * @return \SimpleXMLElement SecurePayMessage with transaction details. 102 | */ 103 | protected function getBasePaymentXML() 104 | { 105 | $xml = $this->getBaseXML(); 106 | 107 | $payment = $xml->addChild('Payment'); 108 | $txnList = $payment->addChild('TxnList'); 109 | $txnList->addAttribute('count', 1); // One transaction per request supported by current API. 110 | 111 | $transaction = $txnList->addChild('Txn'); 112 | $transaction->addAttribute('ID', 1); // One transaction per request supported by current API. 113 | $transaction->addChild('txnType', $this->txnType); 114 | $transaction->addChild('txnSource', 23); // Must always be 23 for SecureXML. 115 | $transaction->addChild('amount', $this->getAmountInteger()); 116 | $transaction->addChild('currency', $this->getCurrency()); 117 | $transaction->purchaseOrderNo = $this->getTransactionId(); 118 | 119 | return $xml; 120 | } 121 | 122 | /** 123 | * @return \SimpleXMLElement SecurePayMessage with transaction and card 124 | * details. 125 | */ 126 | protected function getBasePaymentXMLWithCard() 127 | { 128 | $this->getCard()->validate(); 129 | 130 | $xml = $this->getBasePaymentXML(); 131 | 132 | $card = $xml->Payment->TxnList->Txn->addChild('CreditCardInfo'); 133 | $card->addChild('cardNumber', $this->getCard()->getNumber()); 134 | $card->addChild('cvv', $this->getCard()->getCvv()); 135 | $card->addChild('expiryDate', $this->getCard()->getExpiryDate('m/y')); 136 | 137 | return $xml; 138 | } 139 | 140 | /** 141 | * Generates a SecureXML timestamp. 142 | * 143 | * SecureXML requires a specific timestamp format as per appendix E of the 144 | * documentation. 145 | * 146 | * @return string SecureXML formatted timestamp. 147 | */ 148 | protected function generateTimestamp() 149 | { 150 | $date = new \DateTime(); 151 | 152 | // API requires the timezone offset in minutes 153 | return $date->format(sprintf('YmdHis000%+04d', $date->format('Z') / 60)); 154 | } 155 | } 156 | --------------------------------------------------------------------------------