This guide explains how to integrate bKash payment gateway with the Laravel Payments package.
bKash is Bangladesh's largest mobile financial service provider, offering:
composer require sabitahmad/laravel-bkash
php artisan vendor:publish --tag=bkash-config
php artisan vendor:publish --tag=bkash-migrations
Add your bKash credentials to your .env file:
BKASH_APP_KEY=your_app_key_here
BKASH_APP_SECRET=your_app_secret_here
BKASH_USERNAME=your_username_here
BKASH_PASSWORD=your_password_here
BKASH_TEST_MODE=true
BKASH_CALLBACK_URL=https://yoursite.com/bkash/callback
BKASH_SUCCESS_URL=https://yoursite.com/payment/success
BKASH_FAIL_URL=https://yoursite.com/payment/fail
You can obtain these credentials from your bKash merchant dashboard.
For development/testing:
BKASH_TEST_MODE=true
BKASH_APP_KEY=sandbox_app_key
BKASH_APP_SECRET=sandbox_app_secret
For production:
BKASH_TEST_MODE=false
BKASH_APP_KEY=live_app_key
BKASH_APP_SECRET=live_app_secret
You also need to add the configuration to your config/services.php:
'bkash' => [
'app_key' => env('BKASH_APP_KEY'),
'app_secret' => env('BKASH_APP_SECRET'),
'username' => env('BKASH_USERNAME'),
'password' => env('BKASH_PASSWORD'),
'test_mode' => env('BKASH_TEST_MODE', true),
'callback_url' => env('BKASH_CALLBACK_URL'),
'success_url' => env('BKASH_SUCCESS_URL'),
'fail_url' => env('BKASH_FAIL_URL'),
],
use Mdiqbal\LaravelPayments\Facades\Payment;
$paymentRequest = [
'amount' => 100.00,
'currency' => 'BDT',
'email' => 'customer@example.com',
'transaction_id' => 'TXN' . time(),
'redirect_url' => 'https://yoursite.com/payment/callback',
'customer' => [
'name' => 'John Doe',
'phone' => '01XXXXXXXXX'
],
'metadata' => [
'order_id' => 'ORD123456',
'user_id' => 789
]
];
$payment = Payment::gateway('bkash')->pay($paymentRequest);
This will return a payment URL that you need to redirect the user to:
if ($payment['success']) {
// Store payment_id for later verification
session(['bkash_payment_id' => $payment['payment_id']]);
// Redirect to bKash payment page
return redirect($payment['payment_url']);
}
// First, get the payment ID (stored during initialization)
$paymentId = session('bkash_payment_id');
$verification = Payment::gateway('bkash')->verify($paymentId);
if ($verification['success']) {
$status = $verification['status'];
if ($status === 'completed') {
// Payment was successful
$trxId = $verification['transaction_id_bkash'];
$amount = $verification['amount'];
}
}
$refundData = [
'payment_id' => 'PAYMENT_ID_FROM_BKASH',
'amount' => 50.00,
'trx_id' => 'ORIGINAL_TRANSACTION_ID',
'reason' => 'Customer requested refund'
];
$refund = Payment::gateway('bkash')->refund($refundData);
$transactionDetails = Payment::gateway('bkash')->queryTransaction($paymentId);
$transaction = Payment::gateway('bkash')->searchTransaction($trxId);
$linkData = [
'amount' => 100.00,
'currency' => 'BDT',
'description' => 'Payment for invoice #123',
'customer' => [
'name' => 'John Doe',
'email' => 'customer@example.com'
]
];
$paymentLink = Payment::gateway('bkash')->createPaymentLink($linkData);
bKash's primary currency is BDT (Bangladeshi Taka). The gateway automatically converts other currencies to BDT:
// This will be converted to BDT internally
$paymentRequest = [
'amount' => 1.00,
'currency' => 'USD',
'email' => 'customer@example.com',
'transaction_id' => 'TXN' . time(),
// ... other parameters
];
$payment = Payment::gateway('bkash')->pay($paymentRequest);
// $payment['original_amount'] = 1.00
// $payment['original_currency'] = 'USD'
// $payment['amount'] = 109.50 (1 * 109.50)
// $payment['currency'] = 'BDT'
bKash uses callbacks (webhooks) to notify your application about payment status changes.
Configure your callback URL in the bKash dashboard or in the payment request
Create a route to handle callbacks:
// routes/web.php
Route::post('/bkash/callback', [BkashCallbackController::class, 'handleCallback']);
Route::get('/bkash/success', [BkashController::class, 'success']);
Route::get('/bkash/fail', [BkashController::class, 'fail']);
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Mdiqbal\LaravelPayments\Facades\Payment;
class BkashCallbackController extends Controller
{
public function handleCallback(Request $request)
{
$gateway = Payment::gateway('bkash');
$callbackData = $gateway->parseCallback($request);
// Process the webhook
$result = $gateway->processWebhook($callbackData);
if ($result['success']) {
$eventType = $result['event_type'];
$transactionId = $result['transaction_id'];
$paymentId = $result['payment_id'];
switch ($eventType) {
case 'payment.completed':
$this->handleSuccessfulPayment($result);
break;
case 'payment.failed':
$this->handleFailedPayment($result);
break;
case 'payment.cancelled':
$this->handleCancelledPayment($result);
break;
case 'payment.pending':
$this->handlePendingPayment($result);
break;
}
}
// Always return 200 OK to acknowledge receipt
return response()->json(['status' => 'received']);
}
protected function handleSuccessfulPayment($data)
{
// Update order status
$order = Order::where('transaction_id', $data['transaction_id'])->first();
if ($order) {
$order->status = 'paid';
$order->paid_at = now();
$order->payment_method = 'bkash';
$order->bkash_trx_id = $data['transaction_id_bkash'];
$order->customer_msisdn = $data['customer_msisdn'];
$order->save();
// Send confirmation email
Mail::to($order->customer_email)->send(new PaymentConfirmation($order));
}
}
protected function handleFailedPayment($data)
{
// Log failed payment
Log::warning('bKash payment failed', [
'transaction_id' => $data['transaction_id'],
'payment_id' => $data['payment_id']
]);
// Update order status
$order = Order::where('transaction_id', $data['transaction_id'])->first();
if ($order) {
$order->status = 'failed';
$order->save();
}
}
protected function handleCancelledPayment($data)
{
// Handle cancelled payment
}
protected function handlePendingPayment($data)
{
// Payment is being processed
$order = Order::where('transaction_id', $data['transaction_id'])->first();
if ($order) {
$order->status = 'processing';
$order->save();
}
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class BkashController extends Controller
{
public function success(Request $request)
{
// User returned from bKash after successful payment
// Display success page
return view('payment.bkash-success');
}
public function fail(Request $request)
{
// User returned from bKash after failed payment
// Display failure page
return view('payment.bkash-fail');
}
}
pay() to get payment ID and bKash URLexecutePayment() or queryPayment() to verify statusThe bKash gateway provides detailed error messages:
$payment = Payment::gateway('bkash')->pay($paymentRequest);
if (!$payment['success']) {
$error = $payment['error'];
$message = $error['message'];
$code = $error['code'];
// Handle error based on type
if ($code === 'PAYMENT_FAILED') {
// Payment initialization failed
}
}
PAYMENT_FAILED - Payment initialization failedVERIFICATION_FAILED - Transaction verification failedREFUND_FAILED - Refund processing failedWEBHOOK_FAILED - Webhook processing failedQUERY_FAILED - Transaction query failedSEARCH_FAILED - Transaction search failedUse test credentials for development:
BKASH_TEST_MODE=true
For testing in sandbox mode, bKash provides test credentials that will be provided in their developer documentation.
bKash automatically determines the appropriate payment method based on:
bKash primarily processes payments in BDT (Bangladeshi Taka). However, it can accept multiple currencies with automatic conversion:
bKash primarily serves Bangladesh but can accept:
bKash implements reasonable rate limits. Implement proper rate limiting in your application to avoid being blocked.
pay() - Initialize a paymentverify() - Verify a transaction statusrefund() - Process a refundgetTransactionStatus() - Get transaction statusqueryTransaction() - Query transaction detailssearchTransaction() - Search by bKash transaction IDcreatePaymentLink() - Create a payment linkcreateCustomer() - Note customer information (sent with each payment)parseCallback() - Parse callback parameters from requestgetSupportedCurrencies() - Get supported currenciesgetGatewayConfig() - Get gateway configurationgetPaymentMethodsForCountry() - Get payment methods for a country// If you have multiple bKash accounts
$gateway = Payment::gateway('bkash', [
'app_key' => 'different_app_key',
'app_secret' => 'different_app_secret',
'username' => 'different_username',
'password' => 'different_password'
]);
Override the default exchange rates for currency conversion:
// In a service provider or middleware
$gateway = Payment::gateway('bkash');
// Note: The gateway uses predefined rates, implement your own exchange rate service for production
Since bKash doesn't natively support recurring payments:
// Implement your own recurring payment logic
public function processRecurringPayment($subscription)
{
foreach ($subscription->charges as $charge) {
$paymentRequest = [
'amount' => $charge->amount,
'currency' => 'BDT',
'email' => $subscription->customer_email,
'transaction_id' => 'SUB_' . $subscription->id . '_' . $charge->id,
'description' => $subscription->description,
// ... other parameters
];
$payment = Payment::gateway('bkash')->pay($paymentRequest);
if ($payment['success']) {
// Store payment_id for this charge
$charge->bkash_payment_id = $payment['payment_id'];
$charge->save();
}
// Handle payment and update subscription status
}
}
class PaymentController extends Controller
{
public function initiate(Request $request)
{
$payment = Payment::gateway('bkash')->pay($request->all());
if ($payment['success']) {
// Store payment information in session
session([
'bkash_payment_id' => $payment['payment_id'],
'transaction_id' => $payment['transaction_id'],
'amount' => $payment['amount']
]);
return redirect($payment['payment_url']);
}
return back()->with('error', 'Failed to initialize payment');
}
public function verify(Request $request)
{
$paymentId = session('bkash_payment_id');
if (!$paymentId) {
return back()->with('error', 'Payment information not found');
}
$verification = Payment::gateway('bkash')->verify($paymentId);
if ($verification['success'] && $verification['status'] === 'completed') {
// Clear session
session()->forget(['bkash_payment_id', 'transaction_id', 'amount']);
// Update order status
// Send confirmation
// Redirect to success page
}
return back()->with('error', 'Payment verification failed');
}
}
For bKash-specific support:
For Laravel Payments package support:
How can I help you explore Laravel packages today?