diff --git a/composer.json b/composer.json index db821e7..461fc54 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": "^7.2", + "php": "^7.0", "omnipay/common": "^3.0" }, "require-dev": { diff --git a/src/Gateway.php b/src/Gateway.php index dff28b8..7a995f1 100644 --- a/src/Gateway.php +++ b/src/Gateway.php @@ -5,7 +5,7 @@ use Omnipay\Common\AbstractGateway; use Omnipay\Paystack\Message\CompletePurchaseRequest; use Omnipay\Paystack\Message\PurchaseRequest; -use Omnipay\Paystack\Message\PurchaseResponse; +use Omnipay\Paystack\Message\RefundRequest; /** * PayStack Gateway @@ -81,4 +81,12 @@ public function completePurchase(array $parameters = []) { return $this->createRequest(CompletePurchaseRequest::class, $parameters); } + + /** + * @inheritDoc + */ + public function refund(array $parameters = []) + { + return $this->createRequest(RefundRequest::class, $parameters); + } } diff --git a/src/Message/AbstractRequest.php b/src/Message/AbstractRequest.php index 71e84fa..fbc9bec 100644 --- a/src/Message/AbstractRequest.php +++ b/src/Message/AbstractRequest.php @@ -2,12 +2,11 @@ namespace Omnipay\Paystack\Message; -use Omnipay\Common\Exception\BadMethodCallException; use Omnipay\Common\Exception\InvalidRequestException; abstract class AbstractRequest extends \Omnipay\Common\Message\AbstractRequest { - protected $baseApiEndpoint = 'https://api.paystack.co/'; + protected $baseApiEndpoint = 'https://api.paystack.co'; /** * @return string The URL endpoint for the request @@ -40,17 +39,21 @@ public function setSecretKey($value) protected function sendRequest($method, $endpoint, array $data = null) { - - $headers = [ - 'Authorization' => 'Bearer ' . $this->getSecretKey(), - 'Content-Type' => 'application/json', - 'Cache-Control' => 'no-cache' - ]; - - $response = $this->httpClient->request($method, $this->baseApiEndpoint. $endpoint, $headers, json_encode($data)); - $responseData = json_decode((string)$response->getBody(), true); - - return $responseData; - + $headers = [ + 'Authorization' => 'Bearer ' . $this->getSecretKey(), + 'Content-Type' => 'application/json', + 'Cache-Control' => 'no-cache' + ]; + + $url = $this->baseApiEndpoint . $endpoint; + $response = $this->httpClient->request( + $method, + $url, + $headers, + json_encode($data) + ); + $responseData = json_decode((string)$response->getBody(), true); + + return $responseData; } } diff --git a/src/Message/CompletePurchaseRequest.php b/src/Message/CompletePurchaseRequest.php index 4d69a3e..538acd9 100644 --- a/src/Message/CompletePurchaseRequest.php +++ b/src/Message/CompletePurchaseRequest.php @@ -11,7 +11,7 @@ class CompletePurchaseRequest extends AbstractRequest */ public function getApiEndpoint() { - return $this->baseApiEndpoint . 'transaction/verify/' . rawurlencode($this->getTransactionReference()); + return '/transaction/verify/' . rawurlencode($this->getTransactionReference()); } /** @@ -28,14 +28,11 @@ public function getData() public function sendData($data) { try { - - $response = $this->sendRequest('GET', $this->getApiEndpoint(), json_encode($data)); - + $response = $this->sendRequest('GET', $this->getApiEndpoint(), $data); } catch (\Exception $e) { - throw new InvalidRequestException($e->getMessage(), $e->getCode(), $e); } - return $this->response = new CompletePurchaseResponse($this, $responseData); + return $this->response = new CompletePurchaseResponse($this, $response); } } \ No newline at end of file diff --git a/src/Message/CompletePurchaseResponse.php b/src/Message/CompletePurchaseResponse.php index b0a4aad..a846bdd 100644 --- a/src/Message/CompletePurchaseResponse.php +++ b/src/Message/CompletePurchaseResponse.php @@ -2,7 +2,9 @@ namespace Omnipay\Paystack\Message; -class CompletePurchaseResponse extends \Omnipay\Common\Message\AbstractResponse +use Omnipay\Common\Message\AbstractResponse; + +class CompletePurchaseResponse extends AbstractResponse { public function isSuccessful() diff --git a/src/Message/PurchaseRequest.php b/src/Message/PurchaseRequest.php index c83b45d..70d9712 100644 --- a/src/Message/PurchaseRequest.php +++ b/src/Message/PurchaseRequest.php @@ -11,7 +11,7 @@ class PurchaseRequest extends AbstractRequest */ public function getApiEndpoint() { - return $this->baseApiEndpoint . '/transaction/initialize/'; + return '/transaction/initialize'; } /** @@ -23,13 +23,14 @@ public function getData() $amount = $this->getAmountInteger(); $email = $this->getParameter('email'); - $reference = $this->getTransactionReference(); return [ 'amount' => $amount, + 'currency' => $this->getCurrency(), 'email' => $email, + 'reference' => $this->getTransactionReference(), 'callback_url' => $this->getReturnUrl(), - 'reference' => $reference + 'metadata' => $this->getParameter('metadata') ]; } diff --git a/src/Message/PurchaseResponse.php b/src/Message/PurchaseResponse.php index d89a052..6ff11b3 100644 --- a/src/Message/PurchaseResponse.php +++ b/src/Message/PurchaseResponse.php @@ -7,7 +7,6 @@ class PurchaseResponse extends AbstractResponse implements RedirectResponseInterface { - public function isSuccessful() { return false; diff --git a/src/Message/RefundRequest.php b/src/Message/RefundRequest.php new file mode 100644 index 0000000..82c458e --- /dev/null +++ b/src/Message/RefundRequest.php @@ -0,0 +1,46 @@ +<?php + +namespace Omnipay\Paystack\Message; + +use Omnipay\Common\Exception\InvalidRequestException; + +class RefundRequest extends AbstractRequest +{ + /** + * @inheritDoc + */ + public function getApiEndpoint() + { + return '/refund'; + } + + /** + * @inheritdoc + */ + public function getData() + { + $data = []; + $data['transaction'] = $this->getTransactionReference(); + $data['currency'] = $this->getCurrency(); + + if ($this->getAmountInteger()) { + $data['amount'] = $this->getAmountInteger(); + } + + return $data; + } + + /** + * @inheritdoc + */ + public function sendData($data) + { + try { + $response = $this->sendRequest('POST', $this->getApiEndpoint(), $data); + } catch (\Exception $e) { + throw new InvalidRequestException($e->getMessage(), $e->getCode(), $e); + } + + return $this->response = new RefundResponse($this, $response); + } +} diff --git a/src/Message/RefundResponse.php b/src/Message/RefundResponse.php new file mode 100644 index 0000000..7c95480 --- /dev/null +++ b/src/Message/RefundResponse.php @@ -0,0 +1,55 @@ +<?php + +namespace Omnipay\Paystack\Message; + +use Omnipay\Common\Message\AbstractResponse; + +class RefundResponse extends AbstractResponse +{ + + public function isSuccessful() + { + + if (isset($this->data['data']) && $transaction = $this->data['data']['transaction']) { + if (isset($transaction['status']) && $transaction['status'] == 'reversed') { + return true; + } + } + + return false; + } + + public function isRedirect() + { + return false; + } + + public function getMessage() + { + if (isset($this->data['message']) && $message = $this->data['message']) { + return $message; + } + + return ''; + } + + public function getCode() + { + if (isset($this->data['data']) && $data = $this->data['data']) { + return $data['access_code']; + } + + return ''; + } + + public function getTransactionReference() + { + if (isset($this->data['data']) && $data = $this->data['data']) { + if (isset($data['transaction']) && $transaction = $data['transaction']) { + return $transaction['reference']; + } + } + + return ''; + } +} diff --git a/tests/GatewayTest.php b/tests/GatewayTest.php index 365f356..4ed4dc4 100644 --- a/tests/GatewayTest.php +++ b/tests/GatewayTest.php @@ -13,6 +13,12 @@ class GatewayTest extends GatewayTestCase /** @var Gateway */ protected $gateway; + /** @var array */ + protected $options; + + /** + * + */ public function setUp() { parent::setUp(); @@ -20,27 +26,36 @@ public function setUp() $this->gateway = new Gateway($this->getHttpClient(), $this->getHttpRequest()); $this->options = [ - 'amount' => '100', + 'amount' => '2500', 'reference' => static::PURCHASE_REFERENCE ]; } + /** + * + */ public function testPurchase() { $this->setMockHttpResponse('PurchaseSuccess.txt'); $options = array_merge($this->options, [ - 'email' => 'email@email.com', - 'reference' => static::PURCHASE_REFERENCE + 'email' => 'email@email.com' ]); $response = $this->gateway->purchase($options)->send(); $this->assertTrue($response->isRedirect(), 'Purchase response is a redirect'); - $this->assertEquals(static::PURCHASE_REFERENCE, $response->getTransactionReference(), 'Reference is as we gave it.'); + $this->assertEquals( + static::PURCHASE_REFERENCE, + $response->getTransactionReference(), + 'Reference is as we gave it.' + ); $this->assertEquals('Authorization URL created', $response->getMessage()); } + /** + * + */ public function testRefund() { $this->setMockHttpResponse('RefundSuccess.txt');