allow vendord
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m3s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 32s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s

This commit is contained in:
2026-03-30 14:54:57 +07:00
parent 66aed7c4e8
commit b5e3a778ce
21316 changed files with 2777892 additions and 13 deletions

Binary file not shown.

View File

@@ -0,0 +1,4 @@
vendor
/.idea
/.vscode
composer.lock

View File

@@ -0,0 +1,340 @@
# Bkash Payment Gateway for PHP/Laravel Framework
[![Downloads](https://img.shields.io/packagist/dt/karim007/laravel-bkash-tokenize)](https://packagist.org/packages/karim007/laravel-bkash-tokenize)
[![Starts](https://img.shields.io/packagist/stars/karim007/laravel-bkash-tokenize)](https://packagist.org/packages/karim007/laravel-bkash-tokenize)
## Features
This is a php/laravel wrapper package for [Bkash](https://developer.bka.sh/)
## Requirements
- PHP >=7.4
- Laravel >= 6
## Installation
```bash
composer require karim007/laravel-bkash-tokenize
```
## Examples
![]()<img src="example/bkash1.png" alt="bkash tokenize" width="150" height="150">
![]()<img src="example/bkash2.png" alt="bkash tokenize payment" width="150" height="150">
![]()<img src="example/bkash3.png" alt="bkash" width="150" height="150">
![]()<img src="example/bkash4.png" alt="bkash" width="150" height="150">
![]()<img src="example/bkash5.png" alt="bkash" width="150" height="150">
For video tutorial click the image bellow or https://youtu.be/xue4EP5et58
[![laravel bkash tokenize](https://img.youtube.com/vi/pAbr1X0Jz6s/hqdefault.jpg)](https://youtu.be/pAbr1X0Jz6s)
### vendor publish (config)
```bash
php artisan vendor:publish --provider="Karim007\LaravelBkashTokenize\BkashTokenizeServiceProvider" --tag="config"
```
After publish config file setup your credential. you can see this in your config directory bkash.php file
```
"sandbox" => env("BKASH_SANDBOX", true),
"bkash_app_key" => env("BKASH_APP_KEY", ""),
"bkash_app_secret" => env("BKASH_APP_SECRET", ""),
"bkash_username" => env("BKASH_USERNAME", ""),
"bkash_password" => env("BKASH_PASSWORD", ""),
"bkash_app_key_2" => env("BKASH_APP_KEY_2", ""),
"bkash_app_secret_2" => env("BKASH_APP_SECRET_2", ""),
"bkash_username_2" => env("BKASH_USERNAME_2", ""),
"bkash_password_2" => env("BKASH_PASSWORD_2", ""),
//so on ...
"callbackURL" => env("BKASH_CALLBACK_URL", "http://127.0.0.1:8000/bkash/callback"),
'timezone' => 'Asia/Dhaka',
```
### Set .env configuration
```
BKASH_SANDBOX=true #for production use false
BKASH_APP_KEY=""
BKASH_APP_SECRET=""
BKASH_USERNAME=""
BKASH_PASSWORD=""
#for multi account
BKASH_APP_KEY_2=""
BKASH_APP_SECRET_2=""
BKASH_USERNAME_2=""
BKASH_PASSWORD_2=""
#so on just use _number likes _3, _4, _5
BKASH_CALLBACK_URL=""
```
## Usage
### 1. publish a controller
```
php artisan vendor:publish --provider="Karim007\LaravelBkashTokenize\BkashTokenizeServiceProvider" --tag="controllers"
```
### 2. you can override the routes
```php
Route::group(['middleware' => ['web']], function () {
// Payment Routes for bKash
Route::get('/bkash/payment', [App\Http\Controllers\BkashTokenizePaymentController::class,'index']);
Route::get('/bkash/create-payment', [App\Http\Controllers\BkashTokenizePaymentController::class,'createPayment'])->name('bkash-create-payment');
Route::get('/bkash/callback', [App\Http\Controllers\BkashTokenizePaymentController::class,'callBack'])->name('bkash-callBack');
//search payment
Route::get('/bkash/search/{trxID}', [App\Http\Controllers\BkashTokenizePaymentController::class,'searchTnx'])->name('bkash-serach');
//refund payment routes
Route::get('/bkash/refund', [App\Http\Controllers\BkashTokenizePaymentController::class,'refund'])->name('bkash-refund');
Route::get('/bkash/refund/status', [App\Http\Controllers\BkashTokenizePaymentController::class,'refundStatus'])->name('bkash-refund-status');
});
```
### 3. payment page
you will find it App\Http\Controllers\BkashTokenizePaymentController
```
public function index()
{
return view('bkashT::bkash-payment');
}
```
### 4. create payment
```php
public function createPayment(Request $request)
{
$inv = uniqid();
$request['intent'] = 'sale';
$request['mode'] = '0011';
$request['payerReference'] = $inv;
$request['currency'] = 'BDT';
$request['amount'] = 100;
$request['merchantInvoiceNumber'] = $inv;
$request['callbackURL'] = config("bkash.callbackURL");;
$request_data_json = json_encode($request->all());
$response = BkashPaymentTokenize::cPayment($request_data_json);
//$response = BkashPaymentTokenize::cPayment($request_data_json,1); //last parameter is your account number for multi account its like, 1,2,3,4,cont.. default param is 1
//store paymentID and your account number for matching in callback request
// dd($response) //if you are using sandbox and not submit info to bkash use it for 1 response
if (isset($response['bkashURL'])) return redirect()->away($response['bkashURL']);
else return redirect()->back()->with('error-alert2', $response['statusMessage']);
}
```
###create payment response
```array
array[
"statusCode" => "0000"
"statusMessage" => "Successful"
"paymentID" => "Your payment id"
"bkashURL" => "https://sandbox.payment.bkash.com/redirect/tokenized/?paymentID=your_payment_id&hash=your_hash"
"callbackURL" => "base_url/bkash/callback"
"successCallbackURL" => "base_url/bkash/callback?paymentID=your_payment_id&status=success"
"failureCallbackURL" => "base_url/bkash/callback?paymentID=your_payment_id&status=failure"
"cancelledCallbackURL" => "base_url/bkash/callback?paymentID=your_payment_id&status=cancel"
"amount" => "100"
"intent" => "sale"
"currency" => "BDT"
"paymentCreateTime" => "2023-01-23T02:16:57:784 GMT+0600"
"transactionStatus" => "Initiated"
"merchantInvoiceNumber" => "merchant_invoice_no"
]
```
### 5. callback function
```php
public function callBack(Request $request)
{
//callback request params
// paymentID=your_payment_id&status=success&apiVersion=1.2.0-beta
//using paymentID find the account number for sending params
if ($request->status == 'success'){
$response = BkashPaymentTokenize::executePayment($request->paymentID);
//$response = BkashPaymentTokenize::executePayment($request->paymentID, 1); //last parameter is your account number for multi account its like, 1,2,3,4,cont..
if (!$response){
$response = BkashPaymentTokenize::queryPayment($request->paymentID);
//$response = BkashPaymentTokenize::queryPayment($request->paymentID,1); //last parameter is your account number for multi account its like, 1,2,3,4,cont..
}
if (isset($response['statusCode']) && $response['statusCode'] == "0000" && $response['transactionStatus'] == "Completed") {
/*
* for refund need to store
* paymentID and trxID
* */
return BkashPaymentTokenize::success('Thank you for your payment', $response['trxID']);
}
return BkashPaymentTokenize::failure($response['statusMessage']);
}else if ($request->status == 'cancel'){
return BkashPaymentTokenize::cancel('Your payment is canceled');
}else{
return BkashPaymentTokenize::failure('Your transaction is failed');
}
}
```
### 5. execute payment response
```json
{
"statusCode":"0000",
"statusMessage":"Successful",
"paymentID":"your_payment_id",
"payerReference":"your_ref_id",
"customerMsisdn":"customer_msi",
"trxID":"your_tnx_id",
"amount":"100",
"transactionStatus":"Completed",
"paymentExecuteTime":"2023-01-23T02:04:05:736 GMT+0600",
"currency":"BDT",
"intent":"sale"
}
```
### 6. query payment response
```json
{
"paymentID":"your_payment_id",
"mode":"0011",
"paymentCreateTime":"2023-01-23T02:01:06:713 GMT+0600",
"paymentExecuteTime":"2023-01-23T02:04:05:736 GMT+0600",
"amount":"100",
"currency":"BDT",
"intent":"sale",
"merchantInvoice":"merchant_inv_no",
"trxID":"tnx_no",
"transactionStatus":"Completed",
"verificationStatus":"Complete",
"statusCode":"0000",
"statusMessage":"Successful",
"payerReference":"pay_ref"
}
```
### 7. search transaction
```php
public function searchTnx($trxID)
{
//response
/*{
"trxID":"tnx_no",
"initiationTime":"2023-01-23T12:06:05:000 GMT+0600",
"completedTime":"2023-01-23T12:06:05:000 GMT+0600",
"transactionType":"bKash Tokenized Checkout via API",
"customerMsisdn":"customer_msi",
"transactionStatus":"Completed",
"amount":"20",
"currency":"BDT",
"organizationShortCode":"og_short_code",
"statusCode":"0000",
"statusMessage":"Successful"
}*/
return BkashPaymentTokenize::searchTransaction($trxID);
//return BkashPaymentTokenize::searchTransaction($trxID,1); //last parameter is your account number for multi account its like, 1,2,3,4,cont..
}
```
### 8. refund transaction
```php
public function refund(Request $request)
{
$paymentID='paymentID';
$trxID='trxID';
$amount=5;
$reason='this is test reason';
$sku='abc';
//response
/*{
"statusCode":"0000",
"statusMessage":"Successful",
"originalTrxID":"or_tnx_no",
"refundTrxID":"refund_tnx",
"transactionStatus":"Completed",
"amount":"5",
"currency":"BDT",
"charge":"0.00",
"completedTime":"2023-01-23T15:53:29:120 GMT+0600"
}*/
return BkashRefundTokenize::refund($paymentID,$trxID,$amount,$reason,$sku);
//return BkashRefundTokenize::refund($paymentID,$trxID,$amount,$reason,$sku, 1); //last parameter is your account number for multi account its like, 1,2,3,4,cont..
}
```
### 9. refund status check
```php
public function refundStatus(Request $request)
{
$paymentID='paymentID';
$trxID='trxID';
/*{
"statusCode":"0000",
"statusMessage":"Successful",
"originalTrxID":"ori_tx",
"refundTrxID":"ref_tx",
"transactionStatus":"Completed",
"amount":"5",
"currency":"BDT",
"charge":"0.00",
"completedTime":"2023-01-23T15:53:29:120 GMT+0600"
}*/
return BkashRefundTokenize::refundStatus($paymentID,$trxID);
//return BkashRefundTokenize::refundStatus($paymentID,$trxID, 1); //last parameter is your account number for multi account its like, 1,2,3,4,cont..
}
```
N.B. If you are using single account dont need to think about account parameter ignore it just simply use as usal
#### Required APIs
0. **Developer Portal** (detail Product, workflow, API information): https://developer.bka.sh/docs/checkout-process-overview
1. **Grant Token :** https://developer.bka.sh/v1.2.0-beta/reference#gettokenusingpost
2. **Create Payment :** https://developer.bka.sh/v1.2.0-beta/reference#createpaymentusingpost
3. **Execute Payment :** https://developer.bka.sh/v1.2.0-beta/reference#executepaymentusingpost
4. **Query Payment :** https://developer.bka.sh/v1.2.0-beta/reference#querypaymentusingget
5. **Search Transaction Details :** https://developer.bka.sh/v1.2.0-beta/reference#searchtransactionusingget
### Checkout Demo
1. Go to https://merchantdemo.sandbox.bka.sh/frontend/checkout/version/1.2.0-beta
2. **Wallet Number:** 01770618575
3. **OTP:** 123456
4. **Pin:** 12121
Contributions to the Bkash Payment Gateway package are welcome. Please note the following guidelines before submitting your pull
request.
- Follow [PSR-4](http://www.php-fig.org/psr/psr-4/) coding standards.
- Read bkash API documentations first. Please contact with bkash for their api documentation and sandbox access.
## License
This repository is licensed under the [MIT License](http://opensource.org/licenses/MIT).
Copyright 2022 [md abdul karim](https://github.com/karim-007). We are not affiliated with bkash and don't give any guarantee.

View File

@@ -0,0 +1,40 @@
{
"name": "karim007/laravel-bkash-tokenize",
"description": "This is bKash tokenize payment gateway for laravel",
"type": "library",
"keywords": [
"bkash",
"bkash-payment-gateway",
"bkash-payment",
"laravel-bkash",
"laravel-bkash-payment",
"laravel-bkash-payment-tokenize"
],
"require": {
"php": "^7.4|^8.0|^8.1|^8.2",
"ext-curl": "*"
},
"license": "MIT",
"autoload": {
"psr-4": {
"Karim007\\LaravelBkashTokenize\\": "src/"
}
},
"authors": [
{
"name": "Md abdul karim",
"email": "karim.cse007@gmail.com"
}
],
"minimum-stability": "dev",
"extra": {
"laravel": {
"providers": [
"Karim007\\LaravelBkashTokenize\\BkashTokenizeServiceProvider"
],
"aliases": {
"LaravelBkashTokenize": "Karim007\\LaravelBkashTokenize\\LaravelBkashTokenize"
}
}
}
}

View File

@@ -0,0 +1,28 @@
<?php
return [
"sandbox" => env("BKASH_SANDBOX", true),
"bkash_app_key" => env("BKASH_APP_KEY", ""),
"bkash_app_secret" => env("BKASH_APP_SECRET", ""),
"bkash_username" => env("BKASH_USERNAME", ""),
"bkash_password" => env("BKASH_PASSWORD", ""),
"bkash_app_key_2" => env("BKASH_APP_KEY_2", ""),
"bkash_app_secret_2" => env("BKASH_APP_SECRET_2", ""),
"bkash_username_2" => env("BKASH_USERNAME_2", ""),
"bkash_password_2" => env("BKASH_PASSWORD_2", ""),
"bkash_app_key_3" => env("BKASH_APP_KEY_3", ""),
"bkash_app_secret_3" => env("BKASH_APP_SECRET_3", ""),
"bkash_username_3" => env("BKASH_USERNAME_3", ""),
"bkash_password_3" => env("BKASH_PASSWORD_3", ""),
"bkash_app_key_4" => env("BKASH_APP_KEY_4", ""),
"bkash_app_secret_4" => env("BKASH_APP_SECRET_4", ""),
"bkash_username_4" => env("BKASH_USERNAME_4", ""),
"bkash_password_4" => env("BKASH_PASSWORD_4", ""),
"callbackURL" => env("BKASH_CALLBACK_URL", "http://127.0.0.1:8000/bkash/callback"),
'timezone' => 'Asia/Dhaka',
];

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@@ -0,0 +1,45 @@
<?php
namespace Karim007\LaravelBkashTokenize;
use Karim007\LaravelBkashTokenize\Payment\TBPayment;
use Illuminate\Support\ServiceProvider;
use Karim007\LaravelBkashTokenize\Payment\TBRefund;
class BkashTokenizeServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
$this->publishes([
__DIR__ . "/../config/bkash.php" => config_path("bkash.php")
],'config');
$this->publishes([
__DIR__.'/Controllers/BkashTokenizePaymentController.php' => app_path('Http/Controllers/BkashTokenizePaymentController.php'),
],'controllers');
$this->loadRoutesFrom(__DIR__ . "/routes/bkash_route.php");
$this->loadViewsFrom(__DIR__ . '/Views', 'bkashT');
}
/**
* Register application services
*
* @return void
*/
public function register()
{
$this->mergeConfigFrom(__DIR__ . "/../config/bkash.php", "bkash");
$this->app->bind("tbpayment", function () {
return new TBPayment();
});
$this->app->bind("tbrefund", function () {
return new TBRefund();
});
}
}

View File

@@ -0,0 +1,91 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Karim007\LaravelBkashTokenize\Facade\BkashPaymentTokenize;
use Karim007\LaravelBkashTokenize\Facade\BkashRefundTokenize;
class BkashTokenizePaymentController extends Controller
{
public function index()
{
return view('bkashT::bkash-payment');
}
public function createPayment(Request $request)
{
$inv = uniqid();
$request['intent'] = 'sale';
$request['mode'] = '0011'; //0011 for checkout
$request['payerReference'] = $inv;
$request['currency'] = 'BDT';
$request['amount'] = 10;
$request['merchantInvoiceNumber'] = $inv;
$request['callbackURL'] = config("bkash.callbackURL");;
$request_data_json = json_encode($request->all());
$response = BkashPaymentTokenize::cPayment($request_data_json);
//$response = BkashPaymentTokenize::cPayment($request_data_json,1); //last parameter is your account number for multi account its like, 1,2,3,4,cont..
//store paymentID and your account number for matching in callback request
// dd($response) //if you are using sandbox and not submit info to bkash use it for 1 response
if (isset($response['bkashURL'])) return redirect()->away($response['bkashURL']);
else return redirect()->back()->with('error-alert2', $response['statusMessage']);
}
public function callBack(Request $request)
{
//callback request params
// paymentID=your_payment_id&status=success&apiVersion=1.2.0-beta
//using paymentID find the account number for sending params
if ($request->status == 'success'){
$response = BkashPaymentTokenize::executePayment($request->paymentID);
//$response = BkashPaymentTokenize::executePayment($request->paymentID, 1); //last parameter is your account number for multi account its like, 1,2,3,4,cont..
if (!$response){ //if executePayment payment not found call queryPayment
$response = BkashPaymentTokenize::queryPayment($request->paymentID);
//$response = BkashPaymentTokenize::queryPayment($request->paymentID,1); //last parameter is your account number for multi account its like, 1,2,3,4,cont..
}
if (isset($response['statusCode']) && $response['statusCode'] == "0000" && $response['transactionStatus'] == "Completed") {
/*
* for refund need to store
* paymentID and trxID
* */
return BkashPaymentTokenize::success('Thank you for your payment', $response['trxID']);
}
return BkashPaymentTokenize::failure($response['statusMessage']);
}else if ($request->status == 'cancel'){
return BkashPaymentTokenize::cancel('Your payment is canceled');
}else{
return BkashPaymentTokenize::failure('Your transaction is failed');
}
}
public function searchTnx($trxID)
{
//response
return BkashPaymentTokenize::searchTransaction($trxID);
//return BkashPaymentTokenize::searchTransaction($trxID,1); //last parameter is your account number for multi account its like, 1,2,3,4,cont..
}
public function refund(Request $request)
{
$paymentID='Your payment id';
$trxID='your transaction no';
$amount=5;
$reason='this is test reason';
$sku='abc';
//response
return BkashRefundTokenize::refund($paymentID,$trxID,$amount,$reason,$sku);
//return BkashRefundTokenize::refund($paymentID,$trxID,$amount,$reason,$sku, 1); //last parameter is your account number for multi account its like, 1,2,3,4,cont..
}
public function refundStatus(Request $request)
{
$paymentID='Your payment id';
$trxID='your transaction no';
return BkashRefundTokenize::refundStatus($paymentID,$trxID);
//return BkashRefundTokenize::refundStatus($paymentID,$trxID, 1); //last parameter is your account number for multi account its like, 1,2,3,4,cont..
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Karim007\LaravelBkashTokenize\Exception;
use Exception;
class BkashException extends Exception
{
}

View File

@@ -0,0 +1,11 @@
<?php
namespace Karim007\LaravelBkashTokenize\Exception;
use Exception;
class InvalidPrivateKey extends Exception
{
}

View File

@@ -0,0 +1,11 @@
<?php
namespace Karim007\LaravelBkashTokenize\Exception;
use Exception;
class InvalidPublicKey extends Exception
{
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Karim007\LaravelBkashTokenize\Facade;
use Illuminate\Support\Facades\Facade;
/**
* @method static cPayment($request_data_json, $account=1)
* @method static executePayment($paymentID, $account=1)
* @method static queryPayment($paymentID, $account=1)
* @method static refreshToken($refresh_token, $account=1)
* @method static searchTransaction($trxID, $account=1)
* @method static success($message,$transId)
* @method static cancel($message,$transId=null)
* @method static failure($message,$transId=null)
*/
class BkashPaymentTokenize extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'tbpayment';
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Karim007\LaravelBkashTokenize\Facade;
use Illuminate\Support\Facades\Facade;
/**
* @method static refund($paymentID,$trxID,$amount,$reason=null,$sku=null)
* @method static refundStatus($paymentID,$trxID)
*/
class BkashRefundTokenize extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'tbrefund';
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace Karim007\LaravelBkashTokenize\Payment;
use Karim007\LaravelBkashTokenize\Traits\Helpers;
class TBBaseApi
{
use Helpers;
/**
* @var string $baseUrl
*/
protected $baseUrl;
public function __construct()
{
$this->baseUrl();
}
/**
* bkash Base Url
* if sandbox is true it will be sandbox url otherwise it is host url
*/
private function baseUrl()
{
if (config("bkash.sandbox") == true) {
$this->baseUrl = 'https://tokenized.sandbox.bka.sh/v1.2.0-beta/tokenized';
} else {
$this->baseUrl = 'https://tokenized.pay.bka.sh/v1.2.0-beta/tokenized';
}
}
/**
* bkash Request Headers
*
* @return array
*/
protected function headers()
{
return [
"Content-Type" => "application/json",
"X-KM-IP-V4" => $this->getIp(),
"X-KM-Api-Version" => "v-0.2.0",
"X-KM-Client-Type" => "PC_WEB"
];
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace Karim007\LaravelBkashTokenize\Payment;
use Karim007\LaravelBkashTokenize\Traits\Helpers;
class TBPayment extends TBBaseApi
{
use Helpers;
public function cPayment($request_data_json, $account=1)
{
if ($account == 1) $account=null;
else $account="_$account";
$response = $this->getToken($account);
if (isset($response['id_token']) && $response['id_token']){
return $this->getUrl('/checkout/create','POST',$request_data_json, $account);
}
return $response;
}
public function executePayment($paymentID, $account=1)
{
if ($account == 1) $account=null;
else $account="_$account";
$token = session()->get('bkash_token');
if (!$token) $this->getToken($account);
return $this->getUrl2($paymentID,'/checkout/execute', $account);
}
public function queryPayment($paymentID, $account=1)
{
if ($account == 1) $account=null;
else $account="_$account";
$token = session()->get('bkash_token');
if (!$token) $this->getToken($account);
return $this->getUrl2($paymentID,'/checkout/payment/status', $account);
}
public function refreshToken($refresh_token, $account=1)
{
if ($account == 1) $account=null;
else $account="_$account";
return $this->getUrlToken("/checkout/token/refresh",$refresh_token, $account);
}
public function searchTransaction($trxID, $account=1)
{
if ($account == 1) $account=null;
else $account="_$account";
$post_token = array(
'trxID' => $trxID
);
$posttoken = json_encode($post_token);
$this->getToken($account);
return $this->getUrl3("/checkout/general/searchTransaction",$posttoken, $account);
}
public function success($message,$transId)
{
return view('bkashT::success',compact('message','transId'));
}
public function cancel($message,$transId=null)
{
return view('bkashT::failed',compact('message','transId'));
}
public function failure($message,$transId=null)
{
return view('bkashT::failed',compact('message','transId'));
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace Karim007\LaravelBkashTokenize\Payment;
use Karim007\LaravelBkashTokenize\Traits\Helpers;
class TBRefund extends TBBaseApi
{
use Helpers;
public function refund($paymentID,$trxID,$amount,$reason='refined amount',$sku='abc', $account=1)
{
if ($account == 1) $account=null;
else $account="_$account";
$post_token = array(
'paymentID' => $paymentID,
'amount' => $amount,
'trxID' => $trxID,
'reason' => $reason,
'sku' => $sku,
);
$posttoken = json_encode($post_token);
$this->getToken($account);
return $this->getUrl3("/checkout/payment/refund",$posttoken, $account);
}
public function refundStatus($paymentID,$trxID, $account=1)
{
if ($account == 1) $account=null;
else $account="_$account";
$post_token = array(
'paymentID' => $paymentID,
'trxID' => $trxID,
);
$posttoken = json_encode($post_token);
$this->getToken($account);
return $this->getUrl3("/checkout/payment/refund",$posttoken, $account);
}
}

View File

@@ -0,0 +1,144 @@
<?php
namespace Karim007\LaravelBkashTokenize\Traits;
trait Helpers
{
/**
* @return string|null
*/
public function getIp()
{
return request()->ip();
}
protected function getUrlToken($url,$refresh_token=null, $account=null)
{
// if bkash token exists and not expired, return it, no need to call the bkash api again
if(session()->has(['bkash_token','expires_in'])){
$expires_in = session()->get('expires_in');
if($expires_in && time() < ($expires_in - 200) && !$refresh_token){
return [
'id_token' => session()->get('bkash_token'),
'token_type' => session()->get('bkash_token_type'),
'refresh_token' => session()->get('bkash_refresh_token'),
];
}
}
session()->forget('bkash_token');
session()->forget('bkash_token_type');
session()->forget('bkash_refresh_token');
$post_token = array(
'app_key' => config("bkash.bkash_app_key$account"),
'app_secret' => config("bkash.bkash_app_secret$account"),
'refresh_token' => $refresh_token,
);
$url = curl_init($this->baseUrl.$url);
$post_token = json_encode($post_token);
$username = config("bkash.bkash_username$account");
$password = config("bkash.bkash_password$account");
$header = array(
'Content-Type:application/json',
"password:$password",
"username:$username"
);
curl_setopt($url,CURLOPT_HTTPHEADER, $header);
curl_setopt($url,CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($url,CURLOPT_RETURNTRANSFER, true);
curl_setopt($url,CURLOPT_POSTFIELDS, $post_token);
curl_setopt($url,CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($url, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
$resultdata = curl_exec($url);
curl_close($url);
$response = json_decode($resultdata, true);
if (array_key_exists('msg', $response)) {
return $response;
}
if (isset($response['id_token']) && isset($response['token_type']) && isset($response['refresh_token'])){
if(isset($response['expires_in'])) {
session()->put('expires_in', $response['expires_in']);
}
session()->put('bkash_token', $response['id_token']);
session()->put('bkash_token_type', $response['token_type']);
session()->put('bkash_refresh_token', $response['refresh_token']);
}
return $response;
}
protected function getUrl($url, $method, $data=null, $account=null)
{
$token = session()->get('bkash_token');
$app_key = config("bkash.bkash_app_key$account");
$url = curl_init($this->baseUrl.$url);
$header = array(
'Content-Type:application/json',
"authorization: $token",
"x-app-key: $app_key"
);
curl_setopt($url, CURLOPT_HTTPHEADER, $header);
curl_setopt($url, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($url, CURLOPT_RETURNTRANSFER, true);
if ($data) curl_setopt($url, CURLOPT_POSTFIELDS, $data);
curl_setopt($url, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($url, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
$resultdata = curl_exec($url);
curl_close($url);
return json_decode($resultdata, true);
}
protected function getUrl2($paymentID, $url, $account=null){
$post_token = array(
'paymentID' => $paymentID
);
$url = curl_init($this->baseUrl.$url);
$posttoken = json_encode($post_token);
$app_key = config("bkash.bkash_app_key$account");
$header = array(
'Content-Type:application/json',
'Authorization:' . session()->get('bkash_token'),
'X-APP-Key:'.$app_key
);
curl_setopt($url, CURLOPT_HTTPHEADER, $header);
curl_setopt($url, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($url, CURLOPT_RETURNTRANSFER, true);
curl_setopt($url, CURLOPT_POSTFIELDS, $posttoken);
curl_setopt($url, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($url, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
$resultdata = curl_exec($url);
curl_close($url);
return json_decode($resultdata, true);
}
protected function getUrl3($url,$data, $account=null){
$url = curl_init($this->baseUrl.$url);
$app_key = config("bkash.bkash_app_key$account");
$header = array(
'Content-Type:application/json',
'Authorization:' . session()->get('bkash_token'),
'x-app-key:'.$app_key
);
curl_setopt($url, CURLOPT_HTTPHEADER, $header);
curl_setopt($url, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($url, CURLOPT_RETURNTRANSFER, true);
if($data) curl_setopt($url, CURLOPT_POSTFIELDS, $data);
curl_setopt($url, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($url, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
$resultdata = curl_exec($url);
curl_close($url);
return json_decode($resultdata, true);
}
protected function getToken($account=null)
{
return $this->getUrlToken('/checkout/token/grant',null, $account);
}
}

View File

@@ -0,0 +1,5 @@
<meta name="csrf-token" content="{{ csrf_token() }}" />
<button class="btn btn-success" >
<a href="{{route('bkash-create-payment')}}">Pay with bKash</a>
</button>

View File

@@ -0,0 +1,128 @@
<!DOCTYPE html>
<html>
<head>
<title>The Title</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<style type="text/css">
body {
background: #adadad;
}
#card {
position: relative;
top: 110px;
width: 320px;
display: block;
margin: auto;
text-align: center;
font-family: 'Source Sans Pro', sans-serif;
}
#upper-side {
padding: 2em;
background-color: #bec34a;
display: block;
color: #fff;
border-top-right-radius: 8px;
border-top-left-radius: 8px;
}
#checkmark {
font-weight: lighter;
fill: #fff;
margin: -3.5em auto auto 20px;
}
#status {
font-weight: lighter;
text-transform: uppercase;
letter-spacing: 2px;
font-size: 1em;
margin-top: -.2em;
margin-bottom: 0;
}
#lower-side {
padding: 2em 2em 5em 2em;
background: #fff;
display: block;
border-bottom-right-radius: 8px;
border-bottom-left-radius: 8px;
}
#message {
margin-top: -.5em;
color: #757575;
letter-spacing: 1px;
}
#contBtn {
position: relative;
top: 1.5em;
text-decoration: none;
background: #8bc34a;
color: #fff;
margin: auto;
padding: .8em 3em;
-webkit-box-shadow: 0px 15px 30px rgba(50, 50, 50, 0.21);
-moz-box-shadow: 0px 15px 30px rgba(50, 50, 50, 0.21);
box-shadow: 0px 15px 30px rgba(50, 50, 50, 0.21);
border-radius: 25px;
-webkit-transition: all .4s ease;
-moz-transition: all .4s ease;
-o-transition: all .4s ease;
transition: all .4s ease;
}
#contBtn:hover {
-webkit-box-shadow: 0px 15px 30px rgba(50, 50, 50, 0.41);
-moz-box-shadow: 0px 15px 30px rgba(50, 50, 50, 0.41);
box-shadow: 0px 15px 30px rgba(50, 50, 50, 0.41);
-webkit-transition: all .4s ease;
-moz-transition: all .4s ease;
-o-transition: all .4s ease;
transition: all .4s ease;
}
</style>
</head>
<body>
<div id='card' class="animated fadeIn">
<div id='upper-side'>
<?xml version = "1.0" encoding = "utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="150"
height="150" viewBox="0 0 256 256" xml:space="preserve">
<desc>Created with Fabric.js 1.7.22</desc>
<defs>
</defs>
<g transform="translate(128 128) scale(0.72 0.72)" style="">
<g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;"
transform="translate(-175.05 -175.05000000000004) scale(3.89 3.89)">
<path
d="M 45 88.11 h 40.852 c 3.114 0 5.114 -3.307 3.669 -6.065 L 48.669 4.109 c -1.551 -2.959 -5.786 -2.959 -7.337 0 L 0.479 82.046 c -1.446 2.758 0.555 6.065 3.669 6.065 H 45 z"
style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(214,0,0); fill-rule: nonzero; opacity: 1;"
transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round"/>
<path
d="M 45 64.091 L 45 64.091 c -1.554 0 -2.832 -1.223 -2.9 -2.776 l -2.677 -25.83 c -0.243 -3.245 2.323 -6.011 5.577 -6.011 h 0 c 3.254 0 5.821 2.767 5.577 6.011 L 47.9 61.315 C 47.832 62.867 46.554 64.091 45 64.091 z"
style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1;"
transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round"/>
<circle cx="44.995999999999995" cy="74.02600000000001" r="4.626"
style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1;"
transform=" matrix(1 0 0 1 0 0) "/>
</g>
</g>
</svg>
<h3 id='status'>
Failed
</h3>
</div>
<div id='lower-side'>
<p id='message'>
{{$message}} {{ $transId ??'' }}
</p>
<a href="/" id="contBtn">Continue</a>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,118 @@
<!DOCTYPE html>
<html>
<head>
<title>The Title</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<style type="text/css">
body {
background: #adadad;
}
#card {
position: relative;
top: 110px;
width: 320px;
display: block;
margin: auto;
text-align: center;
font-family: 'Source Sans Pro', sans-serif;
}
#upper-side {
padding: 2em;
background-color: #8BC34A;
display: block;
color: #fff;
border-top-right-radius: 8px;
border-top-left-radius: 8px;
}
#checkmark {
font-weight: lighter;
fill: #fff;
margin: -3.5em auto auto 20px;
}
#status {
font-weight: lighter;
text-transform: uppercase;
letter-spacing: 2px;
font-size: 1em;
margin-top: -.2em;
margin-bottom: 0;
}
#lower-side {
padding: 2em 2em 5em 2em;
background: #fff;
display: block;
border-bottom-right-radius: 8px;
border-bottom-left-radius: 8px;
}
#message {
margin-top: -.5em;
color: #757575;
letter-spacing: 1px;
}
#contBtn {
position: relative;
top: 1.5em;
text-decoration: none;
background: #8bc34a;
color: #fff;
margin: auto;
padding: .8em 3em;
-webkit-box-shadow: 0px 15px 30px rgba(50, 50, 50, 0.21);
-moz-box-shadow: 0px 15px 30px rgba(50, 50, 50, 0.21);
box-shadow: 0px 15px 30px rgba(50, 50, 50, 0.21);
border-radius: 25px;
-webkit-transition: all .4s ease;
-moz-transition: all .4s ease;
-o-transition: all .4s ease;
transition: all .4s ease;
}
#contBtn:hover {
-webkit-box-shadow: 0px 15px 30px rgba(50, 50, 50, 0.41);
-moz-box-shadow: 0px 15px 30px rgba(50, 50, 50, 0.41);
box-shadow: 0px 15px 30px rgba(50, 50, 50, 0.41);
-webkit-transition: all .4s ease;
-moz-transition: all .4s ease;
-o-transition: all .4s ease;
transition: all .4s ease;
}
</style>
</head>
<body>
<div id='card' class="animated fadeIn">
<div id='upper-side'>
<?xml version = "1.0" encoding = "utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="checkmark" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" xml:space="preserve">
<path d="M131.583,92.152l-0.026-0.041c-0.713-1.118-2.197-1.447-3.316-0.734l-31.782,20.257l-4.74-12.65
c-0.483-1.29-1.882-1.958-3.124-1.493l-0.045,0.017c-1.242,0.465-1.857,1.888-1.374,3.178l5.763,15.382
c0.131,0.351,0.334,0.65,0.579,0.898c0.028,0.029,0.06,0.052,0.089,0.08c0.08,0.073,0.159,0.147,0.246,0.209
c0.071,0.051,0.147,0.091,0.222,0.133c0.058,0.033,0.115,0.069,0.175,0.097c0.081,0.037,0.165,0.063,0.249,0.091
c0.065,0.022,0.128,0.047,0.195,0.063c0.079,0.019,0.159,0.026,0.239,0.037c0.074,0.01,0.147,0.024,0.221,0.027
c0.097,0.004,0.194-0.006,0.292-0.014c0.055-0.005,0.109-0.003,0.163-0.012c0.323-0.048,0.641-0.16,0.933-0.346l34.305-21.865
C131.967,94.755,132.296,93.271,131.583,92.152z"/>
<circle fill="none" stroke="#ffffff" stroke-width="5" stroke-miterlimit="10" cx="109.486" cy="104.353"
r="32.53"/>
</svg>
<h3 id='status'>
Success
</h3>
</div>
<div id='lower-side'>
<p id='message'>
{{$message}} Transaction ID {{ $transId }}
</p>
<a href="/" id="contBtn">Continue</a>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,19 @@
<?php
use Illuminate\Support\Facades\Route;
Route::group(['middleware' => ['web']], function () {
// Payment Routes for bKash
Route::get('/bkash/payment', [App\Http\Controllers\BkashTokenizePaymentController::class,'index']);
Route::get('/bkash/create-payment', [App\Http\Controllers\BkashTokenizePaymentController::class,'createPayment'])->name('bkash-create-payment');
Route::get('/bkash/callback', [App\Http\Controllers\BkashTokenizePaymentController::class,'callBack'])->name('bkash-callBack');
//search payment
Route::get('/bkash/search/{trxID}', [App\Http\Controllers\BkashTokenizePaymentController::class,'searchTnx'])->name('bkash-serach');
//refund payment routes
Route::get('/bkash/refund', [App\Http\Controllers\BkashTokenizePaymentController::class,'refund'])->name('bkash-refund');
Route::get('/bkash/refund/status', [App\Http\Controllers\BkashTokenizePaymentController::class,'refundStatus'])->name('bkash-refund-status');
});