├── .gitignore ├── tests ├── Mock │ ├── JsonRefundResponseSuccess.txt │ ├── JsonPurchaseResponseMalformed.txt │ ├── JsonRefundResponseError.txt │ ├── JsonPurchaseResponseError.txt │ ├── JsonPurchaseResponseSuccess.txt │ ├── JsonAuthorizeResponseSuccess.txt │ └── JsonPurchaseResponseFailure.txt ├── Message │ ├── JsonAbstractRequestTest.php │ ├── PurchaseResponseTest.php │ ├── JsonRefundRequestTest.php │ ├── PurchaseRequestTest.php │ ├── JsonAuthorizeRequestTest.php │ ├── CompletePurchaseResponseTest.php │ └── JsonPurchaseRequestTest.php ├── JsonGatewayTest.php └── GatewayTest.php ├── src ├── Message │ ├── JsonAuthorizeResponse.php │ ├── JsonCaptureRequest.php │ ├── JsonAuthorizeRequest.php │ ├── JsonRefundRequest.php │ ├── CompletePurchaseRequest.php │ ├── PurchaseResponse.php │ ├── JsonPurchaseResponse.php │ ├── CompletePurchaseResponse.php │ ├── JsonResponse.php │ ├── JsonPurchaseRequest.php │ ├── JsonAbstractRequest.php │ └── PurchaseRequest.php ├── JsonGateway.php └── Gateway.php ├── 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 | .idea -------------------------------------------------------------------------------- /tests/Mock/JsonRefundResponseSuccess.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Date: Sun, 21 May 2017 23:01:34 GMT 3 | requestId: 4c33d5fc-55d9-48d4-9b33-5d5a213969b2 4 | Server: Windows NT 3.x 5 | X-Content-Type-Options: nosniff 6 | Content-Length: 0 7 | Connection: Close 8 | 9 | -------------------------------------------------------------------------------- /tests/Mock/JsonPurchaseResponseMalformed.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 400 Bad Request 2 | Content-Type: application/json;charset=UTF-8 3 | Date: Sat, 13 May 2017 00:20:08 GMT 4 | requestId: 3c644d2e-082c-430e-a209-fce4c253e49f 5 | Server: Windows NT 3.x 6 | X-Content-Type-Options: nosniff 7 | Content-Length: 0 8 | Connection: Close 9 | 10 | -------------------------------------------------------------------------------- /src/Message/JsonAuthorizeResponse.php: -------------------------------------------------------------------------------- 1 | getAmountInteger(); 18 | 19 | return $data; 20 | } 21 | 22 | /** 23 | * @return string 24 | */ 25 | public function getEndpoint() 26 | { 27 | return $this->endpoint.'/orders/'.$this->getTransactionReference().'/capture'; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/Mock/JsonRefundResponseError.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 400 Bad Request 2 | Content-Type: application/json;charset=UTF-8 3 | Date: Sun, 21 May 2017 23:45:31 GMT 4 | requestId: c6d3c41f-5cdc-4658-9fdc-fc761fd98665 5 | Server: Windows NT 3.x 6 | X-Content-Type-Options: nosniff 7 | Content-Length: 348 8 | Connection: Close 9 | 10 | {"httpStatusCode":400,"customCode":"BAD_REQUEST","message":"TEST Order: e0bf69e8-8c98-4e01-893b-d040fa41dd9b cannot be refunded while in status: REFUNDED - try again later.","description":"Some of request parameters are invalid, please check your request. For more information please refer to Json schema.","errorHelpUrl":null,"originalRequest":""} -------------------------------------------------------------------------------- /src/Message/JsonAuthorizeRequest.php: -------------------------------------------------------------------------------- 1 | validate('amount'); 18 | 19 | $data = array(); 20 | 21 | $data['refundAmount'] = $this->getAmountInteger(); 22 | 23 | return $data; 24 | } 25 | 26 | /** 27 | * @return string 28 | */ 29 | public function getEndpoint() 30 | { 31 | return $this->endpoint.'/orders/'.$this->getTransactionReference().'/refund'; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | ./tests/ 15 | 16 | 17 | 18 | 19 | ./src 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/Message/CompletePurchaseRequest.php: -------------------------------------------------------------------------------- 1 | httpRequest->request->get('callbackPW'); 15 | if ($callbackPW !== $this->getCallbackPassword()) { 16 | throw new InvalidResponseException("Invalid callback password"); 17 | } 18 | 19 | return $this->httpRequest->request->all(); 20 | } 21 | 22 | public function sendData($data) 23 | { 24 | return $this->response = new CompletePurchaseResponse($this, $data); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Message/JsonAbstractRequestTest.php: -------------------------------------------------------------------------------- 1 | request = Mockery::mock('\Omnipay\Worldpay\Message\JsonAbstractRequest')->makePartial(); 13 | $this->request->initialize(); 14 | } 15 | 16 | public function testCardReference() 17 | { 18 | $this->assertSame($this->request, $this->request->setCardReference('abc123')); 19 | $this->assertSame('abc123', $this->request->getCardReference()); 20 | } 21 | 22 | public function testCardToken() 23 | { 24 | $this->assertSame($this->request, $this->request->setToken('abc123')); 25 | $this->assertSame('abc123', $this->request->getToken()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Message/PurchaseResponse.php: -------------------------------------------------------------------------------- 1 | getRequest()->getEndpoint().'?'.http_build_query($this->data); 26 | } 27 | 28 | public function getRedirectMethod() 29 | { 30 | return 'GET'; 31 | } 32 | 33 | public function getRedirectData() 34 | { 35 | return null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/Mock/JsonPurchaseResponseSuccess.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json;charset=UTF-8 3 | Date: Sat, 13 May 2017 00:20:08 GMT 4 | requestId: 3c644d2e-082c-430e-a209-fce4c253e49f 5 | Server: Windows NT 3.x 6 | X-Content-Type-Options: nosniff 7 | Content-Length: 760 8 | Connection: Close 9 | 10 | {"orderCode":"e0bf69e8-8c98-4e01-893b-d040fa41dd9b","token":"TEST_RU_7a22d2ec-6725-48b7-b8e7-243f03914b27","orderDescription":"Order #4","amount":500,"currencyCode":"GBP","paymentStatus":"SUCCESS","paymentResponse":{"type":"ObfuscatedCard","name":"Luke Holder","expiryMonth":1,"expiryYear":2018,"cardType":"MASTERCARD_CREDIT","maskedCardNumber":"**** **** **** 4444","cardSchemeType":"consumer","cardSchemeName":"MCI CREDIT","cardIssuer":"LLOYDS BANK PLC","countryCode":"GB","cardClass":"credit","cardProductTypeDescNonContactless":"MasterCard Business","cardProductTypeDescContactless":"CL MasterCard Bus","prepaid":"unknown"},"environment":"TEST","riskScore":{"value":"1"},"resultCodes":{"avsResultCode":"NOT_SUPPLIED_BY_SHOPPER","cvcResultCode":"APPROVED"}} -------------------------------------------------------------------------------- /tests/Mock/JsonAuthorizeResponseSuccess.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json;charset=UTF-8 3 | Date: Sat, 13 May 2017 00:20:08 GMT 4 | requestId: 3c644d2e-082c-430e-a209-fce4c253e49f 5 | Server: Windows NT 3.x 6 | X-Content-Type-Options: nosniff 7 | Content-Length: 763 8 | Connection: Close 9 | 10 | {"orderCode":"e0bf69e8-8c98-4e01-893b-d040fa41dd9b","token":"TEST_RU_7a22d2ec-6725-48b7-b8e7-243f03914b27","orderDescription":"Order #4","amount":500,"currencyCode":"GBP","paymentStatus":"AUTHORIZED","paymentResponse":{"type":"ObfuscatedCard","name":"Luke Holder","expiryMonth":1,"expiryYear":2018,"cardType":"MASTERCARD_CREDIT","maskedCardNumber":"**** **** **** 4444","cardSchemeType":"consumer","cardSchemeName":"MCI CREDIT","cardIssuer":"LLOYDS BANK PLC","countryCode":"GB","cardClass":"credit","cardProductTypeDescNonContactless":"MasterCard Business","cardProductTypeDescContactless":"CL MasterCard Bus","prepaid":"unknown"},"environment":"TEST","riskScore":{"value":"1"},"resultCodes":{"avsResultCode":"NOT_SUPPLIED_BY_SHOPPER","cvcResultCode":"APPROVED"}} -------------------------------------------------------------------------------- /tests/JsonGatewayTest.php: -------------------------------------------------------------------------------- 1 | gateway = new JsonGateway($this->getHttpClient(), $this->getHttpRequest()); 18 | $this->gateway->setServiceKey('bar123'); 19 | 20 | $this->options = array( 21 | 'amount' => '5.00', 22 | 'token' => 'TEST_RU_7a22d2ec-6725-48b7-b8e7-243f03914b27' 23 | ); 24 | } 25 | 26 | public function testPurchase() 27 | { 28 | $request = $this->gateway->purchase($this->options); 29 | 30 | $this->assertInstanceOf('Omnipay\Worldpay\Message\JsonPurchaseRequest', $request); 31 | $this->assertEquals('TEST_RU_7a22d2ec-6725-48b7-b8e7-243f03914b27', $request->getToken()); 32 | $this->assertEquals('500', $request->getAmountInteger()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Message/PurchaseResponseTest.php: -------------------------------------------------------------------------------- 1 | getMockRequest(), array( 12 | 'amount' => 1000, 13 | 'returnUrl' => 'https://www.example.com/return', 14 | )); 15 | 16 | $this->getMockRequest()->shouldReceive('getEndpoint')->once()->andReturn('https://secure.worldpay.com/wcc/purchase'); 17 | 18 | $this->assertFalse($response->isSuccessful()); 19 | $this->assertTrue($response->isRedirect()); 20 | $this->assertNull($response->getTransactionReference()); 21 | $this->assertNull($response->getMessage()); 22 | $this->assertSame('https://secure.worldpay.com/wcc/purchase?amount=1000&returnUrl=https%3A%2F%2Fwww.example.com%2Freturn', $response->getRedirectUrl()); 23 | $this->assertSame('GET', $response->getRedirectMethod()); 24 | $this->assertNull($response->getRedirectData()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Mock/JsonPurchaseResponseFailure.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json;charset=UTF-8 3 | Date: Sat, 13 May 2017 00:20:08 GMT 4 | requestId: 3c644d2e-082c-430e-a209-fce4c253e49f 5 | Server: Windows NT 3.x 6 | X-Content-Type-Options: nosniff 7 | Content-Length: 836 8 | Connection: Close 9 | 10 | {"orderCode":"e0bf69e8-8c98-4e01-893b-d040fa41dd9b","token":"TEST_RU_7a22d2ec-6725-48b7-b8e7-243f03914b27","orderDescription":"Order #4","amount":500,"currencyCode":"GBP","paymentStatus":"FAILED","paymentStatusReason":"REFUSED","iso8583Status":"5 - REFUSED","paymentResponse":{"type":"ObfuscatedCard","name":"Luke Holder","expiryMonth":1,"expiryYear":2018,"cardType":"MASTERCARD_CREDIT","maskedCardNumber":"**** **** **** 4444","cardSchemeType":"consumer","cardSchemeName":"MCI CREDIT","cardIssuer":"LLOYDS BANK PLC","countryCode":"GB","cardClass":"credit","cardProductTypeDescNonContactless":"MasterCard Business","cardProductTypeDescContactless":"CL MasterCard Bus","prepaid":"unknown"},"environment":"TEST","riskScore":{"value":"1"},"resultCodes":{"avsResultCode":"NOT_SUPPLIED_BY_SHOPPER","cvcResultCode":"NOT_CHECKED_BY_ACQUIRER"}} -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "omnipay/worldpay", 3 | "type": "library", 4 | "description": "WorldPay driver for the Omnipay payment processing library", 5 | "keywords": [ 6 | "gateway", 7 | "merchant", 8 | "omnipay", 9 | "pay", 10 | "payment", 11 | "worldpay" 12 | ], 13 | "homepage": "https://github.com/thephpleague/omnipay-worldpay", 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-worldpay/contributors" 23 | } 24 | ], 25 | "autoload": { 26 | "psr-4": { "Omnipay\\WorldPay\\" : "src/" } 27 | }, 28 | "require": { 29 | "omnipay/common": "~3.0" 30 | }, 31 | "require-dev": { 32 | "omnipay/tests": "~3.0", 33 | "squizlabs/php_codesniffer": "~3.0" 34 | }, 35 | "extra": { 36 | "branch-alias": { 37 | "dev-master": "3.0.x-dev" 38 | } 39 | }, 40 | "prefer-stable": true 41 | } 42 | -------------------------------------------------------------------------------- /src/Message/JsonPurchaseResponse.php: -------------------------------------------------------------------------------- 1 | data['paymentStatus']) && $this->data['paymentStatus'] == $this->successfulPaymentStatus) { 26 | $isPurchaseSuccess = true; 27 | } 28 | 29 | return ($isHttpSuccess && $isPurchaseSuccess); 30 | } 31 | 32 | /** 33 | * What is the relevant description of the transaction response? 34 | * 35 | * @todo Sometimes the 'description' field is more user-friendly (see simulated eror) - how do we decide which one? 36 | * 37 | * @return string|null 38 | */ 39 | public function getMessage() 40 | { 41 | // check for HTTP failure response first 42 | $httpMessage = parent::getMessage(); 43 | if ($httpMessage !== null) { 44 | return $httpMessage; 45 | } 46 | 47 | // check if descriptive failure reason is available 48 | if (!$this->isSuccessful() && isset($this->data['paymentStatusReason'])) { 49 | return $this->data['paymentStatusReason']; 50 | } 51 | 52 | // check if general payment status is available 53 | if (isset($this->data['paymentStatus'])) { 54 | return $this->data['paymentStatus']; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Message/CompletePurchaseResponse.php: -------------------------------------------------------------------------------- 1 | data['transStatus']) && 'Y' === $this->data['transStatus']; 15 | } 16 | 17 | public function isCancelled() 18 | { 19 | return isset($this->data['transStatus']) && 'C' === $this->data['transStatus']; 20 | } 21 | 22 | public function getTransactionReference() 23 | { 24 | return isset($this->data['transId']) ? $this->data['transId'] : null; 25 | } 26 | 27 | public function getMessage() 28 | { 29 | return isset($this->data['rawAuthMessage']) ? $this->data['rawAuthMessage'] : null; 30 | } 31 | 32 | /** 33 | * Optional step: Redirect the customer back to your own domain. 34 | * 35 | * This is achieved by returning a HTML string containing a meta-redirect which is displayed by WorldPay 36 | * to the customer. This is far from ideal, but apparently (according to their support) this is the only 37 | * method currently available. 38 | * 39 | * @param string $returnUrl The URL to forward the customer to. 40 | * @param string|null $message Optional message to display to the customer before they are redirected. 41 | */ 42 | public function confirm($returnUrl, $message = null) 43 | { 44 | if (empty($message)) { 45 | $message = 'Thank you, your transaction has been processed. You are being redirected...'; 46 | } 47 | echo '

'.$message.'

'; 48 | exit; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Omnipay: WorldPay 2 | 3 | **WorldPay driver for the Omnipay PHP payment processing library** 4 | 5 | [![Build Status](https://travis-ci.org/thephpleague/omnipay-worldpay.png?branch=master)](https://travis-ci.org/thephpleague/omnipay-worldpay) 6 | [![Latest Stable Version](https://poser.pugx.org/omnipay/worldpay/version.png)](https://packagist.org/packages/omnipay/worldpay) 7 | [![Total Downloads](https://poser.pugx.org/omnipay/worldpay/d/total.png)](https://packagist.org/packages/omnipay/worldpay) 8 | 9 | [Omnipay](https://github.com/thephpleague/omnipay) is a framework agnostic, multi-gateway payment 10 | processing library for PHP. This package implements WorldPay support for Omnipay. 11 | 12 | ## Installation 13 | 14 | Omnipay is installed via [Composer](http://getcomposer.org/). To install, simply require `league/omnipay` and `omnipay/worldpay` with Composer: 15 | 16 | ``` 17 | composer require league/omnipay omnipay/worldpay 18 | ``` 19 | 20 | ## Basic Usage 21 | 22 | The following gateways are provided by this package: 23 | 24 | * WorldPay 25 | * WorldPay_Json 26 | 27 | For general usage instructions, please see the main [Omnipay](https://github.com/thephpleague/omnipay) 28 | repository. 29 | 30 | ## Support 31 | 32 | If you are having general issues with Omnipay, we suggest posting on 33 | [Stack Overflow](http://stackoverflow.com/). Be sure to add the 34 | [omnipay tag](http://stackoverflow.com/questions/tagged/omnipay) so it can be easily found. 35 | 36 | If you want to keep up to date with release anouncements, discuss ideas for the project, 37 | or ask more detailed questions, there is also a [mailing list](https://groups.google.com/forum/#!forum/omnipay) which 38 | you can subscribe to. 39 | 40 | If you believe you have found a bug, please report it using the [GitHub issue tracker](https://github.com/thephpleague/omnipay-worldpay/issues), 41 | or better yet, fork the library and submit a pull request. 42 | -------------------------------------------------------------------------------- /tests/Message/JsonRefundRequestTest.php: -------------------------------------------------------------------------------- 1 | request = new JsonRefundRequest($this->getHttpClient(), $this->getHttpRequest()); 12 | $this->request->initialize( 13 | array('amount'=>'5.00') 14 | ); 15 | $this->request->setTransactionReference('e0bf69e8-8c98-4e01-893b-d040fa41dd9b'); 16 | } 17 | 18 | public function testSendSuccess() 19 | { 20 | $this->setMockHttpResponse('JsonRefundResponseSuccess.txt'); 21 | $response = $this->request->send(); 22 | 23 | $data = $this->request->getData(); 24 | 25 | $code = $response->response->getStatusCode(); 26 | $this->assertTrue($response->isSuccessful()); 27 | $this->assertEquals(500, $data['refundAmount']); 28 | $this->assertEquals(200, $code); 29 | $this->assertNull($response->getCode()); 30 | $this->assertNull($response->getMessage()); 31 | } 32 | 33 | public function testSendError() 34 | { 35 | $this->setMockHttpResponse('JsonRefundResponseError.txt'); 36 | $response = $this->request->send(); 37 | 38 | $data = $this->request->getData(); 39 | 40 | $code = $response->response->getStatusCode(); 41 | $this->assertFalse($response->isSuccessful()); 42 | $this->assertEquals(500, $data['refundAmount']); 43 | $this->assertEquals(400, $code); 44 | $this->assertSame('BAD_REQUEST', $response->getCode()); 45 | $this->assertSame( 46 | 'TEST Order: e0bf69e8-8c98-4e01-893b-d040fa41dd9b cannot be refunded while in status: REFUNDED - try again later.', 47 | $response->getMessage() 48 | ); 49 | $this->assertNull($response->getTransactionReference()); 50 | $this->assertNull($response->getCardReference()); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tests/Message/PurchaseRequestTest.php: -------------------------------------------------------------------------------- 1 | request = new PurchaseRequest($this->getHttpClient(), $this->getHttpRequest()); 12 | $this->request->initialize( 13 | array( 14 | 'amount' => '10.00', 15 | 'returnUrl' => 'https://example.com/return', 16 | ) 17 | ); 18 | } 19 | 20 | public function testGetData() 21 | { 22 | $this->request->initialize( 23 | array( 24 | 'installationId' => 'id1', 25 | 'accountId' => 'id2', 26 | 'transactionId' => 'id3', 27 | 'description' => 'food', 28 | 'amount' => '12.00', 29 | 'currency' => 'GBP', 30 | 'returnUrl' => 'https://example.com/return', 31 | 'signatureFields' => 'instId:amount:currency', 32 | 'secretWord' => 'such-secret-wow' 33 | ) 34 | ); 35 | 36 | $data = $this->request->getData(); 37 | 38 | $this->assertSame('id1', $data['instId']); 39 | $this->assertSame('id2', $data['accId1']); 40 | $this->assertSame('id3', $data['cartId']); 41 | $this->assertSame('food', $data['desc']); 42 | $this->assertSame('12.00', $data['amount']); 43 | $this->assertSame('GBP', $data['currency']); 44 | $this->assertSame(0, $data['testMode']); 45 | $this->assertSame('https://example.com/return', $data['MC_callback']); 46 | $this->assertSame('instId:amount:currency', $data['signatureFields']); 47 | $this->assertInternalType('string', $data['signature']); 48 | $this->assertEquals(32, strlen($data['signature'])); 49 | } 50 | 51 | public function testGetDataTestMode() 52 | { 53 | $this->request->setTestMode(true); 54 | 55 | $data = $this->request->getData(); 56 | 57 | $this->assertSame(100, $data['testMode']); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /tests/Message/JsonAuthorizeRequestTest.php: -------------------------------------------------------------------------------- 1 | request = new JsonAuthorizeRequest($this->getHttpClient(), $this->getHttpRequest()); 12 | $this->request->initialize( 13 | array( 14 | 'amount' => '12.00', 15 | 'currency' => 'USD', 16 | 'token' => 'TEST_RU_7a22d2ec-6725-48b7-b8e7-243f03914b27', 17 | 'description' => 'Order #4', 18 | 'card' => array( 19 | 'name' => "Luke Holder", 20 | 'address1' => '123 Somewhere St', 21 | 'address2' => 'Suburbia', 22 | 'city' => 'Little Town', 23 | 'postcode' => '1234', 24 | 'state' => 'CA', 25 | 'country' => 'US', 26 | 'phone' => '1-234-567-8900' 27 | ) 28 | ) 29 | ); 30 | } 31 | 32 | public function testGetData() 33 | { 34 | $data = $this->request->getData(); 35 | 36 | $this->assertSame(1200, $data['amount']); 37 | $this->assertSame('USD', $data['currency']); 38 | $this->assertSame('Order #4', $data['orderDescription']); 39 | } 40 | 41 | public function testDataWithToken() 42 | { 43 | $this->request->setToken('xyz'); 44 | $data = $this->request->getData(); 45 | 46 | $this->assertSame('xyz', $data['token']); 47 | } 48 | 49 | public function testSendSuccess() 50 | { 51 | $this->setMockHttpResponse('JsonAuthorizeResponseSuccess.txt'); 52 | $response = $this->request->send(); 53 | 54 | $this->assertTrue($response->isSuccessful()); 55 | $this->assertFalse($response->isRedirect()); 56 | $this->assertSame('e0bf69e8-8c98-4e01-893b-d040fa41dd9b', $response->getTransactionReference()); 57 | $this->assertSame('TEST_RU_7a22d2ec-6725-48b7-b8e7-243f03914b27', $response->getCardReference()); 58 | $this->assertEquals('AUTHORIZED', $response->getMessage()); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Message/JsonResponse.php: -------------------------------------------------------------------------------- 1 | response = $response; 29 | parent::__construct($request, json_decode($response->getBody()->getContents(), true)); 30 | } 31 | 32 | /** 33 | * Is the response successful? 34 | * 35 | * Based on HTTP status code, as some requests have an empty body (no data) but are still a success. 36 | * For example see tests/Mock/JsonRefundResponseSuccess.txt 37 | * 38 | * @return bool 39 | */ 40 | public function isSuccessful() 41 | { 42 | $code = $this->response->getStatusCode(); 43 | return $code == 200; 44 | } 45 | 46 | /** 47 | * @return string|null 48 | */ 49 | public function getMessage() 50 | { 51 | if (!$this->isSuccessful() && isset($this->data['message'])) { 52 | return $this->data['message']; 53 | } 54 | } 55 | 56 | /** 57 | * @return string|null 58 | */ 59 | public function getCode() 60 | { 61 | if (isset($this->data['customCode'])) { 62 | return $this->data['customCode']; 63 | } 64 | } 65 | 66 | /** 67 | * @return string|null 68 | */ 69 | public function getTransactionReference() 70 | { 71 | if (isset($this->data['orderCode'])) { 72 | return $this->data['orderCode']; 73 | } 74 | } 75 | 76 | /** 77 | * @return string|null 78 | */ 79 | public function getCardReference() 80 | { 81 | if (isset($this->data['token'])) { 82 | return $this->data['token']; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /tests/Message/CompletePurchaseResponseTest.php: -------------------------------------------------------------------------------- 1 | getMockRequest(), 13 | array( 14 | 'transStatus' => 'Y', 15 | 'transId' => 'abc123', 16 | 'rawAuthMessage' => 'Success Message' 17 | ) 18 | ); 19 | 20 | $this->assertTrue($response->isSuccessful()); 21 | $this->assertFalse($response->isCancelled()); 22 | $this->assertFalse($response->isRedirect()); 23 | $this->assertSame('abc123', $response->getTransactionReference()); 24 | $this->assertSame('Success Message', $response->getMessage()); 25 | } 26 | 27 | public function testCompletePurchaseCancel() 28 | { 29 | $response = new CompletePurchaseresponse( 30 | $this->getMockRequest(), 31 | array( 32 | 'transStatus' => 'C', 33 | 'transId' => null, 34 | 'rawAuthMessage' => 'Declined' 35 | ) 36 | ); 37 | 38 | $this->assertFalse($response->isSuccessful()); 39 | $this->assertTrue($response->isCancelled()); 40 | $this->assertFalse($response->isRedirect()); 41 | $this->assertNull($response->getTransactionReference()); 42 | $this->assertSame('Declined', $response->getMessage()); 43 | } 44 | 45 | public function testCompletePurchaseFailure() 46 | { 47 | $response = new CompletePurchaseresponse( 48 | $this->getMockRequest(), 49 | array( 50 | 'transStatus' => 'N', 51 | 'transId' => null, 52 | 'rawAuthMessage' => 'Declined' 53 | ) 54 | ); 55 | 56 | $this->assertFalse($response->isSuccessful()); 57 | $this->assertFalse($response->isCancelled()); 58 | $this->assertFalse($response->isRedirect()); 59 | $this->assertNull($response->getTransactionReference()); 60 | $this->assertSame('Declined', $response->getMessage()); 61 | } 62 | 63 | public function testCompletePurchaseInvalid() 64 | { 65 | $response = new CompletePurchaseresponse($this->getMockRequest(), array()); 66 | 67 | $this->assertFalse($response->isSuccessful()); 68 | $this->assertFalse($response->isRedirect()); 69 | $this->assertNull($response->getTransactionReference()); 70 | $this->assertNull($response->getMessage()); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /tests/GatewayTest.php: -------------------------------------------------------------------------------- 1 | gateway = new Gateway($this->getHttpClient(), $this->getHttpRequest()); 14 | $this->gateway->setCallbackPassword('bar123'); 15 | 16 | $this->options = array( 17 | 'amount' => '10.00', 18 | 'returnUrl' => 'https://www.example.com/return', 19 | ); 20 | } 21 | 22 | public function testPurchase() 23 | { 24 | $response = $this->gateway->purchase($this->options)->send(); 25 | 26 | $this->assertFalse($response->isSuccessful()); 27 | $this->assertTrue($response->isRedirect()); 28 | $this->assertNull($response->getTransactionReference()); 29 | $this->assertContains('https://secure.worldpay.com/wcc/purchase?', $response->getRedirectUrl()); 30 | } 31 | 32 | public function testCompletePurchaseSuccess() 33 | { 34 | $this->getHttpRequest()->request->replace( 35 | array( 36 | 'callbackPW' => 'bar123', 37 | 'transStatus' => 'Y', 38 | 'transId' => 'abc123', 39 | 'rawAuthMessage' => 'hello', 40 | ) 41 | ); 42 | 43 | $response = $this->gateway->completePurchase($this->options)->send(); 44 | 45 | $this->assertTrue($response->isSuccessful()); 46 | $this->assertFalse($response->isRedirect()); 47 | $this->assertEquals('abc123', $response->getTransactionReference()); 48 | $this->assertSame('hello', $response->getMessage()); 49 | } 50 | 51 | /** 52 | * @expectedException \Omnipay\Common\Exception\InvalidResponseException 53 | */ 54 | public function testCompletePurchaseInvalidCallbackPassword() 55 | { 56 | $this->getHttpRequest()->request->replace( 57 | array( 58 | 'callbackPW' => 'fake', 59 | ) 60 | ); 61 | 62 | $response = $this->gateway->completePurchase($this->options)->send(); 63 | } 64 | 65 | public function testCompletePurchaseError() 66 | { 67 | $this->getHttpRequest()->request->replace( 68 | array( 69 | 'callbackPW' => 'bar123', 70 | 'transStatus' => 'N', 71 | 'rawAuthMessage' => 'Declined', 72 | ) 73 | ); 74 | 75 | $response = $this->gateway->completePurchase($this->options)->send(); 76 | 77 | $this->assertFalse($response->isSuccessful()); 78 | $this->assertFalse($response->isRedirect()); 79 | $this->assertNull($response->getTransactionReference()); 80 | $this->assertSame('Declined', $response->getMessage()); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Message/JsonPurchaseRequest.php: -------------------------------------------------------------------------------- 1 | validate('amount', 'token'); 18 | 19 | $data = array(); 20 | $data['token'] = $this->getToken(); 21 | $data['amount'] = $this->getAmountInteger(); 22 | $data['currencyCode'] = $this->getCurrency(); 23 | $data['orderDescription'] = $this->getDescription(); 24 | $data['customerOrderCode'] = $this->getTransactionId(); 25 | $data['currency'] = $this->getCurrency(); 26 | 27 | $card = $this->getCard(); 28 | 29 | if ($card) { 30 | $data['billingAddress'] = array(); 31 | $data['billingAddress']['address1'] = $card->getBillingAddress1(); 32 | $data['billingAddress']['address2'] = $card->getBillingAddress2(); 33 | $data['billingAddress']['city'] = $card->getBillingCity(); 34 | $data['billingAddress']['state'] = $card->getBillingState(); 35 | $data['billingAddress']['countryCode'] = $card->getBillingCountry(); 36 | $data['billingAddress']['postalCode'] = $card->getBillingPostcode(); 37 | $data['billingAddress']['telephoneNumber'] = $card->getBillingPhone(); 38 | 39 | $data['name'] = $card->getName(); 40 | 41 | $data['deliveryAddress'] = array(); 42 | 43 | $data['deliveryAddress']['firstName'] = $card->getShippingFirstName(); 44 | $data['deliveryAddress']['lastName'] = $card->getShippingLastName(); 45 | $data['deliveryAddress']['address1'] = $card->getShippingAddress1(); 46 | $data['deliveryAddress']['address2'] = $card->getShippingAddress2(); 47 | $data['deliveryAddress']['city'] = $card->getShippingCity(); 48 | $data['deliveryAddress']['state'] = $card->getShippingState(); 49 | $data['deliveryAddress']['countryCode'] = $card->getShippingCountry(); 50 | $data['deliveryAddress']['postalCode'] = $card->getShippingPostcode(); 51 | $data['deliveryAddress']['telephoneNumber'] = $card->getBillingPhone(); 52 | 53 | $data['shopperEmailAddress'] = $card->getEmail(); 54 | } 55 | 56 | // if billing address is an empty array then we should remove from 57 | // data since WorldPay rejects "{'billingAddress': []}" 58 | if (empty($data['billingAddress'])) { 59 | unset($data['billingAddress']); 60 | } 61 | if (empty($data['deliveryAddress'])) { 62 | unset($data['deliveryAddress']); 63 | } 64 | 65 | $data['shopperIpAddress'] = $this->getClientIp(); 66 | 67 | // Omnipay does not support recurring at the moment 68 | $data['orderType'] = 'ECOM'; 69 | 70 | return $data; 71 | } 72 | 73 | /** 74 | * @return string 75 | */ 76 | public function getEndpoint() 77 | { 78 | return $this->endpoint.'/orders'; 79 | } 80 | 81 | /** 82 | * @return string 83 | */ 84 | public function getResponseClassName() 85 | { 86 | return '\Omnipay\WorldPay\Message\JsonPurchaseResponse'; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Message/JsonAbstractRequest.php: -------------------------------------------------------------------------------- 1 | getParameter('merchantId'); 41 | } 42 | 43 | /** 44 | * Set the stored merchant ID 45 | * 46 | * @param string $value Merchant ID to store 47 | */ 48 | public function setMerchantId($value) 49 | { 50 | return $this->setParameter('merchantId', $value); 51 | } 52 | 53 | /** 54 | * Get the stored service key 55 | * 56 | * @return string 57 | */ 58 | public function getServiceKey() 59 | { 60 | return $this->getParameter('serviceKey'); 61 | } 62 | 63 | /** 64 | * Set the stored service key 65 | * 66 | * @param string $value Service key to store 67 | */ 68 | public function setServiceKey($value) 69 | { 70 | return $this->setParameter('serviceKey', $value); 71 | } 72 | 73 | /** 74 | * Get the stored client key 75 | * 76 | * @return string 77 | */ 78 | public function getClientKey() 79 | { 80 | return $this->getParameter('clientKey'); 81 | } 82 | 83 | /** 84 | * Set the stored client key 85 | * 86 | * @param string $value Client key to store 87 | */ 88 | public function setClientKey($value) 89 | { 90 | return $this->setParameter('clientKey', $value); 91 | } 92 | 93 | /** 94 | * Make the actual request to WorldPay 95 | * 96 | * @param mixed $data The data to encode and send to the API endpoint 97 | * 98 | * @return \Psr\Http\Message\ResponseInterface HTTP response object 99 | */ 100 | public function sendRequest($data) 101 | { 102 | return $this->httpClient->request( 103 | $this->getHttpMethod(), 104 | $this->getEndpoint(), 105 | [ 106 | 'Accept' => 'application/json', 107 | 'Authorization' => $this->getServiceKey(), 108 | 'Content-Type' => 'application/json', 109 | ], 110 | json_encode($data) 111 | ); 112 | } 113 | 114 | /** 115 | * @return string 116 | */ 117 | public function getResponseClassName() 118 | { 119 | return '\Omnipay\WorldPay\Message\JsonResponse'; 120 | } 121 | 122 | /** 123 | * Send the request to the API then build the response object 124 | * 125 | * @param mixed $data The data to encode and send to the API endpoint 126 | * 127 | * @return JsonResponse 128 | */ 129 | public function sendData($data) 130 | { 131 | $httpResponse = $this->sendRequest($data); 132 | 133 | $responseClass = $this->getResponseClassName(); 134 | return $this->response = new $responseClass($this, $httpResponse); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/JsonGateway.php: -------------------------------------------------------------------------------- 1 | '', 34 | 'serviceKey' => '', 35 | 'clientKey' => '', 36 | ); 37 | } 38 | 39 | /** 40 | * Get the stored service key 41 | * 42 | * @return string 43 | */ 44 | public function getServiceKey() 45 | { 46 | return $this->getParameter('serviceKey'); 47 | } 48 | 49 | /** 50 | * Set the stored service key 51 | * 52 | * @param string $value Service key to store 53 | */ 54 | public function setServiceKey($value) 55 | { 56 | return $this->setParameter('serviceKey', $value); 57 | } 58 | 59 | /** 60 | * Get the stored merchant ID 61 | * 62 | * @return string 63 | */ 64 | public function getMerchantId() 65 | { 66 | return $this->getParameter('merchantId'); 67 | } 68 | 69 | /** 70 | * Set the stored merchant ID 71 | * 72 | * @param string $value Merchant ID to store 73 | */ 74 | public function setMerchantId($value) 75 | { 76 | return $this->setParameter('merchantId', $value); 77 | } 78 | 79 | /** 80 | * Get the stored client key 81 | * 82 | * @return string 83 | */ 84 | public function getClientKey() 85 | { 86 | return $this->getParameter('clientKey'); 87 | } 88 | 89 | /** 90 | * Set the stored client key 91 | * 92 | * @param string $value Client key to store 93 | */ 94 | public function setClientKey($value) 95 | { 96 | return $this->setParameter('clientKey', $value); 97 | } 98 | 99 | /** 100 | * Create purchase request 101 | * 102 | * @param array $parameters 103 | * 104 | * @return \Omnipay\WorldPay\Message\JsonPurchaseRequest 105 | */ 106 | public function purchase(array $parameters = array()) 107 | { 108 | return $this->createRequest('\Omnipay\WorldPay\Message\JsonPurchaseRequest', $parameters); 109 | } 110 | 111 | /** 112 | * Create authorize request 113 | * 114 | * @param array $parameters 115 | * 116 | * @return \Omnipay\WorldPay\Message\JsonAuthorizeRequest 117 | */ 118 | public function authorize(array $parameters = array()) 119 | { 120 | return $this->createRequest('\Omnipay\WorldPay\Message\JsonAuthorizeRequest', $parameters); 121 | } 122 | 123 | /** 124 | * Create refund request 125 | * 126 | * @param array $parameters 127 | * 128 | * @return \Omnipay\WorldPay\Message\JsonRefundRequest 129 | */ 130 | public function refund(array $parameters = array()) 131 | { 132 | return $this->createRequest('\Omnipay\WorldPay\Message\JsonRefundRequest', $parameters); 133 | } 134 | 135 | /** 136 | * Create capture request 137 | * 138 | * @param array $parameters 139 | * 140 | * @return \Omnipay\WorldPay\Message\JsonCaptureRequest 141 | */ 142 | public function capture(array $parameters = array()) 143 | { 144 | return $this->createRequest('\Omnipay\WorldPay\Message\JsonCaptureRequest', $parameters); 145 | } 146 | 147 | protected function getDefaultHttpClient() 148 | { 149 | $guzzleClient = Client::createWithConfig([ 150 | 'curl.options' => [ 151 | CURLOPT_SSLVERSION => 6 152 | ] 153 | ]); 154 | 155 | 156 | return new \Omnipay\Common\Http\Client($guzzleClient); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/Gateway.php: -------------------------------------------------------------------------------- 1 | '', 23 | 'accountId' => '', 24 | 'secretWord' => '', 25 | 'callbackPassword' => '', 26 | 'testMode' => false, 27 | 'noLanguageMenu' => false, 28 | 'fixContact' => false, 29 | 'hideContact' => false, 30 | 'hideCurrency' => false, 31 | 'signatureFields' => 'instId:amount:currency:cartId', 32 | ); 33 | } 34 | 35 | public function getSignatureFields() 36 | { 37 | return $this->getParameter('signatureFields'); 38 | } 39 | 40 | public function setSignatureFields($value) 41 | { 42 | return $this->setParameter('signatureFields', $value); 43 | } 44 | 45 | public function getInstallationId() 46 | { 47 | return $this->getParameter('installationId'); 48 | } 49 | 50 | public function setInstallationId($value) 51 | { 52 | return $this->setParameter('installationId', $value); 53 | } 54 | 55 | public function getAccountId() 56 | { 57 | return $this->getParameter('accountId'); 58 | } 59 | 60 | public function setAccountId($value) 61 | { 62 | return $this->setParameter('accountId', $value); 63 | } 64 | 65 | public function getSecretWord() 66 | { 67 | return $this->getParameter('secretWord'); 68 | } 69 | 70 | public function setSecretWord($value) 71 | { 72 | return $this->setParameter('secretWord', $value); 73 | } 74 | 75 | public function getCallbackPassword() 76 | { 77 | return $this->getParameter('callbackPassword'); 78 | } 79 | 80 | public function setCallbackPassword($value) 81 | { 82 | return $this->setParameter('callbackPassword', $value); 83 | } 84 | 85 | /** 86 | * If true, hides WorldPay's language selection menu. 87 | * 88 | * @param boolean 89 | */ 90 | public function getNoLanguageMenu() 91 | { 92 | return $this->getParameter('noLanguageMenu'); 93 | } 94 | 95 | public function setNoLanguageMenu($value) 96 | { 97 | return $this->setParameter('noLanguageMenu', $value); 98 | } 99 | 100 | /** 101 | * If true, prevents editing of address details by user. 102 | * 103 | * @param boolean 104 | */ 105 | public function getFixContact() 106 | { 107 | return $this->getParameter('fixContact'); 108 | } 109 | 110 | public function setFixContact($value) 111 | { 112 | return $this->setParameter('fixContact', $value); 113 | } 114 | 115 | /** 116 | * If true, hides address details from user. 117 | * 118 | * @param boolean 119 | */ 120 | public function getHideContact() 121 | { 122 | return $this->getParameter('hideContact'); 123 | } 124 | 125 | public function setHideContact($value) 126 | { 127 | return $this->setParameter('hideContact', $value); 128 | } 129 | 130 | /** 131 | * If true, hides currency options from user. 132 | * 133 | * @param boolean 134 | */ 135 | public function getHideCurrency() 136 | { 137 | return $this->getParameter('hideCurrency'); 138 | } 139 | 140 | public function setHideCurrency($value) 141 | { 142 | return $this->setParameter('hideCurrency', $value); 143 | } 144 | 145 | public function purchase(array $parameters = array()) 146 | { 147 | return $this->createRequest('\Omnipay\WorldPay\Message\PurchaseRequest', $parameters); 148 | } 149 | 150 | public function completePurchase(array $parameters = array()) 151 | { 152 | return $this->createRequest('\Omnipay\WorldPay\Message\CompletePurchaseRequest', $parameters); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /tests/Message/JsonPurchaseRequestTest.php: -------------------------------------------------------------------------------- 1 | request = new JsonPurchaseRequest($this->getHttpClient(), $this->getHttpRequest()); 12 | $this->request->initialize( 13 | array( 14 | 'amount' => '5.00', 15 | 'currency' => 'USD', 16 | 'token' => 'TEST_RU_7a22d2ec-6725-48b7-b8e7-243f03914b27', 17 | 'description' => 'Order #4', 18 | 'card' => array( 19 | 'name' => "Luke Holder", 20 | 'address1' => '123 Somewhere St', 21 | 'address2' => 'Suburbia', 22 | 'city' => 'Little Town', 23 | 'postcode' => '1234', 24 | 'state' => 'CA', 25 | 'country' => 'US', 26 | 'phone' => '1-234-567-8900' 27 | ) 28 | ) 29 | ); 30 | } 31 | 32 | public function testGetData() 33 | { 34 | $data = $this->request->getData(); 35 | 36 | $this->assertSame(500, $data['amount']); 37 | $this->assertSame('USD', $data['currency']); 38 | $this->assertSame('Order #4', $data['orderDescription']); 39 | } 40 | 41 | public function testDataWithToken() 42 | { 43 | $this->request->setToken('xyz'); 44 | $data = $this->request->getData(); 45 | 46 | $this->assertSame('xyz', $data['token']); 47 | } 48 | 49 | 50 | public function testSendSuccess() 51 | { 52 | $this->setMockHttpResponse('JsonPurchaseResponseSuccess.txt'); 53 | $response = $this->request->send(); 54 | 55 | $this->assertTrue($response->isSuccessful()); 56 | $this->assertFalse($response->isRedirect()); 57 | $this->assertSame('e0bf69e8-8c98-4e01-893b-d040fa41dd9b', $response->getTransactionReference()); 58 | $this->assertSame('TEST_RU_7a22d2ec-6725-48b7-b8e7-243f03914b27', $response->getCardReference()); 59 | $this->assertSame('SUCCESS', $response->getMessage()); 60 | $this->assertSame('\Omnipay\WorldPay\Message\JsonPurchaseResponse', $this->request->getResponseClassName()); 61 | $this->assertSame('Omnipay\WorldPay\Message\JsonPurchaseResponse', get_class($response)); 62 | } 63 | 64 | /** 65 | * Simulate card declined (no error in transit, 200 HTTP response) 66 | */ 67 | public function testSendFailure() 68 | { 69 | $this->setMockHttpResponse('JsonPurchaseResponseFailure.txt'); 70 | $response = $this->request->send(); 71 | 72 | $data = $this->request->getData(); 73 | 74 | $code = $response->response->getStatusCode(); 75 | $this->assertFalse($response->isSuccessful()); 76 | $this->assertEquals(500, $data['amount']); 77 | $this->assertEquals(200, $code); 78 | $this->assertNull($response->getCode()); 79 | $this->assertSame("REFUSED", $response->getMessage()); 80 | $this->assertSame('e0bf69e8-8c98-4e01-893b-d040fa41dd9b', $response->getTransactionReference()); 81 | $this->assertSame('TEST_RU_7a22d2ec-6725-48b7-b8e7-243f03914b27', $response->getCardReference()); 82 | } 83 | 84 | /** 85 | * Simulate bad request (HTTP 400 or similar) 86 | */ 87 | public function testSendError() 88 | { 89 | $this->setMockHttpResponse('JsonPurchaseResponseError.txt'); 90 | $response = $this->request->send(); 91 | 92 | $data = $this->request->getData(); 93 | 94 | $code = $response->response->getStatusCode(); 95 | $this->assertFalse($response->isSuccessful()); 96 | $this->assertEquals(500, $data['amount']); 97 | $this->assertEquals(400, $code); 98 | $this->assertSame('BAD_REQUEST', $response->getCode()); 99 | $this->assertSame("This card is not accepted for Test transactions", $response->getMessage()); 100 | $this->assertNull($response->getTransactionReference()); 101 | $this->assertNull($response->getCardReference()); 102 | } 103 | 104 | /** 105 | * Simulate malformed response body (partial success conditions) 106 | */ 107 | public function testSendMalformed() 108 | { 109 | $this->setMockHttpResponse('JsonPurchaseResponseMalformed.txt'); 110 | $response = $this->request->send(); 111 | 112 | $code = $response->response->getStatusCode(); 113 | $this->assertFalse($response->isSuccessful()); 114 | $this->assertEquals(400, $code); 115 | $this->assertNull($response->getCode()); 116 | $this->assertNull($response->getMessage()); 117 | $this->assertNull($response->getTransactionReference()); 118 | $this->assertNull($response->getCardReference()); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/Message/PurchaseRequest.php: -------------------------------------------------------------------------------- 1 | setParameter('signatureFields', $value); 18 | } 19 | 20 | public function getSignatureFields() 21 | { 22 | return $this->getParameter('signatureFields'); 23 | } 24 | 25 | public function getInstallationId() 26 | { 27 | return $this->getParameter('installationId'); 28 | } 29 | 30 | public function setInstallationId($value) 31 | { 32 | return $this->setParameter('installationId', $value); 33 | } 34 | 35 | public function getAccountId() 36 | { 37 | return $this->getParameter('accountId'); 38 | } 39 | 40 | public function setAccountId($value) 41 | { 42 | return $this->setParameter('accountId', $value); 43 | } 44 | 45 | public function getSecretWord() 46 | { 47 | return $this->getParameter('secretWord'); 48 | } 49 | 50 | public function setSecretWord($value) 51 | { 52 | return $this->setParameter('secretWord', $value); 53 | } 54 | 55 | public function getCallbackPassword() 56 | { 57 | return $this->getParameter('callbackPassword'); 58 | } 59 | 60 | public function setCallbackPassword($value) 61 | { 62 | return $this->setParameter('callbackPassword', $value); 63 | } 64 | 65 | /** 66 | * Pre-selects the card type being used and bypasses the card type selection screen. 67 | * Must match one of: https://support.worldpay.com/support/kb/bg/customisingadvanced/custa9102.html 68 | * 69 | * @param string 70 | */ 71 | public function getPaymentType() 72 | { 73 | return $this->getParameter('paymentType'); 74 | } 75 | 76 | public function setPaymentType($value) 77 | { 78 | return $this->setParameter('paymentType', $value); 79 | } 80 | 81 | /** 82 | * If true, hides WorldPay's language selection menu. 83 | * 84 | * @param boolean 85 | */ 86 | public function getNoLanguageMenu() 87 | { 88 | return $this->getParameter('noLanguageMenu'); 89 | } 90 | 91 | public function setNoLanguageMenu($value) 92 | { 93 | return $this->setParameter('noLanguageMenu', $value); 94 | } 95 | 96 | /** 97 | * If true, prevents editing of address details by user. 98 | * 99 | * @param boolean 100 | */ 101 | public function getFixContact() 102 | { 103 | return $this->getParameter('fixContact'); 104 | } 105 | 106 | public function setFixContact($value) 107 | { 108 | return $this->setParameter('fixContact', $value); 109 | } 110 | 111 | /** 112 | * If true, hides address details from user. 113 | * 114 | * @param boolean 115 | */ 116 | public function getHideContact() 117 | { 118 | return $this->getParameter('hideContact'); 119 | } 120 | 121 | public function setHideContact($value) 122 | { 123 | return $this->setParameter('hideContact', $value); 124 | } 125 | 126 | /** 127 | * If true, hides currency options from user. 128 | * 129 | * @param boolean 130 | */ 131 | public function getHideCurrency() 132 | { 133 | return $this->getParameter('hideCurrency'); 134 | } 135 | 136 | public function setHideCurrency($value) 137 | { 138 | return $this->setParameter('hideCurrency', $value); 139 | } 140 | 141 | public function getData() 142 | { 143 | $this->validate('amount'); 144 | 145 | // Either the nodifyUrl or the returnUrl can be provided. 146 | // The returnUrl is deprecated, as strictly this is a notifyUrl. 147 | if (!$this->getNotifyUrl()) { 148 | $this->validate('returnUrl'); 149 | } 150 | 151 | $data = array(); 152 | $data['instId'] = $this->getInstallationId(); 153 | $data['accId1'] = $this->getAccountId(); 154 | $data['cartId'] = $this->getTransactionId(); 155 | $data['desc'] = $this->getDescription(); 156 | $data['amount'] = $this->getAmount(); 157 | $data['currency'] = $this->getCurrency(); 158 | $data['testMode'] = $this->getTestMode() ? 100 : 0; 159 | $data['MC_callback'] = $this->getNotifyUrl() ?: $this->getReturnUrl(); 160 | $data['MC_returnurl'] = $this->getReturnUrl(); 161 | $data['paymentType'] = $this -> getPaymentType(); 162 | $data['noLanguageMenu'] = $this -> getNoLanguageMenu(); 163 | $data['fixContact'] = $this -> getFixContact(); 164 | $data['hideContact'] = $this -> getHideContact(); 165 | $data['hideCurrency'] = $this -> getHideCurrency(); 166 | 167 | if ($this->getCard()) { 168 | $data['name'] = $this->getCard()->getName(); 169 | $data['address1'] = $this->getCard()->getAddress1(); 170 | $data['address2'] = $this->getCard()->getAddress2(); 171 | $data['town'] = $this->getCard()->getCity(); 172 | $data['region'] = $this->getCard()->getState(); 173 | $data['postcode'] = $this->getCard()->getPostcode(); 174 | $data['country'] = $this->getCard()->getCountry(); 175 | $data['tel'] = $this->getCard()->getPhone(); 176 | $data['email'] = $this->getCard()->getEmail(); 177 | } 178 | 179 | if ($this->getSecretWord()) { 180 | $data['signatureFields'] = $this->getSignatureFields(); 181 | $signature_data = array($this->getSecretWord()); 182 | foreach (explode(':', $data['signatureFields']) as $parameterName) { 183 | $signature_data[] = $data[$parameterName]; 184 | } 185 | 186 | $data['signature'] = md5(implode(':', $signature_data)); 187 | } 188 | 189 | return $data; 190 | } 191 | 192 | public function sendData($data) 193 | { 194 | return $this->response = new PurchaseResponse($this, $data); 195 | } 196 | 197 | public function getEndpoint() 198 | { 199 | return $this->getTestMode() ? $this->testEndpoint : $this->liveEndpoint; 200 | } 201 | } 202 | --------------------------------------------------------------------------------