آموزش اتصال ترب‌پی (TorobPay) به لاراول

در این آموزش، اتصال کامل درگاه پرداخت ترب‌پی به Laravel را پیاده‌سازی می‌کنیم؛ شامل:

  • دریافت Access Token
  • ساخت لینک پرداخت
  • Callback
  • Verify
  • Settle
  • ذخیره تراکنش
  • رفع خطاهای رایج مثل 419 و verify نشدن

ساختار پروژه

در این آموزش از این بخش‌ها استفاده می‌کنیم:

app/Services/TorobPayService.php
app/Http/Controllers/PaymentsController.php
routes/web.php
config/services.php

تنظیمات config/services.php

ابتدا تنظیمات ترب را اضافه کنید.

'torob' => [

    'base_url' => env('TOROB_BASE_URL'),

    'client_id' => env('TOROB_CLIENT_ID'),

    'client_secret' => env('TOROB_CLIENT_SECRET'),

    'username' => env('TOROB_USERNAME'),

    'password' => env('TOROB_PASSWORD'),
],

تنظیمات .env

TOROB_BASE_URL=https://integration.torob.com
TOROB_CLIENT_ID=xxxxxxxx
TOROB_CLIENT_SECRET=xxxxxxxx
TOROB_USERNAME=xxxxxxxx
TOROB_PASSWORD=xxxxxxxx

ساخت سرویس ترب

فایل:

app/Services/TorobPayService.php

دریافت Access Token

public function getAccessToken()
{
    return Cache::remember(
        'torob_token_' . md5(config('services.torob.client_id')),
        3500,
        function () {

            $basic = base64_encode(
                config('services.torob.client_id')
                . ':'
                . config('services.torob.client_secret')
            );

            $res = Http::withHeaders([
                'Authorization' => 'Basic ' . $basic,
                'Accept' => 'application/json',
            ])->post(
                $this->baseUrl() . '/api/online/v1/oauth/token',
                [
                    'username' => config('services.torob.username'),
                    'password' => config('services.torob.password'),
                ]
            );

            if (!$res->successful()) {
                throw new Exception($res->body());
            }

            return $res->json()['access_token'];
        }
    );
}

ساخت پرداخت

public function createPayment($order, $amount)
{
    $token = $this->getAccessToken();

    $res = Http::withToken($token)
        ->acceptJson()
        ->post(
            $this->baseUrl() . '/api/online/payment/v1/token',
            [

                "amount" => (int)$amount,

                "paymentMethodTypeDto" => "ONLINE_CREDIT",

                "returnURL" => route(
                    'torob.callback',
                    ['order_id' => $order->id]
                ),

                "transactionId" => (string)$order->id,

                "cartList" => [
                    [
                        "cartId" => (string)$order->id,

                        "totalAmount" => (int)$amount,

                        "shippingAmount" => 0,

                        "cartItems" => [
                            [
                                "id" => (string)$order->id,

                                "name" => "Order #" . $order->id,

                                "count" => 1,

                                "amount" => (int)$amount,

                                "category" => "general"
                            ]
                        ]
                    ]
                ]
            ]
        );

    if (!$res->successful()) {
        throw new Exception($res->body());
    }

    return $res->json()['response'];
}

Verify پرداخت

public function verifyPayment($paymentToken)
{
    $token = $this->getAccessToken();

    $res = Http::withToken($token)
        ->acceptJson()
        ->post(
            $this->baseUrl() . '/api/online/payment/v1/verify',
            [
                "paymentToken" => $paymentToken
            ]
        );

    if (!$res->successful()) {
        throw new Exception($res->body());
    }

    return $res->json()['response'];
}

Settle پرداخت

public function settlePayment($paymentToken)
{
    $token = $this->getAccessToken();

    $res = Http::withToken($token)
        ->acceptJson()
        ->post(
            $this->baseUrl() . '/api/online/payment/v1/settle',
            [
                "paymentToken" => $paymentToken
            ]
        );

    if (!$res->successful()) {
        throw new Exception($res->body());
    }

    return $res->json()['response'];
}

ساخت Route Callback

فایل:

routes/web.php
Route::match(
    ['get', 'post'],
    '/payment/torob/callback',
    [PaymentsController::class, 'torobResult']
)->name('torob.callback');

غیرفعال کردن CSRF برای Callback

فایل:

app/Http/Middleware/VerifyCsrfToken.php
protected $except = [
    'payment/torob/callback',
];

متد Purchase

if ($request->gateway === 'torob') {

    $torob = new TorobPayService();

    // تبدیل تومان به ریال
    $torobAmount = (int)$amount * 10;

    $result = $torob->createPayment($order, $torobAmount);

    $paymentToken = $result['paymentToken'];

    $paymentUrl = $result['paymentPageUrl'];

    $transaction->transaction_id = $paymentToken;

    $transaction->payment_token = $paymentToken;

    $transaction->save();

    return redirect()->away($paymentUrl);
}

Callback و Verify

public function torobResult(Request $request)
{
    try {

        $orderId = $request->order_id;

        $transaction = Transaction::where('order_id', $orderId)
            ->latest()
            ->first();

        if (!$transaction) {
            throw new \Exception('Transaction not found');
        }

        $paymentToken = $transaction->payment_token;

        $torob = new TorobPayService();

        /*
        |--------------------------------------------------------------------------
        | VERIFY
        |--------------------------------------------------------------------------
        */

        $verify = $torob->verifyPayment($paymentToken);

        /*
        |--------------------------------------------------------------------------
        | SETTLE
        |--------------------------------------------------------------------------
        */

        $settle = $torob->settlePayment($paymentToken);

        /*
        |--------------------------------------------------------------------------
        | SUCCESS
        |--------------------------------------------------------------------------
        */

        $transaction->status = 2;

        $transaction->transaction_result = json_encode([
            'verify' => $verify,
            'settle' => $settle
        ]);

        $transaction->save();

        return redirect('/result?status=2');

    } catch (\Exception $e) {

        Log::error('Torob Error', [
            'message' => $e->getMessage()
        ]);

        return redirect('/result?status=failed');
    }
}

ساخت جدول تراکنش‌ها

نمونه فیلدهای لازم:

Schema::create('transactions', function (Blueprint $table) {

    $table->id();

    $table->unsignedBigInteger('order_id');

    $table->string('transaction_id')->nullable();

    $table->string('payment_token')->nullable();

    $table->longText('transaction_result')->nullable();

    $table->tinyInteger('status')->default(0);

    $table->timestamps();
});

وضعیت‌های تراکنش

وضعیتمعنی
0در انتظار پرداخت
1ناموفق
2موفق

خطاهای رایج

ارور 419

دلیل:

CSRF middleware

راه‌حل:

protected $except = [
    'payment/torob/callback',
];

Verify نشدن

دلیل:

استفاده از transaction_id اشتباه به جای payment_token

اشتباه:

$transaction->transaction_id

درست:

$transaction->payment_token

Callback خالی

در ترب‌پی معمولاً callback پارامتر خاصی برنمی‌گرداند.

به همین دلیل بهتر است order_id را داخل returnURL ارسال کنید.

پاک کردن Cache لاراول

بعد از تغییرات:

php artisan optimize:clear

نتیجه نهایی

بعد از این پیاده‌سازی:

  • پرداخت ترب‌پی کامل کار می‌کند
  • verify و settle انجام می‌شود
  • callback بدون خطا اجرا می‌شود
  • از تداخل تراکنش کاربران جلوگیری می‌شود
  • ساختار سرویس تمیز و قابل توسعه خواهد بود

 

دیدگاه‌ خود را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *