From 7a9e51f2c9e670e90f9a1d54a96dcf5aa1ae2997 Mon Sep 17 00:00:00 2001 From: Madan Sapkota Date: Sat, 24 Aug 2024 17:35:10 +0545 Subject: [PATCH 01/10] Create interface for config --- src/ConfigInterface.php | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/ConfigInterface.php diff --git a/src/ConfigInterface.php b/src/ConfigInterface.php new file mode 100644 index 0000000..f064832 --- /dev/null +++ b/src/ConfigInterface.php @@ -0,0 +1,33 @@ + Date: Sat, 24 Aug 2024 17:35:36 +0545 Subject: [PATCH 02/10] Upgrade config getter and setter --- src/Config.php | 69 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/src/Config.php b/src/Config.php index ea45e05..15f3596 100644 --- a/src/Config.php +++ b/src/Config.php @@ -4,18 +4,79 @@ namespace RemoteMerge\Esewa; -class Config +class Config implements ConfigInterface { + /** + * The merchant code provided by eSewa + */ + private string $merchantCode = 'EPAYTEST'; + /** * The API url for development mode */ - public string $apiUrl = 'https://uat.esewa.com.np'; + private string $apiUrl = 'https://uat.esewa.com.np'; + + /** + * The URL to redirect after successful payment + */ + private string $successUrl = ''; + + /** + * The URL to redirect after failed payment + */ + private string $failureUrl = ''; - public function __construct(public string $successUrl, public string $failureUrl, public string $merchantCode = 'EPAYTEST') + public function __construct(private readonly array $configs = []) { - if ($merchantCode !== 'EPAYTEST') { + // Update the configuration + $this->merchantCode = $this->configs['merchantCode'] ?? $this->merchantCode; + $this->successUrl = $this->configs['successUrl'] ?? $this->successUrl; + $this->failureUrl = $this->configs['failureUrl'] ?? $this->failureUrl; + + // Set the API URL + $this->setApiUrl(); + } + + /** + * Set the API URL based on the merchant code + */ + private function setApiUrl(): void + { + if ($this->getMerchantCode() !== 'EPAYTEST') { // set API URL for production $this->apiUrl = 'https://esewa.com.np'; } } + + /** + * Get the merchant code + */ + public function getMerchantCode(): string + { + return $this->merchantCode; + } + + /** + * Get the API URL + */ + public function getApiUrl(): string + { + return $this->apiUrl; + } + + /** + * Get the URL to redirect after successful payment + */ + public function getSuccessUrl(): string + { + return $this->successUrl; + } + + /** + * Get the URL to redirect after failed payment + */ + public function getFailureUrl(): string + { + return $this->failureUrl; + } } From 6c17ae52c74b72369ede63f3754d91c618461901 Mon Sep 17 00:00:00 2001 From: Madan Sapkota Date: Sat, 24 Aug 2024 17:43:11 +0545 Subject: [PATCH 03/10] Create interface for client --- src/ClientInterface.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/ClientInterface.php diff --git a/src/ClientInterface.php b/src/ClientInterface.php new file mode 100644 index 0000000..f531b82 --- /dev/null +++ b/src/ClientInterface.php @@ -0,0 +1,23 @@ + Date: Sat, 24 Aug 2024 17:43:34 +0545 Subject: [PATCH 04/10] Use config and interface --- src/Client.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Client.php b/src/Client.php index 8741c55..00d895d 100644 --- a/src/Client.php +++ b/src/Client.php @@ -6,23 +6,23 @@ use Exception; -class Client +class Client extends Config implements ClientInterface { - public function __construct(private readonly Config $config) + public function __construct(private readonly array $configs = []) { - // + parent::__construct($this->configs); } /** * This method creates the form in runtime and post the data to eSewa server. */ - public function process(string $productId, float $amount, float $taxAmount, float $serviceAmount = 0.0, float $deliveryAmount = 0.0): void + public function payment(string $productId, float $amount, float $taxAmount, float $serviceAmount = 0.0, float $deliveryAmount = 0.0): void { // format form attributes $formInputs = [ - 'scd' => $this->config->merchantCode, - 'su' => $this->config->successUrl, - 'fu' => $this->config->failureUrl . '?' . http_build_query(['pid' => $productId]), + 'scd' => $this->getMerchantCode(), + 'su' => $this->getSuccessUrl(), + 'fu' => $this->getFailureUrl() . '?' . http_build_query(['pid' => $productId]), 'pid' => $productId, 'amt' => $amount, 'txAmt' => $taxAmount, @@ -32,7 +32,7 @@ public function process(string $productId, float $amount, float $taxAmount, floa ]; // generate form from attributes - $htmlForm = '
'; + $htmlForm = ''; foreach ($formInputs as $name => $value): $htmlForm .= sprintf('', $name, $value); @@ -48,13 +48,13 @@ public function process(string $productId, float $amount, float $taxAmount, floa * This method verifies the payment using the reference ID. * @throws Exception */ - public function verify(string $referenceId, string $productId, float $amount): bool + public function verifyPayment(string $referenceId, string $productId, float $amount): bool { // Initialize a cURL handle $ch = curl_init(); // Set cURL options - curl_setopt($ch, CURLOPT_URL, $this->config->apiUrl . '/epay/transrec'); + curl_setopt($ch, CURLOPT_URL, $this->getApiUrl() . '/epay/transrec'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); @@ -71,7 +71,7 @@ public function verify(string $referenceId, string $productId, float $amount): b // Set the request data curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ - 'scd' => $this->config->merchantCode, + 'scd' => $this->getMerchantCode(), 'rid' => $referenceId, 'pid' => $productId, 'amt' => $amount, From 8462e7842333b649763b6d2f9b066fbeb318c7b1 Mon Sep 17 00:00:00 2001 From: Madan Sapkota Date: Sat, 24 Aug 2024 17:44:56 +0545 Subject: [PATCH 05/10] Update attributes --- src/Config.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Config.php b/src/Config.php index 15f3596..133660e 100644 --- a/src/Config.php +++ b/src/Config.php @@ -29,9 +29,9 @@ class Config implements ConfigInterface public function __construct(private readonly array $configs = []) { // Update the configuration - $this->merchantCode = $this->configs['merchantCode'] ?? $this->merchantCode; - $this->successUrl = $this->configs['successUrl'] ?? $this->successUrl; - $this->failureUrl = $this->configs['failureUrl'] ?? $this->failureUrl; + $this->merchantCode = $this->configs['merchant_code'] ?? $this->merchantCode; + $this->successUrl = $this->configs['success_url'] ?? $this->successUrl; + $this->failureUrl = $this->configs['failure_url'] ?? $this->failureUrl; // Set the API URL $this->setApiUrl(); From f2fa85f1adfa18671f141536df748d552032abee Mon Sep 17 00:00:00 2001 From: Madan Sapkota Date: Sat, 24 Aug 2024 17:48:50 +0545 Subject: [PATCH 06/10] Update API on demo files --- demo/process.php | 12 +++++++----- demo/success.php | 10 ++++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/demo/process.php b/demo/process.php index f3d386b..680e897 100644 --- a/demo/process.php +++ b/demo/process.php @@ -3,7 +3,6 @@ declare(strict_types=1); use RemoteMerge\Esewa\Client; -use RemoteMerge\Esewa\Config; // Init the autoloader require dirname(__DIR__) . '/vendor/autoload.php'; @@ -11,13 +10,16 @@ // Set up the configuration object $successUrl = 'http://localhost:8090/demo/success.php'; $failureUrl = 'http://localhost:8090/demo/failed.php'; -$config = new Config($successUrl, $failureUrl); -// Initialize the client -$esewa = new Client($config); +// Initialize the client with the configuration +$esewa = new Client([ + 'merchant_code' => 'EPAYTEST', + 'success_url' => $successUrl, + 'failure_url' => $failureUrl, +]); // Generate random 16 characters product ID $productId = substr(bin2hex(random_bytes(8)), 0, 16); // Process the payment -$esewa->process($productId, 100, 10); +$esewa->payment($productId, 100, 10); diff --git a/demo/success.php b/demo/success.php index d7ae5fc..62258b2 100644 --- a/demo/success.php +++ b/demo/success.php @@ -3,7 +3,6 @@ declare(strict_types=1); use RemoteMerge\Esewa\Client; -use RemoteMerge\Esewa\Config; // Require the autoloader require dirname(__DIR__) . '/vendor/autoload.php'; @@ -11,10 +10,13 @@ // Set up the configuration object $successUrl = 'http://localhost:8090/demo/success.php'; $failureUrl = 'http://localhost:8090/demo/failed.php'; -$config = new Config($successUrl, $failureUrl); // Initialize the client -$esewa = new Client($config); +$esewa = new Client([ + 'merchant_code' => 'EPAYTEST', + 'success_url' => $successUrl, + 'failure_url' => $failureUrl, +]); // Get the query parameters $productId = $_GET['oid'] ?? null; @@ -23,7 +25,7 @@ try { // Verify the payment and output the result - $status = $esewa->verify($referenceId, $productId, (float) $amount); + $status = $esewa->verifyPayment($referenceId, $productId, (float) $amount); exit($status ? 'The payment is verified.' : 'The payment is not verified.'); } catch (Exception $exception) { exit($exception->getMessage()); From 71628cdb8b3cdffb0cadbd1f66bf8ddeaa7dd658 Mon Sep 17 00:00:00 2001 From: Madan Sapkota Date: Sat, 24 Aug 2024 17:48:55 +0545 Subject: [PATCH 07/10] Update API on test files --- tests/Feature/VerificationTest.php | 4 ++-- tests/ParentTestCase.php | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/Feature/VerificationTest.php b/tests/Feature/VerificationTest.php index 354f810..d2d1383 100644 --- a/tests/Feature/VerificationTest.php +++ b/tests/Feature/VerificationTest.php @@ -14,7 +14,7 @@ final class VerificationTest extends ParentTestCase */ public function test_with_invalid_data(): void { - $response = $this->esewa->verify('Apple', 'Google', 105); + $response = $this->esewa->verifyPayment('Apple', 'Google', 105); self::assertFalse($response); } @@ -28,7 +28,7 @@ public function test_with_valid_data(): void $productId = $_ENV['ESEWA_PRODUCT_ID']; $esewaAmount = (float) $_ENV['ESEWA_PAID_AMOUNT']; - $response = $this->esewa->verify($referenceId, $productId, $esewaAmount); + $response = $this->esewa->verifyPayment($referenceId, $productId, $esewaAmount); self::assertTrue($response); } } diff --git a/tests/ParentTestCase.php b/tests/ParentTestCase.php index fbad981..8fd1789 100644 --- a/tests/ParentTestCase.php +++ b/tests/ParentTestCase.php @@ -6,7 +6,6 @@ use PHPUnit\Framework\TestCase; use RemoteMerge\Esewa\Client; -use RemoteMerge\Esewa\Config; class ParentTestCase extends TestCase { @@ -28,7 +27,10 @@ protected function setUp(): void $successUrl = self::DEMO_URL . 'success.php'; $failureUrl = self::DEMO_URL . 'failed.php'; - $config = new Config($successUrl, $failureUrl); - $this->esewa = new Client($config); + $this->esewa = new Client([ + 'merchant_code' => 'EPAYTEST', + 'success_url' => $successUrl, + 'failure_url' => $failureUrl, + ]); } } From c60aed6d3133ca3a937f95e92b0ea580f6612a96 Mon Sep 17 00:00:00 2001 From: Madan Sapkota Date: Sat, 24 Aug 2024 17:51:28 +0545 Subject: [PATCH 08/10] Replace with port 8080 --- demo/process.php | 4 ++-- demo/success.php | 4 ++-- tests/ParentTestCase.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/demo/process.php b/demo/process.php index 680e897..dee8162 100644 --- a/demo/process.php +++ b/demo/process.php @@ -8,8 +8,8 @@ require dirname(__DIR__) . '/vendor/autoload.php'; // Set up the configuration object -$successUrl = 'http://localhost:8090/demo/success.php'; -$failureUrl = 'http://localhost:8090/demo/failed.php'; +$successUrl = 'http://localhost:8080/demo/success.php'; +$failureUrl = 'http://localhost:8080/demo/failed.php'; // Initialize the client with the configuration $esewa = new Client([ diff --git a/demo/success.php b/demo/success.php index 62258b2..79b001f 100644 --- a/demo/success.php +++ b/demo/success.php @@ -8,8 +8,8 @@ require dirname(__DIR__) . '/vendor/autoload.php'; // Set up the configuration object -$successUrl = 'http://localhost:8090/demo/success.php'; -$failureUrl = 'http://localhost:8090/demo/failed.php'; +$successUrl = 'http://localhost:8080/demo/success.php'; +$failureUrl = 'http://localhost:8080/demo/failed.php'; // Initialize the client $esewa = new Client([ diff --git a/tests/ParentTestCase.php b/tests/ParentTestCase.php index 8fd1789..8fc38d9 100644 --- a/tests/ParentTestCase.php +++ b/tests/ParentTestCase.php @@ -14,7 +14,7 @@ class ParentTestCase extends TestCase /** * @var string */ - private const DEMO_URL = 'http://localhost:8090/demo/'; + private const DEMO_URL = 'http://localhost:8080/demo/'; protected function setUp(): void { From 38a29747f805581d124d751ff7b51af453825153 Mon Sep 17 00:00:00 2001 From: Madan Sapkota Date: Sat, 24 Aug 2024 17:56:06 +0545 Subject: [PATCH 09/10] Update doc for API changes --- README.md | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 7f0a8fe..b47553c 100644 --- a/README.md +++ b/README.md @@ -36,23 +36,27 @@ Bugs and feature requests are tracked using GitHub issues, and prioritization is ```php // Init composer autoloader. -require 'vendor/autoload.php'; +require dirname(__DIR__) . '/vendor/autoload.php'; use RemoteMerge\Esewa\Client; -use RemoteMerge\Esewa\Config; // Set success and failure callback URLs. $successUrl = 'https://example.com/success.php'; $failureUrl = 'https://example.com/failed.php'; -// Config for development. -$config = new Config($successUrl, $failureUrl); - -// Config for production. -$config = new Config($successUrl, $failureUrl, 'b4e...e8c753...2c6e8b'); - -// Initialize eSewa client. -$esewa = new Client($config); +// Initialize eSewa client for development. +$esewa = new Client([ + 'merchant_code' => 'EPAYTEST', + 'success_url' => $successUrl, + 'failure_url' => $failureUrl, +]); + +// Initialize eSewa client for production. +$esewa = new Client([ + 'merchant_code' => 'b4e...e8c753...2c6e8b', + 'success_url' => $successUrl, + 'failure_url' => $failureUrl, +]); ``` Here `b4e...e8c753...2c6e8b` is merchant code retrieved from eSewa. @@ -64,13 +68,13 @@ eSewa system will redirect the user to your specified success URL if the payment the payment fails. ```php -$esewa->process('P101W201', 100, 15, 80, 50); +$esewa->payment('P101W201', 100, 15, 80, 50); ``` The method accepts five parameters. ```text -process(string $pid, float $amt, float $txAmt = 0, float $psc = 0, float $pdc = 0) +payment(string $pid, float $amt, float $txAmt = 0, float $psc = 0, float $pdc = 0) ``` 1. `pid` A unique ID of product or item or ticket etc. @@ -89,7 +93,7 @@ The verification process identifies potentially fraudulent transactions and chec amount and other parameters. ```php -$status = $esewa->verify('R101', 'P101W201', 245); +$status = $esewa->verifyPayment('R101', 'P101W201', 245); if ($status) { // Verification successful. } @@ -98,7 +102,7 @@ if ($status) { The method accepts three parameters. ```text -verify(string $refId, string $oid, float $tAmt) +verifyPayment(string $refId, string $oid, float $tAmt) ``` 1. `refId` A unique payment reference code generated by eSewa. From b42f8184516dbb0845d73b9d11ad0486d9f93ee1 Mon Sep 17 00:00:00 2001 From: Madan Sapkota Date: Sat, 24 Aug 2024 17:59:18 +0545 Subject: [PATCH 10/10] Update package version --- composer.json | 2 +- composer.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index d5f6e51..b80146c 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "remotemerge/esewa-php-sdk", - "version": "3.0.0", + "version": "3.1.0", "type": "library", "description": "eSewa payment gateway integration in PHP.", "homepage": "https://github.com/remotemerge/esewa-php-sdk", diff --git a/composer.lock b/composer.lock index 54c7f8a..714c860 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a8831c236d45f4c5ab28ce50aab0db39", + "content-hash": "062f6e9642797290a6406b60c61b881e", "packages": [], "packages-dev": [ {