آنچه در این مقاله میخوانید [پنهانسازی]
اگر به دنبال راه اندازی تراکنش های وبسایت خود هستید، مهم است مسیر درخواست تا تایید و ثبت نتیجه را شفاف بسازید. در این راهنما، با تمرکز بر پرداخت آنلاین در لاراول، از انتخاب نوع درگاه تا پیاده سازی گردش تراکنش، امنیت وبهوک، ذخیره وضعیت و مدیریت خطاها را به صورت کاربردی مرور می کنیم تا یک تجربه پرداخت سریع و قابل اعتماد ارائه دهید.
سرفصل های مقاله
- انتخاب درگاه و طراحی معماری تراکنش
- پیش نیازها و آماده سازی پروژه
- ساخت جدول پرداخت ها
- تعریف مسیرها و کنترلر
- تنظیمات امنیتی پایه
- پیاده سازی فرایند پرداخت و بازگشت
- نمونه کد آغاز پرداخت
- نمونه کد بازگشت و تایید نهایی
- نکات امنیتی و پایداری
- رایج ترین خطاها و راه حل ها
- بهبود تجربه کاربری
- پیکربندی و محیط آزمایشی
- جمع بندی
انتخاب درگاه و طراحی معماری تراکنش
پیش از نوشتن کد، نقشه کلی فرایند را مشخص کنید. الگوی استاندارد شامل ایجاد رکورد پرداخت در حالت در انتظار، درخواست توکن از درگاه، هدایت کاربر به صفحه پرداخت، بازگشت کاربر به آدرس بازگشت، تایید نهایی سمت سرور و تغییر وضعیت پرداخت است. این چرخه باید ایدمپوتنت باشد تا تکرار درخواست ها باعث دوباره ثبت موفقیت نشود.
در انتخاب درگاه، معیارهایی مثل هزینه، اسناد فنی روشن، پشتیبانی از محیط آزمایشی، زمان تایید تراکنش، امکانات گزارش گیری و کیفیت پشتیبانی اهمیت دارد. برای شروع، داشتن SDK یا API مستند و وبهوک امن اولویت اصلی است.
- توکن پرداخت: کدی که برای هدایت کاربر به صفحه پرداخت استفاده می شود.
- آدرس بازگشت: مسیر برنامه شما که درگاه پس از پرداخت کاربر را به آن بر می گرداند.
- وبهوک یا تایید سمت سرور: بررسی نهایی موفقیت تراکنش از طریق API درگاه.
- وضعیت ها: در انتظار، موفق، ناموفق، لغو شده، بازگشت وجه.
- ایدمپوتنسی: جلوگیری از ثبت تکراری نتیجه واحد تراکنش.
برای درک بهتر تفاوت گزینه های درگاه، این تقسیم بندی کمک می کند:
| گزینه درگاه | برای چه مناسب است |
|---|---|
| درگاه مستقیم بانکی | وبسایت های با حجم تراکنش بالا و نیاز به کارمزد کمتر و یکپارچگی مستقیم |
| درگاه واسط | استارتاپ ها و فروشگاه هایی که راه اندازی سریع، داشبورد و گزارش گیری ساده می خواهند |
| درگاه بین المللی | محصولات ارزی یا بازارهای خارج از کشور با نیاز به کارت های بین المللی |
پس از انتخاب، ویژگی های امنیتی ارائه شده توسط درگاه مانند امضا، کلید مخفی و IP های مجاز را بررسی و یادداشت کنید تا در مرحله پیاده سازی به کار آید.
پیش نیازها و آماده سازی پروژه
برای شروع پیاده سازی عملی پرداخت آنلاین در لاراول لازم است چند تنظیم پایه را انجام دهید. مهم ترین موارد شامل فعال بودن HTTPS روی دامنه اصلی، تنظیم APP_URL در فایل env، همگام بودن منطقه زمانی سیستم و بانک، و آماده بودن پایگاه داده است. توصیه می شود مقادیر پولی را به صورت عدد صحیح ذخیره کنید تا از خطاهای اعشاری جلوگیری شود.
- SSL فعال برای جلوگیری از هشدارهای امنیتی و الزامات بسیاری از درگاه ها
- تنظیم APP_URL و آدرس بازگشت دقیق در پنل درگاه
- ایجاد جدول پرداخت ها و نگهداری لاگ تراکنش
- فعال بودن سیستم لاگ و مانیتورینگ خطا برای عیب یابی
نصب وابستگی مورد نیاز برای ارسال درخواست HTTP به درگاه:
composer require guzzlehttp/guzzle
ساخت جدول پرداخت ها
یک جدول ساده با وضعیت، شناسه مرجع و اطلاعات متا بسازید:
php artisan make:migration create_payments_table
public function up()
{
Schema::create('payments', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
$table->unsignedBigInteger('order_id')->nullable();
$table->unsignedBigInteger('amount'); // ذخیره به صورت عدد صحیح
$table->string('currency', 8)->default('IRR');
$table->string('authority')->nullable(); // توکن یا کد پیگیری اولیه
$table->string('ref_id')->nullable()->unique(); // شناسه مرجع نهایی
$table->string('status')->default('pending'); // pending, paid, failed, canceled, refunded
$table->json('meta')->nullable(); // اطلاعات تکمیلی درگاه
$table->timestamp('paid_at')->nullable();
$table->timestamps();
$table->index(['order_id', 'status']);
});
}
تعریف مسیرها و کنترلر
دو مسیر اصلی کافی است: آغاز پرداخت و بازگشت از درگاه. ابتدای کار، مسیر بازگشت را در پنل درگاه ثبت کنید.
// routes/web.php
use App\Http\Controllers\PaymentController;
Route::post('/payments/start', [PaymentController::class, 'start'])->name('payments.start');
Route::match(['get','post'], '/payments/callback', [PaymentController::class, 'callback'])->name('payments.callback');
php artisan make:controller PaymentController
تنظیمات امنیتی پایه
در بسیاری از موارد، لازم است مسیر بازگشت از بررسی CSRF مستثنا شود و به جای آن از امضا یا کلید مخفی درگاه استفاده کنید. این کار را با احتیاط انجام دهید:
// app/Http/Middleware/VerifyCsrfToken.php
protected $except = [
'payments/callback',
];
اگر درگاه امضا یا هدر امنیتی ارسال می کند، یک میان افزار برای اعتبارسنجی آن اضافه کنید.
پیاده سازی فرایند پرداخت و بازگشت
اکنون بخش اصلی کار یعنی پیاده سازی چرخه تراکنش را اجرا می کنیم. هدف این است که از لحظه ایجاد درخواست تا ثبت نهایی نتیجه، هیچ ابهامی در وضعیت پرداخت باقی نماند و خطاها قابل پیگیری باشند.
- ایجاد رکورد در جدول پرداخت با وضعیت در انتظار و نگهداری مبلغ و سفارش.
- درخواست توکن از درگاه و ذخیره authority در رکورد پرداخت.
- هدایت کاربر به آدرس پرداخت درگاه.
- دریافت بازگشت کاربر و بررسی اولیه پارامترهای ارسالی.
- ارسال درخواست تایید سمت سرور به درگاه و دریافت ref_id.
- به روزرسانی وضعیت پرداخت و ثبت زمان موفقیت.
- اجرای رویدادهای پس از پرداخت مانند صدور فاکتور و ارسال اعلان.
نمونه کد آغاز پرداخت
// app/Http/Controllers/PaymentController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use App\Models\Payment;
use Carbon\Carbon;
class PaymentController extends Controller
{
public function start(Request $request)
{
$validated = $request->validate([
'order_id' => 'nullable|integer',
'amount' => 'required|integer|min:1000',
'callback_url' => 'nullable|url'
]);
// ایجاد رکورد پرداخت
$payment = Payment::create([
'user_id' => optional($request->user())->id,
'order_id' => $validated['order_id'] ?? null,
'amount' => $validated['amount'],
'currency' => 'IRR',
'status' => 'pending',
]);
// درخواست توکن از درگاه نمونه
$gatewayEndpoint = config('services.gateway.request_url');
$merchantId = config('services.gateway.merchant_id');
$callback = $validated['callback_url'] ?? route('payments.callback');
$response = Http::asJson()->post($gatewayEndpoint, [
'merchant_id' => $merchantId,
'amount' => $payment->amount,
'callback_url' => $callback,
'order_id' => (string) $payment->id,
]);
if ($response->failed() || empty($response['authority'])) {
$payment->update(['status' => 'failed', 'meta' => ['reason' => 'request_failed']]);
return back()->withErrors('امکان اتصال به درگاه وجود ندارد.');
}
$payment->update(['authority' => $response['authority']]);
// هدایت به صفحه پرداخت
$redirectUrl = rtrim(config('services.gateway.pay_url'), '/') . '/' . $response['authority'];
return redirect()->away($redirectUrl);
}
نمونه کد بازگشت و تایید نهایی
public function callback(Request $request)
{
$authority = $request->input('authority');
$status = $request->input('status'); // مثلا success یا failed
$signature = $request->header('X-Gateway-Signature'); // در صورت وجود
$payment = Payment::where('authority', $authority)->firstOrFail();
// جلوگیری از دوباره کاری
if ($payment->status === 'paid') {
return redirect()->route('orders.show', $payment->order_id)->with('status', 'قبلا پرداخت شده است.');
}
// تایید سمت سرور
$verifyEndpoint = config('services.gateway.verify_url');
$merchantId = config('services.gateway.merchant_id');
$verify = Http::asJson()->post($verifyEndpoint, [
'merchant_id' => $merchantId,
'authority' => $authority,
'amount' => $payment->amount,
]);
if ($verify->ok() && ($verify['status'] ?? null) === 'paid' && !empty($verify['ref_id'])) {
$payment->update([
'ref_id' => $verify['ref_id'],
'status' => 'paid',
'paid_at' => now(),
'meta' => ['raw' => $verify->json()]
]);
// رویدادهای پس از پرداخت: تکمیل سفارش، صدور فاکتور، ایمیل
// event(new PaymentSucceeded($payment));
return redirect()->route('orders.show', $payment->order_id)->with('status', 'پرداخت با موفقیت انجام شد.');
}
$payment->update(['status' => 'failed', 'meta' => ['raw' => $verify->json()]]);
return redirect()->route('orders.show', $payment->order_id)->withErrors('پرداخت ناموفق بود یا تایید نشد.');
}
}
نکات امنیتی و پایداری
- اعتبارسنجی مبلغ: مقدار ارسالی از درگاه را نادیده بگیرید و همواره مبلغ را از رکورد داخلی بخوانید.
- امضای درخواست: اگر درگاه هدر امضا یا هش می فرستد، آن را با کلید مخفی مقایسه کنید.
- ایدمپوتنسی: روی ستون ref_id ایندکس یکتا بگذارید و قبل از اعمال عملیات پس از پرداخت، وضعیت رکورد را بررسی کنید.
- مدیریت زمان: اختلاف ساعت سرور با بانک می تواند مشکل ساز شود؛ منطقه زمانی را یکسان کنید.
- لاگ ساختاریافته: پاسخ های خام درگاه را در meta ذخیره کنید تا در پشتیبانی و دیباگ کمک کند.
رایج ترین خطاها و راه حل ها
- بازگشت بدون authority: معمولا به دلیل تنظیم نادرست آدرس بازگشت یا منقضی شدن جلسه کاربر است.
- موفق در صفحه بانک ولی ناموفق در سایت: تایید سمت سرور یا دسترسی شبکه به سرویس درگاه مشکل دارد؛ لاگ و فایروال را بررسی کنید.
- ثبت چند باره پرداخت: عدم بررسی وضعیت پیش از اعمال عملیات نهایی؛ کنترل ایدمپوتنسی را اضافه کنید.
- مابه تفاوت واحد پول: برخی درگاه ها ریال و برخی تومان گزارش می دهند؛ واحد را یکپارچه سازی کنید.
بهبود تجربه کاربری
- نمایش تایمر یا وضعیت در حال پردازش هنگام بازگشت کاربر تا پایان تایید سمت سرور.
- ارسال ایمیل یا نوتیفیکیشن پس از موفقیت به همراه شماره پیگیری ref_id.
- صفحه رسید با امکان دانلود فاکتور و مشاهده جزئیات سفارش.
پیکربندی و محیط آزمایشی
مقادیر درگاه را در فایل env قرار دهید و با config/services.php بارگذاری کنید تا بین محیط توسعه و تولید قابل جداسازی باشد. در محیط توسعه از sandbox استفاده کنید و مسیر بازگشت را روی دامنه تست تنظیم نمایید.
// .env
GATEWAY_MERCHANT_ID=your-merchant-id
GATEWAY_REQUEST_URL=https://gateway.example.com/request
GATEWAY_VERIFY_URL=https://gateway.example.com/verify
GATEWAY_PAY_URL=https://gateway.example.com/pay
// config/services.php
'gateway' => [
'merchant_id' => env('GATEWAY_MERCHANT_ID'),
'request_url' => env('GATEWAY_REQUEST_URL'),
'verify_url' => env('GATEWAY_VERIFY_URL'),
'pay_url' => env('GATEWAY_PAY_URL'),
],
برای پوشش پذیری خطاها در تولید، تایید نهایی را در یک Job صف قرار دهید تا در صورت اختلال موقت شبکه، با سیاست تکرار خودکار دوباره امتحان شود. همچنین برای سفارش های حساس، ساز و کار بازبینی دستی در پنل ادمین در نظر بگیرید.
جمع بندی
برای اجرای مطمئن و توسعه پذیر پرداخت آنلاین در لاراول لازم است از یک چرخه روشن شامل ایجاد رکورد داخلی، دریافت توکن، هدایت کاربر، تایید سمت سرور و به روزرسانی وضعیت پیروی کنید. با ذخیره دقیق لاگ، کنترل ایدمپوتنسی، اعتبارسنجی مبلغ و تنظیم درست محیط، خطاها به حداقل می رسد و تجربه کاربری بهبود خواهد یافت. در کنار این اصول، استفاده از محیط آزمایشی و مانیتورینگ مستمر کیفیت عملیات مالی شما را پایدار و قابل اتکا نگه می دارد.






