Skip to content

Instantly share code, notes, and snippets.

@tarikmanoar
Last active June 14, 2023 16:05
Show Gist options
  • Save tarikmanoar/4b34a9af471c2a223aeb459ed95375af to your computer and use it in GitHub Desktop.
Save tarikmanoar/4b34a9af471c2a223aeb459ed95375af to your computer and use it in GitHub Desktop.
This document used for bkash payment for Davinci

web

Past Line Number 610

Route::get('/payments/approved/bkash', 'approvedBkash')->name('user.payments.approved.bkash');

Index.blade.php

Past Line Number 77 - 172

    <div class="card border-0 special-shadow">
        <div class="card-body">
            <h6 class="fs-12 font-weight-bold mb-4"><i class="fa-brands fa-cc-paypal fs-16 mr-2"></i>Bkash Payment Gateway
                <span class="text-primary">({{ __('All Plans') }})</span></h6>

            <div class="row">
                <div class="col-md-6 col-sm-12 mb-2">
                    <div class="form-group">
                        <label class="custom-switch">
                            <input type="checkbox" name="bkash_enable" class="custom-switch-input" @if (config('services.bkash.enable')  == true) checked @endif>
                            <span class="custom-switch-indicator"></span>
                            <span class="custom-switch-description">Enable Bkash</span>
                        </label>
                    </div>
                </div>
                <div class="col-md-6 col-sm-12 mb-2">
                    <div class="form-group">
                        <label class="custom-switch">
                            <input type="checkbox" name="bkash_subscription" class="custom-switch-input" @if (config('services.bkash.subscription')  == true) checked @endif>
                            <span class="custom-switch-indicator"></span>
                            <span class="custom-switch-description">Enable Bkash Subscription</span>
                        </label>
                    </div>
                </div>
                <div class="col-lg-6 col-md-6 col-sm-12">
                    <div class="input-box">
                        <h6>App Key <span class="text-required"><i class="fa-solid fa-asterisk"></i></span></h6>
                        <div class="form-group">
                            <input type="text" class="form-control @error('bkash_app_key') is-danger @enderror"
                                id="bkash_app_key" name="bkash_app_key"
                                value="{{ config('services.bkash.app_key') }}" autocomplete="off">
                        </div>
                        @error('bkash_app_key')
                        <p class="text-danger">{{ $errors->first('bkash_app_key') }}</p>
                        @enderror
                    </div>
                </div>
                <div class="col-lg-6 col-md-6 col-sm-12">
                    <div class="input-box">
                        <h6>App Secret <span class="text-required"><i class="fa-solid fa-asterisk"></i></span></h6>
                        <div class="form-group">
                            <input type="text" class="form-control @error('bkash_app_secret') is-danger @enderror"
                                id="bkash_app_secret" name="bkash_app_secret"
                                value="{{ config('services.bkash.app_secret') }}" autocomplete="off">
                        </div>
                        @error('bkash_app_secret')
                        <p class="text-danger">{{ $errors->first('bkash_app_secret') }}</p>
                        @enderror
                    </div>
                </div>
                <div class="col-lg-6 col-md-6 col-sm-12">
                    <div class="input-box">
                        <h6>Username <span class="text-required"><i class="fa-solid fa-asterisk"></i></span></h6>
                        <div class="form-group">
                            <input type="text" class="form-control @error('bkash_username') is-danger @enderror"
                                id="bkash_username" name="bkash_username"
                                value="{{ config('services.bkash.username') }}" autocomplete="off">
                        </div>
                        @error('bkash_username')
                        <p class="text-danger">{{ $errors->first('bkash_username') }}</p>
                        @enderror
                    </div>
                </div>
                <div class="col-lg-6 col-md-6 col-sm-12">
                    <div class="input-box">
                        <h6>Password <span class="text-required"><i class="fa-solid fa-asterisk"></i></span></h6>
                        <div class="form-group">
                            <input type="text" class="form-control @error('bkash_password') is-danger @enderror"
                                id="bkash_password" name="bkash_password"
                                value="{{ config('services.bkash.password') }}" autocomplete="off">
                        </div>
                        @error('bkash_password')
                        <p class="text-danger">{{ $errors->first('bkash_password') }}</p>
                        @enderror
                    </div>
                </div>

                <div class="col-lg-6 col-md-6 col-sm-12">
                    <div class="input-box">
                        <h6>Bkash Base URI <span class="text-required"><i class="fa-solid fa-asterisk"></i></span></h6>
                        <select id="paypal-url" name="bkash_base_uri"
                            data-placeholder="{{ __('Choose Payment Option') }}:">
                            <option value="https://tokenized.pay.bka.sh/v1.2.0-beta" @if(config('services.bkash.base_uri')=='https://tokenized.pay.bka.sh/v1.2.0-beta' ) selected @endif>Live URL
                            </option>
                            <option value="https://tokenized.sandbox.bka.sh/v1.2.0-beta" @if(config('services.bkash.base_uri')=='https://tokenized.sandbox.bka.sh/v1.2.0-beta' ) selected @endif>
                                Sandbox URL</option>
                        </select>
                        @error('bkash_base_uri')
                        <p class="text-danger">{{ $errors->first('bkash_base_uri') }}</p>
                        @enderror
                    </div>
                </div>
            </div>
        </div>
    </div>

FinanceSettingController

Past Line Number 44 - 52

    'bkash_enable'       => 'sometimes|required',
    'bkash_subscription' => 'sometimes|required',
    'bkash_app_key'      => 'required_if:enable-bkash,on',
    'bkash_app_secret'   => 'required_if:enable-bkash,on',
    'bkash_username'     => 'required_if:enable-bkash,on',
    'bkash_password'     => 'required_if:enable-bkash,on',
    'bkash_base_uri'     => 'required_if:enable-bkash,on',

Past Line Number 129 - 439

    $this->storeConfiguration('BKASH_ENABLE', request('bkash_enable'));
    $this->storeConfiguration('BKASH_SUBSCRIPTION', request('bkash_subscription'));
    $this->storeConfiguration('BKASH_APP_KEY', request('bkash_app_key'));
    $this->storeConfiguration('BKASH_APP_SECRET', request('bkash_app_secret'));
    $this->storeConfiguration('BKASH_USERNAME', request('bkash_username'));
    $this->storeConfiguration('BKASH_PASSWORD', request('bkash_password'));
    $this->storeConfiguration('BKASH_BASE_URI', request('bkash_base_uri'));

Past Line Number 197 - 209

    # Enable/Disable Payment Gateways
    if (request('bkash_enable') == 'on') {
        $bkash = PaymentPlatform::where('name', 'Bkash')->first();
        $bkash->enabled = 1;
        $bkash->save();

    } else {
        $bkash = PaymentPlatform::where('name', 'Bkash')->first();
        $bkash->enabled = 0;
        $bkash->save();
    }

Past Line Number 296 - 309

    # Enable/Disable Payment Gateways Subscription
    // BKASH -Subscription Enable
    if (request('bkash_subscription') == 'on') {
        $bkash = PaymentPlatform::where('name', 'Bkash')->first();
        $bkash->subscriptions_enabled = 1;
        $bkash->save();

    } else {
        $bkash = PaymentPlatform::where('name', 'Bkash')->first();
        $bkash->subscriptions_enabled = 0;
        $bkash->save();
    }

PaymentController

Past Line Number 627

public function approvedBkash(Request $request)
{
    if (session()->has('paymentPlatformID'))  {
        $paymentPlatform = $this->paymentPlatformResolver->resolveService(session()->get('paymentPlatformID'));

        return $paymentPlatform->handleApproval($request);
    }
    if (session()->has('subscriptionPlatformID'))  {
        $paymentPlatform = $this->paymentPlatformResolver->resolveService(session()->get('subscriptionPlatformID'));

        return $paymentPlatform->handleApproval($request);
    }

    toastr()->error(__('There was an error while retrieving payment gateway. Please try again'));
    return redirect()->back();
}

services

Past Line Number 208

'bkash' => [
    "enable"       => env("BKASH_ENABLE", true),
    "subscription" => env("BKASH_SUBSCRIPTION", true),
    "app_key"      => env("BKASH_APP_KEY", "4f6o0cjiki2rfm34kfdadl1eqq"),
    "app_secret"   => env("BKASH_APP_SECRET", "2is7hdktrekvrbljjh44ll3d9l1dtjo4pasmjvs5vl5qr3fug4b"),
    "username"     => env("BKASH_USERNAME", "sandboxTokenizedUser02"),
    "password"     => env("BKASH_PASSWORD", "sandboxTokenizedUser02@12345"),
    "base_uri"     => env("BKASH_BASE_URI", "https://tokenized.sandbox.bka.sh/v1.2.0-beta"),
    "callback"     => env("BKASH_callback", ''),
    'class'        => App\Services\BkashService::class,
],

BkashService

Create new service named #BkashService.php

<?php

namespace App\Services;

use Carbon\Carbon;
use App\Models\User;
use App\Models\Payment;
use App\Models\Setting;
use App\Models\Subscriber;
use App\Models\PrepaidPlan;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use App\Events\PaymentProcessed;
use App\Models\SubscriptionPlan;
use Illuminate\Support\Facades\URL;
use Spatie\Backup\Listeners\Listener;
use App\Traits\ConsumesExternalServiceTrait;

class BkashService
{
    use ConsumesExternalServiceTrait;
    private $app_key;
    private $app_secret;
    private $username;
    private $password;
    private $base_url;

    public function __construct()
    {
        $this->app_key    = config('services.bkash.app_key');
        $this->app_secret = config('services.bkash.app_secret');
        $this->username   = config('services.bkash.username');
        $this->password   = config('services.bkash.password');
        $this->base_url   = config('services.bkash.base_uri');
    }


    public function authHeaders()
    {
        return array(
            'Content-Type:application/json',
            'Authorization:' .$this->grant(),
            'X-APP-Key:'. $this->app_key,
        );
    }

    public function curlWithBody($url, $header, $method, $body_data_json)
    {
        $curl = curl_init($this->base_url.$url);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $body_data_json);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
        $response = curl_exec($curl);
        curl_close($curl);
        return $response;
    }

    public function grant()
    {
        $header = array(
                'Content-Type:application/json',
                'username:'.$this->username,
                'password:'.$this->password,
                );
        $header_data_json=json_encode($header);

        $body_data = array('app_key'=> $this->app_key, 'app_secret'=> $this->app_secret);
        $body_data_json=json_encode($body_data);

        $response = $this->curlWithBody('/tokenized/checkout/token/grant', $header, 'POST', $body_data_json);

        $token = json_decode($response)->id_token;

        return $token;
    }

    public function handlePaymentSubscription(Request $request, SubscriptionPlan $plan)
    {
        $duration = ($plan->payment_frequency == 'monthly') ? 30 : 365;
        $orderID  = strtoupper("INV-".Str::random(10));

        $tax_value = (config('payment.payment_tax') > 0) ? $tax = $plan->price * config('payment.payment_tax') / 100 : 0;
        $total_value = $tax_value + $plan->price;
        $currency    = $plan->currency;

        $subscription = Subscriber::create([
            'active_until'    => Carbon::now()->addDays($duration),
            'user_id'         => auth()->user()->id,
            'plan_id'         => $plan->id,
            'status'          => 'Pending',
            'created_at'      => now(),
            'gateway'         => 'Bkash',
            'frequency'       => $plan->payment_frequency,
            'plan_name'       => $plan->plan_name,
            'words'           => $plan->words,
            'images'          => $plan->images,
            'characters'      => $plan->characters,
            'minutes'         => $plan->minutes,
            'subscription_id' => $orderID,
        ]);

        session()->put('handel_subscription', true);
        session()->put('subscription', $subscription);
        session()->put('amount', $total_value);
        session()->put('plan_id', $plan);

        return $this->createPayment($total_value, $orderID);
    }


    public function handlePaymentPrePaid(Request $request, $plan, $type)
    {
        if ($request->type == 'lifetime') {
            $plan = SubscriptionPlan::where('id', $plan)->first();
            $type = 'lifetime';
        } else {
            $plan = PrepaidPlan::where('id', $plan)->first();
            $type = 'prepaid';
        }

        $tax_value = (config('payment.payment_tax') > 0) ? $tax = $plan->price * config('payment.payment_tax') / 100 : 0;
        $total_value = $tax_value + $plan->price;
        $currency    = $plan->currency;
        $orderID     = strtoupper("INV-".Str::random(10));

        session()->put('amount', $total_value);
        session()->put('type', $type);
        session()->put('plan_id', $plan);

        return $this->createPayment($total_value, $orderID);
    }

    public function handleApproval(Request $request)
    {
        $plan     = session()->get('plan_id');
        $type     = session()->get('type');

        $order_id = '';
        if(isset($request->status) && $request->status == 'failure') {
            toastr()->error(__('Payment Failed, please try again'));
            return redirect(route('user.dashboard'));
        } elseif(isset($request->status) && $request->status == 'cancel') {
            toastr()->error(__('Payment was cancell, please try again'));
            return redirect(route('user.dashboard'));
        } elseif(isset($request->status) && $request->status == 'success') { // if payment success
            $order_id = $request->paymentID;
            $response = $this->executePayment($request->paymentID);
            $arr = json_decode($response, true);

            if(array_key_exists("statusCode", $arr) && $arr['statusCode'] != '0000') {
                toastr()->error(__($arr['statusMessage']));
                return redirect(route('user.dashboard'));
            } elseif (array_key_exists("message", $arr)) { // if execute api failed to response
                sleep(1);
                $query = $this->queryPayment($request->paymentID);
                return view('user.plans.success', compact('plan', 'order_id'));
            }

            return view('user.plans.success', compact('plan', 'order_id'));
        }

        toastr()->error(__('Payment was not successful, please try again'));
        return redirect(route('user.dashboard'));
    }

    public function createPayment($amount, $orderID = 0)
    {
        $header =$this->authHeaders();

        $website_url = URL::to("/");

        $body_data = array(
            'mode'                  => '0011',
            'payerReference'        => ' ',
            'callbackURL'           => route('user.payments.approved.bkash'),
            'amount'                => $amount ? $amount : 10,
            'currency'              => 'BDT',
            'intent'                => 'sale',
            // 'merchantInvoiceNumber' => "INV-".Str::random(8)// you can pass here OrderID
            'merchantInvoiceNumber' => $orderID
        );
        $body_data_json=json_encode($body_data);

        $response = $this->curlWithBody('/tokenized/checkout/create', $header, 'POST', $body_data_json);

        return redirect((json_decode($response)->bkashURL));
    }
    public function executePayment($paymentID)
    {

        $header =$this->authHeaders();

        $body_data = array(
            'paymentID' => $paymentID
        );
        $body_data_json=json_encode($body_data);

        $response = $this->curlWithBody('/tokenized/checkout/execute', $header, 'POST', $body_data_json);

        $res_array = json_decode($response, true);

        if(isset($res_array['trxID'])) {
            // your database insert operation
            $this->dboperation($paymentID);
        }

        return $response;
    }

    public function queryPayment($paymentID)
    {

        $header =$this->authHeaders();

        $body_data = array(
            'paymentID' => $paymentID,
        );
        $body_data_json=json_encode($body_data);

        $response = $this->curlWithBody('/tokenized/checkout/payment/status', $header, 'POST', $body_data_json);

        $res_array = json_decode($response, true);

        if(isset($res_array['trxID'])) {
            // your database insert operation
            $this->dboperation($paymentID);
        }

        return $response;
    }

    public function dboperation($paymentID)
    {
        $plan                = session()->get('plan_id');
        $type                = session()->get('type');
        $amount              = session()->get('amount');
        $subscription        = session()->has('subscription')?session()->get('subscription'):null;

        $user = User::where('id', auth()->user()->id)->first();

        if ($type == 'lifetime') {
            $days = 18250;
            $subscription = Subscriber::create([
                'user_id'         => auth()->user()->id,
                'plan_id'         => $plan->id,
                'status'          => 'Active',
                'created_at'      => now(),
                'gateway'         => 'Bkash',
                'frequency'       => 'lifetime',
                'plan_name'       => $plan->plan_name,
                'words'           => $plan->words,
                'images'          => $plan->images,
                'characters'      => $plan->characters,
                'minutes'         => $plan->minutes,
                'subscription_id' => $paymentID,
                'active_until'    => Carbon::now()->addDays($days),
            ]);
        }

        if (session()->has('handel_subscription') && session()->get('handel_subscription') == true && $subscription != null) {
            $subscription->update([
                'status'          => 'Active',
                'subscription_id' => $paymentID,
            ]);
        }

        $record_payment             = new Payment();
        $record_payment->user_id    = auth()->user()->id;
        $record_payment->order_id   = $paymentID;
        $record_payment->plan_id    = $plan->id;
        $record_payment->plan_name  = $plan->plan_name;
        $record_payment->price      = $amount;
        $record_payment->currency   = $plan->currency;
        $record_payment->gateway    = 'Bkash';
        $record_payment->frequency  = $type;
        $record_payment->status     = 'completed';
        $record_payment->words      = $plan->words;
        $record_payment->images     = $plan->images;
        $record_payment->characters = $plan->characters;
        $record_payment->minutes    = $plan->minutes;
        $record_payment->save();

        $user = User::where('id', auth()->user()->id)->first();

        if ($type == 'lifetime') {
            $group = (auth()->user()->hasRole('admin'))? 'admin' : 'subscriber';
            $user->syncRoles($group);
            $user->group             = $group;
            $user->plan_id           = $plan->id;
            $user->total_words       = $plan->words;
            $user->total_images      = $plan->images;
            $user->total_chars       = $plan->characters;
            $user->total_minutes     = $plan->minutes;
            $user->available_words   = $plan->words;
            $user->available_images  = $plan->images;
            $user->available_chars   = $plan->characters;
            $user->available_minutes = $plan->minutes;
        } else {
            $user->available_words_prepaid   = $user->available_words_prepaid + $plan->words;
            $user->available_images_prepaid  = $user->available_images_prepaid + $plan->images;
            $user->available_chars_prepaid   = $user->available_chars_prepaid + $plan->characters;
            $user->available_minutes_prepaid = $user->available_minutes_prepaid + $plan->minutes;
        }

        $user->save();

        event(new PaymentProcessed(auth()->user()));
    }

}

bkash

get any png bkash logo from online.

Payment Platform

INSERT INTO `payment_platforms` (`id`, `name`, `image`, `enabled`, `subscriptions_enabled`, `created_at`, `updated_at`) VALUES (NULL, 'Bkash', 'img/payments/bkash.png', '1', '1', NULL, NULL);

Env Update

Past Line Number 142

# BKASH
BKASH_ENABLE=
BKASH_SUBSCRIPTION=
BKASH_APP_KEY=
BKASH_APP_SECRET=
BKASH_USERNAME=
BKASH_PASSWORD=
BKASH_BASE_URI=
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment