A Laravel package for setting up and interacting with Jenga V3 API.
njoguamos/laravel-jenga is a Laravel package for a laravel package for setting up and interacting with jenga v3 api..
It currently has 9 GitHub stars and 99 downloads on Packagist (latest version v2.0.6).
Install it with composer require njoguamos/laravel-jenga.
Discover more Laravel packages by njoguamos
or browse all Laravel packages to compare alternatives.
Last updated

access_token after a give period e.g every 15 minutesprivate key and public keyBearer TokenInfo Ready to get started? I have prepared a playground which you can clone and get started. It will help you test your crendentials while showinf you how to integrate this package with your laravel application.
| Version | Supported Laravel | |---------|-------------------| | 1.x | 9.x, 10.x, 11.x | | 2.x | 11.x, 12.x |
Use the Composer package manager to install this package into your Laravel project
composer require njoguamos/laravel-jenga
.env variablesThis package assumes that you have a JengaHQ account, and that you have Api Key, Merchant Code and Consumer Secret (from Jenga)(https://developer.jengaapi.io/docs/developer-quickstart).
Copy the respective keys and place them in the .env as show in the example below.
JENGA_LIVE_MODE=false
JENGA_MERCHANT_CODE=
JENGA_API_KEY=
JENGA_CONSUMER_SECRET=
# Optional
JENGA_DEFAULT_ACC=
JENGA_DEFAULT_WALLET=
JENGA_COUNTRY_CODE=
Note For
JENGA_LIVE_MODEusefalsewhen testing andtruewhen running live transactions
You must run install command that will publish the jenga.php config file and create_jenga_tokens migration
php artisan jenga:install
Note For security reasons,
access_tokenandrefresh_tokenwill be encrypted using youapplication key. You can learn more about encryption from Laravel documentation
You can go ahead and migrate the database.
php artisan migrate
Bearer TokenOnce you have valid credentials, run the following command.
php artisan jenga:auth
This command will get an access_token token from Jenga API and add them into a new record on jenga table.
This command may fail:
Api Key or Consumer Secret or Merchant is/are invalidBearer Token FrequentlyThe generated access_token expires after a particular period usually after one hour. To generate a new access_token automatically, schedule the jenga:auth command in the console kernel. The schedule time should be less than 15 minutes.
// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
# ...
$schedule->command(command: 'jenga:auth')->everyThirtyMinutes();
}
To periodically deleted expired Bearer Token, schedule model:prune command in the console kernel.
// app/Console/Kernel.php
use NjoguAmos\Jenga\Models\JengaToken;
protected function schedule(Schedule $schedule)
{
# ...
$schedule->command(command: 'model:prune', parameters: [
'--model' => [JengaToken::class],
])->everyFiveMinutes();
}
To generate a key pair of private and public key, run the following command.
php artisan jenga:keys
This command will create a jenga.key and jenga.pub.key file in your laravel application storage folder. You can customise the directory using JENGA_KEYS_PATH variable.
# ./yourapplication/storage/jenga.key
-----BEGIN PRIVATE KEY-----
<private key here>
-----END RSA PRIVATE KEY-----
# ./yourapplication/storage/jenga.pub.key
-----BEGIN PUBLIC KEY-----
<public key here>
-----END PUBLIC KEY-----
You may use --force flag to replace existing keys. The default key size is 4096
Warning The generated keys files SHOULD NEVER be kept in source control. Make sure you add them to you gitignore file.
Note Extensions like
bcmath,gmp,libsodiumandopensslare required when generating they keys.
If you attempt to access the API and you get Not Authorized to access the API, confirm that your account has subscribed to the respective service you are trying to access. You can do so by going to the JengaAPI Settings -> Subscriptions, then subscribe or unsubscribe.
Info The data is signed in the order it is passed.
use NjoguAmos\Jenga\JengaSignature;
$data = [
"accountId" => "0011547896523",
"countryCode" => "KE",
"date" => "2022-01-01"
];
$signature = (new JengaSignature(data: $data))->getSignature();
// This will return signature for "0011547896523KE2022-01-01'
// "NCgbapJwPIt+203eyADfPSvPX6uWPPVwMbFdrW+3XoT7oQC2+IaS6srFIGGdMrwrTH ..."
<?php
use NjoguAmos\Jenga\Models\JengaToken;
return view(view: 'check-out', data: [
'token' => JengaToken::query()->latest()->first()?->access_token, // Token generated via auth API
'checkOutUrl' => config(key: 'jenga.checkout'), // Check our url. Don't modify
'merchantCode' => config(key: 'jenga.merchant'), // The merchant code provided at registration.
'wallet' => config(key: 'jenga.wallet'), // The wallet to be used for the transaction
'orderAmount' => '', // The value of the transaction
'orderReference' => '', // The merchant order reference. Min8 characters and It has to be alphanumeric
'productType' => '', // Product category
'productDescription' => '' // A brief summary of the product. Max 200 characters. Alphanumeric only.,
'customerFirstName' => '', // The customer's First Name
'customerLastName' => '', // The customer's Last Name
'customerEmail' => '', // Customer email
'customerPhone' => '', // Customer phone number e.g 700325008
'countryCode' => config(key: 'jenga.country'), // Country code
'customerPostalCodeZip' => '', // Customer’s postal code
'customerAddress' => '', // Customer’s address
'callbackUrl' => '' // Merchant callback url
'extraData' => '', // This data will be echoed back during callback url
]);
Configure your frontend form.
<form id="submitcheckout" action="{{ $checkOutUrl }}" method="POST">
@csrf
<input type="hidden" id="token" name="token" value="{{ $token }}">
<input type="hidden" id="merchantCode" name="merchantCode" value="{{ $merchantCode }}">
<input type="hidden" id="wallet" name="wallet" value="{{ $wallet }}">
<input type="hidden" id="orderAmount" name="orderAmount" autofocus value="{{ $orderAmount }}">
<input type="hidden" id="orderReference" name="orderReference" value="{{ $orderReference }}">
<input type="hidden" id="productType" name="productType" value="{{ $productType }}">
<input type="hidden" id="productDescription" name="productDescription" value="{{ $productDescription }}">
<input type="hidden" id="customerFirstName" name="customerFirstName" value="{{ $customerFirstName }}">
<input type="hidden" id="customerLastName" name="customerLastName" value="{{ $customerLastName }}">
<input type="hidden" id="customerEmail" name="customerEmail" value="{{ $customerEmail }}">
<input type="hidden" id="customerPhone" name="customerPhone" value="{{ $customerPhone }}">
<input type="hidden" id="countryCode" name="countryCode" value="{{ $countryCode }}">
<input type="hidden" id="customerPostalCodeZip" name="customerPostalCodeZip" value="{{ $customerPostalCodeZip }}">
<input type="hidden" id="customerAddress" name="customerAddress" value="{{ $customerAddress }}">
<input type="hidden" id="callbackUrl" name="callbackUrl" value="{{ $callbackUrl }}">
<input type="hidden" id="extraData" name="extraData" value="{{ $extraData }}">
<button type="submit">Subscribe</button>
</form>
A successful response should look like like this.
{
"responseStatus": "true",
"transactionStatus": "SUCCESS",
"orderReference": "226151",
"extraData": "pmQgkBuepzSaiNdRh1rghq2ldPzdq0gQ",
"transactionReference": "RBF2PJILMC",
"transactionDate": "Wed Feb 15 2023",
"transactionAmount": "1",
"transactionCurrency": "KES",
"message": "Transaction completed successfully",
"paymentChannel": "MOBILE",
"orderItems": "undefined",
"secureResponse": "320396408033f540f6c9bcc426d6e3d1206d584984d72da4017cace6337e4e10d1729ed98ee326d5d0c403c298c789a9YhubIYK7B+WE0Bij2XWxn3iOL+MAyfWU3RruohGTfdB9t5j9lmNTqcmIeY8RL5M\/xenV+hIKvdweVIyzqX333PFgFGd4wV3+LwQpx9LGCxDsj0NFC+ouRdFZ0VADWbnCbZbHlBSO8kxIP8urAXuP1JM21DhTPqzbs8TB763IYmqVHCicmalkDdegDwo+BDQ0HJaf0ia3FektL2v\/Hj3nM9RkmNyA59VH0p5gUhRUhioMxNdFjai9TKZ3CwOZ6O75h5sc7L+Z8w3ucpvYOtuaTV5fxKIfSPkfi3mIvuGQEw7QDJeu3333BRDHt3XobtxZv9GW9\/eey1dRnNW9zplMBxQupJAn98fSKSC0VkSByqt5KKibQFAZxCOYjcvIJ0kea8MkBRwA\/z1YRdeQ+TmQmdLFoe3V3jWyE5SsN6EPU4k="
}
A customer should also receive an sms like this.
Your transaction of Kshs. 1.00 has successfully been
credited to Finserve Africa Limited-E Commerce Collection
Account with Ref. Number INVDRT and MPESA Tran Ref
RBF2PJILMC. Thank you
To get account details, call the AccountInquiry and pass the account number and country code. If no parameters passed, the default account and country configured in config will be used
use NjoguAmos\Jenga\Api\AccountInquiry;
$search = (new AccountInquiry())
->search(
countryCode: $data['countryCode'],
accountNumber: $data['accountNumber']
);
The response should look like this
{
"status": true,
"code": 0,
"message": "success",
"data": {
"account": {
"branchCode": "145",
"number": "1450160649886",
"currency": "KES",
"status": "Active"
},
"customer": [
{
"name": "CATHERINE MURANDITSI MUKABWA",
"id": "54307789658",
"type": "Retail"
}
]
}
}
use NjoguAmos\Jenga\Api\ForexExchangeRates;
use NjoguAmos\Jenga\Dto\ExchangeRatesDto;
// Convert 1042 USD into KES using Equity Bank Kenya rate.
$data = new ExchangeRatesDto(
amount: 1042,
currencyCode: "USD",
toCurrency: "KES",
accountNumber: '1450160649886',
countryCode: 'KE'
);
$rates = (new ForexExchangeRates())->convert($data);
Example success response
{
"status": true,
"code": 0,
"message": "success",
"data": {
"convertedAmount": 127749.2,
"rate": 122.6,
"fromAmount": 1042,
"rateCode": "TTB"
}
}
Refer to Forex API Reference
Supported currencies
| Code | Name | |------|------------------------| | KES | Kenyan Shilling | | YNG | Korean Yang | | SSP | South Sudanese Pound | | RWF | Rwandan Franc | | JPY | Japanese Yen | | USD | US Dollar | | GBP | British Pound Sterling | | EURO | European Union (EU) | | ZAR | South African Rand | | RUP | Russian Ruble |
use NjoguAmos\Jenga\Api\IDVerification;
use NjoguAmos\Jenga\Dto\IDVerificationDto;
$data = new IDVerificationDto(
documentNumber: '555555',
firstName: 'John',
lastName: 'Doe',
dateOfBirth: '20 June 1985',
documentType: 'ID',
countryCode: 'KE',
);
$search = (new IDVerification())->search($data);
Example success response
{
"status": true,
"code": 0,
"message": "success",
"data": {
"identity": {
"customer": {
"firstName": "JOHN",
"lastName": "DOE",
"occupation": "",
"gender": "M",
"nationality": "Kenyan",
"deathDate": "",
"fullName": "JOHN JOHN DOE DOE",
"middlename": "JOHN DOE",
"ShortName": "JOHN",
"birthCityName": "",
"birthDate": "1985-06-20T12:00:00",
"faceImage": ""
},
"documentType": "NATIONAL ID",
"documentNumber": "555555",
"documentSerialNumber": "55555555555",
"documentIssueDate": "2011-12-08T12:00:00",
"documentExpirationDate": "",
"IssuedBy": "REPUBLIC OF KENYA",
"additionalIdentityDetails": [
{
"documentType": "",
"documentNumber": "",
"issuedBy": ""
}
],
"address": {
"locationName": "",
"districtName": "",
"subLocationName": "",
"provinceName": "",
"villageName": ""
}
}
}
}
composer test
Please see RELEASES for more information what has changed recently.
Please see CONTRIBUTING for details.
If you discover any security related issues, please email [email protected] instead of using the issue tracker.
The MIT License (MIT). Please see License File for more information.