diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a282a5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/vendor +composer.lock +composer.phar +phpunit.xml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..8574752 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +language: php + +php: + - 5.3 + - 5.4 + - 5.5 + - 5.6 + - 7.0 + - hhvm + +before_script: + - composer install -n --dev --prefer-source + +script: vendor/bin/phpcs --standard=PSR2 -n src && vendor/bin/phpunit --coverage-text diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..d67ed30 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,10 @@ +# Contributing Guidelines + +* Fork the project. +* Make your feature addition or bug fix. +* Add tests for it. This is important so I don't break it in a future version unintentionally. +* Commit just the modifications, do not mess with the composer.json or CHANGELOG.md files. +* 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) + style and that all tests pass. +* Send the pull request. +* Check that the Travis CI build passed. If not, rinse and repeat. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ec909c9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Lee Siong Chan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index dffd755..ad25d7a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,62 @@ -# omnipay-molpay -MOLPay driver for the Omnipay PHP payment processing library +# Omnipay: MOLPay + +**MOLPay driver for the Omnipay PHP payment processing library** + +[![Build Status](https://travis-ci.org/leesiongchan/omnipay-molpay.png?branch=master)](https://travis-ci.org/leesiongchan/omnipay-molpay) +[![Latest Stable Version](https://poser.pugx.org/leesiongchan/omnipay-molpay/v/stable)](https://packagist.org/packages/leesiongchan/omnipay-molpay) +[![Total Downloads](https://poser.pugx.org/leesiongchan/omnipay-molpay/downloads)](https://packagist.org/packages/leesiongchan/omnipay-molpay) +[![Latest Unstable Version](https://poser.pugx.org/leesiongchan/omnipay-molpay/v/unstable)](https://packagist.org/packages/leesiongchan/omnipay-molpay) +[![License](https://poser.pugx.org/leesiongchan/omnipay-molpay/license)](https://packagist.org/packages/leesiongchan/omnipay-molpay) + +[Omnipay](https://github.com/thephpleague/omnipay) is a framework agnostic, multi-gateway payment +processing library for PHP 5.3+. This package implements MOLPay support for Omnipay. + +[MOLPay](http://www.molpay.com) is a payment gateway offering from MOLPay Sdn Bhd. This package follows the **MOLPay API Specification (Version 12.1: Updated on 12 April 2015)**. + +## Installation + +Omnipay is installed via [Composer](http://getcomposer.org/). To install, simply add it +to your `composer.json` file: + +```json +{ + "require": { + "leesiongchan/omnipay-molpay": "~2.0" + } +} +``` + +And run composer to update your dependencies: + + $ curl -s http://getcomposer.org/installer | php + $ php composer.phar update + +## Basic Usage + +The following gateways are provided by this package: + +* MOLPay (MOLPay Payment) + +For general usage instructions, please see the main [Omnipay](https://github.com/thephpleague/omnipay) +repository. + +## Usage + +Coming soon... + +## Out Of Scope + +Omnipay does not cover recurring payments or billing agreements, and so those features are not included in this package. Extensions to this gateway are always welcome. + +## Support + +If you are having general issues with Omnipay, we suggest posting on +[Stack Overflow](http://stackoverflow.com/). Be sure to add the +[omnipay tag](http://stackoverflow.com/questions/tagged/omnipay) so it can be easily found. + +If you want to keep up to date with release anouncements, discuss ideas for the project, +or ask more detailed questions, there is also a [mailing list](https://groups.google.com/forum/#!forum/omnipay) which +you can subscribe to. + +If you believe you have found a bug, please report it using the [GitHub issue tracker](https://github.com/leesiongchan/omnipay-molpay/issues), +or better yet, fork the library and submit a pull request. diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..c0d0009 --- /dev/null +++ b/composer.json @@ -0,0 +1,39 @@ +{ + "name": "leesiongchan/omnipay-molpay", + "type": "library", + "description": "MOLPay gateway for Omnipay payment processing library", + "keywords": [ + "gateway", + "merchant", + "molpay", + "omnipay", + "pay", + "payment", + "purchase" + ], + "homepage": "https://github.com/leesiongchan/omnipay-molpay", + "license": "MIT", + "authors": [ + { + "name": "Lee Siong Chan", + "email": "ahlee2326@me.com" + } + ], + "autoload": { + "psr-4": { "Omnipay\\MOLPay\\" : "src/" } + }, + "autoload-dev": { + "psr-4": { "Omnipay\\MOLPay\\Tests\\": "tests/" } + }, + "require": { + "omnipay/common": "~2.0" + }, + "require-dev": { + "omnipay/tests": "~2.0" + }, + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..a35b736 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,25 @@ + + + + + ./tests/ + + + + + + + + ./src + + + diff --git a/src/Exception/InvalidCreditCardDetailsException.php b/src/Exception/InvalidCreditCardDetailsException.php new file mode 100644 index 0000000..d6a1d24 --- /dev/null +++ b/src/Exception/InvalidCreditCardDetailsException.php @@ -0,0 +1,14 @@ + false, + 'locale' => 'en', + 'testMode' => false, + ); + } + + /** + * Get enableIPN. + * + * @return bool + */ + public function getEnableIPN() + { + return $this->getParameter('enableIPN'); + } + + /** + * Set enableIPN. + * + * @param bool $value + * + * @return $this + */ + public function setEnableIPN($value) + { + return $this->setParameter('enableIPN', $value); + } + + /** + * Get the locale. + * + * The default language is English. + * + * @return string + */ + public function getLocale() + { + return $this->getParameter('locale'); + } + + /** + * Set the locale. + * + * The default language is English. + * + * @param string $value + * + * @return $this + */ + public function setLocale($value) + { + return $this->setParameter('locale', $value); + } + + /** + * Get merchantId. + * + * @return string + */ + public function getMerchantId() + { + return $this->getParameter('merchantId'); + } + + /** + * Set merchantId. + * + * @param string $value + * + * @return $this + */ + public function setMerchantId($value) + { + return $this->setParameter('merchantId', $value); + } + + /** + * Get verifyKey. + * + * @return string + */ + public function getVerifyKey() + { + return $this->getParameter('verifyKey'); + } + + /** + * Set verifyKey. + * + * @param string $value + * + * @return $this + */ + public function setVerifyKey($value) + { + return $this->setParameter('verifyKey', $value); + } + + /** + * Create a purchase request. + * + * @param array $parameters + * + * @return \Omnipay\MOLPay\Message\PurchaseRequest + */ + public function purchase(array $parameters = array()) + { + return $this->createRequest('\Omnipay\MOLPay\Message\PurchaseRequest', $parameters); + } + + /** + * Complete a purchase request. + * + * @param array $parameters + * + * @return \Omnipay\MOLPay\Message\CompletePurchaseRequest + */ + public function completePurchase(array $parameters = array()) + { + return $this->createRequest( + '\Omnipay\MOLPay\Message\CompletePurchaseRequest', + array_merge( + $parameters, + array( + 'appCode' => $this->httpRequest->request->get('appcode'), + 'domain' => $this->httpRequest->request->get('domain'), + 'errorMessage' => $this->httpRequest->request->get('error_desc'), + 'nbcb' => $this->httpRequest->request->get('nbcb'), + 'payDate' => $this->httpRequest->request->get('paydate'), + 'sKey' => $this->httpRequest->request->get('skey'), + 'status' => $this->httpRequest->request->get('status'), + 'transactionReference' => $this->httpRequest->request->get('tranID'), + ) + ) + ); + } +} diff --git a/src/Message/AbstractRequest.php b/src/Message/AbstractRequest.php new file mode 100644 index 0000000..c301798 --- /dev/null +++ b/src/Message/AbstractRequest.php @@ -0,0 +1,193 @@ +getParameter('enableIPN'); + } + + /** + * Set enableIPN. + * + * @param bool $value + * + * @return $this + */ + public function setEnableIPN($value) + { + return $this->setParameter('enableIPN', $value); + } + + /** + * Get locale. + * + * @return string + */ + public function getLocale() + { + return $this->getParameter('locale'); + } + + /** + * Set locale. + * + * @param string $value + * + * @return $this + */ + public function setLocale($value) + { + return $this->setParameter('locale', $value); + } + + /** + * Get merchantId. + * + * @return string + */ + public function getMerchantId() + { + return $this->getParameter('merchantId'); + } + + /** + * Set merchantId. + * + * @param string $value + * + * @return $this + */ + public function setMerchantId($value) + { + return $this->setParameter('merchantId', $value); + } + + /** + * Get verifyKey. + * + * @return string + */ + public function getVerifyKey() + { + return $this->getParameter('verifyKey'); + } + + /** + * Set verifyKey. + * + * @param string $value + * + * @return $this + */ + public function setVerifyKey($value) + { + return $this->setParameter('verifyKey', $value); + } + + /** + * Get endpoint. + * + * @return string + */ + public function getEndpoint() + { + $this->validate('merchantId'); + + return $this->endpoint.$this->getMerchantId().'/'; + } + + /** + * Send IPN (Instant Payment Notification). + */ + protected function sendIPN() + { + $data = $this->httpRequest->request->all(); + + $data['treq'] = 1; // Additional parameter required by IPN + + $this->httpClient->post($this->IPNEndpoint, null, $data)->send(); + } + + /** + * Validate credit card details: + * - country + * - email + * - name + * - phone. + */ + protected function validateCreditCardDetails() + { + $this->validate('card'); + + $card = $this->getCard(); + + foreach (array('country', 'email', 'name', 'phone') as $key) { + $method = 'get'.ucfirst(Helper::camelCase($key)); + + if (null === $card->$method()) { + throw new InvalidCreditCardDetailsException("The $key parameter is required"); + } + } + } + + /** + * Validate payment method: + * - Affin Bank + * - AmOnline + * - CIMB Clicks + * - Credit Card + * - FPX + * - Hong Leong Connect + * - Maybank2u + * - RHB Now. + */ + protected function validatePaymentMethod() + { + $this->validate('paymentMethod'); + + $paymentMethod = $this->getPaymentMethod(); + + if ( + PaymentMethod::AFFIN_BANK !== $paymentMethod && + PaymentMethod::AM_ONLINE !== $paymentMethod && + PaymentMethod::CIMB_CLICKS !== $paymentMethod && + PaymentMethod::CREDIT_CARD !== $paymentMethod && + PaymentMethod::FPX !== $paymentMethod && + PaymentMethod::HONG_LEONG_CONNECT !== $paymentMethod && + PaymentMethod::MAYBANK2U !== $paymentMethod && + PaymentMethod::RHB_NOW !== $paymentMethod + ) { + throw new InvalidPaymentMethodException("The payment method ($paymentMethod) is not supported"); + } + } +} diff --git a/src/Message/CompletePurchaseRequest.php b/src/Message/CompletePurchaseRequest.php new file mode 100644 index 0000000..3f93439 --- /dev/null +++ b/src/Message/CompletePurchaseRequest.php @@ -0,0 +1,270 @@ +getParameter('appCode'); + } + + /** + * Set appCode. + * + * @param string $value + * + * @return $this + */ + public function setAppCode($value) + { + return $this->setParameter('appCode', $value); + } + + /** + * Get domain. + * + * @return string + */ + public function getDomain() + { + return $this->getParameter('domain'); + } + + /** + * Set domain. + * + * @param string $value + * + * @return $this + */ + public function setDomain($value) + { + return $this->setParameter('domain', $value); + } + + /** + * Get errorMessage. + * + * @return string + */ + public function getErrorMessage() + { + return $this->getParameter('errorMessage'); + } + + /** + * Set errorMessage. + * + * @param string $value + * + * @return $this + */ + public function setErrorMessage($value) + { + return $this->setParameter('errorMessage', $value); + } + + /** + * Get payDate. + * + * @return string + */ + public function getPayDate() + { + return $this->getParameter('payDate'); + } + + /** + * Set payDate. + * + * @param string $value + * + * @return $this + */ + public function setPayDate($value) + { + return $this->setParameter('payDate', $value); + } + + /** + * Get nbcb. + * + * @return string + */ + public function getNBCB() + { + return $this->getParameter('nbcb'); + } + + /** + * Set nbcb. + * + * @param string $value + * + * @return $this + */ + public function setNBCB($value) + { + return $this->setParameter('nbcb', $value); + } + + /** + * Get sKey. + * + * @return string + */ + public function getSKey() + { + return $this->getParameter('sKey'); + } + + /** + * Set sKey. + * + * @param string $value + * + * @return $this + */ + public function setSKey($value) + { + return $this->setParameter('sKey', $value); + } + + /** + * Get status. + * + * @return string + */ + public function getStatus() + { + return $this->getParameter('status'); + } + + /** + * Set status. + * + * @param string $value + * + * @return $this + */ + public function setStatus($value) + { + return $this->setParameter('status', $value); + } + + /** + * Get transactionReference. + * + * @return string + */ + public function getTransactionReference() + { + return $this->getParameter('transactionReference'); + } + + /** + * Set transactionReference. + * + * @param string $value + * + * @return $this + */ + public function setTransactionReference($value) + { + return $this->setParameter('transactionReference', $value); + } + + /** + * {@inheritdoc} + */ + public function getData() + { + if (null !== $this->getErrorMessage()) { + throw new InvalidResponseException($this->getErrorMessage()); + } + + $this->validate('sKey'); + + $sKey = $this->getSKey(); // Security key generated by MOLPay + + $generatedSKey = $this->generateSKey(); // Security key generated by merchant + + if ($sKey != $generatedSKey) { + throw new InvalidResponseException('Invalid security key'); + } + + return array( + 'nbcb' => $this->getNBCB(), + 'status' => $this->getStatus(), + 'transactionId' => $this->getTransactionId(), + 'transactionReference' => $this->getTransactionReference(), + ); + } + + /** + * {@inheritdoc} + */ + public function sendData($data) + { + // Acknowledge MOLPay via IPN + if (true === $this->getEnableIPN()) { + $this->sendIPN(); + } + + return $this->response = new CompletePurchaseResponse($this, $data); + } + + /** + * Generate pre-sKey - first hash encryption. + * + * @return string + */ + protected function generatePreSKey() + { + $this->validate('amount', 'currency', 'domain', 'status', 'transactionId', 'transactionReference'); + + return md5($this->getTransactionReference().$this->getTransactionId().$this->getStatus().$this->getDomain().$this->getAmount().$this->getCurrency()); + } + + /** + * Generate sKey - final hash encryption. + * + * @return string + */ + protected function generateSKey() + { + $this->validate('appCode', 'domain', 'payDate', 'verifyKey'); + + return md5($this->getPayDate().$this->getDomain().$this->generatePreSKey().$this->getAppCode().$this->getVerifyKey()); + } +} diff --git a/src/Message/CompletePurchaseResponse.php b/src/Message/CompletePurchaseResponse.php new file mode 100644 index 0000000..9b7ad35 --- /dev/null +++ b/src/Message/CompletePurchaseResponse.php @@ -0,0 +1,68 @@ +getRequest()->getMessage(); + } + + /** + * {@inheritdoc} + */ + public function getTransactionId() + { + return $this->getRequest()->getTransactionId(); + } + + /** + * {@inheritdoc} + */ + public function getTransactionReference() + { + return $this->getRequest()->getTransactionReference(); + } + + /** + * Check if the request is a callback notification. + * + * @return bool + */ + public function isCallbackNotification() + { + return '1' === $this->getRequest()->getNBCB(); + } + + /** + * {@inheritdoc} + */ + public function isCancelled() + { + return '11' === $this->getRequest()->getStatus(); + } + + /** + * {@inheritdoc} + */ + public function isPending() + { + return '22' === $this->getRequest()->getStatus(); + } + + /** + * {@inheritdoc} + */ + public function isSuccessful() + { + return '00' === $this->getRequest()->getStatus(); + } +} diff --git a/src/Message/PurchaseRequest.php b/src/Message/PurchaseRequest.php new file mode 100644 index 0000000..b062287 --- /dev/null +++ b/src/Message/PurchaseRequest.php @@ -0,0 +1,67 @@ +validate('amount', 'card', 'description', 'merchantId', 'transactionId', 'verifyKey'); + $this->validateCreditCardDetails(); + + if ($this->getPaymentMethod()) { + $this->validatePaymentMethod(); + } + + $card = $this->getCard(); + + return array( + 'amount' => $this->getAmount(), + 'bill_desc' => $this->getDescription(), + 'bill_email' => $card->getEmail(), + 'bill_mobile' => $card->getPhone(), + 'bill_name' => $card->getName(), + 'channel' => $this->getPaymentMethod(), + 'country' => $card->getCountry(), + 'currency' => $this->getCurrency(), + 'langcode' => $this->getLocale(), + 'orderid' => $this->getTransactionId(), + 'vcode' => $this->generateVCode(), + ); + } + + /** + * {@inheritdoc} + */ + public function sendData($data) + { + return $this->response = new PurchaseResponse($this, $data); + } + + /** + * Generate vCode. + * + * @return string + */ + protected function generateVCode() + { + $this->validate('amount', 'merchantId', 'transactionId', 'verifyKey'); + + return md5($this->getAmount().$this->getMerchantId().$this->getTransactionId().$this->getVerifyKey()); + } +} diff --git a/src/Message/PurchaseResponse.php b/src/Message/PurchaseResponse.php new file mode 100644 index 0000000..38315af --- /dev/null +++ b/src/Message/PurchaseResponse.php @@ -0,0 +1,49 @@ +getRequest()->getEndpoint().'?'.http_build_query($this->data); + } + + /** + * {@inheritdoc} + */ + public function isRedirect() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function isSuccessful() + { + return false; + } +} diff --git a/src/PaymentMethod.php b/src/PaymentMethod.php new file mode 100644 index 0000000..5a523ae --- /dev/null +++ b/src/PaymentMethod.php @@ -0,0 +1,18 @@ +gateway = new Gateway($this->getHttpClient(), $this->getHttpRequest()); + + $this->gateway->setCurrency('MYR'); + $this->gateway->setLocale('en'); + $this->gateway->setMerchantId('test1234'); + $this->gateway->setVerifyKey('abcdefg'); + + $this->options = array( + 'amount' => '10.00', + 'card' => new CreditCard(array( + 'country' => 'MY', + 'email' => 'ahlee2326@me.com', + 'name' => 'Lee Siong Chan', + 'phone' => '0123456789', + )), + 'description' => 'Test Payment', + 'transactionId' => '20160331082207680000', + 'paymentMethod' => 'credit', + 'returnUrl' => 'https://example.com/return', + 'notifyUrl' => 'https://example.com/notify', + ); + } + + public function testPurchase() + { + $response = $this->gateway->purchase($this->options)->send(); + + $this->assertFalse($response->isSuccessful()); + $this->assertTrue($response->isRedirect()); + $this->assertNull($response->getTransactionReference()); + $this->assertEquals( + 'https://www.onlinepayment.com.my/MOLPay/pay/test1234/?amount=10.00&bill_desc=Test+Payment&bill_email=ahlee2326%40me.com&bill_mobile=0123456789&bill_name=Lee+Siong+Chan&channel=credit&country=MY¤cy=MYR&langcode=en&orderid=20160331082207680000&vcode=f3d5496b444ae3d11e09fa92a753ac60', + $response->getRedirectUrl() + ); + } + + public function testCompletePurchaseSuccess() + { + $this->getHttpRequest()->request->replace(array( + 'appcode' => 'abcdefg', + 'domain' => 'test4321', + 'paydate' => '2016-03-29 04:02:21', + 'skey' => '0c1e98d6d58f9a30b919bcaeb9790852', + 'status' => '00', + 'tranID' => '000001', + )); + + $response = $this->gateway->completePurchase($this->options)->send(); + + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidResponseException + */ + public function testCompletePurchaseInvalidSKey() + { + $this->getHttpRequest()->request->replace(array( + 'appcode' => 'abcdefg', + 'domain' => 'test4321', + 'paydate' => '2016-03-29 04:02:21', + 'skey' => 'I_AM_INVALID_SKEY', + 'status' => '11', + 'tranID' => '000001', + )); + + $response = $this->gateway->completePurchase($this->options)->send(); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidResponseException + */ + public function testCompletePurchaseError() + { + $this->getHttpRequest()->request->replace(array( + 'appcode' => 'abcdefg', + 'domain' => 'test4321', + 'paydate' => 'I am not a date', + 'skey' => 'ef0903d1906d0968605155f85ec9fcd5', + 'status' => '11', + 'error_desc' => 'Invalid date', + 'tranID' => '000001', + )); + + $response = $this->gateway->completePurchase($this->options)->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertNull($response->getTransactionReference()); + $this->assertEquals('Invalid date', $response->getMessage()); + } +} diff --git a/tests/Message/CompletePurchaseRequestTest.php b/tests/Message/CompletePurchaseRequestTest.php new file mode 100644 index 0000000..7876a1c --- /dev/null +++ b/tests/Message/CompletePurchaseRequestTest.php @@ -0,0 +1,76 @@ +request = new CompletePurchaseRequest($this->getHttpClient(), $this->getHttpRequest()); + + $this->request->initialize(array( + 'amount' => '10.00', + 'appCode' => 'abcdefg', + 'currency' => 'MYR', + 'domain' => 'test4321', + 'payDate' => '2016-03-29 04:02:21', + 'sKey' => '0c1e98d6d58f9a30b919bcaeb9790852', + 'status' => '00', + 'transactionId' => '20160331082207680000', + 'transactionReference' => '000001', + 'verifyKey' => 'abcdefg', + )); + } + + public function testGetData() + { + $data = $this->request->getData(); + + $this->assertEquals('00', $data['status']); + $this->assertEquals('000001', $data['transactionReference']); + } + + public function testSendSuccess() + { + $this->request->setStatus('00'); + $this->request->setSKey('0c1e98d6d58f9a30b919bcaeb9790852'); + + $response = $this->request->send(); + + $this->assertEquals('000001', $response->getTransactionReference()); + $this->assertFalse($response->isCancelled()); + $this->assertFalse($response->isPending()); + $this->assertFalse($response->isRedirect()); + $this->assertTrue($response->isSuccessful()); + } + + public function testSendCancel() + { + $this->request->setStatus('11'); + $this->request->setSKey('1298d6c091a476a8e995051eb9d66805'); + + $response = $this->request->send(); + + $this->assertEquals('000001', $response->getTransactionReference()); + $this->assertTrue($response->isCancelled()); + $this->assertFalse($response->isPending()); + $this->assertFalse($response->isRedirect()); + $this->assertFalse($response->isSuccessful()); + } + + public function testSendPending() + { + $this->request->setStatus('22'); + $this->request->setSKey('8192eb5627012f236fc36e73f5d49a5e'); + + $response = $this->request->send(); + + $this->assertEquals('000001', $response->getTransactionReference()); + $this->assertFalse($response->isCancelled()); + $this->assertTrue($response->isPending()); + $this->assertFalse($response->isRedirect()); + $this->assertFalse($response->isSuccessful()); + } +} diff --git a/tests/Message/CompletePurchaseResponseTest.php b/tests/Message/CompletePurchaseResponseTest.php new file mode 100644 index 0000000..fc14b2d --- /dev/null +++ b/tests/Message/CompletePurchaseResponseTest.php @@ -0,0 +1,45 @@ +response = new CompletePurchaseResponse($this->getMockRequest(), array()); + } + + public function testCompletePurchaseSuccess() + { + $this->getMockRequest()->shouldReceive('getStatus')->andReturn('00'); + $this->getMockRequest()->shouldReceive('getTransactionId')->andReturn('20160331082207680000'); + $this->getMockRequest()->shouldReceive('getTransactionReference')->andReturn('000001'); + + $this->assertTrue($this->response->isSuccessful()); + $this->assertEquals('20160331082207680000', $this->response->getTransactionId()); + $this->assertEquals('000001', $this->response->getTransactionReference()); + } + + public function testCompletePurchaseCancel() + { + $this->getMockRequest()->shouldReceive('getStatus')->andReturn('11'); + + $this->assertTrue($this->response->isCancelled()); + } + + public function testCompletePurchasePending() + { + $this->getMockRequest()->shouldReceive('getStatus')->andReturn('22'); + + $this->assertTrue($this->response->isPending()); + } + + public function testCompletePurchaseCallbackNotification() + { + $this->getMockRequest()->shouldReceive('getNBCB')->andReturn('1'); + + $this->assertTrue($this->response->isCallbackNotification()); + } +} diff --git a/tests/Message/PurchaseRequestTest.php b/tests/Message/PurchaseRequestTest.php new file mode 100644 index 0000000..02aba28 --- /dev/null +++ b/tests/Message/PurchaseRequestTest.php @@ -0,0 +1,61 @@ +request = new PurchaseRequest($this->getHttpClient(), $this->getHttpRequest()); + + $this->request->initialize(array( + 'amount' => '10.00', + 'card' => new CreditCard(array( + 'country' => 'MY', + 'email' => 'ahlee2326@me.com', + 'name' => 'Lee Siong Chan', + 'phone' => '0123456789', + )), + 'currency' => 'MYR', + 'description' => 'Test Payment', + 'locale' => 'en', + 'merchantId' => 'test1234', + 'paymentMethod' => 'credit', + 'transactionId' => '20160331082207680000', + 'verifyKey' => 'abcdefg', + )); + } + + public function testGetData() + { + $data = $this->request->getData(); + + $this->assertEquals('10.00', $data['amount']); + $this->assertEquals('MY', $data['country']); + $this->assertEquals('ahlee2326@me.com', $data['bill_email']); + $this->assertEquals('Lee Siong Chan', $data['bill_name']); + $this->assertEquals('0123456789', $data['bill_mobile']); + $this->assertEquals('MYR', $data['currency']); + $this->assertEquals('Test Payment', $data['bill_desc']); + $this->assertEquals('en', $data['langcode']); + $this->assertEquals('credit', $data['channel']); + $this->assertEquals('20160331082207680000', $data['orderid']); + $this->assertEquals('f3d5496b444ae3d11e09fa92a753ac60', $data['vcode']); + } + + public function testSendSuccess() + { + $response = $this->request->send(); + + $this->assertFalse($response->isSuccessful()); + $this->assertTrue($response->isRedirect()); + $this->assertNull($response->getTransactionReference()); + $this->assertEquals( + 'https://www.onlinepayment.com.my/MOLPay/pay/test1234/?amount=10.00&bill_desc=Test+Payment&bill_email=ahlee2326%40me.com&bill_mobile=0123456789&bill_name=Lee+Siong+Chan&channel=credit&country=MY¤cy=MYR&langcode=en&orderid=20160331082207680000&vcode=f3d5496b444ae3d11e09fa92a753ac60', + $response->getRedirectUrl() + ); + } +} diff --git a/tests/Message/PurchaseResponseTest.php b/tests/Message/PurchaseResponseTest.php new file mode 100644 index 0000000..51562c5 --- /dev/null +++ b/tests/Message/PurchaseResponseTest.php @@ -0,0 +1,24 @@ +getMockRequest(), array( + 'amount' => 1000, + )); + + $this->getMockRequest()->shouldReceive('getEndpoint')->once()->andReturn('https://www.onlinepayment.com.my/MOLPay/pay/'); + + $this->assertFalse($response->isSuccessful()); + $this->assertTrue($response->isRedirect()); + $this->assertNull($response->getTransactionReference()); + $this->assertEquals('https://www.onlinepayment.com.my/MOLPay/pay/?amount=1000', $response->getRedirectUrl()); + $this->assertEquals('GET', $response->getRedirectMethod()); + $this->assertNull($response->getRedirectData()); + } +}