Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
a3dfa35
feat(http-client): Set User-Agent header dynamically
Abraham-Flutterwave Oct 15, 2023
a9128db
fix: Transaction Service Event Tracker
Abraham-Flutterwave Oct 15, 2023
2b8541d
test: Handle PHPSAPI requests
Abraham-Flutterwave Oct 15, 2023
38f6cd4
Update CardTest.php
Abraham-Flutterwave Oct 15, 2023
efc50ae
add SDK_VERSION to environment variables
Abraham-Flutterwave Oct 15, 2023
ad40977
test: New Test cards
Abraham-Flutterwave Oct 15, 2023
d51801f
fix: handle vbssecure auth modes in the card charge service
Abraham-Flutterwave Oct 15, 2023
c0ef792
test: create test provider for TransactionTest
Abraham-Flutterwave Oct 15, 2023
563d04f
example: update card sample with config
Abraham-Flutterwave Oct 15, 2023
b94aed1
dev: update makefile and .gitpod.yml config
Abraham-Flutterwave Oct 15, 2023
dd6b9de
update: change-review workflow
Abraham-Flutterwave Oct 15, 2023
caf302f
update: change-review workflow
Abraham-Flutterwave Oct 15, 2023
367b67b
update: change-review workflow
Abraham-Flutterwave Oct 15, 2023
35713ff
update: change-review workflow
Abraham-Flutterwave Oct 15, 2023
3a747c5
update: change-review workflow include php8.3
Abraham-Flutterwave Oct 15, 2023
24f766f
test: remove dirs from bypass whitelist
Abraham-Flutterwave Oct 15, 2023
23fc6e1
dev: gitpod workspace setup
Abraham-Flutterwave Oct 15, 2023
3bb2015
dev: complete gitpod workspace settings
Abraham-Flutterwave Oct 15, 2023
df276a7
update makefile
Abraham-Flutterwave Oct 15, 2023
2aeab42
test: move bypass finals to checkout test
Abraham-Flutterwave Oct 19, 2023
5f17ac6
remove bypass finals
Abraham-Flutterwave Oct 19, 2023
cc738b3
replace the Config -> PackageConfig
Abraham-Flutterwave Feb 21, 2024
662222c
test: separate checkout test
Abraham-Flutterwave Feb 21, 2024
3de93c7
fix: curlClient namespace
Abraham-Flutterwave Feb 21, 2024
1358abb
update: set default the default modal to standard on checkout
Abraham-Flutterwave Feb 21, 2024
65c6c2a
update setup script
Abraham-Flutterwave Feb 21, 2024
238e83e
fix: handle config override
Abraham-Flutterwave Feb 21, 2024
4305433
tests: exclude vendor folder files
Abraham-Flutterwave Feb 21, 2024
cba7079
refact: update card service
Abraham-Flutterwave Feb 21, 2024
6fce11c
update Bill Service
Abraham-Flutterwave Apr 2, 2025
d142f28
update: Payout Subaccount Event tracker
Abraham-Flutterwave Apr 2, 2025
ab0b23b
FTPI-1072: handle final card status responses.
Abraham-Flutterwave Apr 2, 2025
9403e06
FTPI-1077: Fix Bug omitting customer fullname from the standard check…
Abraham-Flutterwave Apr 8, 2025
13ea9ba
FTPI-1078: support environment variables set with the prefix FLW to f…
Abraham-Flutterwave Apr 8, 2025
6418381
fix: handle getenv function returning false
bajoski34 Apr 8, 2025
88d0230
remove previous keys
bajoski34 Apr 8, 2025
bdde581
FTPI-1081: allow Custom Logger Enhancement
bajoski34 Apr 8, 2025
9f32e3d
include yaml release
bajoski34 Apr 8, 2025
0055081
update: sample release
bajoski34 Apr 8, 2025
8250334
update: sample release
bajoski34 Apr 8, 2025
f56f3b4
update: sample release
bajoski34 Apr 8, 2025
c9940a0
update: sample release
bajoski34 Apr 8, 2025
8631716
update: sample release
bajoski34 Apr 8, 2025
9763d9a
update: sample release
bajoski34 Apr 8, 2025
7d711b3
remove artifact release
bajoski34 Apr 8, 2025
e118248
chore: add artifact release workflow
bajoski34 Apr 9, 2025
3858cef
chore: add php 7.4 artifact
bajoski34 Apr 9, 2025
4722614
docs: Update README instructions to download release artifacts
bajoski34 Apr 9, 2025
1432b78
update sample log directory
bajoski34 Apr 9, 2025
d495379
Merge pull request #69 from Abraham-Flutterwave/dev
corneliusyaovi Apr 9, 2025
21ce2cb
test: update card test - preath
bajoski34 Apr 9, 2025
2d6c4d2
update: Enaira, Fawry and GooglePayTest
bajoski34 Apr 9, 2025
aa6b01b
Merge pull request #80 from Abraham-Flutterwave/dev
Abraham-Flutterwave Apr 9, 2025
35ddfa0
test: CardTest
bajoski34 Apr 9, 2025
046db07
update CardTest
bajoski34 Apr 9, 2025
ae87c3c
Merge pull request #81 from Abraham-Flutterwave/dev
Abraham-Flutterwave Apr 9, 2025
6df3900
test: comment card auth redirect
bajoski34 Apr 9, 2025
84c905b
Merge pull request #82 from Abraham-Flutterwave/dev
Abraham-Flutterwave Apr 9, 2025
0df45e2
remove Bill enum.
bajoski34 Apr 9, 2025
26a481e
Merge pull request #83 from Abraham-Flutterwave/dev
Abraham-Flutterwave Apr 9, 2025
a4e0169
remove enums
bajoski34 Apr 9, 2025
6bcc966
update package config
bajoski34 Apr 9, 2025
20c25fb
Merge pull request #84 from Abraham-Flutterwave/dev
Abraham-Flutterwave Apr 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .docker/.gitpod.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM gitpod/workspace-full

RUN sudo install-packages php-xdebug
9 changes: 5 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
PUBLIC_KEY=FLWPUBK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X
SECRET_KEY=FLWSECK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X
ENCRYPTION_KEY=FLWSECK_XXXXXXXXXXXXXXXX
ENV=staging
FLW_PUBLIC_KEY=FLWPUBK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X
FLW_SECRET_KEY=FLWSECK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X
FLW_ENCRYPTION_KEY=FLWSECK_XXXXXXXXXXXXXXXX
FLW_ENV=staging
FLW_LOG_DIR=logs
44 changes: 44 additions & 0 deletions .github/workflows/artifact-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Build and Upload PHP Artifacts

on:
push:
tags:
- '[0-9]+.[0-9]+.[0-9]+' # Match tags like 1.2.3

jobs:
build:
runs-on: ubuntu-latest

strategy:
matrix:
php: ['7.4', '8.1', '8.2', '8.3', '8.4']

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite

- name: Install dependencies
run: composer install --no-dev --optimize-autoloader

- name: Get tag version
id: tag
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> "$GITHUB_ENV"

- name: Create release artifact
run: |
mkdir -p build
cp -r vendor src tests assets composer.json composer.lock .gitignore LICENSE phpunit.xml.dist .env.example processPayment.php paymentForm.php setup.php README.md CHANGELOG.md build/
cd build && zip -r ../flutterwave-php-${VERSION}-php${{ matrix.php }}.zip . && cd ..

- name: Upload artifact to release
uses: softprops/action-gh-release@v1
with:
files: flutterwave-php-${{ env.VERSION }}-php${{ matrix.php }}.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
16 changes: 6 additions & 10 deletions .github/workflows/change-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
fail-fast: true
matrix:
php: [7.4, 8.1, 8.2]
php: [7.4, 8.1, 8.2, 8.3]

env:
XDEBUG_MODE: coverage
Expand Down Expand Up @@ -48,17 +48,13 @@ jobs:
- 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
env:
PUBLIC_KEY: ${{ secrets.PUBLIC_KEY }}
SECRET_KEY: ${{ secrets.SECRET_KEY }}
ENCRYPTION_KEY: ${{ secrets.ENCRYPTION_KEY }}
ENV: ${{ secrets.ENV }}

- name: Upload to Codecov
uses: codecov/codecov-action@v2
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,6 @@ example.php
.phpunit.cache
coverage.xml
.env.local
.php-cs-fixer.cache
.php-cs-fixer.cache
.idx/
.vscode/
15 changes: 15 additions & 0 deletions .gitpod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# This configuration file was automatically generated by Gitpod.
# Please adjust to your needs (see https://www.gitpod.io/docs/introduction/learn-gitpod/gitpod-yaml)
# and commit this file to your remote git repository to share the goodness with others.

# Learn more from ready-to-use templates: https://www.gitpod.io/docs/introduction/getting-started/quickstart

image:
file: .docker/.gitpod.Dockerfile

tasks:
- init: make

vscode:
extensions:
- felixfbecker.php-debug
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
.PHONY: init
test:
check:
@echo "Installing dependencies..."
@composer install
@echo "Installing dependencies... Done"
@./vendor/bin/pest --coverage --min=0 --coverage-clover ./coverage.xml


test:
@./vendor/bin/pest --coverage --min=0 --coverage-clover ./coverage.xml

debug:
XDEBUG_MODE=coverage ./vendor/bin/pest --coverage --coverage-html .log


12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ Available features include:

## Installation

### Download Release Artifact
If you do not want to make use of composer. each [release](https://github.com/Flutterwave/PHP-v3/releases/) contains a zip with all the dependencies installed. Simply download the one that supports your php version.

### Installation via Composer.

To install the package via Composer, run the following command.
Expand All @@ -67,10 +70,11 @@ 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'
FLW_PUBLIC_KEY=FLWSECK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X
FLW_SECRET_KEY=FLWPUBK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X
FLW_ENCRYPTION_KEY=FLWSECK_XXXXXXXXXXXXXXXX
FLW_ENV='staging/production'
FLW_LOG_DIR=logs
```

### Render Payment Modal
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"ext-openssl": "*",
"guzzlehttp/guzzle": "^7.5",
"psr/http-client": "^1.0",
"psr/log": "^1.1 || ^2.0 || ^3.0",
"php-http/guzzle7-adapter": "^1.0",
"composer/ca-bundle": "^1.3"
},
Expand Down
25 changes: 23 additions & 2 deletions examples/card.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,26 @@

use Flutterwave\Util\AuthMode;
use Flutterwave\Util\Currency;
\Flutterwave\Flutterwave::bootstrap();
use Flutterwave\Config\ForkConfig;
use Dotenv\Dotenv;
// custom config.

if(!file_exists( '.env' )) {
$dotenv = Dotenv::createImmutable(__DIR__."/../");
} else {
$dotenv = Dotenv::createImmutable(__DIR__."/");
}

$dotenv->safeLoad();

$config = ForkConfig::setUp(
$_ENV['SECRET_KEY'],
$_ENV['PUBLIC_KEY'],
$_ENV['ENV'],
$_ENV['ENCRYPTION_KEY']
);

\Flutterwave\Flutterwave::bootstrap($config);

try {

Expand Down Expand Up @@ -48,6 +67,8 @@
$data['customer'] = $customerObj;
$payload = $cardpayment->payload->create($data);



if(!empty($_REQUEST))
{
$request = $_REQUEST;
Expand All @@ -59,7 +80,7 @@

if(isset($request['make'])){
$result = $cardpayment->initiate($payload);

dd($cardpayment);
if($result['mode'] === AuthMode::PIN){
$instruction = $result['instruction'];
require __DIR__."/view/form/pin.php";
Expand Down
6 changes: 6 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
<include>
<directory suffix=".php">./src</directory>
</include>
<exclude>
<directory suffix=".php">./vendor</directory>
<directory suffix=".js">./vendor</directory>
<directory suffix=".xml">./vendor</directory>
<file>tests/bootstrap.php</file>
</exclude>
<report>
<clover outputFile="coverage.xml" />
</report>
Expand Down
24 changes: 21 additions & 3 deletions processPayment.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,33 @@
use Flutterwave\EventHandlers\ModalEventHandler as PaymentHandler;
use Flutterwave\Flutterwave;
use Flutterwave\Library\Modal;
use \Flutterwave\Config\ForkConfig;

# start a session.
// start a session.
session_start();

// Define custom config.
// $myConfig = ForkConfig::setUp(
// 'FLWSECK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X', //Secret key
// 'FLWPUBK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X', // Public key
// 'FLWSECK_TESTXXXXXXXXXXX', //Encryption key
// 'staging' //Environment Variable
// );

// uncomment the block if you just want to pass the keys with a specific configuration.
// $_ENV['SECRET_KEY'] = "FLWSECK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X";
// $_ENV['PUBLIC_KEY'] = "FLWPUBK_TEST-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-X";
// $_ENV['ENCRYPTION_KEY'] = "FLWSECK_TESTXXXXXXXXXXXX";
// $_ENV['ENV'] = "staging";

// controller default
$controller = null;

try {
Flutterwave::bootstrap();
Flutterwave::bootstrap(); // create a .env or Flutterwave::bootstrap($myConfig)
$customHandler = new PaymentHandler();
$client = new Flutterwave();
$modalType = Modal::POPUP; // Modal::POPUP or Modal::STANDARD
$modalType = Modal::STANDARD; // Modal::POPUP or Modal::STANDARD
$controller = new PaymentController( $client, $customHandler, $modalType );
} catch(\Exception $e ) {
echo $e->getMessage();
Expand Down
32 changes: 22 additions & 10 deletions setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

$flutterwave_installation = 'composer';

if( !file_exists( '.env' )) {
if( !file_exists( '.env' ) && !is_dir('vendor')) {
$dotenv = Dotenv::createImmutable(__DIR__."/../../../"); # on the event that the package is install via composer.
} else {
$flutterwave_installation = "manual";
Expand All @@ -17,7 +17,12 @@
//check if the current version of php is compatible
if(!Helper\CheckCompatibility::isCompatible())
{
echo "Flutterwave: This SDK only support php version ". Helper\CheckCompatibility::MINIMUM_COMPATIBILITY. " or greater.";
if (PHP_SAPI === 'cli') {
echo "❌ Flutterwave: This SDK only support php version ". Helper\CheckCompatibility::MINIMUM_COMPATIBILITY. " or greater.";
} else {
echo "Flutterwave: This SDK only support php version ". Helper\CheckCompatibility::MINIMUM_COMPATIBILITY. " or greater.";
}

exit;
}

Expand All @@ -28,22 +33,29 @@
try{
foreach($flutterwaveKeys as $key)
{
if( empty( $_ENV[ $key ] ) )

$new_key = sprintf( 'FLW_%s', $key );
if(empty($_ENV[ $new_key ]) && empty(\getenv($new_key)) && empty($_ENV[ $key ]) && empty(\getenv($key)))
{
throw new InvalidArgumentException("$key environment variable missing.");
throw new InvalidArgumentException("$new_key or $key environment variable missing.");
}

}
}catch(\Exception $e)
{
echo "<code>Flutterwave sdk: " .$e->getMessage()."</code>";
if (PHP_SAPI === 'cli') {
echo "❌❌Flutterwave sdk: " .$e->getMessage();
echo "Kindly create a .env in the project root and add the required environment variables. ❌". PHP_EOL;
} else {
echo "Flutterwave: Setup incomplete. check your environment variables are set currently. confirm .env contains the required variables.";
}

echo "<br /> Kindly create a <code>.env </code> in the project root and add the required environment variables.";
exit;
}

$keys = [
'SECRET_KEY' => $_ENV['SECRET_KEY'],
'PUBLIC_KEY' => $_ENV['PUBLIC_KEY'],
'ENV' => $_ENV['ENV'],
'ENCRYPTION_KEY' => $_ENV['ENCRYPTION_KEY']
'SECRET_KEY' => $_ENV['FLW_SECRET_KEY'] ?? ($_ENV['SECRET_KEY'] ?? getenv('FLW_SECRET_KEY') ?: getenv('SECRET_KEY')),
'PUBLIC_KEY' => $_ENV['FLW_PUBLIC_KEY'] ?? ($_ENV['PUBLIC_KEY'] ?? getenv('FLW_PUBLIC_KEY') ?: getenv('PUBLIC_KEY')),
'ENV' => $_ENV['FLW_ENV'] ?? ($_ENV['ENV'] ?? getenv('FLW_ENV') ?: getenv('ENV')),
'ENCRYPTION_KEY' => $_ENV['FLW_ENCRYPTION_KEY'] ?? ($_ENV['ENCRYPTION_KEY'] ?? getenv('FLW_ENCRYPTION_KEY') ?: getenv('ENCRYPTION_KEY'))
];
8 changes: 6 additions & 2 deletions src/Config/AbstractConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ abstract class AbstractConfig
public const ENV = 'ENV';
public const DEFAULT_PREFIX = 'FW|PHP';
public const LOG_FILE_NAME = 'flutterwave-php.log';
protected Logger $logger;
public Logger $logger;
protected string $secret;
protected string $public;

Expand All @@ -43,7 +43,11 @@ protected function __construct(string $secret_key, string $public_key, string $e
[
'base_uri' => EnvVariables::BASE_URL,
'timeout' => 60,
RequestOptions::VERIFY => \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath()
'headers' => ['User-Agent' => sprintf(
'FlutterwavePHP/%d', EnvVariables::SDK_VERSION
)],
RequestOptions::VERIFY =>
\Composer\CaBundle\CaBundle::getSystemCaRootBundlePath()
]
);

Expand Down
30 changes: 26 additions & 4 deletions src/Config/PackageConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,36 @@ final class PackageConfig extends AbstractConfig implements ConfigInterface
private function __construct(string $secretKey, string $publicKey, string $encryptKey, string $env)
{
parent::__construct($secretKey, $publicKey, $encryptKey, $env);
$this->logger->pushHandler(new RotatingFileHandler(__DIR__ . "../../../../../../" . self::LOG_FILE_NAME, 90));
}

public static function setUp(string $secretKey, string $publicKey, string $enc, string $env): ConfigInterface
public static function setUp(string $secretKey, string $publicKey, string $enc, string $env, ?LoggerInterface $customLogger = null): ConfigInterface
{

if (is_null(self::$instance)) {
return new self($secretKey, $publicKey, $enc, $env);
$instance = new self($secretKey, $publicKey, $enc, $env);
if ($customLogger) {
$instance->logger = $customLogger;
} else {
$vendorPath = dirname(__DIR__, 4);
$rootPath = dirname($vendorPath);

$logSubDir = $_ENV['FLW_LOG_DIR'] ?? 'logs';
$logDir = $rootPath . DIRECTORY_SEPARATOR . $logSubDir;

if (!is_dir($logDir)) {
if (!mkdir($logDir, 0775, true) && !is_dir($logDir)) {
throw new \RuntimeException("Flutterwave: Failed to create log directory at $logDir");
}
}

if (!is_writable($logDir)) {
throw new \RuntimeException("Flutterwave: Log directory is not writable: $logDir");
}

$instance->logger->pushHandler(
new RotatingFileHandler($logDir . '/' . self::LOG_FILE_NAME, 90)
);
}
self::$instance = $instance;
}
return self::$instance;
}
Expand Down
Loading