From 817586164cea27c991b374e05735a0d5c3d3c6ce Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Fri, 9 Oct 2020 13:32:15 +0300 Subject: [PATCH 01/25] wip: send c2b --- composer.json | 12 +++--- examples/simple.php | 11 +++++ src/Pesa.php | 103 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 examples/simple.php diff --git a/composer.json b/composer.json index e9bb292..97f0c8e 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,8 @@ { "name": "openpesa/pesa", - "description": "pesa", + "description": "Pesa PHP SDK", "keywords": [ + "api", "openpesa", "pesa" ], @@ -16,25 +17,26 @@ } ], "require": { - "php": "^7.1" + "php": "^7.1", + "guzzlehttp/guzzle": "^7.0", + "phpseclib/phpseclib": "^2.0" }, "require-dev": { "phpunit/phpunit": "^7.0" }, "autoload": { "psr-4": { - "Openpesa\\Pesa\\": "src" + "Openpesa\\SDK\\": "src" } }, "autoload-dev": { "psr-4": { - "Openpesa\\Pesa\\Tests\\": "tests" + "Openpesa\\SDK\\Tests\\": "tests" } }, "scripts": { "test": "vendor/bin/phpunit", "test-coverage": "vendor/bin/phpunit --coverage-html coverage" - }, "config": { "sort-packages": true diff --git a/examples/simple.php b/examples/simple.php new file mode 100644 index 0000000..23ae178 --- /dev/null +++ b/examples/simple.php @@ -0,0 +1,11 @@ +sendPUSH +} + diff --git a/src/Pesa.php b/src/Pesa.php index 0e78b08..c71416d 100644 --- a/src/Pesa.php +++ b/src/Pesa.php @@ -1,8 +1,107 @@ client = new Client([ + 'timeout' => 300, + 'headers' => [ + 'Accept' => 'application/json', + 'Origin' => '*' + ] + ]); + } + + public function GenerateSessionKey() + { + $response = $this->client->request( + 'GET', + 'https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/getSession/', + ['headers' => ['Authorization' => "Bearer {$this->create_bearer_token($this->APIKEY)}"]] + ); + $body = json_decode($response->getBody()); + // print_r($body); + return $body->output_SessionID; + } + + function create_bearer_token($apiKEY) + { + // Need to do these lines to create a 'valid' formatted RSA key for the openssl library + $rsa = new RSA(); + $rsa->loadKey($this->publicKey); + $rsa->setPublicKey($this->publicKey); + + $publickey = $rsa->getPublicKey(); + $api_encrypted = ''; + $encrypted = ''; + + if (openssl_public_encrypt($apiKEY, $encrypted, $publickey)) { + $api_encrypted = base64_encode($encrypted); + } + return $api_encrypted; + } + + function sendUSSDPUSH() + { + try { + //code... + $sessionID = $this->GenerateSessionKey(); + } catch (\Throwable $th) { + //throw $th; + print_r($th->getMessage()); + } + + $token = $this->create_bearer_token($sessionID); + print_r("\n\ntoekn ". $token); + $data = array( + 'input_Amount' => 2030, + 'input_Country' => 'TZN', + 'input_Currency' => 'TZS', + 'input_CustomerMSISDN' => '255766303775', + 'input_ServiceProviderCode' => '000000', + 'input_ThirdPartyConversationID' => 'rerekf', + 'input_TransactionReference' => 'odfdferre', + 'input_PurchasedItemsDesc' => 'Test Two Item' + ); + try { + //code... + $response = $this->client->request('POST', + 'https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/c2bPayment/singleStage/', + $data, + ['headers' => [ + 'Authorization' => "Bearer {$token}" + ]] + ); + } catch (\Throwable $th) { + //throw $th; + print_r($th->getMessage()); + } + + print_r( + json_decode($response->getBody()) + ); + } } + + + +$pesa = new Pesa(); +// $pesa->GenerateSessionKey(); +$pesa->sendUSSDPUSH(); From 171d281d933d1f557e6ad0f44c76118e3b67c222 Mon Sep 17 00:00:00 2001 From: Leylow Lujuo Date: Fri, 9 Oct 2020 17:53:42 +0300 Subject: [PATCH 02/25] done: wrote some tests --- .gitignore | 5 ++- composer.json | 4 +- examples/api.http | 6 +++ phpunit.xml.dist | 2 +- src/Forodha.php | 84 ++++++++++++++++++++++++++++++++++++++++++ tests/ExampleTest.php | 2 +- tests/Fixture.php | 21 +++++++++++ tests/ForodhaTest.php | 86 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 206 insertions(+), 4 deletions(-) create mode 100644 examples/api.http create mode 100644 src/Forodha.php create mode 100644 tests/Fixture.php create mode 100644 tests/ForodhaTest.php diff --git a/.gitignore b/.gitignore index 808f8c5..3f16eef 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,7 @@ build composer.lock docs vendor -coverage \ No newline at end of file +coverage + +.idea +/examples/http-client.private.env.json diff --git a/composer.json b/composer.json index 97f0c8e..95c6a04 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,9 @@ "require": { "php": "^7.1", "guzzlehttp/guzzle": "^7.0", - "phpseclib/phpseclib": "^2.0" + "phpseclib/phpseclib": "^2.0", + "ext-json": "*", + "ext-openssl": "*" }, "require-dev": { "phpunit/phpunit": "^7.0" diff --git a/examples/api.http b/examples/api.http new file mode 100644 index 0000000..216b48e --- /dev/null +++ b/examples/api.http @@ -0,0 +1,6 @@ +GET https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/getSession/ +Accept: application/json +Origin: * +Authorization: Bearer {{token}} + +### diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 22fe879..12ba420 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -22,7 +22,7 @@ - + diff --git a/src/Forodha.php b/src/Forodha.php new file mode 100644 index 0000000..d9513c4 --- /dev/null +++ b/src/Forodha.php @@ -0,0 +1,84 @@ +options = $options; + $this->client = ($client instanceof Client) ? $client : new Client($options); + $this->rsa = ($rsa instanceof RSA) ? $rsa : new RSA(); + + // encrypt public key + $this->encryptPublicKey(); + } + + /** + * Encrypts public key + * @return void + */ + private function encryptPublicKey(): void + { + $this->rsa->loadKey($this->options['public_key']); +// $this->rsa->setPublicKey($this->options['public_key']); + $this->rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1); + $this->encrypted_api_key = base64_encode($this->rsa->encrypt($this->options['api_key'])); + } + + /** + * @return mixed + * @throws GuzzleException + */ + public function generate_session() + { + $response = $this->client->request('GET', $this->options['auth_url'], + ['headers' => ['Authorization' => "Bearer {$this->encrypted_api_key}"]] + ); + return json_decode($response->getBody(), true); + } + + /** + * + * @param $data + * @return mixed + * @throws GuzzleException + */ + public function transact($data) + { + + $response = $this->client->post($this->options['auth_url'], [ + 'json' => $data, + 'headers' => ['Authorization' => "Bearer {$this->encrypted_api_key}"] + ] + ); + return json_decode($response->getBody(), true); + } +} diff --git a/tests/ExampleTest.php b/tests/ExampleTest.php index 5ab7efd..6d6c938 100644 --- a/tests/ExampleTest.php +++ b/tests/ExampleTest.php @@ -1,6 +1,6 @@ 2030, + 'input_Country' => 'TZN', + 'input_Currency' => 'TZS', + 'input_CustomerMSISDN' => '255766303775', + 'input_ServiceProviderCode' => '000000', + 'input_ThirdPartyConversationID' => 'rerekf', + 'input_TransactionReference' => 'odfdferre', + 'input_PurchasedItemsDesc' => 'Test Two Item' + ); +} diff --git a/tests/ForodhaTest.php b/tests/ForodhaTest.php new file mode 100644 index 0000000..ea0a9d2 --- /dev/null +++ b/tests/ForodhaTest.php @@ -0,0 +1,86 @@ + 'Bar'], json_encode([ + 'output_SessionID' => 1 + ])), + new Response(200, ['X-Foo' => 'Bar'], json_encode([ + 'status' => 1 + ])), + new Response(202, ['Content-Length' => 0]), + new RequestException('Error Communicating with Server', new Request('GET', 'test')) + ]); + + $handlerStack = HandlerStack::create($mock); + + $client = new Client(['handler' => $handlerStack]); + + $this->forodha = new Forodha([ + 'api_key' => Fixture::$apiKey, + 'public_key' => Fixture::$publicKey, + 'username' => Fixture::$username, + 'auth_url' => Fixture::$authUrl, + ], $client); + + } + + /** @test */ + public function forodha_instantiable() + { + $this->assertInstanceOf(Forodha::class, $this->forodha); + } + + /** @test */ + public function forodha_has_these_attributes() + { + $this->assertClassHasAttribute('options', get_class($this->forodha)); + $this->assertClassHasAttribute('client', get_class($this->forodha)); + } + + /** @test + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function forodha_generate_session() + { + // Arrange - Done in the set up method + + // Act + $response = $this->forodha->generate_session(); + // Assert + $this->assertArrayHasKey('output_SessionID', $response); + $this->assertEquals(1, $response['output_SessionID']); + } + + /** @test + * @throws \GuzzleHttp\Exception\GuzzleException + */ + public function forodha_transact() + { + // Arrange - Done in the set up method + $this->forodha->generate_session(); + $result = $this->forodha->transact(Fixture::$data); + // Act + // Assert + $this->assertArrayHasKey('status', $result); + $this->assertEquals(1, $result['status']); + } +} From 0482a0ba576e139063215bb48842f8c59c96f062 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Fri, 9 Oct 2020 18:26:46 +0300 Subject: [PATCH 03/25] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e397e5a..983bf47 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Pesa SDK [![Latest Version on Packagist](https://img.shields.io/packagist/v/openpesa/pesa.svg?style=flat-square)](https://packagist.org/packages/openpesa/pesa) -[![Build Status](https://img.shields.io/travis/openpesa/pesa/master.svg?style=flat-square)](https://travis-ci.org/openpesa/pesa) -[![Quality Score](https://img.shields.io/scrutinizer/g/openpesa/pesa.svg?style=flat-square)](https://scrutinizer-ci.com/g/openpesa/pesa) +[![Build Status](https://img.shields.io/travis/openpesa/php-pesa/master.svg?style=flat-square)](https://travis-ci.org/openpesa/php-pesa) +[![Quality Score](https://img.shields.io/scrutinizer/g/openpesa/php-pesa.svg?style=flat-square)](https://scrutinizer-ci.com/g/openpesa/pesa) [![Total Downloads](https://img.shields.io/packagist/dt/openpesa/pesa.svg?style=flat-square)](https://packagist.org/packages/openpesa/pesa) This is where your description should go. Try and limit it to a paragraph or two, and maybe throw in a mention of what PSRs you support to avoid any confusion with users and contributors. From 18aca6db805f00944286f676f7e8f9dc89819be9 Mon Sep 17 00:00:00 2001 From: Leylow Lujuo Date: Fri, 9 Oct 2020 19:01:14 +0300 Subject: [PATCH 04/25] fixed: broken tests added: simple example --- examples/simple.php | 20 +++++++++++------- src/Forodha.php | 49 +++++++++++++++++++++++++++---------------- tests/Fixture.php | 24 +++++++++++++++++++-- tests/ForodhaTest.php | 25 ++++++++++++++-------- 4 files changed, 82 insertions(+), 36 deletions(-) diff --git a/examples/simple.php b/examples/simple.php index 23ae178..fb507ce 100644 --- a/examples/simple.php +++ b/examples/simple.php @@ -1,11 +1,17 @@ sendPUSH -} +$f = new Forodha([ + 'api_key' => '', + 'public_key' => Fixture::$publicKey, + 'auth_url' => Fixture::$authUrl, + 'client_options' => [], +]); + + +$t = $f->transact('c2b', Fixture::data()); +var_dump($t); diff --git a/src/Forodha.php b/src/Forodha.php index d9513c4..cf9b6b8 100644 --- a/src/Forodha.php +++ b/src/Forodha.php @@ -20,10 +20,13 @@ class Forodha * @var null */ private $rsa; - /** - * @var false|string - */ - protected $encrypted_api_key; + + const TRANSACT_TYPE = [ + 'c2b' => [ + 'name' => 'Consumer 2 Business', + 'url' => 'https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/c2bPayment/singleStage/', + ] + ]; /** * Forodha constructor. @@ -34,49 +37,59 @@ class Forodha public function __construct($options, $client = null, $rsa = null) { $this->options = $options; - $this->client = ($client instanceof Client) ? $client : new Client($options); - $this->rsa = ($rsa instanceof RSA) ? $rsa : new RSA(); + $this->client = ($client instanceof Client) + ? $client + : new Client(array_merge([ + 'http_errors' => false, + 'headers' => [ + 'Accept' => 'application/json', + 'Origin' => '*' + ] + ], $options['client_options'])); - // encrypt public key - $this->encryptPublicKey(); + $this->rsa = ($rsa instanceof RSA) ? $rsa : new RSA(); } /** * Encrypts public key - * @return void + * @param $key + * @return string */ - private function encryptPublicKey(): void + private function encrypt_key($key): string { $this->rsa->loadKey($this->options['public_key']); -// $this->rsa->setPublicKey($this->options['public_key']); $this->rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1); - $this->encrypted_api_key = base64_encode($this->rsa->encrypt($this->options['api_key'])); + return base64_encode($this->rsa->encrypt($key)); } /** * @return mixed * @throws GuzzleException */ - public function generate_session() + public function get_session() { - $response = $this->client->request('GET', $this->options['auth_url'], - ['headers' => ['Authorization' => "Bearer {$this->encrypted_api_key}"]] + $response = $this->client->get($this->options['auth_url'], + ['headers' => ['Authorization' => "Bearer {$this->encrypt_key($this->options['api_key'])}"]] ); return json_decode($response->getBody(), true); } /** * + * @param $type * @param $data + * @param $session * @return mixed * @throws GuzzleException */ - public function transact($data) + public function transact($type, $data, $session = null) { + if (! $session) + $session = $this->get_session()['output_SessionID']; - $response = $this->client->post($this->options['auth_url'], [ + $response = $this->client->post(self::TRANSACT_TYPE[$type]['url'], [ 'json' => $data, - 'headers' => ['Authorization' => "Bearer {$this->encrypted_api_key}"] + 'headers' => ['Authorization' => "Bearer {$this->encrypt_key($session)}"] ] ); return json_decode($response->getBody(), true); diff --git a/tests/Fixture.php b/tests/Fixture.php index 17f45b0..51cee51 100644 --- a/tests/Fixture.php +++ b/tests/Fixture.php @@ -8,7 +8,13 @@ class Fixture public static $apiKey = ''; public static $publicKey = 'MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArv9yxA69XQKBo24BaF/D+fvlqmGdYjqLQ5WtNBb5tquqGvAvG3WMFETVUSow/LizQalxj2ElMVrUmzu5mGGkxK08bWEXF7a1DEvtVJs6nppIlFJc2SnrU14AOrIrB28ogm58JjAl5BOQawOXD5dfSk7MaAA82pVHoIqEu0FxA8BOKU+RGTihRU+ptw1j4bsAJYiPbSX6i71gfPvwHPYamM0bfI4CmlsUUR3KvCG24rB6FNPcRBhM3jDuv8ae2kC33w9hEq8qNB55uw51vK7hyXoAa+U7IqP1y6nBdlN25gkxEA8yrsl1678cspeXr+3ciRyqoRgj9RD/ONbJhhxFvt1cLBh+qwK2eqISfBb06eRnNeC71oBokDm3zyCnkOtMDGl7IvnMfZfEPFCfg5QgJVk1msPpRvQxmEsrX9MQRyFVzgy2CWNIb7c+jPapyrNwoUbANlN8adU1m6yOuoX7F49x+OjiG2se0EJ6nafeKUXw/+hiJZvELUYgzKUtMAZVTNZfT8jjb58j8GVtuS+6TM2AutbejaCV84ZK58E2CRJqhmjQibEUO6KPdD7oTlEkFy52Y1uOOBXgYpqMzufNPmfdqqqSM4dU70PO8ogyKGiLAIxCetMjjm6FCMEA3Kc8K0Ig7/XtFm9By6VxTJK1Mg36TlHaZKP6VzVLXMtesJECAwEAAQ=='; public static $authUrl = 'https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/getSession/'; - public static $data = array( + public static $transactionType = [ + 'c2b' => [ + 'name' => 'Consumer 2 Business', + 'url' => 'https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/c2bPayment/singleStage/', + ] + ]; + public static $data = [ 'input_Amount' => 2030, 'input_Country' => 'TZN', 'input_Currency' => 'TZS', @@ -17,5 +23,19 @@ class Fixture 'input_ThirdPartyConversationID' => 'rerekf', 'input_TransactionReference' => 'odfdferre', 'input_PurchasedItemsDesc' => 'Test Two Item' - ); + ]; + + public static function data() + { + return [ + 'input_Amount' => rand(1000,2000), + 'input_Country' => 'TZN', + 'input_Currency' => 'TZS', + 'input_CustomerMSISDN' => '255766303775', + 'input_ServiceProviderCode' => '000000', + 'input_ThirdPartyConversationID' => 'rerekf', + 'input_TransactionReference' => rand(), + 'input_PurchasedItemsDesc' => 'Test Two Item' + ]; + } } diff --git a/tests/ForodhaTest.php b/tests/ForodhaTest.php index ea0a9d2..0d8ef27 100644 --- a/tests/ForodhaTest.php +++ b/tests/ForodhaTest.php @@ -21,10 +21,16 @@ public function setup() // Create a mock and queue two responses. $mock = new MockHandler([ new Response(200, ['X-Foo' => 'Bar'], json_encode([ + 'output_ResponseCode' => 'INS-0', + 'output_ResponseDesc' => 'Request processed successfully', 'output_SessionID' => 1 ])), new Response(200, ['X-Foo' => 'Bar'], json_encode([ - 'status' => 1 + 'output_ResponseCode' => 'INS-0', + 'output_ResponseDesc' => 'Request processed successfully', + 'output_TransactionID' => 2, + 'output_ConversationID' => 'f1ddae567e6c45e580504764571dbe2f', + 'output_ThirdPartyConversationID' => 'Narration', ])), new Response(202, ['Content-Length' => 0]), new RequestException('Error Communicating with Server', new Request('GET', 'test')) @@ -59,12 +65,11 @@ public function forodha_has_these_attributes() /** @test * @throws \GuzzleHttp\Exception\GuzzleException */ - public function forodha_generate_session() + public function forodha_get_session() { // Arrange - Done in the set up method - // Act - $response = $this->forodha->generate_session(); + $response = $this->forodha->get_session(); // Assert $this->assertArrayHasKey('output_SessionID', $response); $this->assertEquals(1, $response['output_SessionID']); @@ -73,14 +78,16 @@ public function forodha_generate_session() /** @test * @throws \GuzzleHttp\Exception\GuzzleException */ - public function forodha_transact() + public function forodha_transact_c2b() { // Arrange - Done in the set up method - $this->forodha->generate_session(); - $result = $this->forodha->transact(Fixture::$data); + $session = $this->forodha->get_session()['output_SessionID']; + $result = $this->forodha->transact('c2b', Fixture::$data, $session); // Act // Assert - $this->assertArrayHasKey('status', $result); - $this->assertEquals(1, $result['status']); + $this->assertArrayHasKey('output_ResponseCode', $result); + $this->assertArrayHasKey('output_ResponseDesc', $result); + $this->assertArrayHasKey('output_ConversationID', $result); + $this->assertArrayHasKey('output_ThirdPartyConversationID', $result); } } From 846acca7bcb800c581073a9a9fd50f40f39f17e1 Mon Sep 17 00:00:00 2001 From: Leylow Lujuo Date: Fri, 9 Oct 2020 19:18:40 +0300 Subject: [PATCH 05/25] fixed: updated the compatibility to 7.1 and refurbished --- .gitignore | 1 + .travis.yml | 2 +- examples/api.http | 2 +- tests/ForodhaTest.php | 12 ++++++++++-- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 3f16eef..f5ce6a9 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ coverage .idea /examples/http-client.private.env.json +/examples/my-simple.php diff --git a/.travis.yml b/.travis.yml index 24c2d6c..a57b1db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: php php: - - 7.1 +# - 7.1 - 7.2 - 7.3 diff --git a/examples/api.http b/examples/api.http index 216b48e..17b07f3 100644 --- a/examples/api.http +++ b/examples/api.http @@ -1,6 +1,6 @@ GET https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/getSession/ Accept: application/json Origin: * -Authorization: Bearer {{token}} +Authorization: Bearer {{api_key}} ### diff --git a/tests/ForodhaTest.php b/tests/ForodhaTest.php index 0d8ef27..e70fabd 100644 --- a/tests/ForodhaTest.php +++ b/tests/ForodhaTest.php @@ -2,6 +2,7 @@ namespace Openpesa\SDK\Tests; +use GuzzleHttp\Exception\GuzzleException; use Openpesa\SDK\Forodha; use PHPUnit\Framework\TestCase; use GuzzleHttp\Client; @@ -53,6 +54,13 @@ public function setup() public function forodha_instantiable() { $this->assertInstanceOf(Forodha::class, $this->forodha); + $this->assertInstanceOf(Forodha::class, new Forodha([ + 'api_key' => Fixture::$apiKey, + 'public_key' => Fixture::$publicKey, + 'username' => Fixture::$username, + 'auth_url' => Fixture::$authUrl, + 'client_options' => [], + ])); } /** @test */ @@ -63,7 +71,7 @@ public function forodha_has_these_attributes() } /** @test - * @throws \GuzzleHttp\Exception\GuzzleException + * @throws GuzzleException */ public function forodha_get_session() { @@ -76,7 +84,7 @@ public function forodha_get_session() } /** @test - * @throws \GuzzleHttp\Exception\GuzzleException + * @throws GuzzleException */ public function forodha_transact_c2b() { From bda25175da277350cebd41de7a46866c13edd089 Mon Sep 17 00:00:00 2001 From: Leylow Lujuo Date: Sat, 10 Oct 2020 16:23:31 +0300 Subject: [PATCH 06/25] done: update usage in README.md --- README.md | 34 +++++++++++----- composer.json | 5 +++ src/Pesa.php | 107 -------------------------------------------------- 3 files changed, 30 insertions(+), 116 deletions(-) delete mode 100644 src/Pesa.php diff --git a/README.md b/README.md index 983bf47..6783b7c 100644 --- a/README.md +++ b/README.md @@ -18,19 +18,35 @@ composer require openpesa/pesa ## Usage ``` php -use Openpesa\SDK\Pesa; -// Set the consumer key and consumer secret as follows -$username = 'YOUR_USERNAME'; // use 'sandbox' for development in the test environment -$apiKey = 'YOUR_API_KEY'; // use your sandbox app API key for development in the test environment - -// Get one of the services -$pesa = new Pesa($public_key, $apiKey); +require '../vendor/autoload.php'; + +use Openpesa\SDK\Forodha; + +// Intiate with keys +$forodha = new Forodha([ + 'api_key' => 'YOUR_API_KEY', // use 'sandbox' for development in the test environment + 'public_key' => 'PUBLIC_KEY', // use your sandbox app API key for development in the test environment + 'client_options' => [], // + ]); + +// Setup the input amount +$data = [ + 'input_Amount' => '10000', + 'input_Country' => 'TZN', + 'input_Currency' => 'TZS', + 'input_CustomerMSISDN' => '255766303775', + 'input_ServiceProviderCode' => '000000', + 'input_ThirdPartyConversationID' => 'rerekf', + 'input_TransactionReference' => rand(), + 'input_PurchasedItemsDesc' => 'Test Two Item' +]; // Use the service -$result = $pesa->c2b($invoice_id, $phone_number, $amount, $reference_id, $shortcode); +$result = $forodha->transact('c2b', $data); + +var_dump($result); -print_r($result); ``` ### Testing diff --git a/composer.json b/composer.json index 95c6a04..872585e 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,11 @@ "name": "Alpha Olomi", "email": "alphaolomi@gmail.com", "role": "Developer" + }, + { + "name": "Leylow Lujuo", + "email": "leyluj21@gmail.com", + "role": "Developer" } ], "require": { diff --git a/src/Pesa.php b/src/Pesa.php deleted file mode 100644 index c71416d..0000000 --- a/src/Pesa.php +++ /dev/null @@ -1,107 +0,0 @@ -client = new Client([ - 'timeout' => 300, - 'headers' => [ - 'Accept' => 'application/json', - 'Origin' => '*' - ] - ]); - } - - public function GenerateSessionKey() - { - $response = $this->client->request( - 'GET', - 'https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/getSession/', - ['headers' => ['Authorization' => "Bearer {$this->create_bearer_token($this->APIKEY)}"]] - ); - $body = json_decode($response->getBody()); - // print_r($body); - return $body->output_SessionID; - } - - function create_bearer_token($apiKEY) - { - // Need to do these lines to create a 'valid' formatted RSA key for the openssl library - $rsa = new RSA(); - $rsa->loadKey($this->publicKey); - $rsa->setPublicKey($this->publicKey); - - $publickey = $rsa->getPublicKey(); - $api_encrypted = ''; - $encrypted = ''; - - if (openssl_public_encrypt($apiKEY, $encrypted, $publickey)) { - $api_encrypted = base64_encode($encrypted); - } - return $api_encrypted; - } - - function sendUSSDPUSH() - { - try { - //code... - $sessionID = $this->GenerateSessionKey(); - } catch (\Throwable $th) { - //throw $th; - print_r($th->getMessage()); - } - - $token = $this->create_bearer_token($sessionID); - print_r("\n\ntoekn ". $token); - $data = array( - 'input_Amount' => 2030, - 'input_Country' => 'TZN', - 'input_Currency' => 'TZS', - 'input_CustomerMSISDN' => '255766303775', - 'input_ServiceProviderCode' => '000000', - 'input_ThirdPartyConversationID' => 'rerekf', - 'input_TransactionReference' => 'odfdferre', - 'input_PurchasedItemsDesc' => 'Test Two Item' - ); - try { - //code... - $response = $this->client->request('POST', - 'https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/c2bPayment/singleStage/', - $data, - ['headers' => [ - 'Authorization' => "Bearer {$token}" - ]] - ); - } catch (\Throwable $th) { - //throw $th; - print_r($th->getMessage()); - } - - print_r( - json_decode($response->getBody()) - ); - } -} - - - -$pesa = new Pesa(); -// $pesa->GenerateSessionKey(); -$pesa->sendUSSDPUSH(); From 4d9130497a1ff61978ad794cfe1d69dd469e1b99 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Sun, 11 Oct 2020 15:34:24 +0300 Subject: [PATCH 07/25] feat(examples): added pesa demo example --- examples/pesa-demo/.env | 4 +++ examples/pesa-demo/.gitignore | 9 +++++++ examples/pesa-demo/composer.json | 16 +++++++++++ examples/pesa-demo/index.php | 46 ++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 examples/pesa-demo/.env create mode 100644 examples/pesa-demo/.gitignore create mode 100644 examples/pesa-demo/composer.json create mode 100644 examples/pesa-demo/index.php diff --git a/examples/pesa-demo/.env b/examples/pesa-demo/.env new file mode 100644 index 0000000..6a8f216 --- /dev/null +++ b/examples/pesa-demo/.env @@ -0,0 +1,4 @@ +USERNAME=sandbox +PUBLICKEY= +AUTHURL= +APIKEY= \ No newline at end of file diff --git a/examples/pesa-demo/.gitignore b/examples/pesa-demo/.gitignore new file mode 100644 index 0000000..f5ce6a9 --- /dev/null +++ b/examples/pesa-demo/.gitignore @@ -0,0 +1,9 @@ +build +composer.lock +docs +vendor +coverage + +.idea +/examples/http-client.private.env.json +/examples/my-simple.php diff --git a/examples/pesa-demo/composer.json b/examples/pesa-demo/composer.json new file mode 100644 index 0000000..1d349a6 --- /dev/null +++ b/examples/pesa-demo/composer.json @@ -0,0 +1,16 @@ +{ + "name": "openpesa/pesa-demo", + "description": "Simple SDK usage", + "type": "project", + "require": { + "php": ">=7.1", + "openpesa/pesa": "dev-develop" + }, + "license": "MIT", + "authors": [ + { + "name": "Alpha Olomi", + "email": "alphaolomi@gmail.com" + } + ] +} \ No newline at end of file diff --git a/examples/pesa-demo/index.php b/examples/pesa-demo/index.php new file mode 100644 index 0000000..48b1db4 --- /dev/null +++ b/examples/pesa-demo/index.php @@ -0,0 +1,46 @@ + 300, + 'headers' => [ + 'Accept' => 'application/json', + 'Origin' => '*' + ] +]); + +$forodha = new Forodha([ + 'api_key' => $apiKey, + 'public_key' => $publicKey, + 'username' => $username, + 'auth_url' => $authUrl, +], $client); + + +$data = [ + 'input_Amount' => 5000, + 'input_CustomerMSISDN' => '000000000001', + 'input_Country' => 'TZN', + 'input_Currency' => 'TZS', + 'input_ServiceProviderCode' => '000000', + 'input_TransactionReference' => 'T12344Z', + 'input_ThirdPartyConversationID' => '1e9b774d1da34af78412a498cbc28f5d', + 'input_PurchasedItemsDesc' => 'Test Three Item' +]; + + +try { + $result = $forodha->transact('c2b', $data); + print_r($result); +} catch (\Throwable $th) { + echo $th->getMessage(); +} From 439580d619dda104705e3c668b57b230679537cf Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Sun, 11 Oct 2020 16:04:10 +0300 Subject: [PATCH 08/25] wip: add supprt for b2c transact --- CHANGELOG.md | 3 ++- src/Forodha.php | 10 ++++++++-- tests/Fixture.php | 20 +++++++++++++++++--- tests/ForodhaTest.php | 18 +++++++++++++++++- 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5f0c77..0431a60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ All notable changes to `pesa` will be documented in this file -## 1.0.0 - 201X-XX-XX +## 0.0.1 - 2020-10-12 - initial release +- Supprt for C2B, B2C \ No newline at end of file diff --git a/src/Forodha.php b/src/Forodha.php index cf9b6b8..5c1c8a2 100644 --- a/src/Forodha.php +++ b/src/Forodha.php @@ -21,11 +21,17 @@ class Forodha */ private $rsa; + const BASE_DOMAIN = "https://openapi.m-pesa.com/sandbox/"; + const TRANSACT_TYPE = [ 'c2b' => [ 'name' => 'Consumer 2 Business', - 'url' => 'https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/c2bPayment/singleStage/', - ] + 'url' => "https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/c2bPayment/singleStage/", + ], + 'b2c' => [ + 'name' => 'Business 2 Consumer', + 'url' =>"https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/b2cPayment/singleStage/", + ], ]; /** diff --git a/tests/Fixture.php b/tests/Fixture.php index 51cee51..c838265 100644 --- a/tests/Fixture.php +++ b/tests/Fixture.php @@ -12,18 +12,32 @@ class Fixture 'c2b' => [ 'name' => 'Consumer 2 Business', 'url' => 'https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/c2bPayment/singleStage/', - ] + ], + 'b2c' => [ + 'name' => 'Business 2 Consumer', + 'url' =>"https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/b2cPayment/singleStage/", + ], ]; - public static $data = [ + public static $data_c2b = [ 'input_Amount' => 2030, 'input_Country' => 'TZN', 'input_Currency' => 'TZS', - 'input_CustomerMSISDN' => '255766303775', + 'input_CustomerMSISDN' => '000000000001', 'input_ServiceProviderCode' => '000000', 'input_ThirdPartyConversationID' => 'rerekf', 'input_TransactionReference' => 'odfdferre', 'input_PurchasedItemsDesc' => 'Test Two Item' ]; + public static $data_b2c = [ + 'input_Amount' => 5030, + 'input_Country' => 'TZN', + 'input_Currency' => 'TZS', + 'input_CustomerMSISDN' => '000000000001', + 'input_ServiceProviderCode' => '000000', + 'input_ThirdPartyConversationID' => 'asv02e5958774f7ab228d83d0d689761', + 'input_TransactionReference' => 'odfdferre', + 'input_PurchasedItemsDesc' => 'Salary payment' + ]; public static function data() { diff --git a/tests/ForodhaTest.php b/tests/ForodhaTest.php index e70fabd..412cdf4 100644 --- a/tests/ForodhaTest.php +++ b/tests/ForodhaTest.php @@ -90,7 +90,23 @@ public function forodha_transact_c2b() { // Arrange - Done in the set up method $session = $this->forodha->get_session()['output_SessionID']; - $result = $this->forodha->transact('c2b', Fixture::$data, $session); + $result = $this->forodha->transact('c2b', Fixture::$data_c2b, $session); + // Act + // Assert + $this->assertArrayHasKey('output_ResponseCode', $result); + $this->assertArrayHasKey('output_ResponseDesc', $result); + $this->assertArrayHasKey('output_ConversationID', $result); + $this->assertArrayHasKey('output_ThirdPartyConversationID', $result); + } + + /** @test + * @throws GuzzleException + */ + public function forodha_transact_b2c() + { + // Arrange - Done in the set up method + $session = $this->forodha->get_session()['output_SessionID']; + $result = $this->forodha->transact('b2c', Fixture::$data_b2c, $session); // Act // Assert $this->assertArrayHasKey('output_ResponseCode', $result); From 2dafe27c02348bf33cf49cba4c5a9a25619ac14f Mon Sep 17 00:00:00 2001 From: Leylow Lujuo Date: Wed, 14 Oct 2020 11:39:59 +0300 Subject: [PATCH 09/25] feat(b2c): add support for b2c transaction feat(rt): add support for reverse transaction fix(example): removed complexity on examples --- CHANGELOG.md | 2 +- examples/pesa-demo/index.php | 17 ++++------------- src/Forodha.php | 6 +++++- tests/Fixture.php | 8 ++++++++ tests/ForodhaTest.php | 18 +++++++++++++++++- 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0431a60..3ce282d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,4 +5,4 @@ All notable changes to `pesa` will be documented in this file ## 0.0.1 - 2020-10-12 - initial release -- Supprt for C2B, B2C \ No newline at end of file +- Support for C2B, B2C, REVERSAL diff --git a/examples/pesa-demo/index.php b/examples/pesa-demo/index.php index 48b1db4..56557ef 100644 --- a/examples/pesa-demo/index.php +++ b/examples/pesa-demo/index.php @@ -2,28 +2,19 @@ require 'vendor/autoload.php'; use Openpesa\SDK\Forodha; -use GuzzleHttp\Client; $username = 'sandbox'; $publicKey = 'MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArv9yxA69XQKBo24BaF/D+fvlqmGdYjqLQ5WtNBb5tquqGvAvG3WMFETVUSow/LizQalxj2ElMVrUmzu5mGGkxK08bWEXF7a1DEvtVJs6nppIlFJc2SnrU14AOrIrB28ogm58JjAl5BOQawOXD5dfSk7MaAA82pVHoIqEu0FxA8BOKU+RGTihRU+ptw1j4bsAJYiPbSX6i71gfPvwHPYamM0bfI4CmlsUUR3KvCG24rB6FNPcRBhM3jDuv8ae2kC33w9hEq8qNB55uw51vK7hyXoAa+U7IqP1y6nBdlN25gkxEA8yrsl1678cspeXr+3ciRyqoRgj9RD/ONbJhhxFvt1cLBh+qwK2eqISfBb06eRnNeC71oBokDm3zyCnkOtMDGl7IvnMfZfEPFCfg5QgJVk1msPpRvQxmEsrX9MQRyFVzgy2CWNIb7c+jPapyrNwoUbANlN8adU1m6yOuoX7F49x+OjiG2se0EJ6nafeKUXw/+hiJZvELUYgzKUtMAZVTNZfT8jjb58j8GVtuS+6TM2AutbejaCV84ZK58E2CRJqhmjQibEUO6KPdD7oTlEkFy52Y1uOOBXgYpqMzufNPmfdqqqSM4dU70PO8ogyKGiLAIxCetMjjm6FCMEA3Kc8K0Ig7/XtFm9By6VxTJK1Mg36TlHaZKP6VzVLXMtesJECAwEAAQ=='; $authUrl = 'https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/getSession/'; -$apiKey = ''; +$apiKey = ''; -$client = new Client([ - 'timeout' => 300, - 'headers' => [ - 'Accept' => 'application/json', - 'Origin' => '*' - ] -]); - $forodha = new Forodha([ 'api_key' => $apiKey, 'public_key' => $publicKey, 'username' => $username, 'auth_url' => $authUrl, -], $client); +]); $data = [ @@ -32,7 +23,7 @@ 'input_Country' => 'TZN', 'input_Currency' => 'TZS', 'input_ServiceProviderCode' => '000000', - 'input_TransactionReference' => 'T12344Z', + 'input_TransactionReference' => 'T12344Z', 'input_ThirdPartyConversationID' => '1e9b774d1da34af78412a498cbc28f5d', 'input_PurchasedItemsDesc' => 'Test Three Item' ]; @@ -41,6 +32,6 @@ try { $result = $forodha->transact('c2b', $data); print_r($result); -} catch (\Throwable $th) { +} catch (Throwable $th) { echo $th->getMessage(); } diff --git a/src/Forodha.php b/src/Forodha.php index 5c1c8a2..6adc2bf 100644 --- a/src/Forodha.php +++ b/src/Forodha.php @@ -22,7 +22,7 @@ class Forodha private $rsa; const BASE_DOMAIN = "https://openapi.m-pesa.com/sandbox/"; - + const TRANSACT_TYPE = [ 'c2b' => [ 'name' => 'Consumer 2 Business', @@ -32,6 +32,10 @@ class Forodha 'name' => 'Business 2 Consumer', 'url' =>"https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/b2cPayment/singleStage/", ], + 'rt' => [ + 'name' => 'Reverse Transaction', + 'url' =>"https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/reversal/", + ] ]; /** diff --git a/tests/Fixture.php b/tests/Fixture.php index c838265..34f01b5 100644 --- a/tests/Fixture.php +++ b/tests/Fixture.php @@ -29,6 +29,14 @@ class Fixture 'input_PurchasedItemsDesc' => 'Test Two Item' ]; public static $data_b2c = [ + 'input_ReversalAmount' => 12.12, + 'input_TransactionID' => 'odfdferre', + 'input_Country' => 'TZN', + 'input_ServiceProviderCode' => '000000', + 'input_ThirdPartyConversationID' => 'asv02e5958774f7ab228d83d0d689761', + ]; + + public static $data_reversal = [ 'input_Amount' => 5030, 'input_Country' => 'TZN', 'input_Currency' => 'TZS', diff --git a/tests/ForodhaTest.php b/tests/ForodhaTest.php index 412cdf4..0909f70 100644 --- a/tests/ForodhaTest.php +++ b/tests/ForodhaTest.php @@ -99,7 +99,7 @@ public function forodha_transact_c2b() $this->assertArrayHasKey('output_ThirdPartyConversationID', $result); } - /** @test + /** @test * @throws GuzzleException */ public function forodha_transact_b2c() @@ -114,4 +114,20 @@ public function forodha_transact_b2c() $this->assertArrayHasKey('output_ConversationID', $result); $this->assertArrayHasKey('output_ThirdPartyConversationID', $result); } + + /** @test + * @throws GuzzleException + */ + public function forodha_transact_reversal() + { + // Arrange - Done in the set up method + $session = $this->forodha->get_session()['output_SessionID']; + $result = $this->forodha->transact('rt', Fixture::$data_reversal, $session); + // Act + // Assert + $this->assertArrayHasKey('output_ResponseCode', $result); + $this->assertArrayHasKey('output_ResponseDesc', $result); + $this->assertArrayHasKey('output_ConversationID', $result); + $this->assertArrayHasKey('output_ThirdPartyConversationID', $result); + } } From cf5556d0852e718157808ecf3612f506e3c30d32 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Thu, 15 Oct 2020 20:16:16 +0300 Subject: [PATCH 10/25] wip: add query, ddc and ddp transact --- examples/pesa-demo/index.php | 5 -- examples/simple.php | 4 +- src/Forodha.php | 101 +++++++++++++++++++++++++++++------ tests/Fixture.php | 38 ++++++++++++- tests/ForodhaTest.php | 47 ++++++++++++---- 5 files changed, 159 insertions(+), 36 deletions(-) diff --git a/examples/pesa-demo/index.php b/examples/pesa-demo/index.php index 56557ef..6d603fe 100644 --- a/examples/pesa-demo/index.php +++ b/examples/pesa-demo/index.php @@ -3,17 +3,12 @@ use Openpesa\SDK\Forodha; -$username = 'sandbox'; $publicKey = 'MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArv9yxA69XQKBo24BaF/D+fvlqmGdYjqLQ5WtNBb5tquqGvAvG3WMFETVUSow/LizQalxj2ElMVrUmzu5mGGkxK08bWEXF7a1DEvtVJs6nppIlFJc2SnrU14AOrIrB28ogm58JjAl5BOQawOXD5dfSk7MaAA82pVHoIqEu0FxA8BOKU+RGTihRU+ptw1j4bsAJYiPbSX6i71gfPvwHPYamM0bfI4CmlsUUR3KvCG24rB6FNPcRBhM3jDuv8ae2kC33w9hEq8qNB55uw51vK7hyXoAa+U7IqP1y6nBdlN25gkxEA8yrsl1678cspeXr+3ciRyqoRgj9RD/ONbJhhxFvt1cLBh+qwK2eqISfBb06eRnNeC71oBokDm3zyCnkOtMDGl7IvnMfZfEPFCfg5QgJVk1msPpRvQxmEsrX9MQRyFVzgy2CWNIb7c+jPapyrNwoUbANlN8adU1m6yOuoX7F49x+OjiG2se0EJ6nafeKUXw/+hiJZvELUYgzKUtMAZVTNZfT8jjb58j8GVtuS+6TM2AutbejaCV84ZK58E2CRJqhmjQibEUO6KPdD7oTlEkFy52Y1uOOBXgYpqMzufNPmfdqqqSM4dU70PO8ogyKGiLAIxCetMjjm6FCMEA3Kc8K0Ig7/XtFm9By6VxTJK1Mg36TlHaZKP6VzVLXMtesJECAwEAAQ=='; -$authUrl = 'https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/getSession/'; $apiKey = ''; - $forodha = new Forodha([ 'api_key' => $apiKey, 'public_key' => $publicKey, - 'username' => $username, - 'auth_url' => $authUrl, ]); diff --git a/examples/simple.php b/examples/simple.php index fb507ce..e6bc718 100644 --- a/examples/simple.php +++ b/examples/simple.php @@ -6,9 +6,7 @@ $f = new Forodha([ 'api_key' => '', - 'public_key' => Fixture::$publicKey, - 'auth_url' => Fixture::$authUrl, - 'client_options' => [], + 'public_key' => Fixture::$publicKey, ]); diff --git a/src/Forodha.php b/src/Forodha.php index 6adc2bf..2ff9878 100644 --- a/src/Forodha.php +++ b/src/Forodha.php @@ -1,6 +1,5 @@ [ 'name' => 'Consumer 2 Business', - 'url' => "https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/c2bPayment/singleStage/", + 'url' => self::BASE_DOMAIN . "ipg/v2/vodacomTZN/c2bPayment/singleStage/", + 'encryptSessionKey' => false, + 'rules' => [] ], 'b2c' => [ 'name' => 'Business 2 Consumer', - 'url' =>"https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/b2cPayment/singleStage/", + 'url' => self::BASE_DOMAIN . "ipg/v2/vodacomTZN/b2cPayment/singleStage/", + 'encryptSessionKey' => false, + 'rules' => [] ], 'rt' => [ 'name' => 'Reverse Transaction', - 'url' =>"https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/reversal/", + 'url' => self::BASE_DOMAIN . "ipg/v2/vodacomTZN/reversal/", + 'encryptSessionKey' => false, + 'rules' => [] + ], + 'query' => [ + 'name' => 'Query Transaction Status', + 'url' => self::BASE_DOMAIN . "ipg/v2/vodacomTZN/queryTransactionStatus/", + 'encryptSessionKey' => false, + 'rules' => [] + ], + 'ddc' => [ + 'name' => 'Direct Debits create', + 'url' => self::BASE_DOMAIN . "ipg/v2/vodacomTZN/directDebitCreation/", + 'encryptSessionKey' => false, + 'rules' => [] + ], + 'ddp' => [ + 'name' => 'Direct Debits payment', + 'url' => self::BASE_DOMAIN . "ipg/v2/vodacomTZN/directDebitPayment/", + 'encryptSessionKey' => false, ] + ]; /** @@ -46,6 +89,8 @@ class Forodha */ public function __construct($options, $client = null, $rsa = null) { + + $options['auth_url'] = $options['auth_url'] ?? self::AUTH_URL; $this->options = $options; $this->client = ($client instanceof Client) ? $client @@ -73,35 +118,59 @@ private function encrypt_key($key): string } /** + * Get Session Key * @return mixed * @throws GuzzleException */ public function get_session() { - $response = $this->client->get($this->options['auth_url'], + $response = $this->client->get( + $this->options['auth_url'], ['headers' => ['Authorization' => "Bearer {$this->encrypt_key($this->options['api_key'])}"]] ); return json_decode($response->getBody(), true); } /** + * Query the status of the transaction that has been initiated. * - * @param $type - * @param $data - * @param $session + * @param $data mixed + * @param $session null|mixed * @return mixed * @throws GuzzleException */ - public function transact($type, $data, $session = null) + public function query($data, $session = null) { - if (! $session) + if (!$session) $session = $this->get_session()['output_SessionID']; + $response = $this->client->get(self::TRANSACT_TYPE['query']['url'], [ + 'json' => $data, + 'headers' => ['Authorization' => "Bearer {$this->encrypt_key($session)}"] + ]); + return json_decode($response->getBody(), true); + } + + /** + * Perform a transaction + * + * @param $type string + * @param $data mixed + * @param $session null|string + * @return mixed + * @throws GuzzleException + */ + public function transact(string $type, $data, $session = null) + { + + $session = ($session) ?? $this->get_session()['output_SessionID']; + + $token = (self::TRANSACT_TYPE[$type]['encryptSessionKey']) ? $this->encrypt_key($session) : $session; + $response = $this->client->post(self::TRANSACT_TYPE[$type]['url'], [ - 'json' => $data, - 'headers' => ['Authorization' => "Bearer {$this->encrypt_key($session)}"] - ] - ); + 'json' => $data, + 'headers' => ['Authorization' => "Bearer {$token}"] + ]); return json_decode($response->getBody(), true); } } diff --git a/tests/Fixture.php b/tests/Fixture.php index 34f01b5..3685211 100644 --- a/tests/Fixture.php +++ b/tests/Fixture.php @@ -15,7 +15,7 @@ class Fixture ], 'b2c' => [ 'name' => 'Business 2 Consumer', - 'url' =>"https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/b2cPayment/singleStage/", + 'url' => "https://openapi.m-pesa.com/sandbox/ipg/v2/vodacomTZN/b2cPayment/singleStage/", ], ]; public static $data_c2b = [ @@ -47,10 +47,44 @@ class Fixture 'input_PurchasedItemsDesc' => 'Salary payment' ]; + public static $data_query = [ + 'input_QueryReference' => '000000000000000000001', + 'input_ServiceProviderCode' => '000000', + 'input_ThirdPartyConversationID' => 'asv02e5958774f7ba228d83d0d689761', + 'input_Country' => 'TZN' + + ]; + + + public static $data_ddc = [ + "input_AgreedTC" => "1", + "input_Country" => "TNZ", + "input_CustomerMSISDN" => "000000000001", + "input_EndRangeOfDays" => "22", + "input_ExpiryDate" => "20201126", + "input_FirstPaymentDate" => "20200324", + "input_Frequency" => "06", // Half Yearly + "input_ServiceProviderCode" => "000000", + "input_StartRangeOfDays" => "01", + "input_ThirdPartyConversationID" => "AAA6d1f9391a0052de0b5334a912jbsj1j2kk", + "input_ThirdPartyReference" => "3333" + ]; + + + public static $data_ddp = [ + "input_Amount" => "10", + "input_Country" => "TNZ", + "input_Currency" => "GHS", + "input_CustomerMSISDN" => "000000000001", + "input_ServiceProviderCode" => "000000", + "input_ThirdPartyConversationID" => "AAA6d1f939c1005v2de053v4912jbasdj1j2kk", + "input_ThirdPartyReference" => "5db410b459bd433ca8e5" + ]; + public static function data() { return [ - 'input_Amount' => rand(1000,2000), + 'input_Amount' => rand(1000, 2000), 'input_Country' => 'TZN', 'input_Currency' => 'TZS', 'input_CustomerMSISDN' => '255766303775', diff --git a/tests/ForodhaTest.php b/tests/ForodhaTest.php index 0909f70..321c354 100644 --- a/tests/ForodhaTest.php +++ b/tests/ForodhaTest.php @@ -2,15 +2,15 @@ namespace Openpesa\SDK\Tests; -use GuzzleHttp\Exception\GuzzleException; -use Openpesa\SDK\Forodha; -use PHPUnit\Framework\TestCase; use GuzzleHttp\Client; +use GuzzleHttp\Exception\GuzzleException; +use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; -use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Request; -use GuzzleHttp\Exception\RequestException; +use GuzzleHttp\Psr7\Response; +use Openpesa\SDK\Forodha; +use PHPUnit\Framework\TestCase; /** * @property Forodha $forodha @@ -44,10 +44,7 @@ public function setup() $this->forodha = new Forodha([ 'api_key' => Fixture::$apiKey, 'public_key' => Fixture::$publicKey, - 'username' => Fixture::$username, - 'auth_url' => Fixture::$authUrl, ], $client); - } /** @test */ @@ -57,8 +54,6 @@ public function forodha_instantiable() $this->assertInstanceOf(Forodha::class, new Forodha([ 'api_key' => Fixture::$apiKey, 'public_key' => Fixture::$publicKey, - 'username' => Fixture::$username, - 'auth_url' => Fixture::$authUrl, 'client_options' => [], ])); } @@ -130,4 +125,36 @@ public function forodha_transact_reversal() $this->assertArrayHasKey('output_ConversationID', $result); $this->assertArrayHasKey('output_ThirdPartyConversationID', $result); } + + /** @test + * @throws GuzzleException + */ + public function forodha_transact_ddc() + { + // Arrange - Done in the set up method + $session = $this->forodha->get_session()['output_SessionID']; + $result = $this->forodha->transact('ddc', Fixture::$data_ddc, $session); + // Act + // Assert + $this->assertArrayHasKey('output_ResponseCode', $result); + $this->assertArrayHasKey('output_ResponseDesc', $result); + $this->assertArrayHasKey('output_ConversationID', $result); + $this->assertArrayHasKey('output_ThirdPartyConversationID', $result); + } + + /** @test + * @throws GuzzleException + */ + public function forodha_transact_ddp() + { + // Arrange - Done in the set up method + $session = $this->forodha->get_session()['output_SessionID']; + $result = $this->forodha->transact('ddp', Fixture::$data_ddp, $session); + // Act + // Assert + $this->assertArrayHasKey('output_ResponseCode', $result); + $this->assertArrayHasKey('output_ResponseDesc', $result); + $this->assertArrayHasKey('output_ConversationID', $result); + $this->assertArrayHasKey('output_ThirdPartyConversationID', $result); + } } From a8a9514ff1270de343db647dbb2947efea3c9866 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Thu, 15 Oct 2020 20:52:46 +0300 Subject: [PATCH 11/25] feat: dowgrade to guzzle 6.5.5 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 872585e..0f870a7 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ ], "require": { "php": "^7.1", - "guzzlehttp/guzzle": "^7.0", + "guzzlehttp/guzzle": "^6.0", "phpseclib/phpseclib": "^2.0", "ext-json": "*", "ext-openssl": "*" From e5cea506e4ad87b40627c109104ec45776238361 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Thu, 15 Oct 2020 20:55:30 +0300 Subject: [PATCH 12/25] feat: add scrutinizer/ocular --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 0f870a7..70f59c8 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,8 @@ "ext-openssl": "*" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^7.0", + "scrutinizer/ocular": "^1.7" }, "autoload": { "psr-4": { From ce72b717d3f3b1f036f4b0bab9c96636a479829a Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Fri, 16 Oct 2020 07:26:33 +0300 Subject: [PATCH 13/25] wip: docs --- .gitattributes | 1 + .gitignore | 2 +- docs/.gitignore | 12 ++ docs/package.json | 19 +++ docs/src/.vuepress/components/Foo/Bar.vue | 15 ++ .../.vuepress/components/OtherComponent.vue | 3 + .../.vuepress/components/demo-component.vue | 15 ++ docs/src/.vuepress/config.js | 68 +++++++++ docs/src/.vuepress/enhanceApp.js | 14 ++ docs/src/.vuepress/styles/index.styl | 8 ++ docs/src/.vuepress/styles/palette.styl | 10 ++ docs/src/README.md | 14 ++ docs/src/config/README.md | 15 ++ docs/src/docs/c2b.md | 130 ++++++++++++++++++ docs/src/docs/composer.md | 26 ++++ docs/src/docs/credits.md | 3 + docs/src/docs/guide.md | 29 ++++ docs/src/docs/installation.md | 13 ++ docs/src/docs/openpesa.md | 3 + docs/src/docs/psr_compliance.md | 19 +++ docs/src/docs/requirements.md | 7 + docs/src/docs/welcome.md | 16 +++ 22 files changed, 441 insertions(+), 1 deletion(-) create mode 100755 docs/.gitignore create mode 100755 docs/package.json create mode 100755 docs/src/.vuepress/components/Foo/Bar.vue create mode 100755 docs/src/.vuepress/components/OtherComponent.vue create mode 100755 docs/src/.vuepress/components/demo-component.vue create mode 100755 docs/src/.vuepress/config.js create mode 100755 docs/src/.vuepress/enhanceApp.js create mode 100755 docs/src/.vuepress/styles/index.styl create mode 100755 docs/src/.vuepress/styles/palette.styl create mode 100755 docs/src/README.md create mode 100755 docs/src/config/README.md create mode 100644 docs/src/docs/c2b.md create mode 100644 docs/src/docs/composer.md create mode 100644 docs/src/docs/credits.md create mode 100644 docs/src/docs/guide.md create mode 100644 docs/src/docs/installation.md create mode 100644 docs/src/docs/openpesa.md create mode 100644 docs/src/docs/psr_compliance.md create mode 100644 docs/src/docs/requirements.md create mode 100644 docs/src/docs/welcome.md diff --git a/.gitattributes b/.gitattributes index bb6265e..06dc57e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,4 +8,5 @@ /phpunit.xml.dist export-ignore /.scrutinizer.yml export-ignore /tests export-ignore +/docs export-ignore /.editorconfig export-ignore diff --git a/.gitignore b/.gitignore index f5ce6a9..d3e29dd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ build composer.lock -docs + vendor coverage diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100755 index 0000000..595e215 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,12 @@ +pids +logs +node_modules +npm-debug.log +coverage/ +run +dist +.DS_Store +.nyc_output +.basement +config.local.js +basement_dist diff --git a/docs/package.json b/docs/package.json new file mode 100755 index 0000000..59c2467 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,19 @@ +{ + "name": "php-pesa", + "version": "0.0.1", + "description": "Pesa PHP SDK", + "main": "index.js", + "authors": { + "name": "Alpha Olomi", + "email": "alphaolomi@gmail.com" + }, + "repository": "https://github.com/openpesa/php-pesa", + "scripts": { + "dev": "vuepress dev src", + "build": "vuepress build src" + }, + "license": "MIT", + "devDependencies": { + "vuepress": "^1.5.3" + } +} diff --git a/docs/src/.vuepress/components/Foo/Bar.vue b/docs/src/.vuepress/components/Foo/Bar.vue new file mode 100755 index 0000000..7ee8286 --- /dev/null +++ b/docs/src/.vuepress/components/Foo/Bar.vue @@ -0,0 +1,15 @@ + + + diff --git a/docs/src/.vuepress/components/OtherComponent.vue b/docs/src/.vuepress/components/OtherComponent.vue new file mode 100755 index 0000000..1d97c7c --- /dev/null +++ b/docs/src/.vuepress/components/OtherComponent.vue @@ -0,0 +1,3 @@ + diff --git a/docs/src/.vuepress/components/demo-component.vue b/docs/src/.vuepress/components/demo-component.vue new file mode 100755 index 0000000..7d49de7 --- /dev/null +++ b/docs/src/.vuepress/components/demo-component.vue @@ -0,0 +1,15 @@ + + + diff --git a/docs/src/.vuepress/config.js b/docs/src/.vuepress/config.js new file mode 100755 index 0000000..fba7fe6 --- /dev/null +++ b/docs/src/.vuepress/config.js @@ -0,0 +1,68 @@ +const { description } = require('../../package') + +module.exports = { + /** + * Ref:https://v1.vuepress.vuejs.org/config/#title + */ + title: 'Pesa PHP SDK', + /** + * Ref:https://v1.vuepress.vuejs.org/config/#description + */ + description: description, + + /** + * Extra tags to be injected to the page HTML `` + * + * ref:https://v1.vuepress.vuejs.org/config/#head + */ + head: [ + ['meta', { name: 'theme-color', content: '#3eaf7c' }], + ['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }], + ['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }] + ], + + /** + * Theme configuration, here is the default theme configuration for VuePress. + * + * ref:https://v1.vuepress.vuejs.org/theme/default-theme-config.html + */ + themeConfig: { + repo: '', + editLinks: false, + docsDir: '', + editLinkText: '', + lastUpdated: false, + nav: [ + { + text: 'Guide', + link: '/docs/guide/', + }, + ], + sidebar: { + '/docs/': [{ + children: [ + 'guide', + 'openpesa', + + 'welcome', + + 'requirements', + 'psr_compliance', + 'credits', + + 'installation', + 'composer', + 'c2b' + ]} + ], + } + }, + + /** + * Apply plugins,ref:https://v1.vuepress.vuejs.org/zh/plugin/ + */ + plugins: [ + '@vuepress/plugin-back-to-top', + '@vuepress/plugin-medium-zoom', + ] +} diff --git a/docs/src/.vuepress/enhanceApp.js b/docs/src/.vuepress/enhanceApp.js new file mode 100755 index 0000000..8452a86 --- /dev/null +++ b/docs/src/.vuepress/enhanceApp.js @@ -0,0 +1,14 @@ +/** + * Client app enhancement file. + * + * https://v1.vuepress.vuejs.org/guide/basic-config.html#app-level-enhancements + */ + +export default ({ + Vue, // the version of Vue being used in the VuePress app + options, // the options for the root Vue instance + router, // the router instance for the app + siteData // site metadata +}) => { + // ...apply enhancements for the site. +} diff --git a/docs/src/.vuepress/styles/index.styl b/docs/src/.vuepress/styles/index.styl new file mode 100755 index 0000000..420feb9 --- /dev/null +++ b/docs/src/.vuepress/styles/index.styl @@ -0,0 +1,8 @@ +/** + * Custom Styles here. + * + * ref:https://v1.vuepress.vuejs.org/config/#index-styl + */ + +.home .hero img + max-width 450px!important diff --git a/docs/src/.vuepress/styles/palette.styl b/docs/src/.vuepress/styles/palette.styl new file mode 100755 index 0000000..6490cb3 --- /dev/null +++ b/docs/src/.vuepress/styles/palette.styl @@ -0,0 +1,10 @@ +/** + * Custom palette here. + * + * ref:https://v1.vuepress.vuejs.org/zh/config/#palette-styl + */ + +$accentColor = #3eaf7c +$textColor = #2c3e50 +$borderColor = #eaecef +$codeBgColor = #282c34 diff --git a/docs/src/README.md b/docs/src/README.md new file mode 100755 index 0000000..ec2f854 --- /dev/null +++ b/docs/src/README.md @@ -0,0 +1,14 @@ +--- +home: true +tagline: Pesa PHP SDK +actionText: Get Started → +actionLink: /docs/guide/ +features: + - title: Easy OpenAPI Intergation + details: intergate OpenAPI with a small footprint. + - title: Zero configuration + details: Library that requires nearly zero configuration. + - title: Documentation + details: Clear, thorough documentation. +footer: Made by Openpesa with ❤️ +--- diff --git a/docs/src/config/README.md b/docs/src/config/README.md new file mode 100755 index 0000000..63a04b9 --- /dev/null +++ b/docs/src/config/README.md @@ -0,0 +1,15 @@ +--- +sidebar: auto +--- + +# Config + +## foo + +- Type: `string` +- Default: `/` + +## bar + +- Type: `string` +- Default: `/` diff --git a/docs/src/docs/c2b.md b/docs/src/docs/c2b.md new file mode 100644 index 0000000..420e6bd --- /dev/null +++ b/docs/src/docs/c2b.md @@ -0,0 +1,130 @@ +# Customer 2 Bussines Transacion Fundamentals + +## How to transact from customer to bussiness + +In this course we will cover what you need to tranct from customer to bussiness using PHP. + +First set up the application in the portal + +When building apps on the sandbox application, Using the sandbox api which allows us to test our application logic without incurring any costs. + +At the bottom left corner of the screen there’s a little phone icon, click it and enter your phone number. This will be the test number you’ll be using and is the number we will send the airtime to. Ensure that you’ve edited the phone number variable we wrote earlier to the phone number you’re using on the simulator. + +we will import the required libraries which have already been preinstalled. + +Here’s the code that does this: + +```php +require 'vendor/autoload.php'; +use Openpesa\SDK\Forodha; +``` + +The above code imports the Pesa SDK for us. + +Next we set our app credentials. + +```php +$apiKey = "your_API_key"; +$publicKey = "your_public_key"; +``` + +These are the credentials that we use to authenticate requests to the OpenAPI service. + +Now we are going to initialize the Pesa SDK. + +```php +$forodha = new Forodha([ + 'api_key' => $apiKey, + 'public_key' => $publicKey, +]); + +``` + +We have just required the Forodha module into our app and assigned it to the `$forodha` variable. We initialize it with our `$api_key` and `$public_key` which will be used to make authenticated calls to the airtime service. Easy right? + +Now let’s setup out transaction. + +```php + +$data = [ + 'input_Amount' => 5000, + 'input_CustomerMSISDN' => '000000000001', + 'input_Country' => 'TZN', + 'input_Currency' => 'TZS', + 'input_ServiceProviderCode' => '000000', + 'input_TransactionReference' => 'T12344Z', + 'input_ThirdPartyConversationID' => '1e9b774d1da34af78412a498cbc28f5d', + 'input_PurchasedItemsDesc' => 'Test Three Item' +]; + +``` + +In order to trnsact from customer to bussines you need the following. + +- An Amount +- A CustomerMSISDN +- Country +- Currency +- Service Provider Code +- Transaction Reference +- Purchased Items Desc +- ThirdParty Conversation ID + +Next up we have a function to execute the transaction right below the `// Execute transaction` line + +```php +try { + // Execute transaction + $result = $forodha->transact('c2b', $data); + print_r($result); +} catch (Throwable $th) { + echo $th->getMessage(); +} + +``` + +If the code works and the transaction is succesiful, it will print the response onto the console logs. If it’s not successful, it will print out an error instead. + +You’re all set! + + +## Example Full + +```php + $apiKey, + 'public_key' => $publicKey, +]); + + +$data = [ + 'input_Amount' => 5000, + 'input_CustomerMSISDN' => '000000000001', + 'input_Country' => 'TZN', + 'input_Currency' => 'TZS', + 'input_ServiceProviderCode' => '000000', + 'input_TransactionReference' => 'T12344Z', + 'input_ThirdPartyConversationID' => '1e9b774d1da34af78412a498cbc28f5d', + 'input_PurchasedItemsDesc' => 'Test Three Item' +]; + + +try { + $result = $forodha->transact('c2b', $data); + print_r($result); +} catch (Throwable $th) { + echo $th->getMessage(); +} + + +``` + +Happy Coding!! 😀 diff --git a/docs/src/docs/composer.md b/docs/src/docs/composer.md new file mode 100644 index 0000000..2e5af48 --- /dev/null +++ b/docs/src/docs/composer.md @@ -0,0 +1,26 @@ +## Installing to an Existing Project + +The Pesa PHP SDK can be an existing project using Composer. + +In your project root: + +```sh +$ composer require openpesa/pesa +``` + +As with the earlier two composer install methods, you can omit installing phpunit and its dependencies by adding the `“–no-dev”` argument to the `“composer require”` command. + +## Set Up + +Copy add API_KEY to your env + + +### Upgrading + +Whenever there is a new release, then from the command line in your project root: + +```sh +$ composer update +``` + +Read the upgrade instructions, and check designated app/Config folders for affected changes. diff --git a/docs/src/docs/credits.md b/docs/src/docs/credits.md new file mode 100644 index 0000000..b090f6a --- /dev/null +++ b/docs/src/docs/credits.md @@ -0,0 +1,3 @@ +# Credits + +Pesa SDK was originally and still being developed by Openpesa. diff --git a/docs/src/docs/guide.md b/docs/src/docs/guide.md new file mode 100644 index 0000000..47b7442 --- /dev/null +++ b/docs/src/docs/guide.md @@ -0,0 +1,29 @@ +# Pesa PHP SDK User Guide + +- Welcome to Pesa PHP SDK + + - Server Requirements + - Credits + - PSR Compliance + +- Getting Started + + - Installation + - Composer Installation + - Upgrading From a Previous Version + - Pesa PHP SDK Repositories + +- Build Your First Application + + - Build Your First Application + - Static pages + - Create news items + - Conclusion + + +- Advanced Topics + - Testing + - Getting Started + - Generating Data + - HTTP Testing + - Debugging Your Application diff --git a/docs/src/docs/installation.md b/docs/src/docs/installation.md new file mode 100644 index 0000000..993b03a --- /dev/null +++ b/docs/src/docs/installation.md @@ -0,0 +1,13 @@ +## Installation + +Pesa PHP SDK can be installed using Composer, + +## + +- [Composer Installation](#) +- [Pesa PHP SDK Repositories](#) + + +> ## Note +> +> Before using Pesa PHP SDK , make sure that your enviroment(server) meets the requirements, in particular the PHP version and the PHP extensions that are needed. You may find that you have to uncomment the php.ini “extension” lines to enable “curl” and “intl”, for instance. diff --git a/docs/src/docs/openpesa.md b/docs/src/docs/openpesa.md new file mode 100644 index 0000000..f5a932c --- /dev/null +++ b/docs/src/docs/openpesa.md @@ -0,0 +1,3 @@ +# Welcome to Openpesa + +Openpesa is a community driven organisation \ No newline at end of file diff --git a/docs/src/docs/psr_compliance.md b/docs/src/docs/psr_compliance.md new file mode 100644 index 0000000..2ceb13e --- /dev/null +++ b/docs/src/docs/psr_compliance.md @@ -0,0 +1,19 @@ +# PSR Compliance + +The PHP-FIG was created in 2009 to help make code more interoperable between frameworks by ratifying Interfaces, style guides, and more that members were free to implement or not. While Pesa PHP SDK is not a member of the FIG, we are compatible with a number of their proposals. This guide is meant to list the status of our compliance with the various accepted, and some draft, proposals. + +## PSR-1: Basic Coding Standard + +This recommendation covers basic class, method, and file-naming standards. Our style guide meets PSR-1 and adds its own requirements on top of it. + +## PSR-2: Coding Style Guide + +This PSR was fairly controversial when it first came out. Pesa PHP SDK meets many of the recommendations within, but does not, and will not, meet all of them. + +## PSR-4: Autoloading Standard + +This PSR provides a method for organizing file and namespaces to allow for a standard method of autoloading classes. Our Autoloader meets the PSR-4 recommendations. + +— + +If you find any places that we claim to meet a PSR but have failed to execute it correctly, please let us know and we will get it fixed, or submit a pull request with the required changes. diff --git a/docs/src/docs/requirements.md b/docs/src/docs/requirements.md new file mode 100644 index 0000000..d9ab635 --- /dev/null +++ b/docs/src/docs/requirements.md @@ -0,0 +1,7 @@ +# Server Requirements + +PHP version 7.1 or newer is required, with the *curl* extension and *mbstring* extension installed. + +The following PHP extensions should be enabled on your server: `php-json`, `php-curl` + +In order to use the CURLRequest, you will need `libcurl` installed. diff --git a/docs/src/docs/welcome.md b/docs/src/docs/welcome.md new file mode 100644 index 0000000..9aa3f30 --- /dev/null +++ b/docs/src/docs/welcome.md @@ -0,0 +1,16 @@ +# Welcome to Pesa PHP SDK + +Pesa PHP SDK is an Software Development Kit - a toolkit - for people who build apps using PHP. Its goal is to enable you to intergrate OpenAPI much faster than you could if you were writing code from scratch, by providing a rich set of function for commonly needed tasks, as well as a simple interface and logical structure to access these libraries. Pesa SDK lets you creatively focus on your project by minimizing the amount of code needed for a given task. + +Where possible, Pesa SDK has been kept as flexible as possible, allowing you to work in the way you want, not being forced into working any certain way. The library can have core parts easily extended or completely replaced to make the system work the way you need it to. In short, Pesa PHP SDK is the malleable framework that tries to provide the tools you need while staying out of the way. + +## Who is Pesa PHP SDK For? + +Pesa PHP SDK is right for you if: + +- You want a intergate OpenAPI with a small footprint. +- You want a library that requires nearly zero configuration. +- You want a library that does not require you to use the command line. +- You are not interested in large-scale monolithic libraries like PEAR. +- You eschew complexity, favoring simple solutions. +- You need clear, thorough documentation. \ No newline at end of file From 0d3bb4fc6fd8d5588c659ce168473f9581f274ba Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Fri, 16 Oct 2020 07:49:18 +0300 Subject: [PATCH 14/25] fix(ci): uploading code covrage to scrutinizer --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index a57b1db..cd951dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,8 @@ before_script: - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source script: - - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover + - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover -after_script: - - php vendor/bin/ocular code-coverage:upload --format=php-clover coverage.clover +after_script: + - wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --repository=openpesa/php-pesa --format=php-clover coverage.clover + \ No newline at end of file From 23b44230cfed7bcfa6103437aee66973b0b838c5 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Fri, 16 Oct 2020 08:19:20 +0300 Subject: [PATCH 15/25] wip: deploy docs on github pages --- .travis.yml | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index a57b1db..2076cd1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,21 +1,38 @@ language: php php: -# - 7.1 - - 7.2 + # - 7.1 + # - 7.2 - 7.3 -env: - matrix: - - COMPOSER_FLAGS="--prefer-lowest" - - COMPOSER_FLAGS="" +# env: +# matrix: +# - COMPOSER_FLAGS="--prefer-lowest" +# - COMPOSER_FLAGS="" + +before_install: + - nvm install stable + - nvm use stable + before_script: - travis_retry composer self-update - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source + - npm ci script: - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover + - cd docs && npm run build after_script: - php vendor/bin/ocular code-coverage:upload --format=php-clover coverage.clover + + +deploy: + provider: pages + skip_cleanup: true + local_dir: docs/src/.vuepress/dist + github_token: $GITHUB_TOKEN + keep_history: true + on: + branch: dov-docs \ No newline at end of file From 49590b23e8d3350f732e8ed0edd76b6979b6f0f1 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Fri, 16 Oct 2020 08:30:42 +0300 Subject: [PATCH 16/25] fix: update license --- LICENSE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.md b/LICENSE.md index a7d6e4b..71a9e00 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) Alpha Olomi +Copyright (c) Openpesa Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From a54fda9f79322e6c78e0bf4bad9d71c20130cde0 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Fri, 16 Oct 2020 08:30:47 +0300 Subject: [PATCH 17/25] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2076cd1..70568f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,7 @@ before_install: before_script: - travis_retry composer self-update - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source - - npm ci + - cd docs && npm ci script: - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover From 65299000446f5397b9026d5359fbe7513b50cf28 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Fri, 16 Oct 2020 08:37:39 +0300 Subject: [PATCH 18/25] Update .travis.yml --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 70568f7..4ab0f5d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,13 +10,17 @@ php: # - COMPOSER_FLAGS="--prefer-lowest" # - COMPOSER_FLAGS="" +cache: + directories: + - $HOME/.composer/cache + before_install: - nvm install stable - nvm use stable before_script: - - travis_retry composer self-update + # - travis_retry composer self-update - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source - cd docs && npm ci From 86eeed2a7caf4d8b784135f0c19e86f1e58e9115 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Fri, 16 Oct 2020 08:44:22 +0300 Subject: [PATCH 19/25] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4ab0f5d..2cfee10 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ before_install: before_script: # - travis_retry composer self-update - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source - - cd docs && npm ci + - cd docs && npm install script: - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover From 9e12a86552655e4cfce09dabe7b2fb1cfc282673 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Fri, 16 Oct 2020 09:08:08 +0300 Subject: [PATCH 20/25] Update .travis.yml --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index c908297..17ef240 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,15 +26,15 @@ before_script: script: - ./vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover - cd docs && npm run build && cd .. - -after_script: - wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --repository=openpesa/php-pesa --format=php-clover coverage.clover +# after_script: + deploy: provider: pages strategy: git - cleanup: false - local_dir: docs/src/.vuepress/dist + skip_cleanup: true + local_dir: ./docs/src/.vuepress/dist token: $GITHUB_TOKEN keep_history: true on: From 183299495a6ab45a456285fb287610f7f6e011b5 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Fri, 16 Oct 2020 09:13:40 +0300 Subject: [PATCH 21/25] Update .travis.yml --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 17ef240..1385746 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,9 @@ php: # - COMPOSER_FLAGS="--prefer-lowest" # - COMPOSER_FLAGS="" -cache: - directories: - - $HOME/.composer/cache +# cache: + # directories: + # - $HOME/.composer/cache before_install: - nvm install stable @@ -25,8 +25,8 @@ before_script: script: - ./vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover + - wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover coverage.clover - cd docs && npm run build && cd .. - - wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --repository=openpesa/php-pesa --format=php-clover coverage.clover # after_script: From 22d0c4166a4582e00f1e893719f30b14312723c0 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Fri, 16 Oct 2020 09:26:42 +0300 Subject: [PATCH 22/25] ci: change code covrage to codecov --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1385746..222ec22 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,11 +24,12 @@ before_script: - cd docs && npm install && cd .. script: - - ./vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover - - wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover coverage.clover + # - ./vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover + - ./vendor/bin/phpunit --coverage-clover coverage.xml - cd docs && npm run build && cd .. -# after_script: +after_success: + - bash <(curl -s https://codecov.io/bash) deploy: provider: pages From cda294eb532f2e51ff13c3e8e06799c2471e3635 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Fri, 16 Oct 2020 10:48:32 +0300 Subject: [PATCH 23/25] docs: fix typos and readme --- README.md | 82 ++++++++++++++++++++++----------- docs/package.json | 5 +- docs/src/.vuepress/config.js | 30 ++++++++++-- docs/src/README.md | 2 +- docs/src/docs/c2b.md | 27 +++++++---- docs/src/docs/composer.md | 4 +- docs/src/docs/installation.md | 4 +- docs/src/docs/psr_compliance.md | 6 ++- docs/src/docs/welcome.md | 7 +-- 9 files changed, 114 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 6783b7c..09343a3 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,60 @@ -# Pesa SDK +# Pesa SDK for PHP -[![Latest Version on Packagist](https://img.shields.io/packagist/v/openpesa/pesa.svg?style=flat-square)](https://packagist.org/packages/openpesa/pesa) -[![Build Status](https://img.shields.io/travis/openpesa/php-pesa/master.svg?style=flat-square)](https://travis-ci.org/openpesa/php-pesa) -[![Quality Score](https://img.shields.io/scrutinizer/g/openpesa/php-pesa.svg?style=flat-square)](https://scrutinizer-ci.com/g/openpesa/pesa) +[![Latest Version on Packagist](https://img.shields.io/packagist/v/openpesa/pesa.svg?style=flat-square&?include_prereleases)](https://packagist.org/packages/openpesa/pesa) +[![Build Status](https://img.shields.io/travis/openpesa/php-pesa/develop.svg?style=flat-square)](https://travis-ci.org/openpesa/php-pesa) +[![codecov.io](https://codecov.io/github/openpesa/php-pesa/coverage.svg)](https://codecov.io/github/openpesa/php-pesa) [![Total Downloads](https://img.shields.io/packagist/dt/openpesa/pesa.svg?style=flat-square)](https://packagist.org/packages/openpesa/pesa) -This is where your description should go. Try and limit it to a paragraph or two, and maybe throw in a mention of what PSRs you support to avoid any confusion with users and contributors. +The **Pesa SDK for PHP** makes it easy for developers to access [OpenAPI](https://openapiportal.m-pesa.com/) in their PHP code, and build robust applications and software using services like Customber 2 Bussiness, Query etc. -## Installation +## Documentation -You can install the package via composer: +Take a look at the [API docs here](https://php-pesa.netlify.app/). + +## Getting Started + +1. **Sign up for OpenAPI Portal** – Before you begin, you need to + sign up for an account and retrieve your credentials. + +1. **Minimum requirements** – To run the SDK, your system will need to meet the + [minimum requirements](https://php-pesa.netlify.app/docs/requirements.html), including having **PHP >= 7.1**. + +1. **Install the SDK** – Using [Composer] is the recommended way to install the + Pesa SDK for PHP. The SDK is available via [Packagist] under the + [`openpesa/php-pesa`](https://packagist.org/packages/openpesa/pesa) package. If Composer is installed globally on your system, you can run the following in the base directory of your project to add the SDK as a dependency: + ```sh + composer require openpesa/pesa + ``` + Please see the + [Installation section of the User Guide](https://php-pesa.netlify.app/docs/installation.html) for more + detailed information about installing the SDK through Composer and other + means. +1. **Using the SDK** – The best way to become familiar with how to use the SDK + is to read the [User Guide](https://php-pesa.netlify.app/docs/guide.html). + + -```bash -composer require openpesa/pesa -``` ## Usage -``` php +### Quick Examples + +```php -require '../vendor/autoload.php'; +require 'vendor/autoload.php'; use Openpesa\SDK\Forodha; -// Intiate with keys +// Intiate with credntials $forodha = new Forodha([ - 'api_key' => 'YOUR_API_KEY', // use 'sandbox' for development in the test environment - 'public_key' => 'PUBLIC_KEY', // use your sandbox app API key for development in the test environment - 'client_options' => [], // + 'api_key' => 'YOUR_API_KEY', + 'public_key' => 'PUBLIC_KEY', + 'client_options' => [], ]); -// Setup the input amount +// Setup the transaction $data = [ 'input_Amount' => '10000', 'input_Country' => 'TZN', @@ -42,26 +66,34 @@ $data = [ 'input_PurchasedItemsDesc' => 'Test Two Item' ]; -// Use the service +// Execute $result = $forodha->transact('c2b', $data); +// Print results var_dump($result); ``` +For more example check [pesa-demo-example](https://github.com/openpesa/php-pesa/tree/develop/examples). + ### Testing -``` bash +```bash composer test ``` +## Opening Issues + +If you have a feature requrest or you encounter a bug, please file an issue on [our issue tracker on GitHub](https://github.com/openpesa/php-pesa/issues). + ### Changelog Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently. ## Contributing -Please see [CONTRIBUTING](CONTRIBUTING.md) for details. +Please review our [CONTRIBUTING](CONTRIBUTING.md) for details. + ### Security @@ -69,14 +101,10 @@ If you discover any security related issues, please email alphaolomi@gmail.com i ## Credits -- [Alpha Olomi](https://github.com/openpesa) -- [Ley](https://github.com/leyluj) -- [All Contributors](../../contributors) +- [Alpha Olomi](https://github.com/openpesa) +- [Ley](https://github.com/leyluj) +- [All Contributors](../../contributors) ## License The MIT License (MIT). Please see [License File](LICENSE.md) for more information. - -## PHP Package Boilerplate - -This package was generated using the [PHP Package Boilerplate](https://laravelpackageboilerplate.com). diff --git a/docs/package.json b/docs/package.json index 59c2467..984ea1a 100755 --- a/docs/package.json +++ b/docs/package.json @@ -1,8 +1,7 @@ { - "name": "php-pesa", + "name": "php-pesa-docs", "version": "0.0.1", - "description": "Pesa PHP SDK", - "main": "index.js", + "description": "Pesa SDK for PHP", "authors": { "name": "Alpha Olomi", "email": "alphaolomi@gmail.com" diff --git a/docs/src/.vuepress/config.js b/docs/src/.vuepress/config.js index fba7fe6..5f967ab 100755 --- a/docs/src/.vuepress/config.js +++ b/docs/src/.vuepress/config.js @@ -27,11 +27,31 @@ module.exports = { * ref:https://v1.vuepress.vuejs.org/theme/default-theme-config.html */ themeConfig: { - repo: '', - editLinks: false, - docsDir: '', - editLinkText: '', - lastUpdated: false, + smoothScroll: true, + + // Assumes GitHub. Can also be a full GitLab url. + repo: 'openpesa/php-pesa', + // Customising the header label + // Defaults to "GitHub"/"GitLab"/"Bitbucket" depending on `themeConfig.repo` + repoLabel: 'Contribute!', + + // Optional options for generating "Edit this page" link + + // if your docs are in a different repo from your main project: + docsRepo: 'openpesa/php-pesa', + // if your docs are not at the root of the repo: + docsDir: 'docs', + // if your docs are in a specific branch (defaults to 'master'): + docsBranch: 'develop', + // defaults to false, set to true to enable + editLinks: true, + // custom text for edit link. Defaults to "Edit this page" + editLinkText: 'Help us improve this page!', + // repo: '', + // editLinks: false, + // docsDir: '', + // editLinkText: '', + lastUpdated: true, nav: [ { text: 'Guide', diff --git a/docs/src/README.md b/docs/src/README.md index ec2f854..6d5c18d 100755 --- a/docs/src/README.md +++ b/docs/src/README.md @@ -5,7 +5,7 @@ actionText: Get Started → actionLink: /docs/guide/ features: - title: Easy OpenAPI Intergation - details: intergate OpenAPI with a small footprint. + details: Intergate OpenAPI with a small footprint. - title: Zero configuration details: Library that requires nearly zero configuration. - title: Documentation diff --git a/docs/src/docs/c2b.md b/docs/src/docs/c2b.md index 420e6bd..260dc86 100644 --- a/docs/src/docs/c2b.md +++ b/docs/src/docs/c2b.md @@ -1,12 +1,12 @@ -# Customer 2 Bussines Transacion Fundamentals +# Customer 2 Bussines Transaction Fundamentals -## How to transact from customer to bussiness +## How to transact from customer to business -In this course we will cover what you need to tranct from customer to bussiness using PHP. +In this course, we will cover what you need to transact from customers to businesses using PHP. First set up the application in the portal -When building apps on the sandbox application, Using the sandbox api which allows us to test our application logic without incurring any costs. +When building apps on the sandbox application, Using the sandbox API which allows us to test our application logic without incurring any costs. At the bottom left corner of the screen there’s a little phone icon, click it and enter your phone number. This will be the test number you’ll be using and is the number we will send the airtime to. Ensure that you’ve edited the phone number variable we wrote earlier to the phone number you’re using on the simulator. @@ -14,6 +14,7 @@ we will import the required libraries which have already been preinstalled. Here’s the code that does this: + ```php require 'vendor/autoload.php'; use Openpesa\SDK\Forodha; @@ -21,7 +22,9 @@ use Openpesa\SDK\Forodha; The above code imports the Pesa SDK for us. -Next we set our app credentials. +Next, we set our app credentials. + + ```php $apiKey = "your_API_key"; @@ -42,7 +45,8 @@ $forodha = new Forodha([ We have just required the Forodha module into our app and assigned it to the `$forodha` variable. We initialize it with our `$api_key` and `$public_key` which will be used to make authenticated calls to the airtime service. Easy right? -Now let’s setup out transaction. +Now let’s set up our transaction. + ```php @@ -59,7 +63,7 @@ $data = [ ``` -In order to trnsact from customer to bussines you need the following. +In order to transact from customer to business, you need the following. - An Amount - A CustomerMSISDN @@ -70,7 +74,8 @@ In order to trnsact from customer to bussines you need the following. - Purchased Items Desc - ThirdParty Conversation ID -Next up we have a function to execute the transaction right below the `// Execute transaction` line +Next up we have a function to execute the transaction right below the `// Execute transaction` line. + ```php try { @@ -83,12 +88,14 @@ try { ``` -If the code works and the transaction is succesiful, it will print the response onto the console logs. If it’s not successful, it will print out an error instead. +If the code works and the transaction is successful, it will print the response onto the console logs. If it’s not successful, it will print out an error instead. You’re all set! -## Example Full + +## Example Full + ```php ## Note > -> Before using Pesa PHP SDK , make sure that your enviroment(server) meets the requirements, in particular the PHP version and the PHP extensions that are needed. You may find that you have to uncomment the php.ini “extension” lines to enable “curl” and “intl”, for instance. +> Before using Pesa PHP SDK, make sure that your environment(server) meets the requirements, in particular, the PHP version and the PHP extensions that are needed. You may find that you have to uncomment the php.ini “extension” lines to enable “curl” and “intl”, for instance. + + diff --git a/docs/src/docs/psr_compliance.md b/docs/src/docs/psr_compliance.md index 2ceb13e..84e84f6 100644 --- a/docs/src/docs/psr_compliance.md +++ b/docs/src/docs/psr_compliance.md @@ -4,7 +4,7 @@ The PHP-FIG was created in 2009 to help make code more interoperable between fra ## PSR-1: Basic Coding Standard -This recommendation covers basic class, method, and file-naming standards. Our style guide meets PSR-1 and adds its own requirements on top of it. +This recommendation covers the basic class, method, and file-naming standards. Our style guide meets PSR-1 and adds its own requirements on top of it. ## PSR-2: Coding Style Guide @@ -12,8 +12,10 @@ This PSR was fairly controversial when it first came out. Pesa PHP SDK meets man ## PSR-4: Autoloading Standard -This PSR provides a method for organizing file and namespaces to allow for a standard method of autoloading classes. Our Autoloader meets the PSR-4 recommendations. +This PSR provides a method for organizing files and namespaces to allow for a standard method of autoloading classes. Our Autoloader meets the PSR-4 recommendations. — If you find any places that we claim to meet a PSR but have failed to execute it correctly, please let us know and we will get it fixed, or submit a pull request with the required changes. + + diff --git a/docs/src/docs/welcome.md b/docs/src/docs/welcome.md index 9aa3f30..cbaaacb 100644 --- a/docs/src/docs/welcome.md +++ b/docs/src/docs/welcome.md @@ -1,6 +1,6 @@ # Welcome to Pesa PHP SDK -Pesa PHP SDK is an Software Development Kit - a toolkit - for people who build apps using PHP. Its goal is to enable you to intergrate OpenAPI much faster than you could if you were writing code from scratch, by providing a rich set of function for commonly needed tasks, as well as a simple interface and logical structure to access these libraries. Pesa SDK lets you creatively focus on your project by minimizing the amount of code needed for a given task. +Pesa PHP SDK is a Software Development Kit - a toolkit - for people who build apps using PHP. Its goal is to enable you to integrate OpenAPI much faster than you could if you were writing code from scratch, by providing a rich set of functions for commonly needed tasks, as well as a simple interface and logical structure to access these libraries. Pesa SDK lets you creatively focus on your project by minimizing the amount of code needed for a given task. Where possible, Pesa SDK has been kept as flexible as possible, allowing you to work in the way you want, not being forced into working any certain way. The library can have core parts easily extended or completely replaced to make the system work the way you need it to. In short, Pesa PHP SDK is the malleable framework that tries to provide the tools you need while staying out of the way. @@ -8,9 +8,10 @@ Where possible, Pesa SDK has been kept as flexible as possible, allowing you to Pesa PHP SDK is right for you if: -- You want a intergate OpenAPI with a small footprint. +- You want to integrate OpenAPI with a small footprint. - You want a library that requires nearly zero configuration. - You want a library that does not require you to use the command line. - You are not interested in large-scale monolithic libraries like PEAR. - You eschew complexity, favoring simple solutions. -- You need clear, thorough documentation. \ No newline at end of file +- You need clear, thorough documentation. + From 1c12889c77e4f6c35da917be2717bd70cf802ad4 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Fri, 16 Oct 2020 10:56:31 +0300 Subject: [PATCH 24/25] test: added forodha_query_status test --- tests/ForodhaTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/ForodhaTest.php b/tests/ForodhaTest.php index 321c354..357ec0e 100644 --- a/tests/ForodhaTest.php +++ b/tests/ForodhaTest.php @@ -126,6 +126,22 @@ public function forodha_transact_reversal() $this->assertArrayHasKey('output_ThirdPartyConversationID', $result); } + /** @test + * @throws GuzzleException + */ + public function forodha_query_status() + { + // Arrange - Done in the set up method + $session = $this->forodha->get_session()['output_SessionID']; + $result = $this->forodha->query(Fixture::$data_query, $session); + // Act + // Assert + $this->assertArrayHasKey('output_ResponseCode', $result); + $this->assertArrayHasKey('output_ResponseDesc', $result); + $this->assertArrayHasKey('output_ConversationID', $result); + $this->assertArrayHasKey('output_ThirdPartyConversationID', $result); + } + /** @test * @throws GuzzleException */ From 4550b696e8c06532fe51d171a91cfe8f58b97ae1 Mon Sep 17 00:00:00 2001 From: Alpha Olomi Date: Fri, 16 Oct 2020 11:26:25 +0300 Subject: [PATCH 25/25] fix: typo + incorrect encryptSessionKey value --- src/Forodha.php | 13 +++++++------ tests/Fixture.php | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Forodha.php b/src/Forodha.php index 2ff9878..575c581 100644 --- a/src/Forodha.php +++ b/src/Forodha.php @@ -46,31 +46,31 @@ class Forodha 'c2b' => [ 'name' => 'Consumer 2 Business', 'url' => self::BASE_DOMAIN . "ipg/v2/vodacomTZN/c2bPayment/singleStage/", - 'encryptSessionKey' => false, + 'encryptSessionKey' => true, 'rules' => [] ], 'b2c' => [ 'name' => 'Business 2 Consumer', 'url' => self::BASE_DOMAIN . "ipg/v2/vodacomTZN/b2cPayment/singleStage/", - 'encryptSessionKey' => false, + 'encryptSessionKey' => true, 'rules' => [] ], 'rt' => [ 'name' => 'Reverse Transaction', 'url' => self::BASE_DOMAIN . "ipg/v2/vodacomTZN/reversal/", - 'encryptSessionKey' => false, + 'encryptSessionKey' => true, 'rules' => [] ], 'query' => [ 'name' => 'Query Transaction Status', 'url' => self::BASE_DOMAIN . "ipg/v2/vodacomTZN/queryTransactionStatus/", - 'encryptSessionKey' => false, + 'encryptSessionKey' => true, 'rules' => [] ], 'ddc' => [ 'name' => 'Direct Debits create', 'url' => self::BASE_DOMAIN . "ipg/v2/vodacomTZN/directDebitCreation/", - 'encryptSessionKey' => false, + 'encryptSessionKey' => true, 'rules' => [] ], 'ddp' => [ @@ -83,7 +83,7 @@ class Forodha /** * Forodha constructor. - * @param $options + * @param $options array * @param null $client * @param null $rsa */ @@ -91,6 +91,7 @@ public function __construct($options, $client = null, $rsa = null) { $options['auth_url'] = $options['auth_url'] ?? self::AUTH_URL; + $options['client_options'] = $options['client_options'] ?? array(); $this->options = $options; $this->client = ($client instanceof Client) ? $client diff --git a/tests/Fixture.php b/tests/Fixture.php index 3685211..2421838 100644 --- a/tests/Fixture.php +++ b/tests/Fixture.php @@ -58,7 +58,7 @@ class Fixture public static $data_ddc = [ "input_AgreedTC" => "1", - "input_Country" => "TNZ", + "input_Country" => "TZN", "input_CustomerMSISDN" => "000000000001", "input_EndRangeOfDays" => "22", "input_ExpiryDate" => "20201126", @@ -74,7 +74,7 @@ class Fixture public static $data_ddp = [ "input_Amount" => "10", "input_Country" => "TNZ", - "input_Currency" => "GHS", + "input_Currency" => "TZS", "input_CustomerMSISDN" => "000000000001", "input_ServiceProviderCode" => "000000", "input_ThirdPartyConversationID" => "AAA6d1f939c1005v2de053v4912jbasdj1j2kk",