PAYING WITH
bKash
Order Reference: #ORD-2026-9048
Delivery: Instant digital delivery to user account
pp_url, and opens the secure ZayanPay modal directly on top of this page!
đ 256-Bit SSL Encrypted & Protected
Secure & instant payment to get your service
Select your preferred payment option
Enter the bKash number you want to pay from
Your order #ORD-2026-9048 has been verified and completed automatically.
Reference documentation for Laravel Backend, Companion Android App verification, ZayanPay API V2, and iframe security headers.
<?php
declare(strict_types=1);
namespace App\Http\Controllers;
use App\Models\Order;
use App\Services\OrderService;
use App\Services\ZayanPayService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Log;
class ZayanPayController extends Controller
{
public function __construct(
private ZayanPayService $zayanpayService,
private OrderService $orderService
) {}
/**
* 1. AJAX Payment Creation (No redirect, returns pp_id & pp_url for modal)
* POST /checkout/zayanpay/create
*/
public function createAjax(Request $request, Order $order): JsonResponse
{
if ($order->user_id !== auth()->id()) {
return response()->json(['status' => 'error', 'message' => 'Unauthorized'], 403);
}
if ($order->isPaid()) {
return response()->json(['status' => 'already_paid', 'redirect_url' => route('checkout.success', $order)]);
}
try {
$callbackUrl = route('zayanpay.callback', ['order' => $order->uuid]);
$cancelUrl = route('checkout.payment', ['order' => $order->uuid]);
$response = $this->zayanpayService->createCharge($order, $callbackUrl, $cancelUrl);
// Store payment reference
$order->update([
'payment_provider' => 'ZayanPay',
'zayanpay_payment_id' => $response['pp_id'] ?? null,
'payment_status' => 'pending',
'payment_details' => json_encode($response),
]);
return response()->json([
'status' => 'success',
'pp_id' => $response['pp_id'],
'pp_url' => $response['pp_url'],
'expires_at' => $response['expires_at'] ?? now()->addMinutes(15)->toIso8601String(),
]);
} catch (\Exception $e) {
Log::error('ZayanPay AJAX init failed: ' . $e->getMessage());
return response()->json(['status' => 'error', 'message' => $e->getMessage()], 500);
}
}
/**
* 2. Webhook Notification from ZayanPay backend
* POST /zayanpay/webhook
*/
public function webhook(Request $request): JsonResponse
{
$ppId = $request->input('pp_id') ?? $request->input('payment_id');
if (!$ppId) {
return response()->json(['status' => 'error', 'message' => 'Missing payment identifier'], 400);
}
// Server-to-server verification check
$verification = $this->zayanpayService->verifyPayment($ppId);
if ($verification['status'] === 'completed') {
$order = Order::where('zayanpay_payment_id', $ppId)->first();
if ($order && !$order->isPaid()) {
$order->update([
'payment_status' => 'completed',
'paid_at' => now(),
]);
$this->orderService->completeOrder($order, $ppId);
// Triggers digital access / email notification
}
return response()->json(['status' => 'ok']);
}
return response()->json(['status' => 'unverified'], 422);
}
}
pp-gateways (ā§Ēā§ŽāĻāĻŋ āĻā§āĻāĻā§ā§ āϞā§āĻā§)Directory path: pp-content/pp-modules/pp-gateways/ â āĻĒā§āϰāϤāĻŋāĻāĻŋ āĻā§āĻāĻā§ā§āϰ āĻ
āĻĢāĻŋāϏāĻŋā§āĻžāϞ āĻ āĻāϏāϞ āϞā§āĻā§ āϤāĻžāϞāĻŋāĻāĻž