diff --git a/.distignore b/.distignore
index dbd5845..d1908d7 100644
--- a/.distignore
+++ b/.distignore
@@ -2,4 +2,6 @@
docker-compose.yml
.gitignore
.github
-.env.example
\ No newline at end of file
+.env.example
+.docker
+Makefile
diff --git a/.docker/docker-compose.yml b/.docker/docker-compose.yml
new file mode 100644
index 0000000..2e89b0e
--- /dev/null
+++ b/.docker/docker-compose.yml
@@ -0,0 +1,17 @@
+services:
+ web:
+ image: nginx:latest
+ ports:
+ - "80:80"
+ volumes:
+ - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
+ depends_on:
+ - app
+ app:
+ build:
+ context: .
+ dockerfile: ./php/Dockerfile
+ db:
+ image: mysql:5.7
+ volumes:
+ - ./mysql:/var/lib/mysql
\ No newline at end of file
diff --git a/.docker/nginx/default.conf b/.docker/nginx/default.conf
new file mode 100644
index 0000000..deea96f
--- /dev/null
+++ b/.docker/nginx/default.conf
@@ -0,0 +1,18 @@
+server {
+ listen 80;
+ server_name localhost;
+ root /var/www/html/public;
+ index index.php;
+
+ location ~ \.php$ {
+ fastcgi_pass app:9000;
+ fastcgi_index index.php;
+ fastcgi_param REQUEST_METHOD $request_method;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ include fastcgi_params;
+ }
+
+ location / {
+ try_files $uri $uri/ /index.php?$query_string;
+ }
+}
\ No newline at end of file
diff --git a/.docker/php/Dockerfile b/.docker/php/Dockerfile
new file mode 100644
index 0000000..0b11c16
--- /dev/null
+++ b/.docker/php/Dockerfile
@@ -0,0 +1,52 @@
+FROM php:8.1-fpm-alpine as app
+
+# Useful PHP extension installer image, copy binary into your container
+COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
+
+# Install php extensions
+# exit on errors, exit on unset variables, print every command as it is executed
+RUN set -eux; \
+ install-php-extensions pdo pdo_mysql;
+
+# RUN docker-php-ext-install pdo pdo_mysql
+
+# allow super user - set this if you use Composer as a
+# super user at all times like in docker containers
+ENV COMPOSER_ALLOW_SUPERUSER=1
+
+# obtain composer using multi-stage build
+# https://docs.docker.com/build/building/multi-stage/
+COPY --from=composer:2.4 /usr/bin/composer /usr/bin/composer
+
+#Here, we are copying only composer.json and composer.lock (instead of copying the entire source)
+# right before doing composer install.
+# This is enough to take advantage of docker cache and composer install will
+# be executed only when composer.json or composer.lock have indeed changed!-
+# https://medium.com/@softius/faster-docker-builds-with-composer-install-b4d2b15d0fff
+COPY ./app/composer.* ./
+
+# install
+RUN composer install --prefer-dist --no-dev --no-scripts --no-progress --no-interaction
+
+# copy application files to the working directory
+COPY ./app .
+
+# run composer dump-autoload --optimize
+RUN composer dump-autoload --optimize
+
+# Dev image
+# This stage is meant to be target-built into a separate image
+# https://docs.docker.com/develop/develop-images/multistage-build/#stop-at-a-specific-build-stage
+# https://docs.docker.com/compose/compose-file/#target
+FROM app as app_dev
+
+# Xdebug has different modes / functionalities. We can default to 'off' and set to 'debug'
+# when we run docker compose up if we need it
+ENV XDEBUG_MODE=off
+
+# Copy xdebug config file into container
+COPY ./php/conf.d/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini
+
+# Install xdebug
+RUN set -eux; \
+ install-php-extensions xdebug
\ No newline at end of file
diff --git a/.docker/php/conf.d/xdebug.ini b/.docker/php/conf.d/xdebug.ini
new file mode 100644
index 0000000..0b4327e
--- /dev/null
+++ b/.docker/php/conf.d/xdebug.ini
@@ -0,0 +1 @@
+xdebug.client_host = 'host.docker.internal'
\ No newline at end of file
diff --git a/.github/workflows/change-review.yml b/.github/workflows/change-review.yml
new file mode 100644
index 0000000..2dc7be7
--- /dev/null
+++ b/.github/workflows/change-review.yml
@@ -0,0 +1,78 @@
+name: Review changes on Dev (Commits/PRs)
+
+on:
+ push:
+ branches: ["dev"]
+ pull_request:
+ types:
+ - opened
+
+jobs:
+ code-check:
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: true
+ matrix:
+ php: [7.4, 8.1, 8.2]
+
+ env:
+ XDEBUG_MODE: coverage
+ PUBLIC_KEY: ${{ secrets.PUBLIC_KEY }}
+ SECRET_KEY: ${{ secrets.SECRET_KEY }}
+ ENCRYPTION_KEY: ${{ secrets.ENCRYPTION_KEY }}
+ ENV: ${{ secrets.ENV }}
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite
+ coverage: xdebug
+
+ - name: Validate composer.json and composer.lock
+ run: composer validate --strict
+
+ - name: Cache Composer packages
+ id: composer-cache
+ uses: actions/cache@v3
+ with:
+ path: vendor
+ key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-php-
+
+ - name: Install dependencies
+ run: composer install --prefer-dist --no-progress
+
+ - name: 'Create env file'
+ run: |
+ touch .env
+ echo PUBLIC_KEY=${PUBLIC_KEY} >> .env
+ echo SECRET_KEY=${SECRET_KEY} >> .env
+ echo ENCRYPTION_KEY=${ENCRYPTION_KEY} >> .env
+ echo ENV=${ENV} >> .env
+ ls -a ${{ github.workspace }}
+
+ - name: run unit tests and coverage scan
+ run: ./vendor/bin/pest --coverage --min=20 --coverage-clover ./coverage.xml
+
+ - name: Upload to Codecov
+ uses: codecov/codecov-action@v2
+ with:
+ token: ${{ secrets.CODE_COV_TOKEN }}
+ files: ./coverage.xml
+ verbose: true
+
+ - name: push build status to Slack
+ uses: 8398a7/action-slack@v3
+ with:
+ status: ${{ job.status }}
+ fields: repo,message,commit,author,action,eventName,ref,workflow,job,took,pullRequest
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
+ MATRIX_CONTEXT: ${{ toJson(matrix) }}
+ if: always()
diff --git a/.github/workflows/package-publish.yml b/.github/workflows/package-publish.yml
new file mode 100644
index 0000000..5d005d2
--- /dev/null
+++ b/.github/workflows/package-publish.yml
@@ -0,0 +1,46 @@
+name: Pre-release
+
+on:
+ release:
+ types: [created]
+
+jobs:
+ check-docs-update:
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: true
+ matrix:
+ php: [7.4, 8.1, 8.2]
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: technote-space/get-diff-action@v6
+ with:
+ PATTERNS: |
+ +(documentation)/*.md
+ *.md
+ CHANGE*.md
+ FILES: |
+ CHANGELOG.md
+
+ - name: log git diff
+ run: |
+ echo ${{ env.GIT_DIFF }}
+ echo ${{ env.MATCHED_FILES }}
+ echo ${{ env.GIT_DIFF_FILTERED }}
+
+ - name: Check if README.md or Doc/** is updated else exit
+ if: (env.GIT_DIFF == '')
+ run: |
+ echo Update documentation files and README.md before push
+ exit 1
+
+ - name: push build status to Slack
+ uses: 8398a7/action-slack@v3
+ with:
+ status: ${{ job.status }}
+ fields: repo,message,commit,author,action,eventName,ref,workflow,job,took,pullRequest
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
+ if: always()
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
deleted file mode 100644
index 596af21..0000000
--- a/.github/workflows/test.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-name: PHP Test
-
-on:
- push:
- branches: [ "development" ]
- pull_request:
- branches: [ "development" ]
-permissions:
- contents: read
-
-jobs:
- build:
-
- runs-on: ubuntu-latest
-
- env:
- PUBLIC_KEY: ${{ secrets.PUBLIC_KEY }}
- SECRET_KEY: ${{ secrets.SECRET_KEY }}
- ENCRYPTION_KEY: ${{ secrets.ENCRYPTION_KEY }}
- ENV: ${{ secrets.ENV }}
-
- steps:
- - uses: actions/checkout@v3
-
- - name: Validate composer.json and composer.lock
- run: composer validate --strict
-
- - name: Cache Composer packages
- id: composer-cache
- uses: actions/cache@v3
- with:
- path: vendor
- key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
- restore-keys: |
- ${{ runner.os }}-php-
-
- - name: Install dependencies
- run: composer install --prefer-dist --no-progress
-
- - name: PHPStan analysis
- run: vendor/bin/phpstan analyse tests --no-progress --no-interaction --error-format=table
-
- - name: Run test suite
- run: ./vendor/bin/pest
diff --git a/.gitignore b/.gitignore
index 3011762..d1eb24c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -195,4 +195,7 @@ examples/*.log
examples/endpoint/*.log
example.php
.phpunit.result.cache
+.phpunit.cache
+coverage.xml
.env.local
+.php-cs-fixer.cache
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..8a0e670
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,8 @@
+## 1.0.4 | 2022-11-06
+
+This release adds support for 7.4 and above. a new workflow for old and new tests.
+
+### Dependency updates and bugfixes
+
+- [ADDED] Support for PHP 7.4 and above
+- [ADDED] New workflow for old and new tests
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..0fa8af9
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+.PHONY: init
+test:
+ @echo "Installing dependencies..."
+ @composer install
+ @echo "Installing dependencies... Done"
+ @./vendor/bin/pest --coverage --min=0 --coverage-clover ./coverage.xml
+
+
diff --git a/README.md b/README.md
index bce45f0..67b1a87 100644
--- a/README.md
+++ b/README.md
@@ -40,34 +40,37 @@ Available features include:
## Requirements
1. Flutterwave for business [API Keys](https://developer.flutterwave.com/docs/integration-guides/authentication)
-2. Acceptable PHP versions: >= 5.4.0
+2. Acceptable PHP versions: >= 7.4.0. for older versions of PHP use the [Legacy Branch]( https://github.com/Flutterwave/PHP-v3/tree/legacy )
## Installation
-The vendor folder is committed into the project to allow easy installation for those who do not have composer installed.
-It is recommended to update the project dependencies using:
+### Installation via Composer.
+To install the package via Composer, run the following command.
```shell
-$ composer require flutterwavedev/flutterwave-v3
+composer require flutterwavedev/flutterwave-v3
```
## Initialization
-Create a .env file and follow the format of the .env.example file
-Save your PUBLIC_KEY, SECRET_KEY, ENV in the .env file
+Create a .env file and follow the format of the `.env.example` file
+Save your PUBLIC_KEY, SECRET_KEY, ENV in the `.env` file
-```env
-
-PUBLIC_KEY="****YOUR**PUBLIC**KEY****" // can be gotten from the dashboard
-SECRET_KEY="****YOUR**SECRET**KEY****" // can be gotten from the dashboard
-ENCRYPTION_KEY="Encryption key"
-ENV="development/production"
+```bash
+cp .env.example .env
+```
+Your `.env` file should look this.
+```env
+PUBLIC_KEY=FLWSECK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X
+SECRET_KEY=FLWPUBK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X
+ENCRYPTION_KEY=FLWSECK_XXXXXXXXXXXXXXXX
+ENV='staging/production'
```
@@ -75,226 +78,87 @@ ENV="development/production"
## Usage
-### Card Charge
-This is used to facilitate card transactions.
-
-Edit the `paymentForm.php` and `processPayment.php` files to suit your purpose. Both files are well documented.
-
-Simply redirect to the `paymentForm.php` file on your browser to process a payment.
-
-In this implementation, we are expecting a form encoded POST request to this script.
-The request will contain the following parameters.
-
-- payment_method `Can be card, account, both`
-- description `Your transaction description`
-- logo `Your logo url`
-- title `Your transaction title`
-- country `Your transaction country`
-- currency `Your transaction currency`
-- email `Your customer's email`
-- firstname `Your customer's first name`
-- lastname `Your customer's last name`
-- phonenumber `Your customer's phonenumber`
-- pay_button_text `The payment button text you prefer`
-- ref `Your transaction reference. It must be unique per transaction. By default, the Rave class generates a unique transaction reference for each transaction. Pass this parameter only if you uncommented the related section in the script below.`
-
-```php
-status === 'successful') {
- if ($transactionData->currency == $_SESSION['currency'] && $transactionData->amount == $_SESSION['amount']) {
-
- if ($_SESSION['publicKey']) {
- header('Location: ' . getURL($_SESSION['successurl'], array('event' => 'successful')));
- $_SESSION = array();
- session_destroy();
- }
- } else {
- if ($_SESSION['publicKey']) {
- header('Location: ' . getURL($_SESSION['failureurl'], array('event' => 'suspicious')));
- $_SESSION = array();
- session_destroy();
- }
- }
- } else {
- $this->onFailure($transactionData);
- }
- }
+declare(strict_types=1);
- /**
- * This is called only when a transaction failed
- * */
- function onFailure($transactionData) {
- // Get the transaction from your DB using the transaction reference (txref)
- // Update the db transaction record (includeing parameters that didn't exist before the transaction is completed. for audit purpose)
- // You can also redirect to your failure page from here
- if ($_SESSION['publicKey']) {
- header('Location: ' . getURL($_SESSION['failureurl'], array('event' => 'failed')));
- $_SESSION = array();
- session_destroy();
- }
- }
+# if vendor file is not present, notify developer to run composer install.
+require __DIR__.'/vendor/autoload.php';
- /**
- * This is called when a transaction is requeryed from the payment gateway
- * */
- function onRequery($transactionReference) {
- // Do something, anything!
- }
+use Flutterwave\Controller\PaymentController;
+use Flutterwave\EventHandlers\ModalEventHandler as PaymentHandler;
+use Flutterwave\Flutterwave;
+use Flutterwave\Library\Modal;
- /**
- * This is called a transaction requery returns with an error
- * */
- function onRequeryError($requeryResponse) {
- echo 'the transaction was not found';
- }
+# start a session.
+session_start();
- /**
- * This is called when a transaction is canceled by the user
- * */
- function onCancel($transactionReference) {
- // Do something, anything!
- // Note: Somethings a payment can be successful, before a user clicks the cancel button so proceed with caution
- if ($_SESSION['publicKey']) {
- header('Location: ' . getURL($_SESSION['failureurl'], array('event' => 'canceled')));
- $_SESSION = array();
- session_destroy();
- }
- }
+try {
+ Flutterwave::bootstrap();
+ $customHandler = new PaymentHandler();
+ $client = new Flutterwave();
+ $modalType = Modal::POPUP; // Modal::POPUP or Modal::STANDARD
+ $controller = new PaymentController( $client, $customHandler, $modalType );
+} catch(\Exception $e ) {
+ echo $e->getMessage();
+}
- /**
- * This is called when a transaction doesn't return with a success or a failure response. This can be a timedout transaction on the Rave server or an abandoned transaction by the customer.
- * */
- function onTimeout($transactionReference, $data) {
- // Get the transaction from your DB using the transaction reference (txref)
- // Queue it for requery. Preferably using a queue system. The requery should be about 15 minutes after.
- // Ask the customer to contact your support and you should escalate this issue to the flutterwave support team. Send this as an email and as a notification on the page. just incase the page timesout or disconnects
- if ($_SESSION['publicKey']) {
- header('Location: ' . getURL($_SESSION['failureurl'], array('event' => 'timedout')));
- $_SESSION = array();
- session_destroy();
- }
+if ($_SERVER["REQUEST_METHOD"] === "POST") {
+ $request = $_REQUEST;
+ $request['redirect_url'] = $_SERVER['HTTP_ORIGIN'] . $_SERVER['REQUEST_URI'];
+ try {
+ $controller->process( $request );
+ } catch(\Exception $e) {
+ echo $e->getMessage();
}
}
-if (isset($postData['amount'])) {
- // Make payment
- $payment
- ->eventHandler(new myEventHandler)
- ->setAmount($postData['amount'])
- ->setPaymentOptions($postData['payment_options']) // value can be card, account or both
- ->setDescription($postData['description'])
- ->setLogo($postData['logo'])
- ->setTitle($postData['title'])
- ->setCountry($postData['country'])
- ->setCurrency($postData['currency'])
- ->setEmail($postData['email'])
- ->setFirstname($postData['firstname'])
- ->setLastname($postData['lastname'])
- ->setPhoneNumber($postData['phonenumber'])
- ->setPayButtonText($postData['pay_button_text'])
- ->setRedirectUrl($URL)
- // ->setMetaData(array('metaname' => 'SomeDataName', 'metavalue' => 'SomeValue')) // can be called multiple times. Uncomment this to add meta datas
- // ->setMetaData(array('metaname' => 'SomeOtherDataName', 'metavalue' => 'SomeOtherValue')) // can be called multiple times. Uncomment this to add meta datas
- ->initialize();
+$request = $_GET;
+# Confirming Payment.
+if(isset($request['tx_ref'])) {
+ $controller->callback( $request );
} else {
- if (isset($getData['cancelled'])) {
- // Handle canceled payments
- $payment
- ->eventHandler(new myEventHandler)
- ->paymentCanceled($getData['cancel_ref']);
- } elseif (isset($getData['tx_ref'])) {
- // Handle completed payments
- $payment->logger->notice('Payment completed. Now requerying payment.');
- $payment
- ->eventHandler(new myEventHandler)
- ->requeryTransaction($getData['transaction_id']);
- } else {
- $payment->logger->warning('Stop!!! Please pass the txref parameter!');
- echo 'Stop!!! Please pass the txref parameter!';
- }
+
}
+exit();
+
```
@@ -302,11 +166,18 @@ if (isset($postData['amount'])) {
Create a .env file and add the bootstrap method first before initiating a charge.
```php
use \Flutterwave\Flutterwave;
+use \Flutterwave\Helper\Config;
# normal configuration
-Flutterwave::bootstrap();
+Flutterwave::bootstrap(); # this will use the default configuration set in .env
# for a custom configuration
-# your config must implement Flutterwave\Contract\ConfigInterface
+# your config must implement Flutterwave\Contract\ConfigInterface
+$myConfig = Config::setUp(
+ 'FLWSECK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X',
+ 'FLWPUBK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X',
+ 'FLWSECK_XXXXXXXXXXXXXXXX',
+ 'staging'
+);
Flutterwave::bootstrap($myConfig);
```
@@ -406,8 +277,8 @@ $data = [
$cardpayment = \Flutterwave\Flutterwave::create("card");
$customerObj = $cardpayment->customer->create([
"full_name" => "Olaobaju Abraham",
- "email" => "olaobajua@gmail.com",
- "phone" => "+2349067985861"
+ "email" => "ola2fhahfj@gmail.com",
+ "phone" => "+234900154861"
]);
$data['customer'] = $customerObj;
$payload = $cardpayment->payload->create($data);
@@ -522,8 +393,8 @@ $data = [
$service = new Transfer();
$customerObj = $service->customer->create([
"full_name" => "Olaobaju Abraham",
- "email" => "olaobajua@gmail.com",
- "phone" => "+2349067985861"
+ "email" => "38djsdjfjc954@gmail.com",
+ "phone" => "+234900085861"
]);
$data['customer'] = $customerObj;
$payload = $service->payload->create($data);
@@ -702,6 +573,33 @@ $response = $service->create($payload);
```
+### Enaira
+
+```php
+use Flutterwave\Util\Currency;
+
+$data = [
+ "amount" => 2000,
+ "is_token" => 1,
+ "currency" => Currency::NGN,
+ "tx_ref" => uniqid().time(),
+ "redirectUrl" => "https://example.com"
+];
+
+$payment = \Flutterwave\Flutterwave::create("enaira");
+$customerObj = $payment->customer->create([
+ "full_name" => "Olaobaju Jesulayomi Abraham",
+ "email" => "developers@flutterwavego.com",
+ "phone" => "+2349060085861"
+]);
+
+$data['customer'] = $customerObj;
+$payload = $payment->payload->create($data);
+$result = $payment->initiate($payload);
+```
+
+
+
### Tokenized Charge
Once the charge and validation process is complete for the first charge on the card, you can make use of the token for subsequent charges.
@@ -723,8 +621,8 @@ $data['redirectUrl'] = "http://{$_SERVER['HTTP_HOST']}/examples/endpoint/verify.
$customerObj = $tokenpayment->customer->create([
"full_name" => "Olaobaju Jesulayomi Abraham",
- "email" => "olaobajua@gmail.com",
- "phone" => "+2349067985861"
+ "email" => "ola3785yfhf@gmail.com",
+ "phone" => "+2349062947561"
]);
$data['customer'] = $customerObj;
$tokenpayment = \Flutterwave\Flutterwave::create("tokenize");
diff --git a/composer.json b/composer.json
index d289016..a2012a4 100644
--- a/composer.json
+++ b/composer.json
@@ -17,8 +17,12 @@
"monolog/monolog": "^2.0 || ^3.0",
"vlucas/phpdotenv": "^2.5 || ^3.0 || ^5.0",
"ext-json": "*",
+ "ext-curl": "*",
+ "ext-openssl": "*",
"guzzlehttp/guzzle": "^7.5",
- "psr/http-client": "^1.0"
+ "psr/http-client": "^1.0",
+ "php-http/guzzle7-adapter": "^1.0",
+ "composer/ca-bundle": "^1.3"
},
"require-dev": {
"phpunit/phpunit": ">=6.0",
@@ -26,7 +30,11 @@
"symfony/var-dumper": "5.4.13",
"phpstan/phpstan": "^1.9",
"pestphp/pest": "^1.22",
- "nunomaduro/phpinsights": "^2.6"
+ "nunomaduro/phpinsights": "^2.6",
+ "eloquent/liberator": "^3.0",
+ "squizlabs/php_codesniffer": "3.*",
+ "dg/bypass-finals": "^1.4",
+ "phpbench/phpbench": "^1.2"
},
"license": "MIT",
"authors": [
@@ -40,5 +48,25 @@
"pestphp/pest-plugin": true,
"dealerdirect/phpcodesniffer-composer-installer": true
}
+ },
+ "scripts": {
+ "php-insight": [
+ "./vendor/bin/phpinsights analyse src"
+ ],
+ "php-insight-fix": [
+ "vendor/bin/phpinsights fix src"
+ ],
+ "phpcs": [
+ "./vendor/bin/phpcs"
+ ],
+ "phpcbf": [
+ "./vendor/bin/phpcbf "
+ ],
+ "test": [
+ "./vendor/bin/pest"
+ ],
+ "pest-filter": [
+ "./vendor/bin/pest --filter"
+ ]
}
}
diff --git a/docker-compose.yml b/docker-compose.yml
deleted file mode 100644
index 869968b..0000000
--- a/docker-compose.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-services:
- web:
- image: nginx
- ports:
- - "80:80"
- volumes:
- - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf
- depends_on:
- - app
- db:
- image: mysql:5.7
- volumes:
- - ./docker/mysql:/var/lib/mysql
\ No newline at end of file
diff --git a/examples/card.php b/examples/card.php
index 653926c..3141857 100644
--- a/examples/card.php
+++ b/examples/card.php
@@ -41,8 +41,8 @@
$customerObj = $cardpayment->customer->create([
"full_name" => "Olaobaju Abraham",
- "email" => "olaobajua@gmail.com",
- "phone" => "+2349067985861"
+ "email" => "ol3746ydgsbc@gmail.com",
+ "phone" => "+2349035462461"
]);
$data['customer'] = $customerObj;
diff --git a/examples/endpoint/validate.php b/examples/endpoint/validate.php
index b1065fe..f44d3d0 100644
--- a/examples/endpoint/validate.php
+++ b/examples/endpoint/validate.php
@@ -23,7 +23,7 @@
if ($res->status === 'success') {
echo "Your payment status: " . $res->processor_response;
}
- } catch (\Unirest\Exception $e) {
+ } catch (\Psr\Http\Client\ClientExceptionInterface $e) {
echo "error: ". $e->getMessage();
}
diff --git a/examples/preauth.php b/examples/preauth.php
index 63eaea1..9c5e55a 100644
--- a/examples/preauth.php
+++ b/examples/preauth.php
@@ -39,9 +39,9 @@
$data['redirectUrl'] = "http://{$_SERVER['HTTP_HOST']}/examples/endpoint/verify.php?tx_ref={$data['tx_ref']}";
$customerObj = $preauthpayment->customer->create([
- "full_name" => "Olaobaju Jesulayomi Abraham",
- "email" => "olaobajua@gmail.com",
- "phone" => "+2349067985861"
+ "full_name" => "Jack Logan Hugh",
+ "email" => "Jhughck@gmail.com",
+ "phone" => "+2349062919861"
]);
$data['customer'] = $customerObj;
diff --git a/examples/tokenized.php b/examples/tokenized.php
index 0d9ab61..9b4b182 100644
--- a/examples/tokenized.php
+++ b/examples/tokenized.php
@@ -27,8 +27,8 @@
$customerObj = $tokenpayment->customer->create([
"full_name" => "Olaobaju Jesulayomi Abraham",
- "email" => "olaobajua@gmail.com",
- "phone" => "+2349067985861"
+ "email" => "olr75756uruf@gmail.com",
+ "phone" => "+2349067263131"
]);
$data['customer'] = $customerObj;
diff --git a/paymentForm.php b/paymentForm.php
index 5bd99ab..34bb9d5 100644
--- a/paymentForm.php
+++ b/paymentForm.php
@@ -24,31 +24,28 @@
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index ec3a541..fc42dbe 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,5 +1,5 @@
-tests
-
+
+
+ ./src
+
+
+
+
+
\ No newline at end of file
diff --git a/processPayment.php b/processPayment.php
index a5da1a5..622ad36 100644
--- a/processPayment.php
+++ b/processPayment.php
@@ -2,196 +2,42 @@
declare(strict_types=1);
+# if vendor file is not present, notify developer to run composer install.
require __DIR__.'/vendor/autoload.php';
-session_start();
-
-use Flutterwave\EventHandlers\EventHandlerInterface;
+use Flutterwave\Controller\PaymentController;
+use Flutterwave\EventHandlers\ModalEventHandler as PaymentHandler;
use Flutterwave\Flutterwave;
+use Flutterwave\Library\Modal;
-Flutterwave::bootstrap();
-
-$URL = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
-$getData = $_GET;
-$postData = $_POST;
-$publicKey = $_SERVER['PUBLIC_KEY'];
-$secretKey = $_SERVER['SECRET_KEY'];
-if (isset($postData['successurl']) && isset($postData['failureurl'])) {
- $success_url = $postData['successurl'];
- $failure_url = $postData['failureurl'];
-}
-
-$env = $_SERVER['ENV'];
-
-if (isset($postData['amount'])) {
- $_SESSION['publicKey'] = $publicKey;
- $_SESSION['secretKey'] = $secretKey;
- $_SESSION['env'] = $env;
- $_SESSION['successurl'] = $success_url ?? null;
- $_SESSION['failureurl'] = $failure_url ?? null;
- $_SESSION['currency'] = $postData['currency'];
- $_SESSION['amount'] = $postData['amount'];
-}
-
-$prefix = 'RV'; // Change this to the name of your business or app
-$overrideRef = false;
-
-// Uncomment here to enforce the useage of your own ref else a ref will be generated for you automatically
-if (isset($postData['ref'])) {
- $prefix = $postData['ref'];
- $overrideRef = true;
-}
-
-$payment = new Flutterwave($prefix, $overrideRef);
+# start a session.
+session_start();
-function getURL($url, $data = []): string
-{
- $urlArr = explode('?', $url);
- $params = array_merge($_GET, $data);
- $new_query_string = http_build_query($params) . '&' . $urlArr[1];
- return $urlArr[0] . '?' . $new_query_string;
+try {
+ Flutterwave::bootstrap();
+ $customHandler = new PaymentHandler();
+ $client = new Flutterwave();
+ $modalType = Modal::POPUP; // Modal::POPUP or Modal::STANDARD
+ $controller = new PaymentController( $client, $customHandler, $modalType );
+} catch(\Exception $e ) {
+ echo $e->getMessage();
}
-// This is where you set how you want to handle the transaction at different stages
-class myEventHandler implements EventHandlerInterface
-{
- /**
- * This is called when the Rave class is initialized
- * */
- public function onInit($initializationData): void
- {
- // Save the transaction to your DB.
- }
-
- /**
- * This is called only when a transaction is successful
- * */
- public function onSuccessful($transactionData): void
- {
- // Get the transaction from your DB using the transaction reference (txref)
- // Check if you have previously given value for the transaction. If you have, redirect to your successpage else, continue
- // Comfirm that the transaction is successful
- // Confirm that the chargecode is 00 or 0
- // Confirm that the currency on your db transaction is equal to the returned currency
- // Confirm that the db transaction amount is equal to the returned amount
- // Update the db transaction record (includeing parameters that didn't exist before the transaction is completed. for audit purpose)
- // Give value for the transaction
- // Update the transaction to note that you have given value for the transaction
- // You can also redirect to your success page from here
- if ($transactionData->status === 'successful') {
- if ($transactionData->currency === $_SESSION['currency'] && $transactionData->amount === $_SESSION['amount']) {
- if ($_SESSION['publicKey']) {
- header('Location: ' . getURL($_SESSION['successurl'], ['event' => 'successful']));
- $_SESSION = [];
- session_destroy();
- }
- } else {
- if ($_SESSION['publicKey']) {
- header('Location: ' . getURL($_SESSION['failureurl'], ['event' => 'suspicious']));
- $_SESSION = [];
- session_destroy();
- }
- }
- } else {
- $this->onFailure($transactionData);
- }
- }
-
- /**
- * This is called only when a transaction failed
- * */
- public function onFailure($transactionData): void
- {
- // Get the transaction from your DB using the transaction reference (txref)
- // Update the db transaction record (includeing parameters that didn't exist before the transaction is completed. for audit purpose)
- // You can also redirect to your failure page from here
- if ($_SESSION['publicKey']) {
- header('Location: ' . getURL($_SESSION['failureurl'], ['event' => 'failed']));
- $_SESSION = [];
- session_destroy();
- }
- }
-
- /**
- * This is called when a transaction is requeryed from the payment gateway
- * */
- public function onRequery($transactionReference): void
- {
- // Do something, anything!
- }
-
- /**
- * This is called a transaction requery returns with an error
- * */
- public function onRequeryError($requeryResponse): void
- {
- echo 'the transaction was not found';
- }
-
- /**
- * This is called when a transaction is canceled by the user
- * */
- public function onCancel($transactionReference): void
- {
- // Do something, anything!
- // Note: Something's a payment can be successful, before a user clicks the cancel button so proceed with caution
- if ($_SESSION['publicKey']) {
- header('Location: ' . getURL($_SESSION['failureurl'], ['event' => 'canceled']));
- $_SESSION = [];
- session_destroy();
- }
- }
-
- /**
- * This is called when a transaction doesn't return with a success or a failure response. This can be a timedout transaction on the Rave server or an abandoned transaction by the customer.
- * */
- public function onTimeout($transactionReference, $data): void
- {
- // Get the transaction from your DB using the transaction reference (txref)
- // Queue it for requery. Preferably using a queue system. The requery should be about 15 minutes after.
- // Ask the customer to contact your support, and you should escalate this issue to the flutterwave support team. Send this as an email and as a notification on the page. just incase the page timesout or disconnects
- if ($_SESSION['publicKey']) {
- header('Location: ' . getURL($_SESSION['failureurl'], ['event' => 'timedout']));
- $_SESSION = [];
- session_destroy();
- }
+if ($_SERVER["REQUEST_METHOD"] === "POST") {
+ $request = $_REQUEST;
+ $request['redirect_url'] = $_SERVER['HTTP_ORIGIN'] . $_SERVER['REQUEST_URI'];
+ try {
+ $controller->process( $request );
+ } catch(\Exception $e) {
+ echo $e->getMessage();
}
}
-if (isset($postData['amount'])) {
- // Make payment
- $payment
- ->eventHandler(new myEventHandler())
- ->setAmount($postData['amount'])
- ->setPaymentOptions($postData['payment_options']) // value can be a card, account or both
- ->setDescription($postData['description'])
- ->setLogo($postData['logo'])
- ->setTitle($postData['title'])
- ->setCountry($postData['country'])
- ->setCurrency($postData['currency'])
- ->setEmail($postData['email'])
- ->setFirstname($postData['firstname'])
- ->setLastname($postData['lastname'])
- ->setPhoneNumber($postData['phonenumber'])
- ->setPayButtonText($postData['pay_button_text'])
- ->setRedirectUrl($URL)
- // ->setMetaData(array('metaname' => 'SomeDataName', 'metavalue' => 'SomeValue')) // can be called multiple times. Uncomment this to add meta datas
- // ->setMetaData(array('metaname' => 'SomeOtherDataName', 'metavalue' => 'SomeOtherValue')) // can be called multiple times. Uncomment this to add meta datas
- ->initialize();
+$request = $_GET;
+# Confirming Payment.
+if(isset($request['tx_ref'])) {
+ $controller->callback( $request );
} else {
- if (isset($getData['cancelled'])) {
- // Handle canceled payments
- $payment
- ->eventHandler(new myEventHandler())
- ->paymentCanceled($getData['cancel_ref']);
- } elseif (isset($getData['tx_ref'])) {
- // Handle completed payments
- $payment->logger->notice('Payment completed. Now requerying payment.');
- $payment
- ->eventHandler(new myEventHandler())
- ->requeryTransaction($getData['transaction_id']);
- } else {
- $payment->logger->warning('Stop!!! Please pass the txref parameter!');
- echo 'Stop!!! Please pass the txref parameter!';
- }
+
}
+exit();
diff --git a/setup.php b/setup.php
index b94f612..1c5b813 100644
--- a/setup.php
+++ b/setup.php
@@ -3,7 +3,15 @@
use Flutterwave\Helper;
use Dotenv\Dotenv;
-$dotenv = Dotenv::createImmutable(__DIR__."/../../../");
+$flutterwave_installation = 'composer';
+
+if( !file_exists( '.env' )) {
+ $dotenv = Dotenv::createImmutable(__DIR__."/../../../"); # on the event that the package is install via composer.
+} else {
+ $flutterwave_installation = "manual";
+ $dotenv = Dotenv::createImmutable(__DIR__); # on the event that the package is forked or donwload directly from Github.
+}
+
$dotenv->safeLoad();
//check if the current version of php is compatible
@@ -13,14 +21,14 @@
exit;
}
-// check for required key in SERVER super global
+// check for required key in ENV super global
$flutterwaveKeys = ["SECRET_KEY","PUBLIC_KEY","ENV", "ENCRYPTION_KEY"];
asort($flutterwaveKeys);
try{
foreach($flutterwaveKeys as $key)
{
- if(!array_key_exists($key, $_SERVER))
+ if( empty( $_ENV[ $key ] ) )
{
throw new InvalidArgumentException("$key environment variable missing.");
}
@@ -31,4 +39,11 @@
echo "
Kindly create a .env
in the project root and add the required environment variables.";
exit;
-}
\ No newline at end of file
+}
+
+$keys = [
+ 'SECRET_KEY' => $_ENV['SECRET_KEY'],
+ 'PUBLIC_KEY' => $_ENV['PUBLIC_KEY'],
+ 'ENV' => $_ENV['ENV'],
+ 'ENCRYPTION_KEY' => $_ENV['ENCRYPTION_KEY']
+];
\ No newline at end of file
diff --git a/src/AbstractPayment.php b/src/AbstractPayment.php
index 032b4dc..b067c6a 100644
--- a/src/AbstractPayment.php
+++ b/src/AbstractPayment.php
@@ -6,19 +6,22 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\EventHandlers\EventHandlerInterface;
+use Flutterwave\Helper\EnvVariables;
use Flutterwave\Traits\ApiOperations as Api;
use Flutterwave\Traits\PayloadOperations as Payload;
use Psr\Log\LoggerInterface;
abstract class AbstractPayment
{
- use Api\Post, Api\Get, Payload\Prepare;
+ use Api\Post;
+ use Api\Get;
+ use Payload\Prepare;
public string $secretKey;
public string $txref;
public $type;
public LoggerInterface $logger;
-// protected ?string $integrityHash = null;
+ // protected ?string $integrityHash = null;
protected string $payButtonText = 'Proceed with Payment';
protected string $redirectUrl;
protected array $meta = [];
@@ -52,12 +55,17 @@ abstract class AbstractPayment
//EndPoints
protected string $end_point;
protected string $flwRef;
- protected static ConfigInterface $config;
+ protected static ?ConfigInterface $config = null;
- public function __construct(string $prefix, bool $overrideRefWithPrefix)
+ public function __construct()
{
- $this->transactionPrefix = $overrideRefWithPrefix ? $prefix : self::$config::DEFAULT_PREFIX . '_';
- $this->baseUrl = self::$config::BASE_URL;
+ $this->transactionPrefix = self::$config::DEFAULT_PREFIX . '_';
+ $this->baseUrl = EnvVariables::BASE_URL;
+ }
+
+ public function getConfig()
+ {
+ return self::$config;
}
abstract public function initialize(): void;
diff --git a/src/Config/AbstractConfig.php b/src/Config/AbstractConfig.php
new file mode 100644
index 0000000..6a34aad
--- /dev/null
+++ b/src/Config/AbstractConfig.php
@@ -0,0 +1,83 @@
+secret = $secret_key;
+ $this->public = $public_key;
+ $this->enc = $encrypt_key;
+ $this->env = $env;
+
+ $this->http = new Client(
+ [
+ 'base_uri' => EnvVariables::BASE_URL,
+ 'timeout' => 60,
+ RequestOptions::VERIFY => \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath()
+ ]
+ );
+
+ $log = new Logger('Flutterwave/PHP');
+ $this->logger = $log;
+ }
+
+ abstract public static function setUp(
+ string $secretKey,
+ string $publicKey,
+ string $enc,
+ string $env
+ ): ConfigInterface;
+
+ public function getHttp(): ClientInterface
+ {
+ return $this->http;
+ }
+
+ public function getLoggerInstance(): LoggerInterface
+ {
+ return $this->logger;
+ }
+
+ abstract public function getEncryptkey(): string;
+
+ abstract public function getPublicKey(): string;
+
+ abstract public function getSecretKey(): string;
+
+ abstract public function getEnv(): string;
+
+ public static function getDefaultTransactionPrefix(): string
+ {
+ return self::DEFAULT_PREFIX;
+ }
+}
diff --git a/src/Config/ForkConfig.php b/src/Config/ForkConfig.php
new file mode 100644
index 0000000..f9983ec
--- /dev/null
+++ b/src/Config/ForkConfig.php
@@ -0,0 +1,55 @@
+logger->pushHandler(new RotatingFileHandler(__DIR__ . "/../../" . self::LOG_FILE_NAME, 90));
+ }
+
+ public static function setUp(string $secretKey, string $publicKey, string $enc, string $env): ConfigInterface
+ {
+ if (is_null(self::$instance)) {
+ return new self($secretKey, $publicKey, $enc, $env);
+ }
+ return self::$instance;
+ }
+
+ public function getEncryptkey(): string
+ {
+ return $this->enc;
+ }
+
+ public function getPublicKey(): string
+ {
+ return $this->public;
+ }
+
+ public function getSecretKey(): string
+ {
+ return $this->secret;
+ }
+
+ public function getEnv(): string
+ {
+ return $this->env;
+ }
+}
diff --git a/src/Config/PackageConfig.php b/src/Config/PackageConfig.php
new file mode 100644
index 0000000..e718437
--- /dev/null
+++ b/src/Config/PackageConfig.php
@@ -0,0 +1,56 @@
+logger->pushHandler(new RotatingFileHandler(__DIR__ . "../../../../../../" . self::LOG_FILE_NAME, 90));
+ }
+
+ public static function setUp(string $secretKey, string $publicKey, string $enc, string $env): ConfigInterface
+ {
+
+ if (is_null(self::$instance)) {
+ return new self($secretKey, $publicKey, $enc, $env);
+ }
+ return self::$instance;
+ }
+
+ public function getEncryptkey(): string
+ {
+ return $this->enc;
+ }
+
+ public function getPublicKey(): string
+ {
+ return $this->public;
+ }
+
+ public function getSecretKey(): string
+ {
+ return $this->secret;
+ }
+
+ public function getEnv(): string
+ {
+ return $this->env;
+ }
+}
diff --git a/src/Contract/ConfigInterface.php b/src/Contract/ConfigInterface.php
index 0e4c2d2..8fcaac6 100644
--- a/src/Contract/ConfigInterface.php
+++ b/src/Contract/ConfigInterface.php
@@ -4,12 +4,11 @@
namespace Flutterwave\Contract;
-use GuzzleHttp\ClientInterface;
+use Psr\Http\Client\ClientInterface;
use Psr\Log\LoggerInterface;
interface ConfigInterface
{
-
public static function setUp(string $secretKey, string $publicKey, string $enc, string $env): ConfigInterface;
public function getHttp(): ClientInterface;
@@ -21,8 +20,6 @@ public function getPublicKey(): string;
public function getSecretKey(): string;
- public static function getBaseUrl(): string;
-
public function getEnv(): string;
public static function getDefaultTransactionPrefix(): string;
diff --git a/src/Contract/CustomerInterface.php b/src/Contract/CustomerInterface.php
index 38d5f92..cc90e41 100644
--- a/src/Contract/CustomerInterface.php
+++ b/src/Contract/CustomerInterface.php
@@ -4,7 +4,7 @@
namespace Flutterwave\Contract;
-use Flutterwave\Customer;
+use Flutterwave\Entities\Customer;
interface CustomerInterface
{
diff --git a/src/Contract/EntityInterface.php b/src/Contract/EntityInterface.php
new file mode 100644
index 0000000..875d75b
--- /dev/null
+++ b/src/Contract/EntityInterface.php
@@ -0,0 +1,10 @@
+ 'POST',
+ 'callback' => 'GET'
+ ];
+
+ public function __construct(
+ Flutterwave $client,
+ EventHandlerInterface $handler,
+ string $modalType
+ ) {
+ Flutterwave::bootstrap();
+ $this->requestMethod = $this->getRequestMethod();
+ $this->handler = $handler;
+ $this->client = $client;
+ $this->modalType = $modalType;
+ }
+
+ private function getRequestMethod(): string
+ {
+ return ($_SERVER["REQUEST_METHOD"] === "POST") ? 'POST' : 'GET';
+ }
+
+ public function __call(string $name, array $args)
+ {
+ if ($this->routes[$name] !== $this->$requestMethod) {
+ // Todo: 404();
+ echo "Unauthorized page!";
+ }
+ call_user_method_array($name, $this, $args);
+ }
+
+ private function handleSessionData( array $request )
+ {
+ $_SESSION['success_url'] = $request['success_url'];
+ $_SESSION['failure_url'] = $request['failure_url'];
+ $_SESSION['currency'] = $request['currency'];
+ $_SESSION['amount'] = $request['amount'];
+ }
+
+ public function process(array $request)
+ {
+ $this->handleSessionData($request);
+
+ try {
+ $_SESSION['p'] = $this->client;
+
+ if('inline' === $this->modalType ) {
+ echo $this->client
+ ->eventHandler($this->handler)
+ ->render(Modal::POPUP)->with($request)->getHtml();
+ } else {
+ $paymentLink = $this->client
+ ->eventHandler($this->handler)
+ ->render(Modal::STANDARD)->with($request)->getUrl();
+ header('Location: ' . $paymentLink);
+ }
+
+ } catch (\Exception $e) {
+ echo $e->getMessage();
+ }
+ }
+
+ public function callback(array $request)
+ {
+ $tx_ref = $request['tx_ref'];
+ $status = $request['status'];
+
+ if (empty($tx_ref)) {
+ session_destroy();
+ }
+
+ if (!isset($_SESSION['p'])) {
+ echo "session expired!. please refresh you browser.";
+ exit();
+ }
+
+ $payment = $_SESSION['p'];
+
+ // $payment::setUp([
+ // 'secret_key' => 'FLWSECK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X',
+ // 'public_key' => 'FLWPUBK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X',
+ // 'encryption_key' => 'FLWSECK_XXXXXXXXXXXXXXXX',
+ // 'environment' => 'staging'
+ // ]);
+
+ $payment::bootstrap();
+
+ if ('cancelled' === $status) {
+ $payment
+ ->eventHandler($this->handler)
+ ->paymentCanceled($tx_ref);
+ }
+
+ if ('successful' === $status && isset($request['transaction_id'])) {
+ $tx_id = $request['transaction_id'];
+
+ if (empty($tx_id) && !empty($tx_ref)) {
+ // get tx_id with the transaction service.
+ $response = (new Transactions())->verifyWithTxref($tx_ref);
+
+ if ('success' === $response->status) {
+ $tx_id = $response->data->id;
+ }
+ }
+
+ $payment->logger->notice('Payment completed. Now requerying payment.');
+ $payment
+ ->eventHandler($this->handler)
+ ->requeryTransaction($tx_id);
+ }
+ }
+}
diff --git a/src/Customer.php b/src/Customer.php
index de4a426..e04453b 100644
--- a/src/Customer.php
+++ b/src/Customer.php
@@ -4,33 +4,37 @@
namespace Flutterwave;
+/**
+ * Class Customer
+ *
+ * @package Flutterwave
+ * @deprecated Use Flutterwave\Entities\Customer instead.
+ */
class Customer
{
- private array $data = [];
-
+ private Entities\Customer $instance;
public function __construct(array $data = [])
{
- //TODO: validate data contains the required fields.
- $this->data = [...$data];
+ $this->instance = new \Flutterwave\Entities\Customer($data);
}
public function get(string $param)
{
- return $this->data[$param];
+ return $this->instance->get($param);
}
public function set(string $param, $value): void
{
- $this->data[$param] = $value;
+ $this->instance->set($param, $value);
}
public function has(string $param): bool
{
- return isset($this->data[$param]);
+ return $this->instance->has($param);
}
public function toArray(): array
{
- return $this->data;
+ return $this->instance->toArray();
}
}
diff --git a/src/Entities/Customer.php b/src/Entities/Customer.php
new file mode 100644
index 0000000..d03adce
--- /dev/null
+++ b/src/Entities/Customer.php
@@ -0,0 +1,36 @@
+data = [...$data];
+ }
+
+ public function get(string $param)
+ {
+ return $this->data[$param];
+ }
+
+ public function set(string $param, $value): void
+ {
+ $this->data[$param] = $value;
+ }
+
+ public function has(string $param): bool
+ {
+ return isset($this->data[$param]);
+ }
+
+ public function toArray(): array
+ {
+ return $this->data;
+ }
+}
diff --git a/src/Entities/Payload.php b/src/Entities/Payload.php
new file mode 100644
index 0000000..8dc637e
--- /dev/null
+++ b/src/Entities/Payload.php
@@ -0,0 +1,147 @@
+has($param)) {
+ return null;
+ }
+ return $this->data[$param];
+ }
+
+ public function set(string $param, $value): void
+ {
+ if ($param === AuthMode::PIN) {
+ $this->data['otherData']['authorization']['mode'] = self::PIN;
+ $this->data['otherData']['authorization'][AuthMode::PIN] = $value;
+ } else {
+ $this->data[$param] = $value;
+ }
+ }
+
+ public function delete(string $param, array $assoc_option = []): void
+ {
+ if (! isset($param)) {
+ return;
+ }
+
+ if ($param === 'otherData' && count($assoc_option) > 0) {
+ foreach ($assoc_option as $option) {
+ unset($this->data['otherData'][$option]);
+ }
+ }
+ unset($this->data[$param]);
+ }
+
+ public function setPayloadType(string $type): self
+ {
+ $this->type = $type;
+ return $this;
+ }
+
+ public function toArray(?string $payment_method = null): array
+ {
+ $data = $this->data;
+ $customer = $data['customer'] ?? new Customer();
+ $additionalData = $data['otherData'] ?? [];
+
+ if (gettype($customer) === 'string') {
+ $string_value = $customer;
+ $customer = new Customer();
+ $customer->set('customer', $string_value);
+ }
+
+ switch ($payment_method) {
+ case 'card':
+ $card_details = $additionalData['card_details'];
+ unset($additionalData['card_details']);
+ $data = array_merge($data, $additionalData, $customer->toArray(), $card_details);
+ break;
+ case 'account':
+ $account_details = $additionalData['account_details'];
+ unset($additionalData['account_details']);
+ $data = array_merge($data, $additionalData, $customer->toArray(), $account_details);
+ break;
+ default:
+ $data = array_merge($data, $additionalData, $customer->toArray());
+ break;
+ }
+
+ if ($payment_method === 'modal') {
+ return $data;
+ }
+
+ unset($data['customer']);
+ unset($data['otherData']);
+
+ //convert customer obj to array
+ $data = array_merge($additionalData, $data, $customer->toArray());
+
+ //if $data['preauthorize'] is false unset
+ if (isset($data['preauthorize']) && empty($data['preauthorize'])) {
+ unset($data['preauthorize']);
+ }
+
+ if (array_key_exists('phone_number', $data) && is_null($data['phone_number'])) {
+ unset($data['phone_number']);
+ }
+
+ //if $data['payment_plan'] is null unset
+ if (isset($data['payment_plan']) && empty($data['payment_plan'])) {
+ unset($data['payment_plan']);
+ }
+ return $data;
+ }
+
+ public function update($param, $value): void
+ {
+ if ($param === 'otherData' && \is_array($value)) {
+ foreach ($value as $key => $item) {
+ $this->data['otherData'][$key] = $item;
+ }
+ }
+
+ $this->data = array_merge($this->data, [$param => $value]);
+ }
+
+ public function empty(): void
+ {
+ $this->data = [];
+ }
+
+ public function has(string $param): bool
+ {
+ if (! isset($this->data[$param])) {
+ return false;
+ }
+ return true;
+ }
+
+ public function size(): int
+ {
+ return count($this->data);
+ }
+
+ public function generateTxRef(): void
+ {
+ if ($this->has('tx_ref')) {
+ $this->set('tx_ref', 'FLWPHP|' . (mt_rand(2, 101) + time()));
+ }
+ }
+}
diff --git a/src/Enum/Bill.php b/src/Enum/Bill.php
index fd5bab9..d1d389d 100644
--- a/src/Enum/Bill.php
+++ b/src/Enum/Bill.php
@@ -6,9 +6,9 @@
//use Cerbero\Enum\Concerns\Enumerates;
-enum Bill:string
+enum Bill: string
{
-// use Enumerates;
+ // use Enumerates;
case AIRTIME = 'AIRTIME';
case DSTV = 'DSTV';
case DSTV_BOX_OFFICE = 'DSTV BOX OFFICE';
diff --git a/src/Enum/Currency.php b/src/Enum/Currency.php
index d014213..12b32a0 100644
--- a/src/Enum/Currency.php
+++ b/src/Enum/Currency.php
@@ -6,9 +6,9 @@
//use Cerbero\Enum\Concerns\Enumerates;
-enum Currency:string
+enum Currency: string
{
-// use Enumerates;
+ // use Enumerates;
case NGN = 'NGN';
case USD = 'USD';
case KES = 'KES';
diff --git a/src/Enum/Method.php b/src/Enum/Method.php
index c19025d..74c5c9a 100644
--- a/src/Enum/Method.php
+++ b/src/Enum/Method.php
@@ -6,9 +6,9 @@
//use Cerbero\Enum\Concerns\Enumerates;
-enum Method:string
+enum Method: string
{
-// use Enumerates;
+ // use Enumerates;
case DEFAULT = 'default';
case STANDARD = 'standard';
case CARD = 'card';
diff --git a/src/Enum/Momo.php b/src/Enum/Momo.php
index adb31fe..a9c2e0c 100644
--- a/src/Enum/Momo.php
+++ b/src/Enum/Momo.php
@@ -6,9 +6,9 @@
//use Cerbero\Enum\Concerns\Enumerates;
-enum Momo:string
+enum Momo: string
{
-// use Enumerates;
+ // use Enumerates;
case GHANA = 'mobile_money_ghana';
case UGANDA = 'mobile_money_uganda';
case FRANCO = 'mobile_money_franco';
diff --git a/src/EventHandlers/AccountEventHandler.php b/src/EventHandlers/AccountEventHandler.php
index 335c47e..30b957c 100644
--- a/src/EventHandlers/AccountEventHandler.php
+++ b/src/EventHandlers/AccountEventHandler.php
@@ -4,8 +4,16 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class AccountEventHandler implements EventHandlerInterface
{
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
use EventTracker;
/**
@@ -83,7 +91,8 @@ public function onTimeout($transactionReference, $data): void
* */
public function onAuthorization(\stdClass $response, ?array $resource = null): array
{
- $mode = $response->meta->authorization->mode;
+
+ $mode = $response->data->meta->authorization->mode;
if (property_exists($response, 'data')) {
$transactionId = $response->data->id;
@@ -95,35 +104,35 @@ public function onAuthorization(\stdClass $response, ?array $resource = null): a
}
switch ($mode) {
- case 'pin':
- $data['dev_instruction'] = "Redirect user to a form to enter his pin and re-initiate the charge adding the params ['pin' => 'USERS_PIN'] to the previous request.";
- $data['instruction'] = 'Enter the pin of your card';
- break;
- case 'redirect':
- $data['dev_instruction'] = 'Redirect the user to the auth link for validation';
- $data['url'] = $response->meta->authorization->redirect;
- break;
- case 'avs':
- throw new \Exception('AVS is currently not available via the SDK. please call the endpoint directly.');
-
- case 'otp':
- $data['dev_instruction'] = 'Redirect user to a form to validate with OTP code sent to their Phone.';
-
- if (property_exists($response->data, 'processor_response')) {
- $data['instruction'] = $response->data->processor_response;
- } else {
- $data['instruction'] = $response->meta->authorization->validate_instructions;
- }
-
- $data['validate'] = true;
- break;
+ case 'pin':
+ $data['dev_instruction'] = "Redirect user to a form to enter his pin and re-initiate the charge adding the params ['pin' => 'USERS_PIN'] to the previous request.";
+ $data['instruction'] = 'Enter the pin of your card';
+ break;
+ case 'redirect':
+ $data['dev_instruction'] = 'Redirect the user to the auth link for validation';
+ $data['url'] = $response->data->meta->authorization->redirect;
+ break;
+ case 'avs':
+ throw new \Exception('AVS is currently not available via the SDK. please call the endpoint directly.');
+
+ case 'otp':
+ $data['dev_instruction'] = 'Redirect user to a form to validate with OTP code sent to their Phone.';
+
+ if (property_exists($response->data, 'processor_response')) {
+ $data['instruction'] = $response->data->processor_response;
+ } else {
+ $data['instruction'] = $response->data->meta->authorization->validate_instructions;
+ }
+
+ $data['validate'] = true;
+ break;
}
$data['mode'] = $mode;
if (is_array($resource) && ! empty($resource)) {
$logger = $resource['logger'];
- $logger->notice('Account Service::Authorization Mode: '.$mode);
+ $logger->notice('Account Service::Authorization Mode: ' . $mode);
}
return $data;
diff --git a/src/EventHandlers/AchEventHandler.php b/src/EventHandlers/AchEventHandler.php
index a428dc8..7dd1c11 100644
--- a/src/EventHandlers/AchEventHandler.php
+++ b/src/EventHandlers/AchEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class AchEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
*
@@ -93,35 +101,35 @@ public function onAuthorization(\stdClass $response, ?array $resource = null): a
}
switch ($mode) {
- case 'pin':
- $data['dev_instruction'] = "Redirect user to a form to enter his pin and re-initiate the charge adding the params ['pin' => 'USERS_PIN'] to the previous request.";
- $data['instruction'] = 'Enter the pin of your card';
- break;
- case 'redirect':
- $data['dev_instruction'] = 'Redirect the user to the auth link for validation';
- $data['url'] = $response->meta->authorization->redirect;
- break;
- case 'avs':
- throw new \Exception('AVS is currently not available via the SDK. please call the endpoint directly.');
-
- case 'otp':
- $data['dev_instruction'] = 'Redirect user to a form to validate with OTP code sent to their Phone.';
-
- if (property_exists($response->data, 'processor_response')) {
- $data['instruction'] = $response->data->processor_response;
- } else {
- $data['instruction'] = $response->meta->authorization->validate_instructions;
- }
-
- $data['validate'] = true;
- break;
+ case 'pin':
+ $data['dev_instruction'] = "Redirect user to a form to enter his pin and re-initiate the charge adding the params ['pin' => 'USERS_PIN'] to the previous request.";
+ $data['instruction'] = 'Enter the pin of your card';
+ break;
+ case 'redirect':
+ $data['dev_instruction'] = 'Redirect the user to the auth link for validation';
+ $data['url'] = $response->meta->authorization->redirect;
+ break;
+ case 'avs':
+ throw new \Exception('AVS is currently not available via the SDK. please call the endpoint directly.');
+
+ case 'otp':
+ $data['dev_instruction'] = 'Redirect user to a form to validate with OTP code sent to their Phone.';
+
+ if (property_exists($response->data, 'processor_response')) {
+ $data['instruction'] = $response->data->processor_response;
+ } else {
+ $data['instruction'] = $response->meta->authorization->validate_instructions;
+ }
+
+ $data['validate'] = true;
+ break;
}
$data['mode'] = $mode;
if (is_array($resource) && ! empty($resource)) {
$logger = $resource['logger'];
- $logger->notice('Ach Event::Authorization Mode: '.$mode);
+ $logger->notice('Ach Event::Authorization Mode: ' . $mode);
}
return $data;
diff --git a/src/EventHandlers/ApplePayEventHandler.php b/src/EventHandlers/ApplePayEventHandler.php
index 6096a83..e984dd5 100644
--- a/src/EventHandlers/ApplePayEventHandler.php
+++ b/src/EventHandlers/ApplePayEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class ApplePayEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
public function onSuccessful($transactionData): void
{
// TODO: Implement onSuccessful() method.
@@ -55,7 +63,7 @@ public function onAuthorization(\stdClass $response, ?array $resource = null): a
if (is_array($resource) && ! empty($resource)) {
$logger = $resource['logger'];
- $logger->notice('Apple Method Event::Apple Authorization Mode: '.$data['mode'] ?? 'redirect');
+ $logger->notice('Apple Method Event::Apple Authorization Mode: ' . $data['mode'] ?? 'redirect');
}
return $data;
diff --git a/src/EventHandlers/BankTransferEventHandler.php b/src/EventHandlers/BankTransferEventHandler.php
index d69d149..b3332c8 100644
--- a/src/EventHandlers/BankTransferEventHandler.php
+++ b/src/EventHandlers/BankTransferEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class BankTransferEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* @inheritDoc
*/
@@ -57,8 +65,8 @@ public function onTimeout($transactionReference, $data): void
}
/**
- * @param \stdClass $response
- * @param array|null $resource
+ * @param \stdClass $response
+ * @param array|null $resource
* @return array
*/
public function onAuthorization(\stdClass $response, ?array $resource = null): array
@@ -76,8 +84,8 @@ public function onAuthorization(\stdClass $response, ?array $resource = null): a
if (is_array($resource) && ! empty($resource)) {
$logger = $resource['logger'];
- $logger->notice('Transfer Authorization Mode: '.$mode);
- $logger->info('Bank Transfer Event::Created Account Info :'.json_encode($data));
+ $logger->notice('Transfer Authorization Mode: ' . $mode);
+ $logger->info('Bank Transfer Event::Created Account Info :' . json_encode($data));
}
return $data;
diff --git a/src/EventHandlers/BillEventHandler.php b/src/EventHandlers/BillEventHandler.php
index f5fbb8e..e4752ee 100644
--- a/src/EventHandlers/BillEventHandler.php
+++ b/src/EventHandlers/BillEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class BillEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
* */
diff --git a/src/EventHandlers/BvnEventHandler.php b/src/EventHandlers/BvnEventHandler.php
index 2fe5105..34a3eb7 100644
--- a/src/EventHandlers/BvnEventHandler.php
+++ b/src/EventHandlers/BvnEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class BvnEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
* */
diff --git a/src/EventHandlers/CardEventHandler.php b/src/EventHandlers/CardEventHandler.php
index e817c07..f254321 100644
--- a/src/EventHandlers/CardEventHandler.php
+++ b/src/EventHandlers/CardEventHandler.php
@@ -4,12 +4,19 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
use Flutterwave\Util\AuthMode;
class CardEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
*
@@ -100,30 +107,30 @@ public function onAuthorization(\stdClass $response, ?array $resource = null): a
}
switch ($mode) {
- case AuthMode::PIN:
- $data['dev_instruction'] = "Redirect user to a form to enter his pin and re-initiate the charge adding the params ['pin' => 'USERS_PIN'] to the payload.";
- $data['instruction'] = 'Enter the pin of your card';
- break;
- case AuthMode::REDIRECT:
- $data['dev_instruction'] = 'Redirect the user to the auth link for validation';
- $data['url'] = $response->meta->authorization->redirect;
- break;
- case AuthMode::AVS:
- $data['dev_instruction'] = "Redirect user to a form to enter certain details and re-initiate the charge adding the params ['mode' => 'avs_noauth', 'city' => 'USER_CITY', 'state' => 'USER_STATE', 'country' => 'USER_COUNTRY', 'zipcode' => 'USER_ZIP'] to the payload.";
- $data['instruction'] = 'please complete the form for Address Verification.';
- break;
- case AuthMode::OTP:
- $data['dev_instruction'] = 'Redirect user to a form to validate with OTP code sent to their Phone.';
- $data['instruction'] = $response->data->processor_response;
- $data['validate'] = true;
- break;
+ case AuthMode::PIN:
+ $data['dev_instruction'] = "Redirect user to a form to enter his pin and re-initiate the charge adding the params ['pin' => 'USERS_PIN'] to the payload.";
+ $data['instruction'] = 'Enter the pin of your card';
+ break;
+ case AuthMode::REDIRECT:
+ $data['dev_instruction'] = 'Redirect the user to the auth link for validation';
+ $data['url'] = $response->meta->authorization->redirect;
+ break;
+ case AuthMode::AVS:
+ $data['dev_instruction'] = "Redirect user to a form to enter certain details and re-initiate the charge adding the params ['mode' => 'avs_noauth', 'city' => 'USER_CITY', 'state' => 'USER_STATE', 'country' => 'USER_COUNTRY', 'zipcode' => 'USER_ZIP'] to the payload.";
+ $data['instruction'] = 'please complete the form for Address Verification.';
+ break;
+ case AuthMode::OTP:
+ $data['dev_instruction'] = 'Redirect user to a form to validate with OTP code sent to their Phone.';
+ $data['instruction'] = $response->data->processor_response;
+ $data['validate'] = true;
+ break;
}
$data['mode'] = $mode;
if (is_array($resource) && ! empty($resource)) {
$logger = $resource['logger'];
- $logger->notice('Card Event::Authorization Mode: '.$mode);
+ $logger->notice('Card Event::Authorization Mode: ' . $mode);
}
return $data;
diff --git a/src/EventHandlers/EnairaEventHandler.php b/src/EventHandlers/EnairaEventHandler.php
new file mode 100644
index 0000000..6ef5b38
--- /dev/null
+++ b/src/EventHandlers/EnairaEventHandler.php
@@ -0,0 +1,78 @@
+data->id;
+ $tx_ref = $response->data->tx_ref;
+ $data['data_to_save'] = [
+ 'transactionId' => $transactionId,
+ 'tx_ref' => $tx_ref,
+ ];
+ $data['mode'] = $response->data->meta->authorization->mode;
+
+ switch ($data['mode']) {
+ case AuthMode::REDIRECT:
+ $data['dev_instruction'] = 'Redirect the user to the auth link for validation';
+ $data['url'] = $response->meta->authorization->redirect;
+ break;
+ case AuthMode::VALIDATE:
+ $data['dev_instruction'] = "To complete the charge, call the validate endpoint and pass the token (OTP generated from the user's speed wallet).";
+ $data['instruction'] = $response->meta->validate_instructions;
+ break;
+ }
+ }
+
+ if (is_array($resource) && ! empty($resource)) {
+ $logger = $resource['logger'];
+ $logger->notice('Enaira Method Event::Enaira Authorization Mode: ' . $data['mode'] ?? 'redirect');
+ }
+
+ return $data;
+ }
+}
\ No newline at end of file
diff --git a/src/EventHandlers/EventTracker.php b/src/EventHandlers/EventTracker.php
index d5b8c11..0c8ba00 100644
--- a/src/EventHandlers/EventTracker.php
+++ b/src/EventHandlers/EventTracker.php
@@ -4,8 +4,8 @@
namespace Flutterwave\EventHandlers;
-use Unirest\Request;
-use Unirest\Request\Body;
+use Flutterwave\Service\Service as Http;
+use Psr\Http\Client\ClientExceptionInterface;
trait EventTracker
{
@@ -22,6 +22,9 @@ public static function setResponseTime(): void
self::$response_time = microtime(true) - self::$time_start;
}
+ /**
+ * @throws ClientExceptionInterface
+ */
public static function sendAnalytics($title): void
{
if (self::$response_time <= 0) {
@@ -37,8 +40,8 @@ public static function sendAnalytics($title): void
'title' => $title,
'message' => self::$response_time,
];
- $body = Body::json($data);
- Request::post($url, [], $body);
+
+ $response = (new Http(static::$config))->request($data, 'POST', $url, true);
self::resetTime();
}
diff --git a/src/EventHandlers/FawryEventHandler.php b/src/EventHandlers/FawryEventHandler.php
new file mode 100644
index 0000000..a4a40d5
--- /dev/null
+++ b/src/EventHandlers/FawryEventHandler.php
@@ -0,0 +1,68 @@
+data->id;
+ $tx_ref = $response->data->tx_ref;
+ $data['data_to_save'] = [
+ 'transactionId' => $transactionId,
+ 'tx_ref' => $tx_ref,
+ ];
+ $data['mode'] = $response->data->meta->authorization->mode;
+ }
+
+ $data['dev_instruction'] = 'Redirect the user to the auth link for validation. verfiy via the verify endpoint.';
+
+ if (is_array($resource) && ! empty($resource)) {
+ $logger = $resource['logger'];
+ $logger->notice('Fawry Method Event::Fawry Authorization Mode: ' . $data['mode'] ?? 'fawry_pay');
+ }
+
+ return $data;
+ }
+}
\ No newline at end of file
diff --git a/src/EventHandlers/GooglePayEventHandler.php b/src/EventHandlers/GooglePayEventHandler.php
new file mode 100644
index 0000000..d481232
--- /dev/null
+++ b/src/EventHandlers/GooglePayEventHandler.php
@@ -0,0 +1,71 @@
+data->id;
+ $tx_ref = $response->data->tx_ref;
+ $data['data_to_save'] = [
+ 'transactionId' => $transactionId,
+ 'tx_ref' => $tx_ref,
+ ];
+ $data['mode'] = $response->data->meta->authorization->mode;
+ }
+
+ $data['dev_instruction'] = 'Redirect the user to the auth link for validation. verfiy via the verify endpoint.';
+ $data['url'] = $response->data->meta->authorization->redirect;
+
+ if (is_array($resource) && ! empty($resource)) {
+ $logger = $resource['logger'];
+ $logger->notice('Google Method Event::Apple Authorization Mode: ' . $data['mode'] ?? 'redirect');
+ }
+
+ return $data;
+ }
+}
\ No newline at end of file
diff --git a/src/EventHandlers/ModalEventHandler.php b/src/EventHandlers/ModalEventHandler.php
new file mode 100644
index 0000000..ae5fcb8
--- /dev/null
+++ b/src/EventHandlers/ModalEventHandler.php
@@ -0,0 +1,114 @@
+status === 'successful') {
+ $currency = $_SESSION['currency'];
+ $amount = $_SESSION['amount'];
+
+ if ($transactionData->currency === $currency && floatval($transactionData->amount) === floatval($amount)) {
+ header('Location: ' . $_SESSION['success_url']);
+ session_destroy();
+ }
+
+ if ($transactionData->currency === $currency && floatval($transactionData->amount) < floatval($amount)) {
+ // TODO: replace this a custom action.
+ echo "This Event Handler is an Implementation of " . __NAMESPACE__ . "\EventHandlerInterface ";
+ echo "Partial Payment Made ! replace this with your own action! ";
+ session_destroy();
+ }
+
+ if ($transactionData->currency !== $currency && floatval($transactionData->amount) === floatval($amount)) {
+ // TODO: replace this a custom action.
+ echo "This Event Handler is an Implementation of " . __NAMESPACE__ . "\EventHandlerInterface ";
+ echo "Currency mismatch. please look into it ! replace this with your own action ";
+ session_destroy();
+ }
+ } else {
+ $this->onFailure($transactionData);
+ }
+ }
+
+ /**
+ * This is called only when a transaction failed
+ * */
+ public function onFailure($transactionData): void
+ {
+ // Get the transaction from your DB using the transaction reference (txref)
+ // Update the db transaction record (includeing parameters that didn't exist before the transaction is completed. for audit purpose)
+ // You can also redirect to your failure page from here.
+ // TODO: replace this a custom action.
+ header('Location: ' . $_SESSION['failure_url']);
+ session_destroy();
+ }
+
+ /**
+ * This is called when a transaction is requeryed from the payment gateway
+ * */
+ public function onRequery($transactionReference): void
+ {
+ // do not include any business logic here, this function is likely to be depricated.
+ }
+
+ /**
+ * This is called a transaction requery returns with an error
+ * */
+ public function onRequeryError($requeryResponse): void
+ {
+ echo "Flutterwave: error querying the transaction.";
+ // trigger webhook notification from Flutterwave.
+ $service = new Flutterwave\Service\Transaction();
+ $service->resendFailedHooks($data->id);
+ header('Location: ' . $_SERVER['HTTP_ORIGIN']);
+ }
+
+ /**
+ * This is called when a transaction is canceled by the user
+ * */
+ public function onCancel($transactionReference): void
+ {
+ // TODO: replace this a custom action.
+ echo "This Event Handler is an Implementation of " . __NAMESPACE__ . "\EventHandlerInterface ";
+ echo "Payment was cancelled ! replace this with your own action.";
+ session_destroy();
+ }
+
+ /**
+ * This is called when a transaction doesn't return with a success or a failure response. This can be a timedout transaction on the Rave server or an abandoned transaction by the customer.
+ * */
+ public function onTimeout($transactionReference, $data): void
+ {
+ // trigger webhook notification from Flutterwave.
+ $service = new Flutterwave\Service\Transaction();
+ $service->resendFailedHooks($data->id);
+ header('Location: ' . $_SERVER['HOST']);
+ }
+}
diff --git a/src/EventHandlers/MomoEventHandler.php b/src/EventHandlers/MomoEventHandler.php
index 37991ed..1695701 100644
--- a/src/EventHandlers/MomoEventHandler.php
+++ b/src/EventHandlers/MomoEventHandler.php
@@ -4,12 +4,19 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
use Flutterwave\Util\AuthMode;
class MomoEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
*
@@ -89,20 +96,21 @@ public function onAuthorization(\stdClass $response, ?array $resource = null): a
$data['data_to_save'] = [
'transactionId' => $transactionId,
'tx_ref' => $tx_ref,
+ 'status' => $response->data->status
];
}
if (property_exists($response, 'meta')) {
$mode = $response->meta->authorization->mode;
switch ($mode) {
- case AuthMode::REDIRECT:
- $data['dev_instruction'] = 'Redirect the user to the auth link for validation';
- $data['url'] = $response->meta->authorization->redirect;
- break;
- case AuthMode::CALLBACK:
- $data['dev_instruction'] = "The customer needs to authorize with their mobile money service, and then we'll send you a webhook.";
- $data['instruction'] = 'please kindly authorize with your mobile money service';
- break;
+ case AuthMode::REDIRECT:
+ $data['dev_instruction'] = 'Redirect the user to the auth link for validation';
+ $data['url'] = $response->meta->authorization->redirect;
+ break;
+ case AuthMode::CALLBACK:
+ $data['dev_instruction'] = "The customer needs to authorize with their mobile money service, and then we'll send you a webhook.";
+ $data['instruction'] = 'please kindly authorize with your mobile money service';
+ break;
}
}
@@ -110,7 +118,7 @@ public function onAuthorization(\stdClass $response, ?array $resource = null): a
if (is_array($resource) && ! empty($resource)) {
$logger = $resource['logger'];
- $logger->notice('Momo Service::Authorization Mode: '.($mode ?? 'none'));
+ $logger->notice('Momo Service::Authorization Mode: ' . ($mode ?? 'none'));
}
return $data;
diff --git a/src/EventHandlers/MpesaEventHandler.php b/src/EventHandlers/MpesaEventHandler.php
index 230f504..5c0530e 100644
--- a/src/EventHandlers/MpesaEventHandler.php
+++ b/src/EventHandlers/MpesaEventHandler.php
@@ -4,15 +4,26 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+use Psr\Http\Client\ClientExceptionInterface;
+
class MpesaEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
*
- * @param array
- * */
+ * @param array $transactionData
+ *
+ * @throws ClientExceptionInterface
+ */
public function onSuccessful($transactionData): void
{
// Get the transaction from your DB using the transaction reference (txref)
diff --git a/src/EventHandlers/PaymentPlanEventHandler.php b/src/EventHandlers/PaymentPlanEventHandler.php
index eed7e55..1469b9e 100644
--- a/src/EventHandlers/PaymentPlanEventHandler.php
+++ b/src/EventHandlers/PaymentPlanEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class PaymentPlanEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
* */
diff --git a/src/EventHandlers/PayoutSubaccoutEventHandler.php b/src/EventHandlers/PayoutSubaccoutEventHandler.php
index 403734d..cf96c90 100644
--- a/src/EventHandlers/PayoutSubaccoutEventHandler.php
+++ b/src/EventHandlers/PayoutSubaccoutEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class PayoutSubaccoutEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
public function onSuccessful($transactionData): void
{
// TODO: Implement onSuccessful() method.
diff --git a/src/EventHandlers/PreEventHandler.php b/src/EventHandlers/PreEventHandler.php
index 75a5c81..c6e0384 100644
--- a/src/EventHandlers/PreEventHandler.php
+++ b/src/EventHandlers/PreEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class PreEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
public function onSuccessful($transactionData): void
{
self::sendAnalytics('Initiate-Preauth');
diff --git a/src/EventHandlers/RecipientEventHandler.php b/src/EventHandlers/RecipientEventHandler.php
index 9f43599..b5f7326 100644
--- a/src/EventHandlers/RecipientEventHandler.php
+++ b/src/EventHandlers/RecipientEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class RecipientEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
* */
diff --git a/src/EventHandlers/SettlementEventHandler.php b/src/EventHandlers/SettlementEventHandler.php
index 66d4620..1ad3927 100644
--- a/src/EventHandlers/SettlementEventHandler.php
+++ b/src/EventHandlers/SettlementEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class SettlementEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
* */
diff --git a/src/EventHandlers/SubaccountEventHandler.php b/src/EventHandlers/SubaccountEventHandler.php
index 33e610e..450fa4d 100644
--- a/src/EventHandlers/SubaccountEventHandler.php
+++ b/src/EventHandlers/SubaccountEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class SubaccountEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
* */
diff --git a/src/EventHandlers/SubscriptionEventHandler.php b/src/EventHandlers/SubscriptionEventHandler.php
index af103d1..06bb87b 100644
--- a/src/EventHandlers/SubscriptionEventHandler.php
+++ b/src/EventHandlers/SubscriptionEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class SubscriptionEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
* */
diff --git a/src/EventHandlers/TkEventHandler.php b/src/EventHandlers/TkEventHandler.php
index 697a69e..cba58a5 100644
--- a/src/EventHandlers/TkEventHandler.php
+++ b/src/EventHandlers/TkEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class TkEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
* */
diff --git a/src/EventHandlers/TransactionVerificationEventHandler.php b/src/EventHandlers/TransactionVerificationEventHandler.php
index 5e4cf9c..701ded8 100644
--- a/src/EventHandlers/TransactionVerificationEventHandler.php
+++ b/src/EventHandlers/TransactionVerificationEventHandler.php
@@ -4,14 +4,21 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class TransactionVerificationEventHandler implements EventHandlerInterface
{
/**
* This is called only when a transaction is successful
* */
-
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
public function onSuccessful($transactionData): void
{
// Get the transaction from your DB using the transaction reference (txref)
diff --git a/src/EventHandlers/TransferEventHandler.php b/src/EventHandlers/TransferEventHandler.php
index da3dee0..69cbc64 100644
--- a/src/EventHandlers/TransferEventHandler.php
+++ b/src/EventHandlers/TransferEventHandler.php
@@ -5,12 +5,19 @@
namespace Flutterwave\EventHandlers;
use Exception;
+use Flutterwave\Contract\ConfigInterface;
use stdClass;
class TransferEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ?ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
*
@@ -83,21 +90,21 @@ public function onTimeout($transactionReference, $data): void
public function onAuthorization(stdClass $response, ?array $resource = null): array
{
// $auth = $response->meta->authorization;
-// $mode = $auth->mode;
-// $data['dev_instruction'] = "Display the transfer data for the user to make a transfer to the generated account number. verify via Webhook Service.";
-// $data['instruction'] = $auth->transfer_note;
-// $data['transfer_reference'] = $auth->transfer_reference;
-// $data['transfer_account'] = $auth->transfer_account;
-// $data['transfer_bank'] = $auth->transfer_bank;
-// $data['account_expiration'] = $auth->account_expiration;
-// $data['transfer_amount'] = $auth->transfer_amount;
-// $data['mode'] = $mode;
-//
-// if(is_array($resource) && !empty($resource))
-// {
-// $logger = $resource['logger'];
-// $logger->notice("Transfer Authorization Mode: ".$mode);
-// }
+ // $mode = $auth->mode;
+ // $data['dev_instruction'] = "Display the transfer data for the user to make a transfer to the generated account number. verify via Webhook Service.";
+ // $data['instruction'] = $auth->transfer_note;
+ // $data['transfer_reference'] = $auth->transfer_reference;
+ // $data['transfer_account'] = $auth->transfer_account;
+ // $data['transfer_bank'] = $auth->transfer_bank;
+ // $data['account_expiration'] = $auth->account_expiration;
+ // $data['transfer_amount'] = $auth->transfer_amount;
+ // $data['mode'] = $mode;
+ //
+ // if(is_array($resource) && !empty($resource))
+ // {
+ // $logger = $resource['logger'];
+ // $logger->notice("Transfer Authorization Mode: ".$mode);
+ // }
return [];
}
diff --git a/src/EventHandlers/UssdEventHandler.php b/src/EventHandlers/UssdEventHandler.php
index 610c8b1..fca6c09 100644
--- a/src/EventHandlers/UssdEventHandler.php
+++ b/src/EventHandlers/UssdEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class UssdEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
* */
@@ -101,7 +109,7 @@ public function onAuthorization(\stdClass $response, ?array $resource = null): a
if (is_array($resource) && ! empty($resource)) {
$logger = $resource['logger'];
- $logger->notice('Ussd Authorization Mode: '.$data['mode']);
+ $logger->notice('Ussd Authorization Mode: ' . $data['mode']);
}
return $data;
diff --git a/src/EventHandlers/VirtualAccountEventHandler.php b/src/EventHandlers/VirtualAccountEventHandler.php
index eeb4269..99e7ae7 100644
--- a/src/EventHandlers/VirtualAccountEventHandler.php
+++ b/src/EventHandlers/VirtualAccountEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class VirtualAccountEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
* */
diff --git a/src/EventHandlers/VoucherEventHandler.php b/src/EventHandlers/VoucherEventHandler.php
index 04034d6..0d6d530 100644
--- a/src/EventHandlers/VoucherEventHandler.php
+++ b/src/EventHandlers/VoucherEventHandler.php
@@ -4,10 +4,18 @@
namespace Flutterwave\EventHandlers;
+use Flutterwave\Contract\ConfigInterface;
+
class VoucherEventHandler implements EventHandlerInterface
{
use EventTracker;
+ private static ConfigInterface $config;
+ public function __construct($config)
+ {
+ self::$config = $config;
+ }
+
/**
* This is called only when a transaction is successful
*
diff --git a/src/Exception/ApiException.php b/src/Exception/ApiException.php
index 370151d..3ead755 100644
--- a/src/Exception/ApiException.php
+++ b/src/Exception/ApiException.php
@@ -4,6 +4,8 @@
namespace Flutterwave\Exception;
-class ApiException extends \Unirest\Exception
+use Psr\Http\Client\ClientExceptionInterface;
+
+class ApiException extends \Exception
{
}
diff --git a/src/Exception/AuthenticationException.php b/src/Exception/AuthenticationException.php
index 8c4f648..f6bfec8 100644
--- a/src/Exception/AuthenticationException.php
+++ b/src/Exception/AuthenticationException.php
@@ -6,4 +6,14 @@
class AuthenticationException extends \Exception
{
+ public function invalidBearerToken(): void
+ {
+ $this->message = "Invalid Secret Key passed.";
+ }
+
+ public function unauthorizedAccess(): void
+ {
+ $this->message = "You currently do not have permission to access this feature.
+ kindly reachout to the Account owner.";
+ }
}
diff --git a/src/Exception/ClientException.php b/src/Exception/ClientException.php
new file mode 100644
index 0000000..f749d57
--- /dev/null
+++ b/src/Exception/ClientException.php
@@ -0,0 +1,12 @@
+request = $request;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRequest(): RequestInterface
+ {
+ return $this->request;
+ }
+}
diff --git a/src/Exception/RequestException.php b/src/Exception/RequestException.php
new file mode 100644
index 0000000..58fa87d
--- /dev/null
+++ b/src/Exception/RequestException.php
@@ -0,0 +1,45 @@
+request = $request;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRequest(): RequestInterface
+ {
+ return $this->request;
+ }
+}
diff --git a/src/Factories/CustomerFactory.php b/src/Factories/CustomerFactory.php
new file mode 100644
index 0000000..6c264f9
--- /dev/null
+++ b/src/Factories/CustomerFactory.php
@@ -0,0 +1,29 @@
+set('fullname', $data['full_name']);
+ $person->set('email', $data['email']);
+ $person->set('phone_number', $data['phone']);
+ $person->set('address', $data['address'] ?? null);
+
+ return $person;
+ }
+}
diff --git a/src/Factories/PayloadFactory.php b/src/Factories/PayloadFactory.php
new file mode 100644
index 0000000..df4d62a
--- /dev/null
+++ b/src/Factories/PayloadFactory.php
@@ -0,0 +1,75 @@
+validSuppliedData($data);
+ if (! $check['result']) {
+ throw new \InvalidArgumentException(
+ "" . $check['missing_param'] . '' .
+ ' is required in the payload'
+ );
+ }
+
+ $currency = $data['currency'];
+ $amount = $data['amount'];
+ $customer = $data['customer'];
+ $redirectUrl = $data['redirectUrl'] ?? null;
+ $otherData = $data['additionalData'] ?? null;
+ $phone_number = $data['phone'] ?? null;
+
+ if (isset($data['pin']) && ! empty($data['pin'])) {
+ $otherData['pin'] = $data['pin'];
+ }
+
+ $payload = new Load();
+
+ if (! \is_null($phone_number)) {
+ $payload->set('phone', $phone_number);
+ }
+
+ $tx_ref = $data['tx_ref'] ?? $payload->generateTxRef();
+
+ // $payload->set('phone_number', $phone_number); // customer factory handles that
+ $payload->set('currency', $currency);
+ $payload->set('amount', $amount);
+ $payload->set('tx_ref', $tx_ref);
+ $payload->set('customer', $customer);
+ $payload->set('redirect_url', $redirectUrl);
+ $payload->set('otherData', $otherData);
+
+ return $payload;
+ }
+
+ public function validSuppliedData(array $data): array
+ {
+ $params = $this->requiredParams;
+
+ foreach ($params as $param) {
+ if (! array_key_exists($param, $data)) {
+ return ['missing_param' => $param, 'result' => false];
+ }
+ }
+
+ if (! $data['customer'] instanceof \Flutterwave\Entities\Customer) {
+ return ['missing_param' => 'customer', 'result' => false];
+ }
+
+ return ['missing_param' => null, 'result' => true];
+ }
+}
diff --git a/src/Flutterwave.php b/src/Flutterwave.php
index b1b8849..01d1825 100644
--- a/src/Flutterwave.php
+++ b/src/Flutterwave.php
@@ -4,11 +4,16 @@
namespace Flutterwave;
+use Flutterwave\Config\ForkConfig;
use Flutterwave\EventHandlers\EventHandlerInterface;
+use Flutterwave\Exception\ApiException;
+use Flutterwave\Helper\CheckCompatibility;
use Flutterwave\Traits\PaymentFactory;
use Flutterwave\Traits\Setup\Configure;
+use Flutterwave\Library\Modal;
+use Psr\Http\Client\ClientExceptionInterface;
-define('FLW_PHP_ASSET_DIR', __DIR__.'../assets/');
+define('FLW_PHP_ASSET_DIR', __DIR__ . '../assets/');
/**
* Flutterwave PHP SDK
@@ -19,25 +24,35 @@
*/
class Flutterwave extends AbstractPayment
{
- use Configure,PaymentFactory;
+ use Configure;
+ use PaymentFactory;
/**
* Flutterwave Construct
+ *
* @param string $prefix
- * @param bool $overrideRefWithPrefix Set this parameter to true to use your prefix as the transaction reference
+ * @param bool $overrideRefWithPrefix Set this parameter to true to use your prefix as the transaction reference
*/
- public function __construct(string $prefix, bool $overrideRefWithPrefix = false)
+ public function __construct()
{
- parent::__construct($prefix, $overrideRefWithPrefix);
- $this->overrideTransactionReference = $overrideRefWithPrefix;
+ parent::__construct();
+ $this->checkPageIsSecure();
// create a log channel
$this->logger = self::$config->getLoggerInstance();
$this->createReferenceNumber();
$this->logger->notice('Main Class Initializes....');
}
+ private function checkPageIsSecure()
+ {
+ if(!CheckCompatibility::isSsl() && 'production' === $this->getConfig()->getEnv()) {
+ throw new \Exception('Flutterwave: cannot load checkout modal on an unsecure page - no SSL detected. ');
+ }
+ }
+
/**
* Sets the transaction amount
+ *
* @param string $amount Transaction amount
* */
public function setAmount(string $amount): object
@@ -57,6 +72,16 @@ public function setPaymentOptions(string $paymentOptions): object
return $this;
}
+ /**
+ * get event handler.
+ *
+ * @param string $paymentOptions The allowed payment methods. Can be card, account or both
+ */
+ public function getEventHandler()
+ {
+ return $this->handler;
+ }
+
/**
* Sets the transaction description
*
@@ -82,7 +107,8 @@ public function setLogo(string $customLogo): object
/**
* Sets the payment page title
*
- * @param string $customTitle A title for the payment. It can be the product name, your business name or anything short and descriptive
+ * @param string $customTitle A title for the payment.
+ * It can be the product name, your business name or anything short and descriptive
*/
public function setTitle(string $customTitle): object
{
@@ -159,7 +185,8 @@ public function setPhoneNumber(string $customerPhone): object
/**
* Sets the payment page button text
*
- * @param string $payButtonText This is the text that should appear on the payment button on the Rave payment gateway.
+ * @param string $payButtonText This is the text that should appear
+ * on the payment button on the Rave payment gateway.
*/
public function setPayButtonText(string $payButtonText): object
{
@@ -170,7 +197,8 @@ public function setPayButtonText(string $payButtonText): object
/**
* Sets the transaction redirect url
*
- * @param string $redirectUrl This is where the Rave payment gateway will redirect to after completing a payment
+ * @param string $redirectUrl This is where the Flutterwave will redirect to after
+ * completing a payment
*/
public function setRedirectUrl(string $redirectUrl): object
{
@@ -181,7 +209,9 @@ public function setRedirectUrl(string $redirectUrl): object
/**
* Sets the transaction meta data. Can be called multiple time to set multiple meta data
*
- * @param array $meta This are the other information you will like to store with the transaction. It is a key => value array. eg. PNR for airlines, product colour or attributes. Example. array('name' => 'femi')
+ * @param array $meta This are the other information you will like to store
+ * with the transaction. It is a key => value array. eg. PNR for airlines,
+ * product colour or attributes. Example. array('name' => 'femi')
*/
public function setMetaData(array $meta): object
{
@@ -192,7 +222,8 @@ public function setMetaData(array $meta): object
/**
* Sets the event hooks for all available triggers
*
- * @param EventHandlerInterface $handler This is a class that implements the Event Handler Interface
+ * @param EventHandlerInterface $handler This is a class that implements the
+ * Event Handler Interface
*/
public function eventHandler(EventHandlerInterface $handler): object
{
@@ -203,7 +234,9 @@ public function eventHandler(EventHandlerInterface $handler): object
/**
* Requerys a previous transaction from the Rave payment gateway
*
- * @param string $referenceNumber This should be the reference number of the transaction you want to requery
+ * @param string $referenceNumber This should be the reference number of the transaction you want to requery
+ * @throws ClientExceptionInterface
+ * @throws ApiException
*/
public function requeryTransaction(string $referenceNumber): object
{
@@ -219,37 +252,35 @@ public function requeryTransaction(string $referenceNumber): object
// 'only_successful' => '1'
];
- // make request to endpoint using unirest.
- $headers = ['Content-Type' => 'application/json', 'Authorization' => 'Bearer '.self::$config->getSecretKey()];
- $body = Body::json($data);
- $url = $this->baseUrl . '/transactions/' . $data['id'] . '/verify';
- // Make `POST` request and handle response with unirest
- $response = Request::get($url, $headers);
+ $url = '/transactions/' . $data['id'] . '/verify';
-// print_r($response);
+ $response = $this->getURL(static::$config, $url);
- //check the status is success
- if ($response->body && $response->body->status === 'success') {
- if ($response->body && $response->body->data && $response->body->data->status === 'successful') {
- $this->logger->notice('Requeryed a successful transaction....' . json_encode($response->body->data));
- // Handle successful
+ //check the status is success.
+ if ($response->status === 'success') {
+ if ($response->data && $response->data->status === 'successful') {
+ $this->logger->notice('Requeryed a successful transaction....' . json_encode($response->data));
+ // Handle successful.
if (isset($this->handler)) {
- $this->handler->onSuccessful($response->body->data);
+ $this->handler->onSuccessful($response->data);
}
- } elseif ($response->body && $response->body->data && $response->body->data->status === 'failed') {
+ } elseif ($response->data && $response->data->status === 'failed') {
// Handle Failure
- $this->logger->warning('Requeryed a failed transaction....' . json_encode($response->body->data));
+ $this->logger->warning('Requeryed a failed transaction....' . json_encode($response->data));
if (isset($this->handler)) {
- $this->handler->onFailure($response->body->data);
+ $this->handler->onFailure($response->data);
}
} else {
// Handled an undecisive transaction. Probably timed out.
- $this->logger->warning('Requeryed an undecisive transaction....' . json_encode($response->body->data));
- // I will requery again here. Just incase we have some devs that cannot setup a queue for requery. I don't like this.
+ $this->logger->warning(
+ 'Requeryed an undecisive transaction....' . json_encode($response->data)
+ );
+ // I will requery again here. Just incase we have some devs that cannot setup a queue for requery.
+ // I don't like this.
if ($this->requeryCount > 4) {
// Now you have to setup a queue by force. We couldn't get a status in 5 requeries.
if (isset($this->handler)) {
- $this->handler->onTimeout($this->txref, $response->body);
+ $this->handler->onTimeout($this->txref, $response->data);
}
} else {
$this->logger->notice('delaying next requery for 3 seconds');
@@ -259,10 +290,9 @@ public function requeryTransaction(string $referenceNumber): object
}
}
} else {
- // $this->logger->warn('Requery call returned error for transaction reference.....'.json_encode($response->body).'Transaction Reference: '. $this->txref);
// Handle Requery Error
if (isset($this->handler)) {
- $this->handler->onRequeryError($response->body);
+ $this->handler->onRequeryError($response->data);
}
}
return $this;
@@ -279,10 +309,11 @@ public function initialize(): void
echo '';
echo '';
-// $loader_img_src = FLW_PHP_ASSET_DIR."js/v3.js";
- echo 'Proccessing...

';
-// $script_src = FLW_PHP_ASSET_DIR."js/v3.js";
- echo '';
+ // $loader_img_src = FLW_PHP_ASSET_DIR."js/v3.js";
+ echo '
+ Proccessing...

';
+ // $script_src = FLW_PHP_ASSET_DIR."js/v3.js";
+ echo '';
echo '';
+ $html .= '';
+ $html .= '';
+ $html .= '';
+
+ $this->logger->info('Rendered Payment Modal Successfully..');
+ return $html;
+ }
+
+ public function getUrl()
+ {
+
+ if ($this->type !== self::STANDARD) {
+ return $this->returnHtml();
+ }
+
+ $default_options = CheckoutHelper::getDefaultPaymentOptions();
+ $payload = $this->payload->toArray('modal');
+ $currency = $payload['currency'];
+ $country = CheckoutHelper::getSupportedCountry($currency);
+
+ $payload['country'] = $country;
+ $payload['customer'] = $payload['customer']->toArray();
+ $payload['payment_method'] ?? $default_options;
+
+ $this->logger->info('Generating Payment link for [' . $payload['tx_ref'] . ']');
+ $response = (new Http(self::$config))->request($payload, 'POST', 'payments');
+ return $response->data->link;
+ }
+}
diff --git a/src/Payload.php b/src/Payload.php
index 01e65de..cc4644a 100644
--- a/src/Payload.php
+++ b/src/Payload.php
@@ -4,141 +4,72 @@
namespace Flutterwave;
-use Flutterwave\Util\AuthMode;
-
+/**
+ * Class Payload
+ *
+ * @package Flutterwave
+ * @deprecated Use Flutterwave\Entities\Payload instead.
+ */
class Payload
{
- public const PIN = 'pin';
- public const OTP = 'otp';
- public const REDIRECT = 'redirect';
- public const NOAUTH = 'noauth';
- public const AVS = 'avs';
-
- protected array $data = [];
+ private Entities\Payload $instance;
- protected ?string $type = null;
+ public function __construct()
+ {
+ $this->instance = new \Flutterwave\Entities\Payload();
+ }
public function get(string $param)
{
- if (! $this->has($param)) {
+ if (! $this->instance->has($param)) {
return null;
}
- return $this->data[$param];
+ return $this->instance->get($param);
}
public function set(string $param, $value): void
{
- if ($param === AuthMode::PIN) {
- $this->data['otherData']['authorization']['mode'] = self::PIN;
- $this->data['otherData']['authorization'][AuthMode::PIN] = $value;
- } else {
- $this->data[$param] = $value;
- }
+ $this->instance->set($param, $value);
}
public function delete(string $param, array $assoc_option = []): void
{
- if (! isset($param)) {
- return;
- }
-
- if ($param === 'otherData' && count($assoc_option) > 0) {
- foreach ($assoc_option as $option) {
- unset($this->data['otherData'][$option]);
- }
- }
- unset($this->data[$param]);
+ $this->instance->delete($param, $assoc_option);
}
- public function setPayloadType(string $type): self
+ public function setPayloadType(string $type): Entities\Payload
{
- $this->type = $type;
- return $this;
+ $this->instance->setPayloadType($type);
+ return $this->instance;
}
public function toArray(?string $payment_method = null): array
{
- $data = $this->data;
- $customer = $data['customer'] ?? new Customer();
- $additionalData = $data['otherData'] ?? [];
-
- if (gettype($customer) === 'string') {
- $string_value = $customer;
- $customer = new Customer();
- $customer->set('customer', $string_value);
- }
-
- switch ($payment_method) {
- case 'card':
- $card_details = $additionalData['card_details'];
- unset($additionalData['card_details']);
- $data = array_merge($data, $additionalData, $customer->toArray(), $card_details);
- break;
- case 'account':
- $account_details = $additionalData['account_details'];
- unset($additionalData['account_details']);
- $data = array_merge($data, $additionalData, $customer->toArray(), $account_details);
- break;
- default:
- $data = array_merge($data, $additionalData, $customer->toArray());
- break;
- }
-
- unset($data['customer']);
- unset($data['otherData']);
-
- //convert customer obj to array
- $data = array_merge($additionalData, $data, $customer->toArray());
-
- //if $data['preauthorize'] is false unset
- if (isset($data['preauthorize']) && empty($data['preauthorize'])) {
- unset($data['preauthorize']);
- }
-
- if (array_key_exists('phone_number', $data) && is_null($data['phone_number'])) {
- unset($data['phone_number']);
- }
-
- //if $data['payment_plan'] is null unset
- if (isset($data['payment_plan']) && empty($data['payment_plan'])) {
- unset($data['payment_plan']);
- }
- return $data;
+ return $this->instance->toArray($payment_method);
}
public function update($param, $value): void
{
- if ($param === 'otherData' && \is_array($value)) {
- foreach ($value as $key => $item) {
- $this->data['otherData'][$key] = $item;
- }
- }
-
- $this->data = array_merge($this->data, [$param => $value]);
+ $this->instance->update($param, $value);
}
public function empty(): void
{
- $this->data = [];
+ $this->instance->empty();
}
public function has(string $param): bool
{
- if (! isset($this->data[$param])) {
- return false;
- }
- return true;
+ return $this->instance->has($param);
}
public function size(): int
{
- return count($this->data);
+ return $this->instance->size();
}
public function generateTxRef(): void
{
- if ($this->has('tx_ref')) {
- $this->set('tx_ref', 'FLWPHP|' . (mt_rand(2, 101) + time()));
- }
+ $this->instance->generateTxRef();
}
}
diff --git a/src/Service/AccountPayment.php b/src/Service/AccountPayment.php
index ef7c605..1748883 100644
--- a/src/Service/AccountPayment.php
+++ b/src/Service/AccountPayment.php
@@ -8,23 +8,27 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\Contract\Payment;
use Flutterwave\EventHandlers\AccountEventHandler;
-use Flutterwave\Payload;
+use Flutterwave\Entities\Payload;
use Flutterwave\Traits\Group\Charge;
+use Flutterwave\Util\Currency;
use GuzzleHttp\Exception\GuzzleException;
use InvalidArgumentException;
+use Psr\Http\Client\ClientExceptionInterface;
use stdClass;
class AccountPayment extends Service implements Payment
{
use Charge;
+
public const ENDPOINT = 'charge';
- public const DEBIT_NG = 'debit_ng_account';
- public const DEBIT_UK = 'debit_uk_account';
+ public const DEBIT_NG = 'mono';
+ public const DEBIT_UK = 'account-ach-uk';
public const TYPE = 'account';
protected array $accounts = [
- 'NG' => self::DEBIT_NG,
- 'UK' => self::DEBIT_UK,
- ];
+ Currency::NGN => self::DEBIT_NG,
+ Currency::GBP => self::DEBIT_UK,
+ Currency::EUR => self::DEBIT_UK
+ ];
protected string $country = 'NG';
private AccountEventHandler $eventHandler;
@@ -34,8 +38,8 @@ public function __construct(?ConfigInterface $config = null)
$endpoint = $this->getEndpoint();
- $this->url = $this->baseUrl.'/'.$endpoint.'?type=';
- $this->eventHandler = new AccountEventHandler();
+ $this->url = $this->baseUrl . '/' . $endpoint . '?type=';
+ $this->eventHandler = new AccountEventHandler($config);
}
public function setCountry(string $country): void
@@ -53,6 +57,12 @@ public function setCountry(string $country): void
*/
public function initiate(Payload $payload): array
{
+ if($payload->has('currency') && !key_exists($payload->get('currency'), $this->accounts)) {
+ $msg = 'Account Service: The Currency passed is not supported. kindy pass NGN, GBP or EUR.';
+ $this->logger->info($msg);
+ throw new InvalidArgumentException($msg);
+ }
+
if ($this->checkPayloadIsValid($payload, 'account_details')) {
return $this->charge($payload);
}
@@ -62,23 +72,26 @@ public function initiate(Payload $payload): array
}
/**
+ * @param Payload $payload
* @return array
*
- * @throws GuzzleException
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function charge(Payload $payload): array
{
$this->logger->notice('Account Service::Charging Account ...');
- $this->checkSpecialCasesParams($payload);
+ if($payload->has('currency') && $payload->get('currency') === Currency::NGN ) {
+ $this->checkSpecialCasesParams($payload);
+ }
+
$payload = $payload->toArray(self::TYPE);
//request payload
$body = $payload;
//check which country was passed.
- $account = $this->accounts[$payload['country']];
+ $account = $this->accounts[$payload['currency']];
unset($body['country']);
unset($body['address']);
@@ -97,7 +110,7 @@ public function save(callable $callback): void
private function checkSpecialCasesParams(Payload $payload)
{
$details = $payload->get('otherData')['account_details'];
- $banks = require __DIR__ . '/../Util/unique_bank_cases.php';
+ $banks = include __DIR__ . '/../Util/unique_bank_cases.php';
foreach ($banks as $code => $case) {
if ($details['account_bank'] === $code) {
@@ -125,7 +138,8 @@ private function checkSpecialCasesParams(Payload $payload)
}
/**
- * @param array $payload
+ * @param stdClass $response
+ * @param array $payload
*
* @return array
*
diff --git a/src/Service/AchPayment.php b/src/Service/AchPayment.php
index 75e4816..653b0e2 100644
--- a/src/Service/AchPayment.php
+++ b/src/Service/AchPayment.php
@@ -8,8 +8,9 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\Contract\Payment;
use Flutterwave\EventHandlers\AchEventHandler;
-use Flutterwave\Payload;
+use Flutterwave\Entities\Payload;
use Flutterwave\Traits\Group\Charge;
+use Flutterwave\Util\Currency;
use GuzzleHttp\Exception\GuzzleException;
use stdClass;
@@ -18,12 +19,11 @@ class AchPayment extends Service implements Payment
use Charge;
public const TYPE = 'ach_payment';
- public const USD = 'USD';
- public const ZAR = 'ZAR';
+
protected string $country = 'US';
protected array $currency = [
- self::USD => 'US',
- self::ZAR => 'ZA',
+ Currency::USD => 'US',
+ Currency::ZAR => 'ZA',
];
private AchEventHandler $eventHandler;
@@ -32,8 +32,8 @@ public function __construct(?ConfigInterface $config = null)
parent::__construct($config);
$endpoint = $this->getEndpoint();
- $this->url = $this->baseUrl.'/'.$endpoint.'?type=';
- $this->eventHandler = new AchEventHandler();
+ $this->url = $this->baseUrl . '/' . $endpoint . '?type=';
+ $this->eventHandler = new AchEventHandler($config);
}
public function setCountry(string $country): void
diff --git a/src/Service/ApplePay.php b/src/Service/ApplePay.php
index 5ab7812..498f7f5 100644
--- a/src/Service/ApplePay.php
+++ b/src/Service/ApplePay.php
@@ -7,9 +7,10 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\Contract\Payment;
use Flutterwave\EventHandlers\ApplePayEventHandler;
-use Flutterwave\Payload;
+use Flutterwave\Entities\Payload;
use Flutterwave\Traits\Group\Charge;
use GuzzleHttp\Exception\GuzzleException;
+use Psr\Http\Client\ClientExceptionInterface;
use stdClass;
class ApplePay extends Service implements Payment
@@ -24,8 +25,8 @@ public function __construct(?ConfigInterface $config = null)
parent::__construct($config);
$endpoint = $this->getEndpoint();
- $this->url = $this->baseUrl.'/'.$endpoint.'?type=';
- $this->eventHandler = new ApplePayEventHandler();
+ $this->url = $this->baseUrl . '/' . $endpoint . '?type=';
+ $this->eventHandler = new ApplePayEventHandler($config);
}
/**
@@ -39,9 +40,10 @@ public function initiate(Payload $payload): array
}
/**
+ * @param Payload $payload
* @return array
*
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
public function charge(Payload $payload): array
{
diff --git a/src/Service/BankTransfer.php b/src/Service/BankTransfer.php
index b150213..748038d 100644
--- a/src/Service/BankTransfer.php
+++ b/src/Service/BankTransfer.php
@@ -8,9 +8,10 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\Contract\Payment;
use Flutterwave\EventHandlers\BankTransferEventHandler;
-use Flutterwave\Payload;
+use Flutterwave\Entities\Payload;
use Flutterwave\Traits\Group\Charge;
use GuzzleHttp\Exception\GuzzleException;
+use Psr\Http\Client\ClientExceptionInterface;
use stdClass;
class BankTransfer extends Service implements Payment
@@ -26,8 +27,8 @@ public function __construct(?ConfigInterface $config = null)
parent::__construct($config);
$endpoint = $this->getEndpoint();
- $this->url = $this->baseUrl.'/'.$endpoint.'?type=';
- $this->eventHandler = new BankTransferEventHandler();
+ $this->url = $this->baseUrl . '/' . $endpoint . '?type=';
+ $this->eventHandler = new BankTransferEventHandler($config);
}
public function makePermanent(): void
@@ -38,10 +39,10 @@ public function makePermanent(): void
}
/**
- * @param Payload $payload
+ * @param Payload $payload
* @return array
*
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
public function initiate(Payload $payload): array
{
@@ -49,11 +50,11 @@ public function initiate(Payload $payload): array
}
/**
- * @param Payload $payload
+ * @param Payload $payload
* @return array
*
- * @throws GuzzleException
- * @throws Exception
+ * @throws ClientExceptionInterface
+ * @throws Exception|ClientExceptionInterface
*/
public function charge(Payload $payload): array
{
@@ -65,9 +66,9 @@ public function charge(Payload $payload): array
//request payload
$body = $payload;
- BankTransferEventHandler::startRecording();
+ $this->eventHandler::startRecording();
$request = $this->request($body, 'POST', self::TYPE);
- BankTransferEventHandler::setResponseTime();
+ $this->eventHandler::setResponseTime();
return $this->handleAuthState($request, $body);
}
@@ -77,8 +78,8 @@ public function save(callable $callback): void
}
/**
- * @param stdClass $response
- * @param array $payload
+ * @param stdClass $response
+ * @param array $payload
* @return array
* @throws Exception
*/
diff --git a/src/Service/Banks.php b/src/Service/Banks.php
index 132f180..17795d7 100644
--- a/src/Service/Banks.php
+++ b/src/Service/Banks.php
@@ -6,11 +6,13 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\EventHandlers\EventTracker;
-use GuzzleHttp\Exception\GuzzleException;
+use Psr\Http\Client\ClientExceptionInterface;
+use stdClass;
class Banks extends Service
{
use EventTracker;
+
private string $name = 'banks';
public function __construct(?ConfigInterface $config = null)
{
@@ -18,25 +20,25 @@ public function __construct(?ConfigInterface $config = null)
}
/**
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
- public function getByCountry(string $country = 'NG'): \stdClass
+ public function getByCountry(string $country = 'NG'): stdClass
{
$this->logger->notice("Bank Service::Retrieving banks in country:({$country}).");
self::startRecording();
- $response = $this->request(null, 'GET', $this->name."/{$country}");
+ $response = $this->request(null, 'GET', $this->name . "/{$country}");
self::setResponseTime();
return $response;
}
/**
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
- public function getBranches(string $id): \stdClass
+ public function getBranches(string $id): stdClass
{
$this->logger->notice("Bank Service::Retrieving Bank Branches bank_id:({$id}).");
self::startRecording();
- $response = $this->request(null, 'GET', $this->name."/{$id}/branches");
+ $response = $this->request(null, 'GET', $this->name . "/{$id}/branches");
self::setResponseTime();
return $response;
}
diff --git a/src/Service/Beneficiaries.php b/src/Service/Beneficiaries.php
index d4c5f04..de10433 100644
--- a/src/Service/Beneficiaries.php
+++ b/src/Service/Beneficiaries.php
@@ -6,14 +6,16 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\EventHandlers\EventTracker;
-use Flutterwave\Payload;
+use Flutterwave\Entities\Payload;
use GuzzleHttp\Exception\GuzzleException;
use InvalidArgumentException;
+use Psr\Http\Client\ClientExceptionInterface;
use stdClass;
class Beneficiaries extends Service
{
use EventTracker;
+
private string $name = 'beneficiaries';
private array $requiredParams = [
'account_bank','account_number','beneficiary_name',
@@ -24,21 +26,25 @@ public function __construct(?ConfigInterface $config = null)
}
/**
- * @throws GuzzleException
+ * @param Payload $payload
+ * @return stdClass
+ * @throws ClientExceptionInterface
*/
public function create(Payload $payload): stdClass
{
$payload = $payload->toArray();
if (array_key_exists('customer', $payload)) {
- $this->logger->error('Beneficiaries Service::The required parameter customer Object is not present in payload');
- throw new InvalidArgumentException('Beneficiaries Service:The required parameter Object is not present in payload');
+ $msg = 'The required parameter customer Object is not present in payload';
+ $this->logger->error('Beneficiaries Service::' . $msg);
+ throw new InvalidArgumentException('Beneficiaries Service:' . $msg);
}
foreach ($this->requiredParams as $param) {
if (! array_key_exists($param, $payload)) {
- $this->logger->error("Beneficiaries Service::The required parameter {$param} is not present in payload");
- throw new InvalidArgumentException("Beneficiaries Service:The required parameter {$param} is not present in payload");
+ $msg = 'The required parameter {$param} is not present in payload';
+ $this->logger->error("Beneficiaries Service::$msg");
+ throw new InvalidArgumentException("Beneficiaries Service:$msg");
}
}
@@ -53,7 +59,8 @@ public function create(Payload $payload): stdClass
}
/**
- * @throws GuzzleException
+ * @return stdClass
+ * @throws ClientExceptionInterface
*/
public function list(): stdClass
{
@@ -65,25 +72,29 @@ public function list(): stdClass
}
/**
- * @throws GuzzleException
+ * @param string $id
+ * @return stdClass
+ * @throws ClientExceptionInterface
*/
public function get(string $id): stdClass
{
$this->logger->notice('Beneficiaries Service::Retrieving a Beneficiary.');
self::startRecording();
- $response = $this->request(null, 'GET', $this->name."/{$id}");
+ $response = $this->request(null, 'GET', $this->name . "/{$id}");
self::setResponseTime();
return $response;
}
/**
- * @throws GuzzleException
+ * @param string $id
+ * @return stdClass
+ * @throws ClientExceptionInterface
*/
public function delete(string $id): stdClass
{
$this->logger->notice('Beneficiaries Service::Delete a Beneficiary.');
self::startRecording();
- $response = $this->request(null, 'DELETE', $this->name."/{$id}");
+ $response = $this->request(null, 'DELETE', $this->name . "/{$id}");
self::setResponseTime();
return $response;
}
diff --git a/src/Service/Bill.php b/src/Service/Bill.php
index dcc177e..661cce5 100644
--- a/src/Service/Bill.php
+++ b/src/Service/Bill.php
@@ -6,11 +6,12 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\EventHandlers\EventTracker;
-use Unirest\Exception;
+use Psr\Http\Client\ClientExceptionInterface;
class Bill extends Service
{
use EventTracker;
+
protected ?array $categories = null;
private string $name = 'bill-categories';
private array $requiredParams = [
@@ -19,11 +20,11 @@ class Bill extends Service
public function __construct(?ConfigInterface $config = null)
{
parent::__construct($config);
- $this->categories = require __DIR__ . '/../Util/bill_categories.php';
+ $this->categories = include __DIR__ . '/../Util/bill_categories.php';
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function getCategories(): \stdClass
{
@@ -35,28 +36,28 @@ public function getCategories(): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function validateService(string $item_code): \stdClass
{
$this->logger->notice('Bill Payment Service::Retrieving all Plans.');
self::startRecording();
- $response = $this->request(null, 'GET', $this->name."bill-item/{$item_code}/validate");
+ $response = $this->request(null, 'GET', $this->name . "bill-item/{$item_code}/validate");
self::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function createPayment(\Flutterwave\Payload $payload): \stdClass
{
- $payload =
$payload = $payload->toArray();
foreach ($this->requiredParams as $param) {
if (! array_key_exists($param, $payload)) {
- $this->logger->error("Bill Payment Service::The required parameter {$param} is not present in payload");
- throw new \InvalidArgumentException("Bill Payment Service:The required parameter {$param} is not present in payload");
+ $msg = 'The required parameter {$param} is not present in payload';
+ $this->logger->error("Bill Payment Service::$msg");
+ throw new \InvalidArgumentException("Bill Payment Service:$msg");
}
}
@@ -73,8 +74,9 @@ public function createPayment(\Flutterwave\Payload $payload): \stdClass
public function createBulkPayment(array $bulkPayload): \stdClass
{
if (empty($bulkPayload)) {
- $this->logger->error('Bill Payment Service::Bulk Payload is empty. Pass a filled array');
- throw new \InvalidArgumentException('Bill Payment Service::Bulk Payload is currently empty. Pass a filled array');
+ $msg = 'Bulk Payload is empty. Pass a filled array';
+ $this->logger->error('Bill Payment Service::' . $msg);
+ throw new \InvalidArgumentException('Bill Payment Service::' . $msg);
}
$body = $bulkPayload;
@@ -87,7 +89,7 @@ public function createBulkPayment(array $bulkPayload): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function getBillStatus(string $reference): \stdClass
{
@@ -99,7 +101,7 @@ public function getBillStatus(string $reference): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function getBillPayments(): \stdClass
{
diff --git a/src/Service/CardPayment.php b/src/Service/CardPayment.php
index f6eb668..0bbf487 100644
--- a/src/Service/CardPayment.php
+++ b/src/Service/CardPayment.php
@@ -4,17 +4,20 @@
namespace Flutterwave\Service;
+use Exception;
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\Contract\Payment;
use Flutterwave\EventHandlers\CardEventHandler;
-use Flutterwave\Payload;
+use Flutterwave\Entities\Payload;
use Flutterwave\Traits\Group\Charge;
use GuzzleHttp\Exception\GuzzleException;
use InvalidArgumentException;
+use Psr\Http\Client\ClientExceptionInterface;
class CardPayment extends Service implements Payment
{
use Charge;
+
public const ENDPOINT = 'charges';
public const TYPE = 'card';
protected static int $count = 0;
@@ -31,17 +34,17 @@ public function __construct(?ConfigInterface $config = null)
$endpoint = $this->getEndpoint();
- $this->url = $this->baseUrl.'/'.$endpoint.'?type='.self::TYPE;
- $this->end_point = self::ENDPOINT.'?type='.self::TYPE;
- $this->eventHandler = new CardEventHandler();
+ $this->url = $this->baseUrl . '/' . $endpoint . '?type=' . self::TYPE;
+ $this->end_point = self::ENDPOINT . '?type=' . self::TYPE;
+ $this->eventHandler = new CardEventHandler($config);
}
/**
- * @param Payload $payload
+ * @param Payload $payload
* @return array
* @throws GuzzleException
*/
- public function initiate(\Flutterwave\Payload $payload): array
+ public function initiate(Payload $payload): array
{
if (self::$count >= 2) {
//TODO: if payload does not have pin on 2nd request, trigger a warning.
@@ -64,11 +67,12 @@ public function save(callable $callback): void
}
/**
+ * @param Payload $payload
* @return array
*
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
- public function charge(\Flutterwave\Payload $payload): array
+ public function charge(Payload $payload): array
{
$tx_ref = $payload->get('tx_ref');
$this->logger->notice("Card Service::Started Charging Card tx_ref:({$tx_ref})...");
@@ -86,16 +90,18 @@ public function charge(\Flutterwave\Payload $payload): array
'client' => $client,
];
- CardEventHandler::startRecording();
+ $this->eventHandler::startRecording();
$request = $this->request($body, 'POST');
- CardEventHandler::setResponseTime();
+ $this->eventHandler::setResponseTime();
return $this->handleAuthState($request, $payload);
}
/**
- * this is the encrypt3Des function that generates an encryption Key for you by passing your transaction Util and Secret Key as a parameter.
- * @param string $data
- * @param $key
+ * this is the encrypt3Des function that generates an encryption Key for you
+ * by passing your transaction Util and Secret Key as a parameter.
+ *
+ * @param string $data
+ * @param $key
* @return string
*/
@@ -118,7 +124,10 @@ public function encryption(string $params): string
}
/**
- * @throws \Exception
+ * @param \stdClass $response
+ * @param $payload
+ * @return array
+ * @throws Exception
*/
public function handleAuthState(\stdClass $response, $payload): array
{
diff --git a/src/Service/ChargeBacks.php b/src/Service/ChargeBacks.php
index d5082fd..f61812d 100644
--- a/src/Service/ChargeBacks.php
+++ b/src/Service/ChargeBacks.php
@@ -11,6 +11,7 @@
class ChargeBacks extends Service
{
use EventTracker;
+
private string $name = 'chargebacks';
public function __construct(?ConfigInterface $config = null)
{
@@ -24,7 +25,7 @@ public function get(string $flw_ref): \stdClass
{
$this->logger->notice("ChargeBacks Service::Retrieving Chargeback.[flw_ref:{$flw_ref}]");
self::startRecording();
- $response = $this->request(null, 'GET', $this->name."?flw_ref={$flw_ref}");
+ $response = $this->request(null, 'GET', $this->name . "?flw_ref={$flw_ref}");
self::setResponseTime();
return $response;
}
@@ -37,7 +38,7 @@ public function getAll(array $filters = []): \stdClass
$query = http_build_query($filters) ?? '';
$this->logger->notice('ChargeBacks Service::Retrieving Chargebacks.[all]');
self::startRecording();
- $response = $this->request(null, 'GET', $this->name."?{$query}");
+ $response = $this->request(null, 'GET', $this->name . "?{$query}");
self::setResponseTime();
return $response;
}
@@ -49,7 +50,7 @@ public function accept(string $chargeback_id): \stdClass
{
$this->logger->notice("ChargeBacks Service::Accepting Chargeback [{$chargeback_id}].");
self::startRecording();
- $response = $this->request([ 'action' => 'accept'], 'PUT', $this->name."/{$chargeback_id}");
+ $response = $this->request([ 'action' => 'accept'], 'PUT', $this->name . "/{$chargeback_id}");
self::setResponseTime();
return $response;
}
@@ -61,7 +62,7 @@ public function decline(string $chargeback_id): \stdClass
{
$this->logger->notice("ChargeBacks Service::Declining Chargeback [{$chargeback_id}].");
self::startRecording();
- $response = $this->request([ 'action' => 'decline'], 'PUT', $this->name."/{$chargeback_id}");
+ $response = $this->request([ 'action' => 'decline'], 'PUT', $this->name . "/{$chargeback_id}");
self::setResponseTime();
return $response;
}
diff --git a/src/Service/CollectionSubaccount.php b/src/Service/CollectionSubaccount.php
index 9fd56d4..b28ac75 100644
--- a/src/Service/CollectionSubaccount.php
+++ b/src/Service/CollectionSubaccount.php
@@ -6,20 +6,27 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\EventHandlers\SubaccountEventHandler;
-use Flutterwave\Payload;
+use Flutterwave\Entities\Payload;
use GuzzleHttp\Exception\GuzzleException;
class CollectionSubaccount extends Service
{
private SubaccountEventHandler $eventHandler;
+
private string $name = 'subaccounts';
- private array $requiredParams = [ 'account_bank', 'account_number', 'business_name', 'split_value', 'business_mobile','business_email', 'country' ];
+
+ private array $requiredParams = [
+ 'account_bank', 'account_number',
+ 'business_name', 'split_value',
+ 'business_mobile','business_email', 'country'
+ ];
private array $requiredParamsUpdate = [ 'split_value'];
+
public function __construct(?ConfigInterface $config = null)
{
parent::__construct($config);
$endpoint = $this->name;
- $this->url = $this->baseUrl.'/'.$endpoint;
+ $this->url = $this->baseUrl . '/' . $endpoint;
$this->eventHandler = new SubaccountEventHandler();
}
@@ -27,8 +34,9 @@ public function confirmPayload(Payload $payload): array
{
foreach ($this->requiredParams as $param) {
if (! $payload->has($param)) {
- $this->logger->error("Subaccount Service::The required parameter {$param} is not present in payload");
- throw new \InvalidArgumentException("Subaccount Service:The required parameter {$param} is not present in payload");
+ $msg = "The required parameter {$param} is not present in payload";
+ $this->logger->error("Subaccount Service::" . $msg);
+ throw new \InvalidArgumentException("Subaccount Service:" . $msg);
}
}
@@ -36,7 +44,7 @@ public function confirmPayload(Payload $payload): array
}
/**
- * @param Payload $payload
+ * @param Payload $payload
* @return \stdClass
* @throws GuzzleException
*/
@@ -71,7 +79,7 @@ public function list(): \stdClass
}
/**
- * @param string $id
+ * @param string $id
* @return \stdClass
* @throws GuzzleException
*/
@@ -84,8 +92,8 @@ public function get(string $id): \stdClass
}
/**
- * @param string $id
- * @param Payload $payload
+ * @param string $id
+ * @param Payload $payload
* @return \stdClass
* @throws GuzzleException
*/
@@ -93,8 +101,9 @@ public function update(string $id, Payload $payload): \stdClass
{
foreach ($this->requiredParamsUpdate as $param) {
if (! $payload->has($param)) {
- $this->logger->error("Subaccount Service::The required parameter {$param} is not present in payload");
- throw new \InvalidArgumentException("Subaccount Service:The required parameter {$param} is not present in payload");
+ $msg = "The required parameter {$param} is not present in payload";
+ $this->logger->error("Subaccount Service::" . $msg);
+ throw new \InvalidArgumentException("Subaccount Service:" . $msg);
}
}
@@ -106,7 +115,7 @@ public function update(string $id, Payload $payload): \stdClass
}
/**
- * @param string $id
+ * @param string $id
* @return \stdClass
* @throws GuzzleException
*/
diff --git a/src/Service/Customer.php b/src/Service/Customer.php
index bfaf444..f924b6a 100644
--- a/src/Service/Customer.php
+++ b/src/Service/Customer.php
@@ -5,24 +5,26 @@
namespace Flutterwave\Service;
use Flutterwave\Contract\CustomerInterface;
-use Flutterwave\Customer as Person;
+use Flutterwave\Entities\Customer as Person;
+use Flutterwave\Factories\CustomerFactory;
use InvalidArgumentException;
-class Customer implements CustomerInterface
+/**
+ * Class Customer.
+ *
+ * @deprecated use \Flutterwave\Factories\CustomerFactory instead
+ */
+class Customer
{
- public function create(array $data = []): Person
- {
- $data = array_change_key_case($data);
- if (empty($data)) {
- throw new InvalidArgumentException('Customer data is empty');
- }
+ protected CustomerInterface $customerFactory;
- $person = new Person();
- $person->set('fullname', $data['full_name']);
- $person->set('email', $data['email']);
- $person->set('phone_number', $data['phone']);
- $person->set('address', $data['address'] ?? null);
+ public function __construct()
+ {
+ $this->customerFactory = new CustomerFactory();
+ }
- return $person;
+ public function create(array $data = []): Person
+ {
+ return $this->customerFactory->create($data);
}
}
diff --git a/src/Service/Enaira.php b/src/Service/Enaira.php
new file mode 100644
index 0000000..3b928ad
--- /dev/null
+++ b/src/Service/Enaira.php
@@ -0,0 +1,75 @@
+getEndpoint();
+ $this->url = $this->baseUrl . '/' . $endpoint . '?type=';
+ $this->eventHandler = new ApplePayEventHandler($config);
+ }
+
+ /**
+ * @return array
+ *
+ * @throws GuzzleException
+ */
+ public function initiate(Payload $payload): array
+ {
+ return $this->charge($payload);
+ }
+
+ /**
+ * @param Payload $payload
+ * @return array
+ *
+ * @throws ClientExceptionInterface
+ */
+ public function charge(Payload $payload): array
+ {
+ $this->logger->notice('Enaira Service::Started Charging Process ...');
+
+ $payload = $payload->toArray();
+
+ //request payload
+ $body = $payload;
+
+ ApplePayEventHandler::startRecording();
+ $request = $this->request($body, 'POST', self::TYPE);
+ ApplePayEventHandler::setResponseTime();
+ return $this->handleAuthState($request, $body);
+ }
+
+ public function save(callable $callback): void
+ {
+ // TODO: Implement save() method.
+ }
+
+ /**
+ * @param array $payload
+ *
+ * @return array
+ */
+ private function handleAuthState(stdClass $response, array $payload): array
+ {
+ return $this->eventHandler->onAuthorization($response, ['logger' => $this->logger]);
+ }
+}
\ No newline at end of file
diff --git a/src/Service/Fawry.php b/src/Service/Fawry.php
new file mode 100644
index 0000000..0eaad3f
--- /dev/null
+++ b/src/Service/Fawry.php
@@ -0,0 +1,81 @@
+getEndpoint();
+ $this->url = $this->baseUrl . '/' . $endpoint . '?type=';
+ $this->eventHandler = new GooglePayEventHandler($config);
+ }
+
+ /**
+ * @return array
+ *
+ * @throws GuzzleException
+ */
+ public function initiate(Payload $payload): array
+ {
+ return $this->charge($payload);
+ }
+
+ /**
+ * @param Payload $payload
+ * @return array
+ *
+ * @throws ClientExceptionInterface
+ */
+ public function charge(Payload $payload): array
+ {
+ $this->logger->notice('Google Service::Started Charging Process ...');
+
+ $payload = $payload->toArray();
+
+ if($payload['currency'] !== 'EGP') {
+ throw new \InvalidArgumentException("Invalid currency. This transaction is only allowed for EGP");
+ }
+
+ //request payload
+ $body = $payload;
+
+ unset($body['country']);
+ unset($body['address']);
+
+ $this->eventHandler::startRecording();
+ $request = $this->request($body, 'POST', self::TYPE);
+ $this->eventHandler::setResponseTime();
+ return $this->handleAuthState($request, $body);
+ }
+
+ public function save(callable $callback): void
+ {
+ // TODO: Implement save() method.
+ }
+
+ /**
+ * @param array $payload
+ *
+ * @return array
+ */
+ private function handleAuthState(stdClass $response, array $payload): array
+ {
+ return $this->eventHandler->onAuthorization($response, ['logger' => $this->logger]);
+ }
+}
\ No newline at end of file
diff --git a/src/Service/GooglePay.php b/src/Service/GooglePay.php
new file mode 100644
index 0000000..2868f5c
--- /dev/null
+++ b/src/Service/GooglePay.php
@@ -0,0 +1,79 @@
+getEndpoint();
+ $this->url = $this->baseUrl . '/' . $endpoint . '?type=';
+ $this->eventHandler = new GooglePayEventHandler($config);
+ }
+
+ /**
+ * @return array
+ *
+ * @throws GuzzleException
+ */
+ public function initiate(Payload $payload): array
+ {
+ return $this->charge($payload);
+ }
+
+ /**
+ * @param Payload $payload
+ * @return array
+ *
+ * @throws ClientExceptionInterface
+ */
+ public function charge(Payload $payload): array
+ {
+ $this->logger->notice('Google Service::Started Charging Process ...');
+
+ $payload = $payload->toArray();
+
+ //request payload
+ $body = $payload;
+
+ unset($body['country']);
+ unset($body['address']);
+
+ $this->eventHandler::startRecording();
+ $request = $this->request($body, 'POST', self::TYPE);
+ $this->eventHandler::setResponseTime();
+ return $this->handleAuthState($request, $body);
+ }
+
+ public function save(callable $callback): void
+ {
+ // TODO: Implement save() method.
+ }
+
+ /**
+ * @param array $payload
+ *
+ * @return array
+ */
+ private function handleAuthState(stdClass $response, array $payload): array
+ {
+ return $this->eventHandler->onAuthorization($response, ['logger' => $this->logger]);
+ }
+}
\ No newline at end of file
diff --git a/src/Service/Misc.php b/src/Service/Misc.php
index 59cf6b7..ac4f9fc 100644
--- a/src/Service/Misc.php
+++ b/src/Service/Misc.php
@@ -6,11 +6,12 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\EventHandlers\EventTracker;
-use Unirest\Exception;
+use Psr\Http\Client\ClientExceptionInterface;
class Misc extends Service
{
use EventTracker;
+
private string $name = 'balances';
private array $requiredParamsHistory = [
'from','to','currency',
@@ -27,7 +28,7 @@ public function __construct(?ConfigInterface $config = null)
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function getWallet($currency): \stdClass
{
@@ -39,7 +40,7 @@ public function getWallet($currency): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function getWallets(): \stdClass
{
@@ -51,14 +52,15 @@ public function getWallets(): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function getBalanceHistory(array $queryParams): \stdClass
{
foreach ($this->requiredParamsHistory as $param) {
if (! array_key_exists($param, $queryParams)) {
- $this->logger->error("Misc Service::The following parameter is missing to check balance history: {$param}");
- throw new \InvalidArgumentException("The following parameter is missing to check balance history: {$param}");
+ $msg = "The following parameter is missing to check balance history: {$param}";
+ $this->logger->error("Misc Service::$msg");
+ throw new \InvalidArgumentException($msg);
}
}
@@ -71,7 +73,7 @@ public function getBalanceHistory(array $queryParams): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function resolveAccount(\Flutterwave\Payload $payload): \stdClass
{
@@ -91,7 +93,7 @@ public function resolveAccount(\Flutterwave\Payload $payload): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function resolveBvn(string $bvn): \stdClass
{
@@ -103,7 +105,7 @@ public function resolveBvn(string $bvn): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function resolveCardBin(string $bin): \stdClass
{
@@ -115,14 +117,15 @@ public function resolveCardBin(string $bin): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function userBackgroundCheck(array $data): \stdClass
{
foreach ($this->requiredParamsUserBackground as $param) {
if (! array_key_exists($param, $data)) {
- $this->logger->error("Misc Service::The following parameter is missing to check user background: {$param}");
- throw new \InvalidArgumentException("The following parameter is missing to check user background: {$param}");
+ $msg = "The following parameter is missing to check user background: {$param}";
+ $this->logger->error("Misc Service::$msg");
+ throw new \InvalidArgumentException($msg);
}
}
diff --git a/src/Service/MobileMoney.php b/src/Service/MobileMoney.php
index 9a2369f..a546bc8 100644
--- a/src/Service/MobileMoney.php
+++ b/src/Service/MobileMoney.php
@@ -7,10 +7,10 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\Contract\Payment;
use Flutterwave\EventHandlers\MomoEventHandler;
-use Flutterwave\Payload;
+use Flutterwave\Entities\Payload;
use Flutterwave\Traits\Group\Charge;
use Flutterwave\Util\Currency;
-use GuzzleHttp\Exception\GuzzleException;
+use Psr\Http\Client\ClientExceptionInterface;
class MobileMoney extends Service implements Payment
{
@@ -23,12 +23,14 @@ class MobileMoney extends Service implements Payment
Currency::UGX => 'mobile_money_uganda',
Currency::XAF => 'mobile_money_franco',
Currency::ZMW => 'mobile_money_zambia',
+ Currency::TZS => 'mobile_money_tanzania'
];
private array $networks = [
'GH' => ['MTN','VODOFONE','TIGO'],
'UG' => ['MTN', 'AIRTEL'],
'ZM' => ['MTN', 'ZAMTEL'],
+ 'Tz' => ['AIRTEL', 'TIGO', 'HALOPESA', 'VODOFONE' ]
];
private array $supported_countries_franco = [
@@ -40,39 +42,42 @@ public function __construct(?ConfigInterface $config = null)
{
parent::__construct($config);
$endpoint = $this->getEndpoint();
- $this->url = $this->baseUrl.'/'.$endpoint.'?type=';
- $this->eventHandler = new MomoEventHandler();
+ $this->url = $this->baseUrl . '/' . $endpoint . '?type=';
+ $this->eventHandler = new MomoEventHandler($config);
}
/**
- * @param Payload $payload
+ * @param Payload $payload
* @return array
- * @throws \Exception
+ * @throws ClientExceptionInterface
*/
- public function initiate(\Flutterwave\Payload $payload): array
+ public function initiate(Payload $payload): array
{
return $this->charge($payload);
}
/**
- * @param Payload $payload
+ * @param Payload $payload
* @return array
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
- public function charge(\Flutterwave\Payload $payload): array
+ public function charge(Payload $payload): array
{
$currency = $payload->get('currency');
$otherData = $payload->get('otherData');
if (! array_key_exists($currency, $this->types)) {
$supported_currencies = json_encode(array_keys($this->types));
- $this->logger->warning("Momo Service::The currency {$currency} is not supported for this payment method. options [ {$supported_currencies} ]");
- throw new \InvalidArgumentException("The currency {$currency} is not supported for this payment method. options [ {$supported_currencies} ]");
+ $msg = "The currency {$currency} is not supported for this payment method.
+ options [ {$supported_currencies} ]";
+ $this->logger->warning("Momo Service:: $msg");
+ throw new \InvalidArgumentException($msg);
}
if (is_null($otherData)) {
- $this->logger->error("Momo Service::Please pass the parameter 'network' into the additionalData array");
- throw new \InvalidArgumentException("Please pass the parameter 'network' into the additionalData array");
+ $msg = "Please pass the parameter 'network' into the additionalData array";
+ $this->logger->error("Momo Service::$msg");
+ throw new \InvalidArgumentException($msg);
}
$this->isNetworkValid($otherData, $currency);
@@ -86,7 +91,6 @@ public function charge(\Flutterwave\Payload $payload): array
MomoEventHandler::startRecording();
$request = $this->request($body, 'POST', $type);
MomoEventHandler::setResponseTime();
-
return $this->handleAuthState($request, $body);
}
@@ -97,55 +101,60 @@ public function save(callable $callback): void
private function isNetworkValid(array $otherData, string $currency): bool
{
- switch($currency) {
- case Currency::GHS:
- if (! isset($otherData['network'])) {
- $this->logger->error('Ghana Momo Service::network parameter is required.');
- throw new \InvalidArgumentException('Ghana Momo Service: network parameter is required.');
- }
- if (! in_array($otherData['network'], $this->networks['GH'])) {
- $this->logger->error('network passed is not supported for ghana momo.');
- throw new \InvalidArgumentException('Ghana Momo Service: network passed is not supported. options: '. json_encode($this->networks['GH']));
- }
- break;
- case Currency::UGX:
- if (! isset($otherData['network'])) {
- $this->logger->error('Uganda Momo Service::network parameter is required.');
- throw new \InvalidArgumentException('Uganda Momo Service: network parameter is required.');
- }
- if (! in_array($otherData['network'], $this->networks['UG'])) {
- $this->logger->error('network passed is not supported for uganda momo.');
- throw new \InvalidArgumentException('Uganda Momo Service: network passed is not supported.');
- }
- break;
- case Currency::ZMW:
- if (! isset($otherData['network'])) {
- $this->logger->error('Zambia Momo Service::network parameter is required.');
- throw new \InvalidArgumentException('Uganda Momo Service: network parameter is required.');
- }
- if (! in_array($otherData['network'], $this->networks['ZM'])) {
- $this->logger->error('network passed is not supported for zambia momo.');
- throw new \InvalidArgumentException('Zambia Momo Service: network passed is not supported.');
- }
- break;
- case Currency::XAF:
- if (! isset($otherData['country'])) {
- $this->logger->error('Franco Momo Service::country parameter is required.');
- throw new \InvalidArgumentException('Franco Momo Service: country parameter is required.');
- }
- if (! in_array($otherData['country'], $this->supported_countries_franco)) {
- $this->logger->error('Franco Momo Service::country passed is not supported.');
- throw new \InvalidArgumentException('Franco Momo Service: country passed is not supported.');
- }
- break;
+ switch ($currency) {
+ case Currency::GHS:
+ if (! isset($otherData['network'])) {
+ $msg = "network parameter is required.";
+ $this->logger->error('Ghana Momo Service::' . $msg);
+ throw new \InvalidArgumentException('Ghana Momo Service:' . $msg);
+ }
+ if (! in_array($otherData['network'], $this->networks['GH'])) {
+ $msg = "network passed is not supported.";
+ $this->logger->error('Ghana Momo Service::' . $msg);
+ throw new \InvalidArgumentException(
+ 'Ghana Momo Service: ' . $msg .
+ '. options: ' . json_encode($this->networks['GH'])
+ );
+ }
+ break;
+ case Currency::UGX:
+ if (! isset($otherData['network'])) {
+ $this->logger->error('Uganda Momo Service::network parameter is required.');
+ throw new \InvalidArgumentException('Uganda Momo Service: network parameter is required.');
+ }
+ if (! in_array($otherData['network'], $this->networks['UG'])) {
+ $this->logger->error('network passed is not supported for uganda momo.');
+ throw new \InvalidArgumentException('Uganda Momo Service: network passed is not supported.');
+ }
+ break;
+ case Currency::ZMW:
+ if (! isset($otherData['network'])) {
+ $this->logger->error('Zambia Momo Service::network parameter is required.');
+ throw new \InvalidArgumentException('Uganda Momo Service: network parameter is required.');
+ }
+ if (! in_array($otherData['network'], $this->networks['ZM'])) {
+ $this->logger->error('network passed is not supported for zambia momo.');
+ throw new \InvalidArgumentException('Zambia Momo Service: network passed is not supported.');
+ }
+ break;
+ case Currency::XAF:
+ if (! isset($otherData['country'])) {
+ $this->logger->error('Franco Momo Service::country parameter is required.');
+ throw new \InvalidArgumentException('Franco Momo Service: country parameter is required.');
+ }
+ if (! in_array($otherData['country'], $this->supported_countries_franco)) {
+ $this->logger->error('Franco Momo Service::country passed is not supported.');
+ throw new \InvalidArgumentException('Franco Momo Service: country passed is not supported.');
+ }
+ break;
}
return true;
}
/**
- * @param \stdClass $response
- * @param array $payload
+ * @param \stdClass $response
+ * @param array $payload
* @return array
*/
private function handleAuthState(\stdClass $response, array $payload): array
diff --git a/src/Service/Mpesa.php b/src/Service/Mpesa.php
index 5ac7a02..3949ae2 100644
--- a/src/Service/Mpesa.php
+++ b/src/Service/Mpesa.php
@@ -8,7 +8,7 @@
use Flutterwave\Contract\Payment;
use Flutterwave\EventHandlers\MpesaEventHandler;
use Flutterwave\Traits\Group\Charge;
-use Unirest\Exception;
+use Psr\Http\Client\ClientExceptionInterface;
class Mpesa extends Service implements Payment
{
@@ -22,23 +22,23 @@ public function __construct(?ConfigInterface $config = null)
parent::__construct($config);
$endpoint = $this->getEndpoint();
- $this->url = $this->baseUrl.'/'.$endpoint.'?type=';
- $this->eventHandler = new MpesaEventHandler();
+ $this->url = $this->baseUrl . '/' . $endpoint . '?type=';
+ $this->eventHandler = new MpesaEventHandler($config);
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
- public function initiate(\Flutterwave\Payload $payload): array
+ public function initiate(\Flutterwave\Entities\Payload $payload): array
{
return $this->charge($payload);
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
* @throws \Exception
*/
- public function charge(\Flutterwave\Payload $payload): array
+ public function charge(\Flutterwave\Entities\Payload $payload): array
{
$this->logger->notice('Charging via Mpesa ...');
@@ -63,9 +63,9 @@ public function charge(\Flutterwave\Payload $payload): array
unset($body['country']);
unset($body['address']);
- MpesaEventHandler::startRecording();
+ $this->eventHandler::startRecording();
$request = $this->request($body, 'POST', self::TYPE);
- MpesaEventHandler::setResponseTime();
+ $this->eventHandler::setResponseTime();
return $this->handleAuthState($request, $body);
}
@@ -85,7 +85,8 @@ private function handleAuthState(\stdClass $response, array $payload): array
return [
'status' => $response->data->status,
'transactionId' => $response->data->id,
- 'dev_instruction' => 'The customer should authorize the payment on their Phones via the Mpesa. status is pending',
+ 'dev_instruction' => 'The customer should authorize the payment on their Phones
+ via the Mpesa. status is pending',
'instruction' => 'Please kindly authorize the payment on your Mobile phone',
'mode' => $mode,
];
diff --git a/src/Service/Otps.php b/src/Service/Otps.php
index b4fc496..35f8763 100644
--- a/src/Service/Otps.php
+++ b/src/Service/Otps.php
@@ -6,11 +6,12 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\EventHandlers\EventTracker;
-use Unirest\Exception;
+use Psr\Http\Client\ClientExceptionInterface;
class Otps extends Service
{
use EventTracker;
+
private string $name = 'otps';
public function __construct(?ConfigInterface $config = null)
@@ -19,7 +20,7 @@ public function __construct(?ConfigInterface $config = null)
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function create(\Flutterwave\Payload $payload): \stdClass
{
@@ -62,7 +63,7 @@ public function validate(?string $otp = null, ?string $reference = null): \stdCl
$body = ['otp' => $otp];
$this->logger->notice('OTP Service::Validating OTP.');
self::startRecording();
- $response = $this->request($body, 'POST', $this->name."/{$reference}/validate");
+ $response = $this->request($body, 'POST', $this->name . "/{$reference}/validate");
$this->logger->notice('OTP Service::Validated OTP Successfully.');
self::setResponseTime();
return $response;
@@ -71,28 +72,38 @@ public function validate(?string $otp = null, ?string $reference = null): \stdCl
private function checkPayloadOTP(\Flutterwave\Payload $payload): void
{
if (! $payload->has('length')) {
- throw new \InvalidArgumentException("OTP Service:: Required Parameter 'length'.
- This is Integer length of the OTP being generated. Expected values are between 5 and 7.");
+ throw new \InvalidArgumentException(
+ "OTP Service:: Required Parameter 'length'.
+ This is Integer length of the OTP being generated. Expected values are between 5 and 7."
+ );
}
if (! $payload->has('customer')) {
- throw new \InvalidArgumentException("OTP Service:: Required Parameter 'customer'.
- This is customer object used to include the recipient information.");
+ throw new \InvalidArgumentException(
+ "OTP Service:: Required Parameter 'customer'.
+ This is customer object used to include the recipient information."
+ );
}
if (! $payload->has('sender')) {
- throw new \InvalidArgumentException("OTP Service:: Required Parameter 'sender'.
- This is your merchant/business name. It would display when the OTP is sent.");
+ throw new \InvalidArgumentException(
+ "OTP Service:: Required Parameter 'sender'.
+ This is your merchant/business name. It would display when the OTP is sent."
+ );
}
if (! $payload->has('send')) {
- throw new \InvalidArgumentException("OTP Service:: Required Parameter 'send'.
- Set to true to send otp to customer..");
+ throw new \InvalidArgumentException(
+ "OTP Service:: Required Parameter 'send'.
+ Set to true to send otp to customer.."
+ );
}
if (! $payload->has('medium')) {
- throw new \InvalidArgumentException("OTP Service:: Required Parameter 'medium'.
- Pass the medium you want your customers to receive the OTP on. Expected values are sms, email and whatsapp.");
+ throw new \InvalidArgumentException(
+ "OTP Service:: Required Parameter 'medium'.
+ Pass the medium you want your customers to receive the OTP on. Expected values are sms, email and whatsapp."
+ );
}
}
}
diff --git a/src/Service/Payload.php b/src/Service/Payload.php
index 37c22f8..06d9318 100644
--- a/src/Service/Payload.php
+++ b/src/Service/Payload.php
@@ -4,65 +4,28 @@
namespace Flutterwave\Service;
-use Flutterwave\Payload as Load;
+use Flutterwave\Factories\PayloadFactory as Factory;
+/**
+ * Class Payload.
+ *
+ * @deprecated use \Flutterwave\Factories\PayloadFactory instead
+ */
class Payload
{
- protected array $requiredParams = [
- 'amount','tx_ref','currency','customer',
- ];
-
- public function create(array $data): Load
+ private Factory $payloadFactory;
+ public function __construct()
{
- $check = $this->validSuppliedData($data);
- if (! $check['result']) {
- throw new \InvalidArgumentException("".$check['missing_param'].''.' is required in the payload');
- }
-
- $currency = $data['currency'];
- $amount = $data['amount'];
- $customer = $data['customer'];
- $redirectUrl = $data['redirectUrl'] ?? null;
- $otherData = $data['additionalData'] ?? null;
- $phone_number = $data['phone'] ?? null;
-
- if (isset($data['pin']) && ! empty($data['pin'])) {
- $otherData['pin'] = $data['pin'];
- }
-
- $payload = new Load();
-
- if (! \is_null($phone_number)) {
- $payload->set('phone', $phone_number);
- }
-
- $tx_ref = $data['tx_ref'] ?? $payload->generateTxRef();
-
-// $payload->set('phone_number', $phone_number); // customer factory handles that
- $payload->set('currency', $currency);
- $payload->set('amount', $amount);
- $payload->set('tx_ref', $tx_ref);
- $payload->set('customer', $customer);
- $payload->set('redirect_url', $redirectUrl);
- $payload->set('otherData', $otherData);
+ $this->payloadFactory = new Factory();
+ }
- return $payload;
+ public function create(array $data): \Flutterwave\Entities\Payload
+ {
+ return $this->payloadFactory->create($data);
}
public function validSuppliedData(array $data): array
{
- $params = $this->requiredParams;
-
- foreach ($params as $param) {
- if (! array_key_exists($param, $data)) {
- return ['missing_param' => $param, 'result' => false];
- }
- }
-
- if (! $data['customer'] instanceof \Flutterwave\Customer) {
- return ['missing_param' => 'customer', 'result' => false];
- }
-
- return ['missing_param' => null, 'result' => true];
+ return $this->payloadFactory->validSuppliedData($data);
}
}
diff --git a/src/Service/PaymentPlan.php b/src/Service/PaymentPlan.php
index 0f433af..26c016f 100644
--- a/src/Service/PaymentPlan.php
+++ b/src/Service/PaymentPlan.php
@@ -6,11 +6,12 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\EventHandlers\EventTracker;
-use Unirest\Exception;
+use Psr\Http\Client\ClientExceptionInterface;
class PaymentPlan extends Service
{
use EventTracker;
+
private array $requiredParams = [
'amount','name','interval','duration',
];
@@ -21,15 +22,16 @@ public function __construct(?ConfigInterface $config = null)
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function create(\Flutterwave\Payload $payload): \stdClass
{
$payload = $payload->toArray();
foreach ($this->requiredParams as $param) {
if (! array_key_exists($param, $payload)) {
- $this->logger->error("Payment Plan Service::The required parameter {$param} is not present in payload");
- throw new \InvalidArgumentException("Payment Plan Service:The required parameter {$param} is not present in payload");
+ $msg = "The required parameter {$param} is not present in payload";
+ $this->logger->error("Payment Plan Service::" . $msg);
+ throw new \InvalidArgumentException("Payment Plan Service:" . $msg);
}
}
@@ -44,19 +46,19 @@ public function create(\Flutterwave\Payload $payload): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function get(string $id): \stdClass
{
$this->logger->notice("Payment Plan Service::Retrieving a Plan ({$id}).");
self::startRecording();
- $response = $this->request(null, 'GET', $this->name."/{$id}");
+ $response = $this->request(null, 'GET', $this->name . "/{$id}");
self::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function list(): \stdClass
{
@@ -68,7 +70,7 @@ public function list(): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function update(string $id, \Flutterwave\Payload $payload): \stdClass
{
@@ -80,19 +82,19 @@ public function update(string $id, \Flutterwave\Payload $payload): \stdClass
$this->logger->notice("Payment Plan Service::Updating Plan id:({$id})");
self::startRecording();
- $response = $this->request(null, 'PUT', $this->name."/{$id}");
+ $response = $this->request(null, 'PUT', $this->name . "/{$id}");
self::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function cancel(string $id): \stdClass
{
$this->logger->notice("Payment Plan Service::Canceling Plan id:({$id})");
self::startRecording();
- $response = $this->request(null, 'PUT', $this->name."/{$id}/cancel");
+ $response = $this->request(null, 'PUT', $this->name . "/{$id}/cancel");
self::setResponseTime();
return $response;
}
diff --git a/src/Service/PayoutSubaccount.php b/src/Service/PayoutSubaccount.php
index 73b45ab..e63dcaf 100644
--- a/src/Service/PayoutSubaccount.php
+++ b/src/Service/PayoutSubaccount.php
@@ -7,7 +7,8 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\EventHandlers\PayoutSubaccoutEventHandler;
use Flutterwave\Payload;
-use Unirest\Exception;
+use Psr\Http\Client\ClientExceptionInterface;
+use stdClass;
class PayoutSubaccount extends Service
{
@@ -19,7 +20,7 @@ public function __construct(?ConfigInterface $config = null)
{
parent::__construct($config);
$endpoint = $this->name;
- $this->url = $this->baseUrl.'/'.$endpoint;
+ $this->url = $this->baseUrl . '/' . $endpoint;
$this->eventHandler = new PayoutSubaccoutEventHandler();
}
@@ -41,9 +42,11 @@ public function confirmPayload(Payload $payload): array
}
/**
- * @throws Exception
+ * @param Payload $payload
+ * @return stdClass
+ * @throws ClientExceptionInterface
*/
- public function create(Payload $payload): \stdClass
+ public function create(Payload $payload): stdClass
{
$this->logger->notice('PSA Service::Creating new Payout Subaccount.');
$body = $this->confirmPayload($payload);
@@ -55,9 +58,9 @@ public function create(Payload $payload): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
- public function list(): \stdClass
+ public function list(): stdClass
{
$this->eventHandler::startRecording();
$response = $this->request(null, 'GET');
@@ -66,18 +69,18 @@ public function list(): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function get(string $account_reference): \stdClass
{
$this->eventHandler::startRecording();
- $response = $this->request(null, 'GET', "/{$account_reference}");
+ $response = $this->request(null, 'GET', "/$account_reference");
$this->eventHandler::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function update(string $account_reference, Payload $payload): \stdClass
{
@@ -94,7 +97,7 @@ public function update(string $account_reference, Payload $payload): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function fetchTransactions(string $account_reference): \stdClass
{
@@ -105,7 +108,7 @@ public function fetchTransactions(string $account_reference): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function fetchAvailableBalance(string $account_reference, string $currency = 'NGN'): \stdClass
{
@@ -116,9 +119,9 @@ public function fetchAvailableBalance(string $account_reference, string $currenc
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
- public function fetchStaticVirtualAccounts(string $account_reference, string $currency = 'NGN'): \stdClass
+ public function fetchStaticVirtualAccounts(string $account_reference, string $currency = 'NGN'): stdClass
{
$this->eventHandler::startRecording();
$response = $this->request(null, 'GET', "/{$account_reference}/static-account?currency={$currency}");
diff --git a/src/Service/Preauth.php b/src/Service/Preauth.php
index f8565b9..ec954dc 100644
--- a/src/Service/Preauth.php
+++ b/src/Service/Preauth.php
@@ -7,8 +7,9 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\Contract\Payment;
use Flutterwave\EventHandlers\PreEventHandler;
+use Flutterwave\Entities\Payload;
use Flutterwave\Traits\Group\Charge;
-use Unirest\Exception;
+use Psr\Http\Client\ClientExceptionInterface;
class Preauth extends Service implements Payment
{
@@ -22,14 +23,15 @@ public function __construct(?ConfigInterface $config = null)
parent::__construct($config);
$this->cardService = new CardPayment($config);
$endpoint = $this->getEndpoint();
- $this->url = $this->baseUrl.'/'.$endpoint;
+ $this->url = $this->baseUrl . '/' . $endpoint;
$this->eventHandler = new PreEventHandler();
}
/**
- * @throws Exception
+ * @param Payload $payload
+ * @return array|null
*/
- public function initiate(\Flutterwave\Payload $payload): ?array
+ public function initiate(Payload $payload): array
{
$this->logger->info('Preauth Service::Updated Payload...');
$payload->set('preauthorize', 1);
@@ -39,9 +41,9 @@ public function initiate(\Flutterwave\Payload $payload): ?array
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
- public function charge(\Flutterwave\Payload $payload): ?array
+ public function charge(Payload $payload): array
{
PreEventHandler::startRecording();
$response = $this->cardService->initiate($payload);
@@ -55,24 +57,24 @@ public function save(callable $callback): void
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function capture(string $flw_ref, string $method = 'card', string $amount = '0'): array
{
$method = strtolower($method);
switch ($method) {
- case 'paypal':
- $data = [
- 'flw_ref' => $flw_ref,
- ];
- $this->logger->info("Preauth Service::Capturing PayPal Payment with FLW_REF:{$flw_ref}...");
- $response = $this->request($data, 'POST', '/paypal-capture');
- break;
- default:
- $data = ['amount' => $amount];
- $this->logger->info("Preauth Service::Capturing Payment with FLW_REF:{$flw_ref}...");
- $response = $this->request($data, 'POST', "/{$flw_ref}/capture");
- break;
+ case 'paypal':
+ $data = [
+ 'flw_ref' => $flw_ref,
+ ];
+ $this->logger->info("Preauth Service::Capturing PayPal Payment with FLW_REF:{$flw_ref}...");
+ $response = $this->request($data, 'POST', '/paypal-capture');
+ break;
+ default:
+ $data = ['amount' => $amount];
+ $this->logger->info("Preauth Service::Capturing Payment with FLW_REF:{$flw_ref}...");
+ $response = $this->request($data, 'POST', "/{$flw_ref}/capture");
+ break;
}
$data['message'] = null;
@@ -94,27 +96,27 @@ public function capture(string $flw_ref, string $method = 'card', string $amount
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function void(string $flw_ref, string $method = 'card'): array
{
$method = strtolower($method);
switch ($method) {
- case 'paypal':
- $data = [
- 'flw_ref' => $flw_ref,
- ];
- $this->logger->info("Preauth Service::Voiding Payment with FLW_REF:{$flw_ref}...");
- PreEventHandler::startRecording();
- $response = $this->request($data, 'POST', '/paypal-void');
- PreEventHandler::setResponseTime();
- break;
- default:
- PreEventHandler::startRecording();
- $this->logger->info("Preauth Service::Voiding Payment with FLW_REF:{$flw_ref}...");
- PreEventHandler::setResponseTime();
- $response = $this->request(null, 'POST', "/{$flw_ref}/void");
- break;
+ case 'paypal':
+ $data = [
+ 'flw_ref' => $flw_ref,
+ ];
+ $this->logger->info("Preauth Service::Voiding Payment with FLW_REF:{$flw_ref}...");
+ PreEventHandler::startRecording();
+ $response = $this->request($data, 'POST', '/paypal-void');
+ PreEventHandler::setResponseTime();
+ break;
+ default:
+ PreEventHandler::startRecording();
+ $this->logger->info("Preauth Service::Voiding Payment with FLW_REF:{$flw_ref}...");
+ PreEventHandler::setResponseTime();
+ $response = $this->request(null, 'POST', "/{$flw_ref}/void");
+ break;
}
$data['message'] = null;
@@ -136,7 +138,7 @@ public function void(string $flw_ref, string $method = 'card'): array
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function refund(string $flw_ref): array
{
diff --git a/src/Service/Service.php b/src/Service/Service.php
index d065d68..0ad3760 100644
--- a/src/Service/Service.php
+++ b/src/Service/Service.php
@@ -5,20 +5,26 @@
namespace Flutterwave\Service;
use Flutterwave\Contract\ConfigInterface;
+use Flutterwave\Contract\FactoryInterface;
use Flutterwave\Contract\ServiceInterface;
+use Flutterwave\Config\ForkConfig;
+use Flutterwave\Factories\CustomerFactory as Customer;
+use Flutterwave\Factories\PayloadFactory as Payload;
use Flutterwave\Helper\Config;
-use GuzzleHttp\ClientInterface;
-use GuzzleHttp\Exception\GuzzleException;
+use Flutterwave\Helper\EnvVariables;
+use Psr\Http\Client\ClientInterface;
use InvalidArgumentException;
-use function is_null;
+use Psr\Http\Client\ClientExceptionInterface;
use Psr\Log\LoggerInterface;
use stdClass;
+use function is_null;
+
class Service implements ServiceInterface
{
public const ENDPOINT = '';
- public ?Payload $payload;
- public ?Customer $customer;
+ public ?FactoryInterface $payload;
+ public ?FactoryInterface $customer;
protected string $baseUrl;
protected LoggerInterface $logger;
protected ConfigInterface $config;
@@ -37,8 +43,8 @@ public function __construct(?ConfigInterface $config = null)
$this->http = $this->config->getHttp();
$this->logger = $this->config->getLoggerInstance();
$this->secret = $this->config->getSecretKey();
- $this->url = $this->config::getBaseUrl().'/';
- $this->baseUrl = $this->config::getBaseUrl();
+ $this->url = EnvVariables::BASE_URL . '/';
+ $this->baseUrl = EnvVariables::BASE_URL;
}
public function getName(): string
@@ -47,55 +53,69 @@ public function getName(): string
}
/**
- * @param array|null $data
- * @param string $verb
- * @param string $additionalurl
+ * @param array|null $data
+ * @param string $verb
+ * @param string $additionalurl
* @return stdClass
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
- protected function request(?array $data = null, string $verb = 'GET', string $additionalurl = ''): stdClass
- {
+ public function request(
+ ?array $data = null,
+ string $verb = 'GET',
+ string $additionalurl = '',
+ bool $overrideUrl = false
+ ): stdClass {
+
$secret = $this->config->getSecretKey();
+ $url = $this->getUrl($overrideUrl, $additionalurl);
switch ($verb) {
- case 'POST':
- $response = $this->http->request('POST', $this->url.$additionalurl, [
- 'debug' => false, # TODO: turn to false on release.
- 'headers' => [
- 'Authorization' => "Bearer $secret",
- 'Content-Type' => 'application/json',
- ],
- 'json' => $data,
- ]);
- break;
- case 'PUT':
- $response = $this->http->request('PUT', $this->url.$additionalurl, [
- 'debug' => false, # TODO: turn to false on release.
- 'headers' => [
- 'Authorization' => "Bearer $secret",
- 'Content-Type' => 'application/json',
- ],
- 'json' => $data ?? [],
- ]);
- break;
- case 'DELETE':
- $response = $this->http->request('DELETE', $this->url.$additionalurl, [
- 'debug' => false,
- 'headers' => [
- 'Authorization' => "Bearer $secret",
- 'Content-Type' => 'application/json',
- ],
- ]);
- break;
- default:
- $response = $this->http->request('GET', $this->url.$additionalurl, [
- 'debug' => false,
- 'headers' => [
- 'Authorization' => "Bearer $secret",
- 'Content-Type' => 'application/json',
- ],
- ]);
- break;
+ case 'POST':
+ $response = $this->http->request(
+ 'POST', $url, [
+ 'debug' => false, // TODO: turn to false on release.
+ 'headers' => [
+ 'Authorization' => "Bearer $secret",
+ 'Content-Type' => 'application/json',
+ ],
+ 'json' => $data,
+ ]
+ );
+ break;
+ case 'PUT':
+ $response = $this->http->request(
+ 'PUT', $url, [
+ 'debug' => false, // TODO: turn to false on release.
+ 'headers' => [
+ 'Authorization' => "Bearer $secret",
+ 'Content-Type' => 'application/json',
+ ],
+ 'json' => $data ?? [],
+ ]
+ );
+ break;
+ case 'DELETE':
+ $response = $this->http->request(
+ 'DELETE', $url, [
+ 'debug' => false,
+ 'headers' => [
+ 'Authorization' => "Bearer $secret",
+ 'Content-Type' => 'application/json',
+ ],
+ ]
+ );
+ break;
+ default:
+ $response = $this->http->request(
+ 'GET', $url, [
+ 'debug' => false,
+ 'headers' => [
+ 'Authorization' => "Bearer $secret",
+ 'Content-Type' => 'application/json',
+ ],
+ ]
+ );
+ break;
}
$body = $response->getBody()->getContents();
@@ -116,14 +136,34 @@ protected function checkTransactionId($transactionId): void
private static function bootstrap(?ConfigInterface $config = null): void
{
if (is_null($config)) {
- require __DIR__.'/../../setup.php';
- $config = Config::setUp(
- $_SERVER[Config::SECRET_KEY],
- $_SERVER[Config::PUBLIC_KEY],
- $_SERVER[Config::ENCRYPTION_KEY],
- $_SERVER['ENV']
- );
+ include __DIR__ . '/../../setup.php';
+
+ if ('composer' === $flutterwave_installation) {
+ $config = Config::setUp(
+ $keys[Config::SECRET_KEY],
+ $keys[Config::PUBLIC_KEY],
+ $keys[Config::ENCRYPTION_KEY],
+ $keys[Config::ENV]
+ );
+ }
+
+ if ('manual' === $flutterwave_installation) {
+ $config = ForkConfig::setUp(
+ $keys[Config::SECRET_KEY],
+ $keys[Config::PUBLIC_KEY],
+ $keys[Config::ENCRYPTION_KEY],
+ $keys[Config::ENV]
+ );
+ }
}
self::$spareConfig = $config;
}
+ private function getUrl(bool $overrideUrl, string $additionalurl): string
+ {
+ if ($overrideUrl) {
+ return $additionalurl;
+ }
+
+ return $this->url . $additionalurl;
+ }
}
diff --git a/src/Service/Settlement.php b/src/Service/Settlement.php
index 8f56990..ab4ad05 100644
--- a/src/Service/Settlement.php
+++ b/src/Service/Settlement.php
@@ -6,11 +6,12 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\EventHandlers\EventTracker;
-use Unirest\Exception;
+use Psr\Http\Client\ClientExceptionInterface;
class Settlement extends Service
{
use EventTracker;
+
private string $name = 'settlements';
public function __construct(?ConfigInterface $config = null)
{
@@ -18,19 +19,19 @@ public function __construct(?ConfigInterface $config = null)
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function get(string $id): \stdClass
{
$this->logger->notice("Settlement Service::Retrieving Settlement [{$id}].");
self::startRecording();
- $response = $this->request(null, 'GET', $this->name."/{$id}");
+ $response = $this->request(null, 'GET', $this->name . "/{$id}");
self::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function list(): \stdClass
{
diff --git a/src/Service/Subscription.php b/src/Service/Subscription.php
index 40a154c..48322d6 100644
--- a/src/Service/Subscription.php
+++ b/src/Service/Subscription.php
@@ -6,11 +6,12 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\EventHandlers\EventTracker;
-use Unirest\Exception;
+use Psr\Http\Client\ClientExceptionInterface;
class Subscription extends Service
{
use EventTracker;
+
private string $name = 'subscriptions';
public function __construct(?ConfigInterface $config = null)
{
@@ -18,7 +19,7 @@ public function __construct(?ConfigInterface $config = null)
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function list(): \stdClass
{
@@ -30,25 +31,25 @@ public function list(): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function activate(string $id): \stdClass
{
$this->logger->notice("Subscription Service::Activating a Subscriptions [{$id}].");
self::startRecording();
- $response = $this->request(null, 'PUT', $this->name."/{$id}/activate");
+ $response = $this->request(null, 'PUT', $this->name . "/{$id}/activate");
self::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function deactivate(string $id): \stdClass
{
$this->logger->notice("Subscription Service::Deactivating a Subscriptions [{$id}].");
self::startRecording();
- $response = $this->request(null, 'PUT', $this->name."/{$id}/cancel");
+ $response = $this->request(null, 'PUT', $this->name . "/{$id}/cancel");
self::setResponseTime();
return $response;
}
diff --git a/src/Service/TokenizedCharge.php b/src/Service/TokenizedCharge.php
index 548c82d..ab080e0 100644
--- a/src/Service/TokenizedCharge.php
+++ b/src/Service/TokenizedCharge.php
@@ -8,7 +8,7 @@
use Flutterwave\Contract\Payment;
use Flutterwave\EventHandlers\TkEventHandler;
use Flutterwave\Traits\Group\Charge;
-use Unirest\Exception;
+use Psr\Http\Client\ClientExceptionInterface;
class TokenizedCharge extends Service implements Payment
{
@@ -21,14 +21,14 @@ public function __construct(?ConfigInterface $config = null)
{
parent::__construct($config);
$endpoint = "tokenized-{$this->getEndpoint()}";
- $this->url = $this->baseUrl.'/'.$endpoint;
+ $this->url = $this->baseUrl . '/' . $endpoint;
$this->eventHandler = new TkEventHandler();
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
- public function initiate(\Flutterwave\Payload $payload)
+ public function initiate(\Flutterwave\Entities\Payload $payload): array
{
$this->logger->notice('Tokenize Service::Initiating Card Payment...');
if (! $this->checkPayloadIsValid($payload, 'token')) {
@@ -42,11 +42,11 @@ public function initiate(\Flutterwave\Payload $payload)
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
- public function charge(\Flutterwave\Payload $payload): array
+ public function charge(\Flutterwave\Entities\Payload $payload): array
{
- # format the customer object to extract the first_name and the last name.
+ // format the customer object to extract the first_name and the last name.
$customer = $payload->get('customer')->toArray();
$fullname = $customer['fullname'];
$names = explode(' ', $fullname);
diff --git a/src/Service/Transactions.php b/src/Service/Transactions.php
index 14439ac..ea40d0e 100644
--- a/src/Service/Transactions.php
+++ b/src/Service/Transactions.php
@@ -7,13 +7,14 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\EventHandlers\TransactionVerificationEventHandler;
use Flutterwave\Traits\ApiOperations\Post;
-use Unirest\Exception;
+use Psr\Http\Client\ClientExceptionInterface;
class Transactions extends Service
{
use Post;
+
public const ENDPOINT = 'transactions';
- public const REFUND_PATH = '/:id'.'/refund';
+ public const REFUND_PATH = '/:id' . '/refund';
public const MULTI_REFUND_ENDPOINT = '/refunds';
public const REFUND_DETAILS_PATH = 'refunds/:id';
public const TRANSACTION_FEE_PATH = '/fee';
@@ -36,17 +37,17 @@ public function __construct(?ConfigInterface $config = null)
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function verify(string $transactionId): \stdClass
{
$this->checkTransactionId($transactionId);
- $this->logger->notice('Transaction Service::Verifying Transaction...'.$transactionId);
+ $this->logger->notice('Transaction Service::Verifying Transaction...' . $transactionId);
TransactionVerificationEventHandler::startRecording();
$response = $this->request(
null,
'GET',
- self::ENDPOINT."/{$transactionId}/verify",
+ self::ENDPOINT . "/{$transactionId}/verify",
);
TransactionVerificationEventHandler::setResponseTime();
@@ -54,23 +55,23 @@ public function verify(string $transactionId): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function verifyWithTxref(string $tx_ref): \stdClass
{
- $this->logger->notice('Transaction Service::Verifying Transaction...'.$tx_ref);
+ $this->logger->notice('Transaction Service::Verifying Transaction...' . $tx_ref);
TransactionVerificationEventHandler::startRecording();
$response = $this->request(
null,
'GET',
- self::ENDPOINT.'/verify_by_reference?tx_ref='.$tx_ref,
+ self::ENDPOINT . '/verify_by_reference?tx_ref=' . $tx_ref,
);
TransactionVerificationEventHandler::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function refund(string $trasanctionId): \stdClass
{
@@ -80,14 +81,14 @@ public function refund(string $trasanctionId): \stdClass
$response = $this->request(
null,
'GET',
- self::ENDPOINT."/{$trasanctionId}/refund",
+ self::ENDPOINT . "/{$trasanctionId}/refund",
);
TransactionVerificationEventHandler::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function getAllTransactions(): \stdClass
{
@@ -103,7 +104,7 @@ public function getAllTransactions(): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function getRefundInfo(string $trasanctionId): \stdClass
{
@@ -120,10 +121,13 @@ public function getRefundInfo(string $trasanctionId): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
- public function getTransactionFee(string $amount, string $currency = 'NGN', string $payment_type = 'card'): \stdClass
- {
+ public function getTransactionFee(
+ string $amount,
+ string $currency = 'NGN',
+ string $payment_type = 'card'
+ ): \stdClass {
if (! $amount) {
$msg = 'Please pass a valid amount';
$this->logger->warning($msg);
@@ -151,14 +155,14 @@ public function getTransactionFee(string $amount, string $currency = 'NGN', stri
$response = $this->request(
null,
'GET',
- self::ENDPOINT."/fee?{$query}",
+ self::ENDPOINT . "/fee?{$query}",
);
TransactionVerificationEventHandler::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function resendFailedHooks(string $transactionId): \stdClass
{
@@ -168,31 +172,33 @@ public function resendFailedHooks(string $transactionId): \stdClass
$response = $this->request(
null,
'GET',
- self::ENDPOINT."/{$transactionId}/resend-hook",
+ self::ENDPOINT . "/{$transactionId}/resend-hook",
);
TransactionVerificationEventHandler::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function retrieveTimeline(string $transactionId): \stdClass
{
$this->checkTransactionId($transactionId);
- $this->logger->notice("Transaction Service::Retrieving Transaction Timeline: TransactionId => {$transactionId}");
+ $this->logger->notice(
+ "Transaction Service::Retrieving Transaction Timeline: TransactionId => {$transactionId}"
+ );
TransactionVerificationEventHandler::startRecording();
$response = $this->request(
null,
'GET',
- self::ENDPOINT."/{$transactionId}/timeline",
+ self::ENDPOINT . "/{$transactionId}/timeline",
);
TransactionVerificationEventHandler::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function validate(string $otp, string $flw_ref): \stdClass
{
@@ -203,12 +209,12 @@ public function validate(string $otp, string $flw_ref): \stdClass
]
);
- $this->logger->notice('Transaction Service::Validating Transaction ...'.$logData);
+ $this->logger->notice('Transaction Service::Validating Transaction ...' . $logData);
$data = [
'otp' => $otp,
'flw_ref' => $flw_ref,
-// "type" => "card" //default would be card
+ // "type" => "card" //default would be card
];
return $this->request(
diff --git a/src/Service/Transfer.php b/src/Service/Transfer.php
index 2b574c3..efffb46 100644
--- a/src/Service/Transfer.php
+++ b/src/Service/Transfer.php
@@ -7,15 +7,17 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\Contract\Payment;
use Flutterwave\EventHandlers\TransferEventHandler;
-use Flutterwave\Payload;
+use Flutterwave\Entities\Payload;
use Flutterwave\Traits\Group\Charge;
use GuzzleHttp\Exception\GuzzleException;
use InvalidArgumentException;
+use Psr\Http\Client\ClientExceptionInterface;
use stdClass;
class Transfer extends Service implements Payment
{
use Charge;
+
public const TYPE = 'transfers';
private TransferEventHandler $eventHandler;
private string $name = 'transfers';
@@ -23,21 +25,21 @@ class Transfer extends Service implements Payment
'amount', 'currency',
];
private array $requiredParamsRate = [
- 'amount', 'destination_currency'. 'source_currency',
+ 'amount', 'destination_currency' . 'source_currency',
];
public function __construct(?ConfigInterface $config = null)
{
parent::__construct($config);
$endpoint = 'transfers';
- $this->url = $this->baseUrl.'/'.$endpoint;
- $this->eventHandler = new TransferEventHandler();
+ $this->url = $this->baseUrl . '/' . $endpoint;
+ $this->eventHandler = new TransferEventHandler($config);
}
/**
- * @param Payload $payload
+ * @param Payload $payload
* @return array
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
public function initiate(Payload $payload): array
{
@@ -50,9 +52,9 @@ public function initiate(Payload $payload): array
}
/**
- * @param Payload $payload
+ * @param Payload $payload
* @return array
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
public function charge(Payload $payload): array
{
@@ -86,7 +88,7 @@ private function handleInitiationResponse(stdClass $data): array
'bank_code' => $root->bank_code,
'full_name' => $root->full_name,
'currency' => $root->currency,
-// 'debit_currency' => $root->debit_currency,
+ // 'debit_currency' => $root->debit_currency,
'reference' => $root->reference,
'amount' => $root->amount,
'status' => $root->status,
@@ -100,32 +102,33 @@ public function save(callable $callback): void
}
/**
- * @param string|null $transactionId
+ * @param string|null $transactionId
* @return stdClass
* retry a previously failed transfer.
*
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
public function retry(?string $transactionId): stdClass
{
$this->checkTransactionId($transactionId);
$this->logger->notice("Transfer Service::Retrieving Settlement [$transactionId].");
$this->eventHandler::startRecording();
- $response = $this->request(null, 'POST', $this->name."/$transactionId/retries");
+ $response = $this->request(null, 'POST', $this->name . "/$transactionId/retries");
$this->eventHandler::setResponseTime();
return $response;
}
/**
- * @param Payload $payload
+ * @param Payload $payload
* @return stdClass
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
public function createBulk(Payload $payload): stdClass
{
if (! $payload->has('bulk_data')) {
- $this->logger->error('Transfer Service::Bulk Payload is empty. Pass a filled array');
- throw new InvalidArgumentException('Transfer Service::Bulk Payload is currently empty. Pass a filled array');
+ $msg = 'Bulk Payload is empty. Pass a filled array';
+ $this->logger->error('Transfer Service::' . $msg);
+ throw new InvalidArgumentException('Transfer Service::' . $msg);
}
$body = $payload->toArray();
@@ -138,22 +141,22 @@ public function createBulk(Payload $payload): stdClass
}
/**
- * @param string $id
+ * @param string $id
* @return stdClass
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
public function get(string $id): stdClass
{
$this->logger->notice("Transfer Service::Retrieving Transfer id:($id)");
$this->eventHandler::startRecording();
- $response = $this->request(null, 'GET', $this->name."/$id");
+ $response = $this->request(null, 'GET', $this->name . "/$id");
$this->eventHandler::setResponseTime();
return $response;
}
/**
* @return stdClass
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
public function getAll(): stdClass
{
@@ -165,16 +168,17 @@ public function getAll(): stdClass
}
/**
- * @param array $params
+ * @param array $params
* @return stdClass
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
public function getFee(array $params = []): stdClass
{
foreach ($this->requiredParamsFee as $param) {
if (! array_key_exists($param, $params)) {
- $this->logger->error("Transfer Service::the following param is required to get transfer fee: $param");
- throw new InvalidArgumentException("Transfer Service::the following param is required to get transfer fee: $param");
+ $msg = "the following param is required to get transfer fee: $param";
+ $this->logger->error("Transfer Service::$msg");
+ throw new InvalidArgumentException("Transfer Service::$msg");
}
}
@@ -187,9 +191,9 @@ public function getFee(array $params = []): stdClass
}
/**
- * @param string $id
+ * @param string $id
* @return stdClass
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
public function getRetry(string $id): stdClass
{
@@ -202,9 +206,9 @@ public function getRetry(string $id): stdClass
}
/**
- * @param string $batch_id
+ * @param string $batch_id
* @return stdClass
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
public function getBulk(string $batch_id): stdClass
{
@@ -217,16 +221,17 @@ public function getBulk(string $batch_id): stdClass
}
/**
- * @param array $params
+ * @param array $params
* @return stdClass
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
public function getRates(array $params): stdClass
{
foreach ($this->requiredParamsRate as $param) {
if (! array_key_exists($param, $params)) {
- $this->logger->error("Transfer Service::the following param is required to get transfer rate: $param");
- throw new InvalidArgumentException("Transfer Service::the following param is required to get transfer rate: $param");
+ $msg = "the following param is required to get transfer rate: $param";
+ $this->logger->error("Transfer Service::$msg");
+ throw new InvalidArgumentException("Transfer Service::$msg");
}
}
diff --git a/src/Service/Ussd.php b/src/Service/Ussd.php
index 39f1ef1..bd082e3 100644
--- a/src/Service/Ussd.php
+++ b/src/Service/Ussd.php
@@ -7,9 +7,10 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\Contract\Payment;
use Flutterwave\EventHandlers\UssdEventHandler;
-use Flutterwave\Payload;
+use Flutterwave\Entities\Payload;
use Flutterwave\Traits\Group\Charge;
use GuzzleHttp\Exception\GuzzleException;
+use Psr\Http\Client\ClientExceptionInterface;
class Ussd extends Service implements Payment
{
@@ -45,27 +46,27 @@ public function __construct(?ConfigInterface $config = null)
parent::__construct($config);
$endpoint = $this->getEndpoint();
- $this->url = $this->baseUrl.'/'.$endpoint.'?type=';
- $this->eventHandler = new UssdEventHandler();
+ $this->url = $this->baseUrl . '/' . $endpoint . '?type=';
+ $this->eventHandler = new UssdEventHandler($config);
}
/**
- * @param Payload $payload
+ * @param Payload $payload
* @return array
- * @throws \Exception
+ * @throws ClientExceptionInterface
*/
- public function initiate(\Flutterwave\Payload $payload): array
+ public function initiate(Payload $payload): array
{
$this->logger->info('Ussd Service::Initiated Ussd Charge');
return $this->charge($payload);
}
/**
- * @param Payload $payload
+ * @param Payload $payload
* @return array
- * @throws GuzzleException
+ * @throws ClientExceptionInterface
*/
- public function charge(\Flutterwave\Payload $payload): array
+ public function charge(Payload $payload): array
{
$otherData = $payload->get('otherData');
@@ -86,8 +87,9 @@ public function charge(\Flutterwave\Payload $payload): array
$bank = $otherData['account_bank'];
if (! array_key_exists($bank, $this->supported_banks)) {
- $this->logger->error('USSD Service: We do not support your bank. please kindly use another. ');
- throw new \InvalidArgumentException('USSD Service: We do not support your bank. please kindly use another. ');
+ $msg = 'We do not support your bank. please kindly use another. ';
+ $this->logger->error('USSD Service:' . $msg);
+ throw new \InvalidArgumentException('USSD Service:' . $msg);
}
$payload = $payload->toArray();
@@ -98,11 +100,11 @@ public function charge(\Flutterwave\Payload $payload): array
unset($body['country']);
unset($body['address']);
- UssdEventHandler::startRecording();
+ $this->eventHandler::startRecording();
$this->logger->info('Ussd Service::Generating Ussd Code');
$request = $this->request($body, 'POST', self::TYPE);
$this->logger->info('Ussd Service::Generated Ussd Code Successfully');
- UssdEventHandler::setResponseTime();
+ $this->eventHandler::setResponseTime();
return $this->handleAuthState($request, $body);
}
@@ -113,8 +115,8 @@ public function save(callable $callback): void
}
/**
- * @param \stdClass $response
- * @param array $payload
+ * @param \stdClass $response
+ * @param array $payload
* @return array
* @throws \Exception
*/
diff --git a/src/Service/VirtualAccount.php b/src/Service/VirtualAccount.php
index 8248f9a..9442241 100644
--- a/src/Service/VirtualAccount.php
+++ b/src/Service/VirtualAccount.php
@@ -6,11 +6,12 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\EventHandlers\EventTracker;
-use Unirest\Exception;
+use Psr\Http\Client\ClientExceptionInterface;
class VirtualAccount extends Service
{
use EventTracker;
+
private string $name = 'virtual-account-numbers';
public function __construct(?ConfigInterface $config = null)
{
@@ -18,7 +19,7 @@ public function __construct(?ConfigInterface $config = null)
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function create(array $payload): \stdClass
{
@@ -26,8 +27,9 @@ public function create(array $payload): \stdClass
//check email and bvn are in payload
if (! isset($payload['email']) || ! isset($payload['bvn'])) {
- $this->logger->error('VirtualAccount Service::The required parameter email or bvn is not present in payload');
- throw new \InvalidArgumentException('The required parameter email or bvn is not present in payload');
+ $msg = 'The required parameter email or bvn is not present in payload';
+ $this->logger->error('VirtualAccount Service::' . $msg);
+ throw new \InvalidArgumentException($msg);
}
$this->logger->notice('VirtualAccount Service::Payload Confirmed.');
@@ -38,7 +40,7 @@ public function create(array $payload): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function createBulk(array $payload): \stdClass
{
@@ -49,8 +51,9 @@ public function createBulk(array $payload): \stdClass
$this->logger->notice('VirtualAccount Service::Creating Bulk Virtual Accounts.');
//check accounts and email are in payload
if (! isset($payload['accounts']) || ! isset($payload['email'])) {
- $this->logger->error('VirtualAccount Service::The required parameter accounts or email is not present in payload');
- throw new \InvalidArgumentException('The required parameter accounts or email is not present in payload');
+ $msg = 'The required parameter accounts or email is not present in payload';
+ $this->logger->error('VirtualAccount Service::' . $msg);
+ throw new \InvalidArgumentException($msg);
}
$this->logger->notice('VirtualAccount Service:: Payload Confirmed [Bulk].');
@@ -62,7 +65,7 @@ public function createBulk(array $payload): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function get($order_ref): \stdClass
{
@@ -74,7 +77,7 @@ public function get($order_ref): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function getBulk($batch_id): \stdClass
{
@@ -86,14 +89,15 @@ public function getBulk($batch_id): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function update(array $payload): \stdClass
{
//check email and bvn are in payload
if (! isset($payload['order_ref']) || ! isset($payload['bvn'])) {
- $this->logger->error('VirtualAccount Service::The required parameter order_ref or bvn is not present in payload');
- throw new \InvalidArgumentException('The required parameter order_ref or bvn is not present in payload');
+ $msg = 'The required parameter order_ref or bvn is not present in payload';
+ $this->logger->error('VirtualAccount Service::' . $msg);
+ throw new \InvalidArgumentException($msg);
}
$order_ref = $payload['order_ref'];
@@ -108,7 +112,7 @@ public function update(array $payload): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function delete($order_ref): \stdClass
{
diff --git a/src/Service/VirtualCard.php b/src/Service/VirtualCard.php
index 07e7933..76097b9 100644
--- a/src/Service/VirtualCard.php
+++ b/src/Service/VirtualCard.php
@@ -8,13 +8,25 @@
use Flutterwave\EventHandlers\EventTracker;
use Flutterwave\Payload;
use InvalidArgumentException;
-use Unirest\Exception;
+use Psr\Http\Client\ClientExceptionInterface;
class VirtualCard extends Service
{
use EventTracker;
+
private string $name = 'virtual-cards';
- private array $requiredParams = [ 'currency', 'amount', 'first_name', 'last_name', 'date_of_birth','email', 'phone', 'title', 'gender' ];
+ private array $requiredParams = [
+ 'currency',
+ 'amount',
+ 'first_name',
+ 'last_name',
+ 'date_of_birth',
+ 'email',
+ 'phone',
+ 'title',
+ 'gender'
+ ];
+
private array $requiredParamsFund = ['debit_currency','amount'];
public function __construct(?ConfigInterface $config = null)
{
@@ -25,8 +37,9 @@ public function confirmPayload(Payload $payload): array
{
foreach ($this->requiredParams as $param) {
if (! $payload->has($param)) {
- $this->logger->error("VirtualCard Service::The required parameter {$param} is not present in payload");
- throw new InvalidArgumentException("The required parameter {$param} is not present in payload");
+ $msg = "The required parameter {$param} is not present in payload";
+ $this->logger->error("VirtualCard Service::$msg");
+ throw new InvalidArgumentException($msg);
}
}
@@ -34,7 +47,7 @@ public function confirmPayload(Payload $payload): array
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function create(Payload $payload): \stdClass
{
@@ -48,19 +61,19 @@ public function create(Payload $payload): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function get(string $id): \stdClass
{
$this->logger->notice("VirtualCard Service::Retrieving Virtual Card [{$id}].");
self::startRecording();
- $response = $this->request(null, 'GET', $this->name."/{$id}");
+ $response = $this->request(null, 'GET', $this->name . "/{$id}");
self::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function list(): \stdClass
{
@@ -72,81 +85,82 @@ public function list(): \stdClass
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function fund(string $id, array $data): \stdClass
{
foreach ($this->requiredParamsFund as $param) {
if (! array_key_exists($param, $data)) {
- $this->logger->error("Misc Service::The following parameter is missing to check balance history: {$param}");
- throw new \InvalidArgumentException("The following parameter is missing to check balance history: {$param}");
+ $msg = "The following parameter is missing to check balance history: {$param}";
+ $this->logger->error("Misc Service::$msg");
+ throw new \InvalidArgumentException($msg);
}
}
$this->logger->notice("VirtualCard Service::Funding Virtual Card [{$id}].");
self::startRecording();
- $response = $this->request($data, 'POST', $this->name."/{$id}/fund");
+ $response = $this->request($data, 'POST', $this->name . "/{$id}/fund");
self::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function withdraw(string $id, string $amount = '0'): \stdClass
{
$this->logger->notice("VirtualCard Service::Withdrawing from Virtual Card [{$id}].");
self::startRecording();
- $response = $this->request([ 'amount' => $amount ], 'POST', $this->name."/{$id}/withdraw");
+ $response = $this->request([ 'amount' => $amount ], 'POST', $this->name . "/{$id}/withdraw");
self::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function block(string $id): \stdClass
{
$this->logger->notice("VirtualCard Service::Blocking Virtual Card [{$id}].");
self::startRecording();
- $response = $this->request(null, 'PUT', $this->name."/{$id}/status/block");
+ $response = $this->request(null, 'PUT', $this->name . "/{$id}/status/block");
self::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function unblock(string $id): \stdClass
{
$this->logger->notice("VirtualCard Service::Unblocking Virtual Card [{$id}].");
self::startRecording();
- $response = $this->request(null, 'PUT', $this->name."/{$id}/status/unblock");
+ $response = $this->request(null, 'PUT', $this->name . "/{$id}/status/unblock");
self::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function terminate(string $id): \stdClass
{
$this->logger->notice("VirtualCard Service::Terminating Virtual Card [{$id}].");
self::startRecording();
- $response = $this->request(null, 'PUT', $this->name."/{$id}/terminate");
+ $response = $this->request(null, 'PUT', $this->name . "/{$id}/terminate");
self::setResponseTime();
return $response;
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function getTransactions(string $id, array $options = ['index' => 0, 'size' => 20]): \stdClass
{
$query = http_build_query($options);
$this->logger->notice("VirtualCard Service::Retrieving transaction for Virtual Card [{$id}].");
self::startRecording();
- $response = $this->request(null, 'GET', $this->name."/{$id}/transactions?{$query}");
+ $response = $this->request(null, 'GET', $this->name . "/{$id}/transactions?{$query}");
self::setResponseTime();
return $response;
}
diff --git a/src/Traits/ApiOperations/Delete.php b/src/Traits/ApiOperations/Delete.php
index e3fd677..1040c11 100644
--- a/src/Traits/ApiOperations/Delete.php
+++ b/src/Traits/ApiOperations/Delete.php
@@ -4,17 +4,16 @@
namespace Flutterwave\Traits\ApiOperations;
-use Unirest\Request;
+use Flutterwave\Contract\ConfigInterface;
+use Flutterwave\Service\Service as Http;
+use Psr\Http\Client\ClientExceptionInterface;
trait Delete
{
- public function delURL(string $url): string
+ public function deleteURL(ConfigInterface $config, string $url): string
{
- $bearerTkn = 'Bearer ' . $this->secretKey;
- $headers = ['Content-Type' => 'application/json', 'Authorization' => $bearerTkn];
- //$body = Body::json($data);
- $path = $this->baseUrl . '/' . $this->end_point;
- $response = Request::delete($path . $url, $headers);
- return $response->raw_body;
+ $response = (new Http($config))->request(null, 'DELETE', $url);
+
+ return '';
}
}
diff --git a/src/Traits/ApiOperations/Get.php b/src/Traits/ApiOperations/Get.php
index 640d8c8..89dd415 100644
--- a/src/Traits/ApiOperations/Get.php
+++ b/src/Traits/ApiOperations/Get.php
@@ -4,18 +4,27 @@
namespace Flutterwave\Traits\ApiOperations;
-use Unirest\Request;
+use Flutterwave\Contract\ConfigInterface;
+use Flutterwave\Exception\ApiException;
+use Flutterwave\Service\Service as Http;
+use Psr\Http\Client\ClientExceptionInterface;
+use stdClass;
trait Get
{
- public function getURL(string $url): string
+ /**
+ * @param ConfigInterface $config
+ * @param string $url
+ * @return stdClass
+ * @throws ClientExceptionInterface
+ * @throws ApiException
+ */
+ public function getURL(ConfigInterface $config, string $url): stdClass
{
- // make request to endpoint using unirest.
- $bearerTkn = 'Bearer ' . $this->secretKey;
- $headers = ['Content-Type' => 'application/json', 'Authorization' => $bearerTkn];
- //$body = Body::json($data);
- $path = $this->baseUrl . '/' . $this->end_point;
- $response = Request::get($path . $url, $headers);
- return $response->raw_body; // Unparsed body
+ $response = (new Http($config))->request(null, 'GET', $url);
+ if ($response->status === 'success') {
+ return $response;
+ }
+ throw new ApiException($response->message);
}
}
diff --git a/src/Traits/ApiOperations/Post.php b/src/Traits/ApiOperations/Post.php
index 801392e..d9b0215 100644
--- a/src/Traits/ApiOperations/Post.php
+++ b/src/Traits/ApiOperations/Post.php
@@ -4,25 +4,23 @@
namespace Flutterwave\Traits\ApiOperations;
-use Unirest\Exception;
-use Unirest\Request;
-use Unirest\Request\Body;
+use Flutterwave\Contract\ConfigInterface;
+use Flutterwave\Service\Service as Http;
+use Psr\Http\Client\ClientExceptionInterface;
trait Post
{
/**
- * @param array $data
+ * @param ConfigInterface $config
+ * @param array $data
*
- * @throws Exception
+ * @return string
+ * @throws ClientExceptionInterface
*/
- public function postURL(array $data): string
+ public function postURL(ConfigInterface $config, array $data): string
{
- // make request to endpoint using unirest
- $bearerTkn = 'Bearer ' . $this->config->getSecretKey();
- $headers = ['Content-Type' => 'application/json', 'Authorization' => $bearerTkn];
- $body = Body::json($data);
- $url = $this->baseUrl . '/' . $this->end_point;
- $response = Request::post($url, $headers, $body);
- return $response->raw_body; // Unparsed body
+ $response = (new Http($config))->request($data, 'POST', $this->end_point);
+
+ return '';
}
}
diff --git a/src/Traits/ApiOperations/Put.php b/src/Traits/ApiOperations/Put.php
index 48560cb..65d9f7b 100644
--- a/src/Traits/ApiOperations/Put.php
+++ b/src/Traits/ApiOperations/Put.php
@@ -4,24 +4,23 @@
namespace Flutterwave\Traits\ApiOperations;
-use Unirest\Exception;
-use Unirest\Request;
-use Unirest\Request\Body;
+use Flutterwave\Contract\ConfigInterface;
+use Flutterwave\Service\Service as Http;
+use Psr\Http\Client\ClientExceptionInterface;
trait Put
{
/**
- * @param array $data
+ * @param ConfigInterface $config
+ * @param array $data
*
- * @throws Exception
+ * @return string
+ * @throws ClientExceptionInterface
*/
- public function putURL(array $data): string
+ public function putURL(ConfigInterface $config, array $data): string
{
- $bearerTkn = 'Bearer ' . $this->secretKey;
- $headers = ['Content-Type' => 'application/json', 'Authorization' => $bearerTkn];
- $body = Body::json($data);
- $url = $this->baseUrl . '/' . $this->end_point;
- $response = Request::put($url, $headers, $body);
- return $response->raw_body;
+ $response = (new Http($config))->request($data, 'PUT', $this->end_point);
+
+ return '';
}
}
diff --git a/src/Traits/Group/Charge.php b/src/Traits/Group/Charge.php
index b3be91e..160bc27 100644
--- a/src/Traits/Group/Charge.php
+++ b/src/Traits/Group/Charge.php
@@ -5,7 +5,7 @@
namespace Flutterwave\Traits\Group;
use Flutterwave\Service\Transactions;
-use Unirest\Exception;
+use Psr\Http\Client\ClientExceptionInterface;
trait Charge
{
@@ -15,7 +15,7 @@ public function getEndpoint(): string
}
/**
- * @throws Exception
+ * @throws ClientExceptionInterface
*/
public function verify(?string $transactionId = null): \stdClass
{
@@ -26,7 +26,7 @@ public function verify(?string $transactionId = null): \stdClass
return (new Transactions($this->config))->verify($transactionId);
}
- private function checkPayloadIsValid(\Flutterwave\Payload $payload, string $criteria): bool
+ private function checkPayloadIsValid(\Flutterwave\Entities\Payload $payload, string $criteria): bool
{
$this->logger->notice('Charge Group::Verifying Payload ...');
//if does not payload contains $criteria :: false
diff --git a/src/Traits/PayloadOperations/Prepare.php b/src/Traits/PayloadOperations/Prepare.php
index 754a2f2..f265f0e 100644
--- a/src/Traits/PayloadOperations/Prepare.php
+++ b/src/Traits/PayloadOperations/Prepare.php
@@ -16,11 +16,7 @@ trait Prepare
public function createReferenceNumber(): self
{
$this->logger->notice('Generating Reference Number....');
- if ($this->overrideTransactionReference) {
- $this->txref = $this->transactionPrefix;
- } else {
- $this->txref = uniqid($this->transactionPrefix);
- }
+ $this->txref = uniqid($this->transactionPrefix);
$this->logger->notice('Generated Reference Number....' . $this->txref);
return $this;
}
diff --git a/src/Traits/Setup/Configure.php b/src/Traits/Setup/Configure.php
index be8de8d..981fea9 100644
--- a/src/Traits/Setup/Configure.php
+++ b/src/Traits/Setup/Configure.php
@@ -6,21 +6,38 @@
use Flutterwave\Contract\ConfigInterface;
use Flutterwave\Helper\Config;
+use Flutterwave\Config\ForkConfig;
trait Configure
{
public static function bootstrap(?ConfigInterface $config = null): void
{
if (\is_null($config)) {
- require __DIR__.'/../../../setup.php';
- $config = Config::setUp(
- $_SERVER[Config::SECRET_KEY],
- $_SERVER[Config::PUBLIC_KEY],
- $_SERVER[Config::ENCRYPTION_KEY],
- $_SERVER['ENV']
- );
+ include __DIR__ . '/../../../setup.php';
+
+ if ('composer' === $flutterwave_installation) {
+ $config = Config::setUp(
+ $keys[Config::SECRET_KEY],
+ $keys[Config::PUBLIC_KEY],
+ $keys[Config::ENCRYPTION_KEY],
+ $keys[Config::ENV]
+ );
+ }
+
+ if ('manual' === $flutterwave_installation) {
+ $config = ForkConfig::setUp(
+ $keys[ForkConfig::SECRET_KEY],
+ $keys[ForkConfig::PUBLIC_KEY],
+ $keys[ForkConfig::ENCRYPTION_KEY],
+ $keys[ForkConfig::ENV]
+ );
+ }
+ }
+
+ if (\is_null(self::$config)) {
+ self::$config = $config;
}
- self::$config = $config;
- self::$methods = require __DIR__ . '/../../Util/methods.php';
+
+ self::$methods = include __DIR__ . '/../../Util/methods.php';
}
}
diff --git a/src/Util/Currency.php b/src/Util/Currency.php
index e5c4c88..21977f1 100644
--- a/src/Util/Currency.php
+++ b/src/Util/Currency.php
@@ -14,8 +14,10 @@ class Currency
public const ZMW = 'ZMW';
public const EUR = 'EUR';
public const GHS = 'GHS';
- public const TNZ = 'TNZ';
+ public const TZS = 'TZS';
public const RWF = 'RWF';
public const XAF = 'XAF';
public const XOF = 'XOF';
+ public const EGP = 'EGP';
+ public const GBP = 'GBP';
}
diff --git a/src/Util/methods.php b/src/Util/methods.php
index 0a656a2..3e5fd20 100644
--- a/src/Util/methods.php
+++ b/src/Util/methods.php
@@ -16,6 +16,10 @@
use Flutterwave\Service\TokenizedCharge;
use Flutterwave\Service\Transfer;
use Flutterwave\Service\Ussd;
+use Flutterwave\Service\GooglePay;
+use Flutterwave\Service\Enaira;
+use Flutterwave\Service\Fawry;
+
//use Flutterwave\Service\PayPal;
//use Flutterwave\Service\Remita;
//use Flutterwave\Service\VoucherPayment;
@@ -35,6 +39,9 @@
'tokenize' => TokenizedCharge::class,
'transfer' => Transfer::class,
'ussd' => Ussd::class,
+ 'google' => GooglePay::class,
+ 'enaira' => Enaira::class,
+ 'fawry' => Fawry::class
// "paypal" => PayPal::class,
// "remita" => Remita::class,
// "voucher" => VoucherPayment::class,
diff --git a/tests/Resources/setup/Config.php b/tests/Resources/Setup/Config.php
similarity index 77%
rename from tests/Resources/setup/Config.php
rename to tests/Resources/Setup/Config.php
index ed7ae94..eea6a86 100644
--- a/tests/Resources/setup/Config.php
+++ b/tests/Resources/Setup/Config.php
@@ -5,12 +5,14 @@
namespace Flutterwave\Test\Resources\Setup;
use Flutterwave\Contract\ConfigInterface;
+use Flutterwave\Helper\EnvVariables;
use GuzzleHttp\Client;
-use GuzzleHttp\ClientInterface;
+
use function is_null;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Logger;
use Psr\Log\LoggerInterface;
+use Psr\Http\Client\ClientInterface;
class Config implements ConfigInterface
{
@@ -18,8 +20,6 @@ class Config implements ConfigInterface
public const SECRET_KEY = 'SECRET_KEY';
public const ENCRYPTION_KEY = 'ENCRYPTION_KEY';
public const ENV = 'ENV';
- public const VERSION = 'v3';
- public const BASE_URL = 'https://api.flutterwave.com/'.self::VERSION;
public const DEFAULT_PREFIX = 'FW|PHP';
public const LOG_FILE_NAME = 'flutterwave-php.log';
protected Logger $logger;
@@ -31,19 +31,21 @@ class Config implements ConfigInterface
private ClientInterface $http;
private string $enc;
- private function __construct(string $secretKey, string $publicKey, string $encryptKey, string $env)
+ private function __construct(
+ string $secretKey,
+ string $publicKey,
+ string $encryptKey,
+ string $env
+ )
{
$this->secret = $secretKey;
$this->public = $publicKey;
$this->enc = $encryptKey;
$this->env = $env;
-
- $this->http = new Client([
- 'base_uri' => $this->getBaseUrl(),
- 'timeout' => 60,
- ]);
-
- $log = new Logger('Flutterwave/PHP');
+ # when creating a custom config, you may choose to use other dependencies here.
+ # http-client - Guzzle, logger - Monolog.
+ $this->http = new Client(['base_uri' => EnvVariables::BASE_URL, 'timeout' => 60 ]);
+ $log = new Logger('Flutterwave/PHP'); // making use of Monolog;
$this->logger = $log;
$log->pushHandler(new RotatingFileHandler(self::LOG_FILE_NAME, 90));
}
@@ -58,6 +60,7 @@ public static function setUp(string $secretKey, string $publicKey, string $enc,
public function getHttp(): ClientInterface
{
+ # for custom implementation, please ensure the
return $this->http ?? new Client();
}
@@ -76,11 +79,6 @@ public function getPublicKey(): string
return $this->public;
}
- public static function getBaseUrl(): string
- {
- return self::BASE_URL;
- }
-
public function getSecretKey(): string
{
return $this->secret;
diff --git a/tests/Unit/Service/AccountTest.php b/tests/Unit/Service/AccountTest.php
index d3a629c..ed31cbd 100644
--- a/tests/Unit/Service/AccountTest.php
+++ b/tests/Unit/Service/AccountTest.php
@@ -3,69 +3,95 @@
namespace Unit\Service;
use PHPUnit\Framework\TestCase;
+use Flutterwave\Flutterwave;
use Flutterwave\Util\AuthMode;
use Flutterwave\Util\Currency;
-use Flutterwave\Helper\Config;
+use Flutterwave\Test\Resources\Setup\Config;
class AccountTest extends TestCase
{
protected function setUp(): void
{
- \Flutterwave\Flutterwave::bootstrap();
+ Flutterwave::bootstrap();
}
-// public function testAuthModeReturn()
-// {
-// //currently returning "Sorry, we could not connect to your bank";
-//
-// $data = [
-// "amount" => 2000,
-// "currency" => Currency::NGN,
-// "tx_ref" => uniqid().time(),
-// "additionalData" => [
-// "account_details" => [
-// "account_bank" => "044",
-// "account_number" => "0690000034",
-// "country" => "NG"
-// ]
-// ],
-// ];
-//
-// $accountpayment = \Flutterwave\Flutterwave::create("account");
-// $customerObj = $accountpayment->customer->create([
-// "full_name" => "Temi Adekunle",
-// "email" => "developers@flutterwavego.com",
-// "phone" => "+2349067985861"
-// ]);
-//
-// $data['customer'] = $customerObj;
-// $payload = $accountpayment->payload->create($data);
-// $this->expectException(\Exception::class);
-// $result = $accountpayment->initiate($payload);
-//
-// //check mode returned is either OTP or Redirect
-//// $this->assertTrue($result['mode'] === AuthMode::OTP || $result['mode'] === AuthMode::REDIRECT );
-// }
+ public function testNgnAuthModeReturn()
+ {
+ //currently returning "Sorry, we could not connect to your bank";
+
+ $data = [
+ "amount" => 2000,
+ "currency" => Currency::NGN,
+ "tx_ref" => uniqid().time(),
+ "additionalData" => [
+ "account_details" => [
+ "account_bank" => "044",
+ "account_number" => "0690000034",
+ "country" => "NG"
+ ]
+ ],
+ ];
+
+ $accountpayment = \Flutterwave\Flutterwave::create("account");
+ $customerObj = $accountpayment->customer->create([
+ "full_name" => "Temi Adekunle",
+ "email" => "developers@flutterwavego.com",
+ "phone" => "+2349067985861"
+ ]);
+
+ $data['customer'] = $customerObj;
+ $payload = $accountpayment->payload->create($data);
+ $result = $accountpayment->initiate($payload);
+ $this->assertTrue( $result['mode'] === AuthMode::REDIRECT );
+ }
+
+ public function testInvalidParam()
+ {
+ $data = [
+ "amount" => 2000,
+ "currency" => Currency::NGN,
+ "tx_ref" => uniqid().time(),
+ "additionalData" => null,
+ ];
-// public function testInvalidParam()
-// {
-// $data = [
-// "amount" => 2000,
-// "currency" => Currency::NGN,
-// "tx_ref" => uniqid().time(),
-// "additionalData" => null,
-// ];
-//
-// $accountpayment = \Flutterwave\Flutterwave::create("account");
-// $customerObj = $accountpayment->customer->create([
-// "full_name" => "Jake Jesulayomi Ola",
-// "email" => "developers@flutterwavego.com",
-// "phone" => "+2349067985861"
-// ]);
-//
-// $data['customer'] = $customerObj;
-// $payload = $accountpayment->payload->create($data);
-// $this->expectException(\InvalidArgumentException::class);
-// $result = $accountpayment->initiate($payload);
-// }
+ $accountpayment = \Flutterwave\Flutterwave::create("account");
+ $customerObj = $accountpayment->customer->create([
+ "full_name" => "Jake Jesulayomi Ola",
+ "email" => "developers@flutterwavego.com",
+ "phone" => "+2349067985861"
+ ]);
+
+ $data['customer'] = $customerObj;
+ $payload = $accountpayment->payload->create($data);
+ $this->expectException(\InvalidArgumentException::class);
+ $result = $accountpayment->initiate($payload);
+ }
+
+ public function testUKBankAccountAuthMode() {
+ $data = [
+ "amount" => 2000,
+ "currency" => Currency::NGN,
+ "tx_ref" => uniqid().time(),
+ "additionalData" => [
+ "account_details" => [
+ "account_bank" => "044",
+ "account_number" => "0690000034",
+ "country" => "UK" //or EU
+ ]
+ ],
+ ];
+
+ $accountpayment = \Flutterwave\Flutterwave::create("account");
+ $customerObj = $accountpayment->customer->create([
+ "full_name" => "Jake Jesulayomi Ola",
+ "email" => "developers@flutterwavego.com",
+ "phone" => "+2349067985861"
+ ]);
+
+ $data['customer'] = $customerObj;
+ $payload = $accountpayment->payload->create($data);
+ $result = $accountpayment->initiate($payload);
+
+ $this->assertTrue( $result['mode'] === AuthMode::REDIRECT );
+ }
}
\ No newline at end of file
diff --git a/tests/Unit/Service/AchTest.php b/tests/Unit/Service/AchTest.php
index cd5dc79..c10db98 100644
--- a/tests/Unit/Service/AchTest.php
+++ b/tests/Unit/Service/AchTest.php
@@ -4,13 +4,16 @@
use Flutterwave\Util\AuthMode;
use PHPUnit\Framework\TestCase;
+use Flutterwave\Flutterwave;
use Flutterwave\Util\Currency;
+use Flutterwave\Test\Resources\Setup\Config;
+
class AchTest extends TestCase
{
protected function setUp(): void
{
- \Flutterwave\Flutterwave::bootstrap();
+ Flutterwave::bootstrap();
}
// public function testAuthModeReturnRedirect()
@@ -22,7 +25,7 @@ protected function setUp(): void
// "redirectUrl" => "https://google.com"
// ];
//
-// $achpayment = \Flutterwave\Flutterwave::create("ach");
+// $achpayment = Flutterwave::create("ach");
// $customerObj = $achpayment->customer->create([
// "full_name" => "Olaobaju Jesulayomi Abraham",
// "email" => "vicomma@gmail.com",
@@ -37,25 +40,25 @@ protected function setUp(): void
// $this->assertSame(AuthMode::REDIRECT, $result['mode']);
// }
-// public function testBankPermittedToMerchant()
-// {
-// $data = [
-// "amount" => 2000,
-// "currency" => Currency::ZAR,
-// "tx_ref" => uniqid().time(),
-// "redirectUrl" => "https://google.com"
-// ];
-//
-// $achpayment = \Flutterwave\Flutterwave::create("ach");
-// $customerObj = $achpayment->customer->create([
-// "full_name" => "Olaobaju Jesulayomi Abraham",
-// "email" => "vicomma@gmail.com",
-// "phone" => "+2349067985861"
-// ]);
-//
-// $data['customer'] = $customerObj;
-// $payload = $achpayment->payload->create($data);
-// $this->expectExceptionMessage("This bank payment option is not permitted to the merchant");
-// $result = $achpayment->initiate($payload);
-// }
+ // public function testBankPermittedToMerchant()
+ // {
+ // $data = [
+ // "amount" => 2000,
+ // "currency" => Currency::ZAR,
+ // "tx_ref" => uniqid().time(),
+ // "redirectUrl" => "https://google.com"
+ // ];
+
+ // $achpayment = Flutterwave::create("ach");
+ // $customerObj = $achpayment->customer->create([
+ // "full_name" => "Olaobaju Jesulayomi Abraham",
+ // "email" => "vicomma@gmail.com",
+ // "phone" => "+2349067985861"
+ // ]);
+
+ // $data['customer'] = $customerObj;
+ // $payload = $achpayment->payload->create($data);
+ // $this->expectExceptionMessage("This bank payment option is not permitted to the merchant");
+ // $result = $achpayment->initiate($payload);
+ // }
}
\ No newline at end of file
diff --git a/tests/Unit/Service/ApplePayTest.php b/tests/Unit/Service/ApplePayTest.php
index 6c2b6d4..db72ced 100644
--- a/tests/Unit/Service/ApplePayTest.php
+++ b/tests/Unit/Service/ApplePayTest.php
@@ -8,57 +8,56 @@
class ApplePayTest extends TestCase
{
-// protected function setUp(): void
-// {
-// \Flutterwave\Flutterwave::bootstrap();
-// }
-//
-// public function testAuthModeReturnRedirect()
-// {
-// $data = [
-// "amount" => 2000,
-// "currency" => Currency::NGN,
-// "tx_ref" => uniqid().time(),
-// "redirectUrl" => "https://example.com"
-// ];
-//
-// $applepayment = \Flutterwave\Flutterwave::create("apple");
-// $customerObj = $applepayment->customer->create([
-// "full_name" => "Olaobaju Jesulayomi Abraham",
-// "email" => "vicomma@gmail.com",
-// "phone" => "+2349067985861"
-// ]);
-//
-// $data['customer'] = $customerObj;
-// $payload = $applepayment->payload->create($data);
-// $result = $applepayment->initiate($payload);
-//
-// $this->assertSame(AuthMode::REDIRECT, $result['mode']);
-// }
-//
-// public function testInvalidParams()
-// {
-// $data = [
-// "amount" => 2000,
-// "currency" => Currency::NGN,
-// "tx_ref" => uniqid().time(),
-// "redirectUrl" => "https://example.com"
-// ];
-//
-// $applepayment = \Flutterwave\Flutterwave::create("apple");
-// //no customer object;
-// $this->expectException(\InvalidArgumentException::class);
-// $payload = $applepayment->payload->create($data);
-// $result = $applepayment->initiate($payload);
-// }
-//
-// public function testEmptyParamsPassed()
-// {
-// $data = [];
-// $applepayment = \Flutterwave\Flutterwave::create("apple");
-// $this->expectException(\InvalidArgumentException::class);
-// $payload = $applepayment->payload->create($data);
-// $result = $applepayment->initiate($payload);
-//
-// }
+ protected function setUp(): void
+ {
+ \Flutterwave\Flutterwave::bootstrap();
+ }
+
+ public function testAuthModeReturnRedirect()
+ {
+ $data = [
+ "amount" => 2000,
+ "currency" => Currency::NGN,
+ "tx_ref" => uniqid().time(),
+ "redirectUrl" => "https://example.com"
+ ];
+
+ $applepayment = \Flutterwave\Flutterwave::create("apple");
+ $customerObj = $applepayment->customer->create([
+ "full_name" => "Olaobaju Jesulayomi Abraham",
+ "email" => "vicomma@gmail.com",
+ "phone" => "+2349060085861"
+ ]);
+
+ $data['customer'] = $customerObj;
+ $payload = $applepayment->payload->create($data);
+ $result = $applepayment->initiate($payload);
+
+ $this->assertSame(AuthMode::REDIRECT, $result['mode']);
+ }
+
+ public function testInvalidParams()
+ {
+ $data = [
+ "amount" => 2000,
+ "currency" => Currency::NGN,
+ "tx_ref" => uniqid().time(),
+ "redirectUrl" => "https://example.com"
+ ];
+
+ $applepayment = \Flutterwave\Flutterwave::create("apple");
+ $this->expectException(\InvalidArgumentException::class);
+ $payload = $applepayment->payload->create($data);
+ $result = $applepayment->initiate($payload);
+ }
+
+ public function testEmptyParamsPassed()
+ {
+ $data = [];
+ $applepayment = \Flutterwave\Flutterwave::create("apple");
+ $this->expectException(\InvalidArgumentException::class);
+ $payload = $applepayment->payload->create($data);
+ $result = $applepayment->initiate($payload);
+
+ }
}
\ No newline at end of file
diff --git a/tests/Unit/Service/BankTest.php b/tests/Unit/Service/BankTest.php
index c7cea09..4e5a8a1 100644
--- a/tests/Unit/Service/BankTest.php
+++ b/tests/Unit/Service/BankTest.php
@@ -11,14 +11,7 @@ class BankTest extends TestCase
public Banks $service;
protected function setUp(): void
{
- $this->service = new Banks(
- Config::setUp(
- $_SERVER[Config::SECRET_KEY],
- $_SERVER[Config::PUBLIC_KEY],
- $_SERVER[Config::ENCRYPTION_KEY],
- $_SERVER[Config::ENV]
- )
- );
+ $this->service = new Banks();
}
public function testRetrievingBankByCountry()
diff --git a/tests/Unit/Service/BankTransferTest.php b/tests/Unit/Service/BankTransferTest.php
index 80959c1..559a9b5 100644
--- a/tests/Unit/Service/BankTransferTest.php
+++ b/tests/Unit/Service/BankTransferTest.php
@@ -13,14 +13,7 @@ class BankTransferTest extends TestCase
{
protected function setUp(): void
{
- Flutterwave::bootstrap(
- Config::setUp(
- $_SERVER[Config::SECRET_KEY],
- $_SERVER[Config::PUBLIC_KEY],
- $_SERVER[Config::ENCRYPTION_KEY],
- $_SERVER[Config::ENV]
- )
- );
+ Flutterwave::bootstrap();
}
public function testAuthModeReturnBankTransfer()
@@ -44,4 +37,28 @@ public function testAuthModeReturnBankTransfer()
$result = $btpayment->initiate($payload);
$this->assertSame(AuthMode::BANKTRANSFER, $result['mode']);
}
+
+
+ public function testExpiryOption()
+ {
+ $data = [
+ "amount" => 2000,
+ "currency" => Currency::NGN,
+ "tx_ref" => uniqid().time(),
+ "redirectUrl" => "https://google.com",
+ "expires" => 3600
+ ];
+
+ $btpayment = Flutterwave::create("bank-transfer");
+ $customerObj = $btpayment->customer->create([
+ "full_name" => "Olaobaju Jesulayomi Abraham",
+ "email" => "developers@flutterwavego.com",
+ "phone" => "+2349067985011"
+ ]);
+
+ $data['customer'] = $customerObj;
+ $payload = $btpayment->payload->create($data);
+ $result = $btpayment->initiate($payload);
+ $this->assertTrue(isset($result['account_expiration']));
+ }
}
\ No newline at end of file
diff --git a/tests/Unit/Service/BillTest.php b/tests/Unit/Service/BillTest.php
index b1c5efa..a2b0cba 100644
--- a/tests/Unit/Service/BillTest.php
+++ b/tests/Unit/Service/BillTest.php
@@ -13,14 +13,7 @@ class BillTest extends \PHPUnit\Framework\TestCase
public Bill $service;
protected function setUp(): void
{
- $this->service = new Bill(
- Config::setUp(
- $_SERVER[Config::SECRET_KEY],
- $_SERVER[Config::PUBLIC_KEY],
- $_SERVER[Config::ENCRYPTION_KEY],
- $_SERVER[Config::ENV]
- )
- );
+ $this->service = new Bill();
}
// public function testBillCreation()
// {
diff --git a/tests/Unit/Service/CardTest.php b/tests/Unit/Service/CardTest.php
index 81fe1e8..93c9b5a 100644
--- a/tests/Unit/Service/CardTest.php
+++ b/tests/Unit/Service/CardTest.php
@@ -13,14 +13,7 @@ class CardTest extends TestCase
{
protected function setUp(): void
{
- Flutterwave::bootstrap(
- Config::setUp(
- $_SERVER[Config::SECRET_KEY],
- $_SERVER[Config::PUBLIC_KEY],
- $_SERVER[Config::ENCRYPTION_KEY],
- $_SERVER[Config::ENV]
- )
- );
+ Flutterwave::bootstrap();
}
public function testAuthModeReturnPin()
@@ -51,7 +44,7 @@ public function testAuthModeReturnPin()
$cardpayment = Flutterwave::create("card");
$customerObj = $cardpayment->customer->create([
"full_name" => "Olaobaju Abraham",
- "email" => "olaobajua@gmail.com",
+ "email" => "ol868gjdfjua@gmail.com",
"phone" => "+2349067985861"
]);
$data['customer'] = $customerObj;
@@ -74,8 +67,8 @@ public function testInvalidArgumentExceptionThrowOnNoCardDetails()
$cardpayment = Flutterwave::create("card");
$customerObj = $cardpayment->customer->create([
"full_name" => "Olaobaju Abraham",
- "email" => "olaobajua@gmail.com",
- "phone" => "+2349067985861"
+ "email" => "ola57679urhfdjf@gmail.com",
+ "phone" => "+234906792751"
]);
$data['customer'] = $customerObj;
$payload = $cardpayment->payload->create($data);
@@ -112,8 +105,8 @@ public function testAuthModeReturnRedirect()
$cardpayment = Flutterwave::create("card");
$customerObj = $cardpayment->customer->create([
"full_name" => "Olaobaju Abraham",
- "email" => "olaobajua@gmail.com",
- "phone" => "+2349067985861"
+ "email" => "ol868gjdfjua@gmail.com",
+ "phone" => "+2349062985861"
]);
$data['customer'] = $customerObj;
$payload = $cardpayment->payload->create($data);
@@ -125,42 +118,42 @@ public function testAuthModeReturnRedirect()
}
- public function testAuthModeReturnAVS()
- {
- $data = [
- "amount" => 2000,
- "currency" => Currency::NGN,
- "tx_ref" => "TEST-".uniqid().time(),
- "redirectUrl" => "https://www.example.com",
- "additionalData" => [
- "subaccounts" => [
- ["id" => "RSA_345983858845935893"]
- ],
- "meta" => [
- "unique_id" => uniqid().uniqid()
- ],
- "preauthorize" => false,
- "payment_plan" => null,
- "card_details" => [
- "card_number" => "4556052704172643",
- "cvv" => "899",
- "expiry_month" => "01",
- "expiry_year" => "23"
- ]
- ],
- ];
-
- $cardpayment = Flutterwave::create("card");
- $customerObj = $cardpayment->customer->create([
- "full_name" => "Olaobaju Abraham",
- "email" => "olaobajua@gmail.com",
- "phone" => "+2349067985861"
- ]);
- $data['customer'] = $customerObj;
- $payload = $cardpayment->payload->create($data);
- $result = $cardpayment->initiate($payload);
- $this->assertSame(AuthMode::AVS, $result['mode']);
- }
+ // public function testAuthModeReturnAVS()
+ // {
+ // $data = [
+ // "amount" => 2000,
+ // "currency" => Currency::NGN,
+ // "tx_ref" => "TEST-".uniqid().time(),
+ // "redirectUrl" => "https://www.example.com",
+ // "additionalData" => [
+ // "subaccounts" => [
+ // ["id" => "RSA_345983858845935893"]
+ // ],
+ // "meta" => [
+ // "unique_id" => uniqid().uniqid()
+ // ],
+ // "preauthorize" => false,
+ // "payment_plan" => null,
+ // "card_details" => [
+ // "card_number" => "4556052704172643",
+ // "cvv" => "899",
+ // "expiry_month" => "09",
+ // "expiry_year" => "32"
+ // ]
+ // ],
+ // ];
+
+ // $cardpayment = Flutterwave::create("card");
+ // $customerObj = $cardpayment->customer->create([
+ // "full_name" => "Olaobaju Abraham",
+ // "email" => "oyudfjmscfka@gmail.com",
+ // "phone" => "+2349067968461"
+ // ]);
+ // $data['customer'] = $customerObj;
+ // $payload = $cardpayment->payload->create($data);
+ // $result = $cardpayment->initiate($payload);
+ // $this->assertSame(AuthMode::AVS, $result['mode']);
+ // }
public function testAuthModelReturnNoauth()
{
diff --git a/tests/Unit/Service/CheckoutTest.php b/tests/Unit/Service/CheckoutTest.php
new file mode 100644
index 0000000..f8680ac
--- /dev/null
+++ b/tests/Unit/Service/CheckoutTest.php
@@ -0,0 +1,123 @@
+paymentHandler = new ModalEventHandler();
+ }
+
+ /**
+ * Tests Inline Setup.
+ *
+ * @dataProvider checkoutProvider
+ */
+ public function testCheckoutProcess(
+ string $modalType,
+ array $generatedTransactionData,
+ EventHandlerInterface $paymentHandler,
+ ConfigInterface $config,
+ array $request
+ ){
+ $mockClient = $this->createMock(Flutterwave::class);
+ $mockModal = $this->createMock(Modal::class);
+
+ $mockModal
+ ->expects($this->exactly(1))
+ ->method('with')
+ ->will($this->returnValue($mockModal));
+
+ if( 'standard' === $modalType ) {
+ $mockModal
+ ->expects($this->exactly(1))
+ ->method('getUrl')
+ ->will($this->returnValue(''));
+ } else {
+ $mockModal
+ ->expects($this->exactly(1))
+ ->method('getHtml')
+ ->will($this->returnValue(''));
+ }
+
+ $mockClient
+ ->expects($this->exactly(1))
+ ->method('render')
+ ->with( $modalType )
+ ->will($this->returnValue($mockModal));
+
+ $mockClient
+ ->expects($this->exactly(1))
+ ->method('eventHandler')
+ ->will($this->returnValue($mockClient));
+
+ $_SERVER['REQUEST_METHOD'] = 'POST';
+
+ $controller = new PaymentController( $mockClient , $paymentHandler, $modalType );
+
+ $controller->process( $request );
+ }
+
+ public function checkoutProvider() {
+ return [
+ [
+ Modal::STANDARD,
+ [ "tx_ref" => 'FLW_TEST|' . random_int( 10, 2000) . '|' . uniqid('aMx') ],
+ new ModalEventHandler(),
+ ForkConfig::setUp(
+ $_ENV['SECRET_KEY'],
+ $_ENV['PUBLIC_KEY'],
+ $_ENV['ENCRYPTION_KEY'],
+ $_ENV['ENV']
+ ),
+ [
+ 'amount' => 3000,
+ 'currency' => Currency::NGN,
+ 'phone_number' => '080000000000',
+ 'first_name' => 'Abraham',
+ 'last_name' => 'Olaobaju',
+ 'success_url' => null,
+ 'failure_url' => null,
+ ]
+ ],
+ [
+ Modal::POPUP,
+ [ "tx_ref" => 'FLW_TEST|' . random_int( 10, 2000) . '|' . uniqid('mAx') ],
+ new ModalEventHandler(),
+ ForkConfig::setUp(
+ $_ENV['SECRET_KEY'],
+ $_ENV['PUBLIC_KEY'],
+ $_ENV['ENCRYPTION_KEY'],
+ $_ENV['ENV']
+ ),
+ [
+ 'amount' => 1500,
+ 'currency' => Currency::NGN,
+ 'phone_number' => '08000000000',
+ 'first_name' => 'John',
+ 'last_name' => 'Doe',
+ 'success_url' => null,
+ 'failure_url' => null,
+ ]
+ ]
+
+
+ ];
+ }
+
+}
\ No newline at end of file
diff --git a/tests/Unit/Service/EnairaTest.php b/tests/Unit/Service/EnairaTest.php
new file mode 100644
index 0000000..3129783
--- /dev/null
+++ b/tests/Unit/Service/EnairaTest.php
@@ -0,0 +1,39 @@
+ 2000,
+ "is_token" => 1,
+ "currency" => Currency::NGN,
+ "tx_ref" => uniqid().time(),
+ "redirectUrl" => "https://example.com"
+ ];
+
+ $payment = \Flutterwave\Flutterwave::create("enaira");
+ $customerObj = $payment->customer->create([
+ "full_name" => "Flutterwave Developers",
+ "email" => "olaobaju@gmail.com",
+ "phone" => "+2349067985861"
+ ]);
+
+ $data['customer'] = $customerObj;
+ $payload = $payment->payload->create($data);
+ $result = $payment->initiate($payload);
+ $this->assertSame(AuthMode::REDIRECT, $result['mode']);
+ }
+}
\ No newline at end of file
diff --git a/tests/Unit/Service/FawryTest.php b/tests/Unit/Service/FawryTest.php
new file mode 100644
index 0000000..6f68a67
--- /dev/null
+++ b/tests/Unit/Service/FawryTest.php
@@ -0,0 +1,40 @@
+ 2000,
+ "currency" => Currency::EGP,
+ "tx_ref" => uniqid().time(),
+ "redirectUrl" => "https://example.com"
+ ];
+
+ $payment = \Flutterwave\Flutterwave::create("fawry");
+ $customerObj = $payment->customer->create([
+ "full_name" => "Olaobaju Jesulayomi Abraham",
+ "email" => "vicomma@gmail.com",
+ "phone" => "+2349060085861"
+ ]);
+
+ $data['customer'] = $customerObj;
+ $payload = $payment->payload->create($data);
+ $result = $payment->initiate($payload);
+
+ $this->assertSame('fawry_pay', $result['mode']);
+ }
+
+}
\ No newline at end of file
diff --git a/tests/Unit/Service/GooglePayTest.php b/tests/Unit/Service/GooglePayTest.php
new file mode 100644
index 0000000..d9e269a
--- /dev/null
+++ b/tests/Unit/Service/GooglePayTest.php
@@ -0,0 +1,38 @@
+ 2000,
+ "currency" => Currency::NGN,
+ "tx_ref" => uniqid().time(),
+ "redirectUrl" => "https://example.com"
+ ];
+
+ $googlepayment = \Flutterwave\Flutterwave::create("google");
+ $customerObj = $googlepayment->customer->create([
+ "full_name" => "Olaobaju Jesulayomi Abraham",
+ "email" => "vicomma@gmail.com",
+ "phone" => "+2349060085861"
+ ]);
+
+ $data['customer'] = $customerObj;
+ $payload = $googlepayment->payload->create($data);
+ $result = $googlepayment->initiate($payload);
+
+ $this->assertSame(AuthMode::REDIRECT, $result['mode']);
+ }
+}
\ No newline at end of file
diff --git a/tests/Unit/Service/MomoTest.php b/tests/Unit/Service/MomoTest.php
index 24a4d49..0afd9ab 100644
--- a/tests/Unit/Service/MomoTest.php
+++ b/tests/Unit/Service/MomoTest.php
@@ -12,14 +12,7 @@ class MomoTest extends TestCase
{
protected function setUp(): void
{
- Flutterwave::bootstrap(
- Config::setUp(
- $_SERVER[Config::SECRET_KEY],
- $_SERVER[Config::PUBLIC_KEY],
- $_SERVER[Config::ENCRYPTION_KEY],
- $_SERVER[Config::ENV]
- )
- );
+ Flutterwave::bootstrap();
}
public function testAuthModeRwandaRedirect(){
@@ -49,6 +42,32 @@ public function testAuthModeRwandaRedirect(){
$this->assertSame(AuthMode::REDIRECT,$result['mode']);
}
+
+ public function testInitiateTanzaniaRedirect(){
+ $data = [
+ "amount" => 2000,
+ "currency" => Currency::TZS,
+ "tx_ref" => uniqid().time(),
+ "redirectUrl" => null,
+ "additionalData" => [
+ "network" => "VODAFONE",
+ ]
+ ];
+
+ $momopayment = \Flutterwave\Flutterwave::create("momo");
+ $customerObj = $momopayment->customer->create([
+ "full_name" => "Abiodun Abrahams",
+ "email" => "developers@flutterwavego.com",
+ "phone" => "+2349067982061"
+ ]);
+
+ $data['customer'] = $customerObj;
+
+ $payload = $momopayment->payload->create($data);
+ $result = $momopayment->initiate($payload);
+ $this->assertSame('pending',$result['data_to_save']['status']);
+ }
+
public function testAuthModeGhanaRedirect(){
$data = [
"amount" => 2000,
diff --git a/tests/Unit/Service/PaymentPlanTest.php b/tests/Unit/Service/PaymentPlanTest.php
index 16cee35..8db92b4 100644
--- a/tests/Unit/Service/PaymentPlanTest.php
+++ b/tests/Unit/Service/PaymentPlanTest.php
@@ -13,14 +13,7 @@ class PaymentPlanTest extends TestCase
public PaymentPlan $service;
protected function setUp(): void
{
- $this->service = new PaymentPlan(
- Config::setUp(
- $_SERVER[Config::SECRET_KEY],
- $_SERVER[Config::PUBLIC_KEY],
- $_SERVER[Config::ENCRYPTION_KEY],
- $_SERVER[Config::ENV]
- )
- );
+ $this->service = new PaymentPlan();
}
public function testPlanCreation()
diff --git a/tests/Unit/Service/TransferTest.php b/tests/Unit/Service/TransferTest.php
index 1cabb23..7da166f 100644
--- a/tests/Unit/Service/TransferTest.php
+++ b/tests/Unit/Service/TransferTest.php
@@ -13,14 +13,7 @@ class TransferTest extends TestCase
public Transfer $service;
protected function setUp(): void
{
- $this->service = new Transfer(
- Config::setUp(
- $_SERVER[Config::SECRET_KEY],
- $_SERVER[Config::PUBLIC_KEY],
- $_SERVER[Config::ENCRYPTION_KEY],
- $_SERVER[Config::ENV]
- )
- );
+ $this->service = new Transfer();
}
public function testInitiatingTransfer()
@@ -42,9 +35,9 @@ public function testInitiatingTransfer()
];
$customerObj = $this->service->customer->create([
- "full_name" => "Olaobaju Abraham",
- "email" => "olaobajua@gmail.com",
- "phone" => "+2349067985861"
+ "full_name" => "Time Squad",
+ "email" => "ol868gjdfjua@gmail.com",
+ "phone" => "+234900000001"
]);
$data['customer'] = $customerObj;
$payload = $this->service->payload->create($data);
diff --git a/tests/Unit/Service/UssdTest.php b/tests/Unit/Service/UssdTest.php
index 89d188a..4a98a85 100644
--- a/tests/Unit/Service/UssdTest.php
+++ b/tests/Unit/Service/UssdTest.php
@@ -12,14 +12,7 @@ class UssdTest extends TestCase
{
protected function setUp(): void
{
- Flutterwave::bootstrap(
- Config::setUp(
- $_SERVER[Config::SECRET_KEY],
- $_SERVER[Config::PUBLIC_KEY],
- $_SERVER[Config::ENCRYPTION_KEY],
- $_SERVER[Config::ENV]
- )
- );
+ Flutterwave::bootstrap();
}
// public function testAuthModeReturnUssd()
@@ -98,7 +91,7 @@ public function testInvalidBank()
$data['customer'] = $customerObj;
$payload = $ussdpayment->payload->create($data);
- $this->expectExceptionMessage("USSD Service: We do not support your bank. please kindly use another.");
+ $this->expectExceptionMessage("USSD Service:We do not support your bank. please kindly use another. ");
$result = $ussdpayment->initiate($payload);
}
}
\ No newline at end of file
diff --git a/tests/Unit/Service/VirtualAccountTest.php b/tests/Unit/Service/VirtualAccountTest.php
index 402cb59..ed61adb 100644
--- a/tests/Unit/Service/VirtualAccountTest.php
+++ b/tests/Unit/Service/VirtualAccountTest.php
@@ -14,14 +14,7 @@ class VirtualAccountTest extends TestCase
public VirtualAccount $service;
protected function setUp(): void
{
- $this->service = new VirtualAccount(
- Config::setUp(
- $_SERVER[Config::SECRET_KEY],
- $_SERVER[Config::PUBLIC_KEY],
- $_SERVER[Config::ENCRYPTION_KEY],
- $_SERVER[Config::ENV]
- )
- );
+ $this->service = new VirtualAccount();
}
public function testVirtualAccountCreation()
@@ -29,6 +22,8 @@ public function testVirtualAccountCreation()
$payload = [
"email" => "kennyio@gmail.com",
"bvn" => "12345678901",
+ "amount" => "3000",
+ "currency" => "NGN"
];
$response = $this->service->create($payload);
diff --git a/tests/Unit/Service/VirtualCardTest.php b/tests/Unit/Service/VirtualCardTest.php
index a2d6e8c..e573892 100644
--- a/tests/Unit/Service/VirtualCardTest.php
+++ b/tests/Unit/Service/VirtualCardTest.php
@@ -5,113 +5,113 @@
use Flutterwave\Payload;
use Flutterwave\Service\VirtualCard;
use Flutterwave\Util\Currency;
+use Flutterwave\Test\Resources\Setup\Config;
use PHPUnit\Framework\TestCase;
+
class VirtualCardTest extends TestCase
{
-// public function testVirtualCardCreation()
-// {
-// $payload = new Payload();
-// $service = new VirtualCard();
-//
-// $payload->set("first_name","PHP");
-// $payload->set("last_name","SDK");
-// $payload->set("date_of_birth","1994-03-01");
-// $payload->set("title","Mr");
-// $payload->set("gender","M"); //M or F
-// $payload->set("email","developers@flutterwavego.com");
-// $payload->set("currency", Currency::NGN);
-// $payload->set("amount", "5000");
-// $payload->set("debit_currency", Currency::NGN);
-// $payload->set("phone", "+234505394568");
-// $payload->set("billing_name", "Abraham Ola");
-// $payload->set("firstname", "Abraham");
-// $response = $service->create($payload);
-// $this->assertTrue(property_exists(
-// $response, "data") && !empty($response->data->id) && isset($response->data->card_pan)
-// );
-//
-// return $response->data->id;
-// }
-//
-// public function testRetrievingAllVirtualCards()
-// {
-// $service = new VirtualCard();
-// $request = $service->list();
-// $this->assertTrue(property_exists($request,'data') && \is_array($request->data));
-// }
-//
-// /**
-// * @depends testVirtualCardCreation
-// */
-// public function testRetrievingVirtualCard(string $id)
-// {
-// $service = new VirtualCard();
-// $request = $service->get($id);
-// $this->assertTrue(property_exists($request,'data') && !empty($request->data->id));
-// }
-//
-//
-// /**
-// * @depends testVirtualCardCreation
-// */
-// public function testVirtualCardFund(string $id)
-// {
-// $data = [
-// "amount"=>"3500",
-// "debit_currency" => Currency::NGN
-// ];
-// $service = new VirtualCard();
-// $request = $service->fund($id, $data);
-// $this->assertTrue(property_exists($request,'data') && $request->message == "Card funded successfully");
-// }
-//
-// /**
-// * @depends testVirtualCardCreation
-// */
-// public function testVirtualCardWithdraw(string $id)
-// {
-// $card_id = $id;
-// $amount = "3500";
-// $service = new VirtualCard();
-// $request = $service->withdraw($card_id,$amount);
-// $this->assertTrue(property_exists($request,'data'));
-// }
-//
-//// /**
-//// * @depends testVirtualCardCreation
-//// */
-//// public function testVirtualCardBlock(string $id)
-//// {
-//// $service = new VirtualCard();
-//// $request = $service->block($id);
-//// $this->assertTrue(property_exists($request,'data') && $request->message == "Card blocked successfully");
-//// }
-//
-// /**
-// * @depends testVirtualCardCreation
-// */
-// public function testVirtualCardTerminate(string $id)
-// {
-// $service = new VirtualCard();
-// $request = $service->terminate($id);
-// $this->assertTrue(property_exists($request,'data') && $request->message == "Card terminated successfully");
-// }
-//
-// /**
-// * @depends testVirtualCardCreation
-// */
-// public function testRetrievingCardTransactions(string $id)
-// {
-// $data = [
-// "from" => "2019-01-01",
-// "to" => "2020-01-13",
-// "index" => "2",
-// "size" => "3"
-// ];
-//
-// $service = new VirtualCard();
-// $request = $service->getTransactions($id, $data);
-// $this->assertTrue(property_exists($request,'data') && $request->message == "Card transactions fetched successfully");
-// }
+ public VirtualCard $service;
+ protected function setUp(): void
+ {
+ $this->service = new VirtualCard();
+ }
+
+// public function testVirtualCardCreation()
+// {
+// $payload = new Payload();
+
+// $payload->set("first_name","PHP");
+// $payload->set("last_name","SDK");
+// $payload->set("date_of_birth","1994-03-01");
+// $payload->set("title","Mr");
+// $payload->set("gender","M"); //M or F
+// $payload->set("email","developers@flutterwavego.com");
+// $payload->set("currency", Currency::NGN);
+// $payload->set("amount", "5000");
+// $payload->set("debit_currency", Currency::NGN);
+// $payload->set("phone", "+234505394568");
+// $payload->set("billing_name", "Abraham Ola");
+// $payload->set("firstname", "Abraham");
+// $response = $this->service->create($payload);
+// $this->assertTrue(property_exists(
+// $response, "data") && !empty($response->data->id) && isset($response->data->card_pan)
+// );
+
+// return $response->data->id;
+// }
+
+ public function testRetrievingAllVirtualCards()
+ {
+ $request = $this->service->list();
+ $this->assertTrue(property_exists($request,'data') && \is_array($request->data));
+ }
+
+// /**
+// * @depends testVirtualCardCreation
+// */
+// public function testRetrievingVirtualCard(string $id)
+// {
+// $request = $this->service->get($id);
+// $this->assertTrue(property_exists($request,'data') && !empty($request->data->id));
+// }
+
+
+// /**
+// * @depends testVirtualCardCreation
+// */
+// public function testVirtualCardFund(string $id)
+// {
+// $data = [
+// "amount"=>"3500",
+// "debit_currency" => Currency::NGN
+// ];
+// $request = $this->service->fund($id, $data);
+// $this->assertTrue(property_exists($request,'data') && $request->message == "Card funded successfully");
+// }
+
+// /**
+// * @depends testVirtualCardCreation
+// */
+// public function testVirtualCardWithdraw(string $id)
+// {
+// $card_id = $id;
+// $amount = "3500";
+// $request = $this->service->withdraw($card_id,$amount);
+// $this->assertTrue(property_exists($request,'data'));
+// }
+
+// // /**
+// // * @depends testVirtualCardCreation
+// // */
+// // public function testVirtualCardBlock(string $id)
+// // {
+// // $request = $this->service->block($id);
+// // $this->assertTrue(property_exists($request,'data') && $request->message == "Card blocked successfully");
+// // }
+
+// /**
+// * @depends testVirtualCardCreation
+// */
+// public function testVirtualCardTerminate(string $id)
+// {
+// $request = $this->service->terminate($id);
+// $this->assertTrue(property_exists($request,'data') && $request->message == "Card terminated successfully");
+// }
+
+// /**
+// * @depends testVirtualCardCreation
+// */
+// public function testRetrievingCardTransactions(string $id)
+// {
+// $data = [
+// "from" => "2019-01-01",
+// "to" => "2020-01-13",
+// "index" => "2",
+// "size" => "3"
+// ];
+
+// $request = $this->service->getTransactions($id, $data);
+// $this->assertTrue(property_exists($request,'data') && $request->message == "Card transactions fetched successfully");
+// }
}
\ No newline at end of file
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 36de571..a0eed40 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -14,7 +14,7 @@
* ####### ############### ######## ########
* ####### ############### ###### ######
*
- * Flutterwave API Library for PHP
+ * Flutterwave Client Library for PHP
*
* Copyright (c) 2020 Flutterwave inc.
* This file is open source and available under the MIT license.
@@ -22,4 +22,19 @@
*
*/
-require_once __DIR__ . '/../vendor/autoload.php';
\ No newline at end of file
+# include vendor directory
+require_once __DIR__ . '/../vendor/autoload.php';
+
+# by pass final definitions.
+DG\BypassFinals::enable();
+DG\BypassFinals::setWhitelist([
+ '*/src/Library/*',
+ '*/src/Entities/*',
+ '*/src/Factories/*',
+ '*/src/HttpAdapter/*',
+ '*/src/Controller/*',
+]);
+
+# flutterwave setup.
+require_once __DIR__ . '/../setup.php';
+