C

CodeXsell Merchant Store

Order Reference: #ORD-2026-9048

Checkout Demo

Items in your cart

Premium Game Credit Topup (100 Coins)

Delivery: Instant digital delivery to user account

10.00 BDT

Customer Billing Information

Name: Asif Arman Saikot
Mobile: 01719364298
💡 New Checkout Flow: Clicking Complete Order no longer redirects away from this website. Instead, an AJAX request contacts Laravel, fetches pp_url, and opens the secure ZayanPay modal directly on top of this page!

Select Payment Provider

Subtotal 10.00 BDT
Total Amount Due 10.00 BDT

🔒 256-Bit SSL Encrypted & Protected

Complete Your Payment

Secure & instant payment to get your service

Codex Seller

TrxID: 63254057790486...
Expires in 14:54
10.00 BDT
Subtotal 10.00 BDT
Total Amount 10.00 BDT
Customer Details
Asif Arman Saikot
01719364298
Please complete the payment within time.
Your order will be cancelled automatically after the expiry time.

Choose Payment Method

Select your preferred payment option

All transactions are secure
Available Personal Wallets (2)
Instant Automated MFS
Bkash Personal
Bkash Personal
Nagad Personal
Nagad Personal
Trusted
C

Codex Seller

SECURE CHECKOUT
bKash Logo

Your bKash Account

Enter the bKash number you want to pay from

Make sure the number is correct before proceeding.
C

Codex Seller

SECURE CHECKOUT

Send Money

Gateway Logo
āĻŦāĻŋāĻ•āĻžāĻļ
ā§ŗ āĻŦā§āϝāĻžāϞ⧇āĻ¨ā§āϏ āĻĻ⧇āϖ⧁āύ
ā§§
āφāĻĒāύāĻžāϰ āĻŦāĻŋāĻ•āĻžāĻļ āĻ…ā§āϝāĻžāĻĒ āĻĨ⧇āϕ⧇ āϏ⧇āĻ¨ā§āĻĄ āĻŽāĻžāύāĻŋ āύāĻŋāĻ°ā§āĻŦāĻžāϚāύ āĻ•āϰ⧁āύ
⧍
āύāĻŋāĻšā§‡āϰ āĻŦāĻŋāĻ•āĻžāĻļ āĻĒāĻžāĻ°ā§āϏ⧋āύāĻžāϞ āύāĻžāĻŽā§āĻŦāĻžāϰ āĻ•āĻĒāĻŋ āĻ•āϰ⧁āύ
ā§Š
āϟāĻžāĻ•āĻžāϰ āĻĒāϰāĻŋāĻŽāĻžāĻŖ āĻ•āĻĒāĻŋ āĻ•āϰ⧇ āϏ⧇āĻ¨ā§āĻĄ āĻŽāĻžāύāĻŋ āĻ•āϰ⧁āύ
BKASH PERSONAL NUMBER
01719364298
AMOUNT TO SEND
10.00 BDT
Time Remaining: 00:55
Waiting for payment... Checking automatically

Payment Successful!

Your order #ORD-2026-9048 has been verified and completed automatically.

Merchant Codex Seller
Transaction ID (TrxID) 9J27KLA19M
Sender Mobile 01719364298
Payment Gateway bKash Personal (Automation)
Verification Method Companion App Auto-Match
Total Paid 10.00 BDT

Technical Architecture & Integration Specifications

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);
    }
}
Copied to clipboard