Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Bkash Laravel Package

sabitahmad/laravel-bkash

Integrate bKash payments in Laravel (API v1.2.0) with tokenized and regular checkout, sandbox/production switching, auto token refresh, payment and agreement operations (create/execute/query/refund/search), transaction logging, retries, and validation.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require sabitahmad/laravel-bkash
    php artisan vendor:publish --tag="laravel-bkash-migrations"
    php artisan vendor:publish --tag="laravel-bkash-config"
    php artisan migrate
    
  2. Environment Setup: Add these to .env:

    BKASH_SANDBOX=true
    BKASH_APP_KEY=your_app_key
    BKASH_APP_SECRET=your_app_secret
    BKASH_USERNAME=your_username
    BKASH_PASSWORD=your_password
    BKASH_CALLBACK_URL=/bkash/callback
    
  3. First Use Case: Initiate a payment in a controller:

    use SabitAhmad\Bkash\Facades\Bkash;
    
    $payment = Bkash::createPayment(
        payerReference: 'CUST-1001',
        amount: 100.50,
        invoiceNumber: 'INV-1001'
    );
    
    if ($payment->isSuccess()) {
        return redirect()->away($payment->getPaymentUrl());
    }
    

Where to Look First

  • Configuration: config/bkash.php (published via vendor:publish)
  • Facade: SabitAhmad\Bkash\Facades\Bkash (primary entry point)
  • Response Methods: Response Handling section in README
  • Example Controller: examples/BkashController.php (if included in package)

Implementation Patterns

Core Workflows

1. Tokenized Checkout (Agreement Flow)

// Create Agreement
$agreement = Bkash::createAgreement('CUST-1001');
if ($agreement->isSuccess()) {
    return redirect()->away($agreement->getAgreementUrl());
}

// Handle Callback (after user completes agreement)
$execution = Bkash::executeAgreement($request->paymentID);
if ($execution->isSuccess()) {
    $agreementId = $execution->getAgreementId();
    // Store for future payments
}

2. Regular Payment Flow

// Initiate Payment
$payment = Bkash::createPayment(
    payerReference: 'CUST-1001',
    amount: 100.50,
    invoiceNumber: 'INV-1001',
    callbackURL: '/payment/callback'
);
if ($payment->isSuccess()) {
    return redirect()->away($payment->getPaymentUrl());
}

// Handle Callback
$execution = Bkash::executePayment($request->paymentID);
if ($execution->isCompleted()) {
    event(new PaymentCompleted($execution));
}

3. Tokenized Payment (Using Existing Agreement)

$payment = Bkash::createPayment(
    payerReference: 'CUST-1001',
    amount: 100.50,
    invoiceNumber: 'INV-1002',
    agreementId: 'AGR123456' // Pre-existing agreement
);

Integration Tips

1. Webhook/Callback Handling

Route::post('/bkash/callback', function (Request $request) {
    $response = Bkash::executePayment($request->paymentID);

    if ($response->isCompleted()) {
        // Update order status, send confirmation, etc.
        event(new PaymentCompleted($response));
        return response()->json(['status' => 'success']);
    }

    return response()->json(['status' => 'failed'], 400);
});

2. Transaction Logging

Enable in config/bkash.php:

'log_transactions' => env('BKASH_LOG_TRANSACTIONS', true),

Logs are stored in bkash_transactions table (migrated via vendor:publish).

3. Error Handling

try {
    $payment = Bkash::createPayment(...);
    if (!$payment->isSuccess()) {
        throw new \Exception($payment->getErrorMessage());
    }
} catch (SabitAhmad\Bkash\Exceptions\BkashException $e) {
    Log::error('bKash Error: ' . $e->getMessage());
    return back()->with('error', 'Payment failed. Please try again.');
}

4. Retry Mechanism for Failed Requests

Configure retries in .env:

BKASH_RETRY_ATTEMPTS=3
BKASH_RETRY_DELAY=1000

The package automatically retries failed API calls.

5. Sandbox vs Production

Toggle with:

// In config/bkash.php
'sandbox' => env('BKASH_SANDBOX', true),

Use sandbox (true) for testing, set to false for production.


Advanced Patterns

1. Agreement-Based Subscription Model

// Create agreement for recurring payments
$agreement = Bkash::createAgreement('SUBSCRIBER_123');

// Store agreement ID in user model
$user->bkash_agreement_id = $agreement->getAgreementId();
$user->save();

// For subsequent payments
$payment = Bkash::createPayment(
    payerReference: 'SUBSCRIBER_123',
    amount: 50.00,
    invoiceNumber: 'SUB_'.now()->format('YmdHis'),
    agreementId: $user->bkash_agreement_id
);

2. Refund Workflow

$refund = Bkash::refundPayment(
    paymentId: 'PAY123456',
    amount: 100.50,
    reason: 'Customer requested refund'
);

if ($refund->isSuccess()) {
    // Update order status, notify customer, etc.
    $order->status = 'refunded';
    $order->save();
}

3. Querying Payment Status

$query = Bkash::queryPayment('PAY123456');
if ($query->isCompleted()) {
    // Payment is confirmed
    $trxId = $query->getTrxId();
} elseif ($query->isFailed()) {
    // Handle failure
}

4. Searching Transactions

$search = Bkash::searchTransaction('TRX123456');
$transactions = $search->getTransactions();

foreach ($transactions as $tx) {
    if ($tx['transactionStatus'] === 'Completed') {
        // Process completed transaction
    }
}

5. Event-Driven Architecture

Listen for payment events in EventServiceProvider:

protected $listen = [
    \SabitAhmad\Bkash\Events\PaymentCompleted::class => [
        \App\Listeners\UpdateOrderStatus::class,
        \App\Listeners\SendConfirmationEmail::class,
    ],
    \SabitAhmad\Bkash\Events\PaymentFailed::class => [
        \App\Listeners\NotifyAdmin::class,
    ],
];

Gotchas and Tips

Pitfalls

1. Token Expiry

  • bKash tokens expire after 1 hour (default BKASH_TOKEN_CACHE_TTL=3300 seconds).
  • Solution: Configure BKASH_TOKEN_CACHE_TTL in .env or handle token refresh manually:
    $token = Bkash::getToken(); // Auto-refreshes if expired
    

2. Callback URL Mismatch

  • bKash strictly validates the callbackURL during payment creation.
  • Solution: Ensure the URL matches exactly (including https://):
    $payment = Bkash::createPayment(..., callbackURL: 'https://yourdomain.com/bkash/callback');
    

3. Sandbox vs Production Endpoints

  • Gotcha: Forgetting to switch between sandbox (true) and production (false) modes.
  • Solution: Use .env variables and test thoroughly in sandbox before going live.

4. Amount Validation

  • bKash enforces minimum (BKASH_MIN_AMOUNT) and maximum (BKASH_MAX_AMOUNT) amounts.
  • Solution: Validate amounts before calling the API:
    if ($amount < config('bkash.min_amount')) {
        throw new \InvalidArgumentException('Amount too low');
    }
    

5. MSISDN Format

  • Gotcha: bKash requires 8-digit MSISDN (e.g., 01712345678).
  • Solution: Validate and format user input:
    $msisdn = preg_replace('/[^0-9]/', '', $request->phone);
    if (strlen($msisdn) !== 11) { // +88 prefix
        throw new \InvalidArgumentException('Invalid phone number');
    }
    

Debugging Tips

1. Enable Detailed Logging

// In config/bkash.php
'log_transactions' => true,
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony
spatie/flare-daemon-runtime