برنامه نویس، کارشناس ارشد فناوری اطلاعات
ماژول اتصال به درگاه های پرداخت ایرانی برای لاراول (لاراپی)
تقریبا بزرگترین مشکلی که تمام برنامه نویس ها حداقل یک بار در طول مدت کارشون باهاش مواجه میشن، اتصال به درگاه های پرداخت هستش. هر بانکی روش خاص خودش رو برای استفاده از درگاهش داره و معمولا مستندات هم خیلی دقیق و به روز نیستند. از طرف دیگه هیچ امکان تست هم جز روی سروری که به بانک معرفی کردید وجود نداره. بدترین قسمت داستان هم زمانیه که پروژه آماده نیست و هنوز درگاه پرداخت ندارید و باید کد پرداخت رو آماده کنید! حالا ما اومدیم یک پکیج برای لاراول آماده کردیم که با کمترین زمان بتونید پرداخت آنلاین رو به پروژه خودتون استفاده کنید و اون را با banktest.ir تست کنید.
بانک تست چیه؟ سایت بانک تست تمام درگاه های پرداخت رو شبیه سازی کرده و می تونید به راحتی به جای اتصال به درگاه واقعی از بانک تست استفاده کنید. لاراپی هم این قابلیت رو پیاده سازی کرده و در زمان توسعه به صورت پیش فرض به بانک تست وصل خواهد شد.
همین ابتدا بگم که پروژه های مشابه برای لارول وجود داره ولی ما سعی کردیم این ماژول رو رو خیلی به روز تر و با معماری دقیق تر پیاده سازی کنیم. استفاده از ساختار Morph در پایگاه داده و Trait باعث شده خیلی راحت و مثل ماژول های Spatie بتونید این ماژول رو به پروژه اضافه کنید.
نصب
پروژه به صورت متن باز روی گیت هاب قرار گرفته و میتونید علاوه بر مشاهده کد و مستندات ما رو در توسعه لاراپی هم کمک کنید. همراه لاراپی یه پکیج دیگه استفاده شده به اسم XLog که یه سری قابلیت جدید به لاگ لاراول اضافه میکنه.
با این دستور آخرین نسخه از لاراپی رو به composer پروژه اضافه کنید.
composer require tartan/laravel-online-payment
این دوتا کلاس رو به config/app.php انتهای قسمت providers اضافه کنید:
Tartan\Larapay\LarapayServiceProvider::class,
Tartan\Log\XLogServiceProvider::class,
این دو خط هم به قسمت alias همون فایل اضافه کنید:
'Larapay' => Tartan\Larapay\Facades\Larapay::class,
'XLog' => Tartan\Log\Facades\XLog::class,
لاراپی یک سری assets داره که باید با این دستور اون ها رو به پروژه خودتون اضافه کنید:
php artisan vendor:publish --provider="Tartan\Larapay\LarapayServiceProvider"
بعد این دستور رو اجرا کنید تا دیتابیس لاراپی به اسم larapay_transactions توی دیتابیس ساخته بشه:
php artisan migrate
تنظیمات
اگر مراحل نصب رو تکمیل کرده باشید، فایل larapay.php به پوشه config پروژه اضافه شده. تمام کانفیگ های لاراپی توی این فایل موجوده و ما بخشی از اون رو توضیح میدیم:
برای اینکه به بانک تست وصل بشید باید حالت development و درصورتی که اتصال به بانک حالت production رو برای LARAPAY_MODE تو فایل .env انتخاب کنید
#Banktest Mode
LARAPAY_MODE=development
#Producation Mode
LARAPAY_MODE=production
اطلاعات بانک هم به این صورت باید به .env اضافه کنید. این پارامتر ها رو وقتی از بانک درگاه یا از بانک تست اکانت گرفتید در اختیار دارید. تمام این تنظیمات داخل larapay.php هستند. دو نمونه بانک سامان و ملت این شکلی هستند:
SAMAN_MERCHANT_ID=bmcf****
SAMAN_MERCHANT_PASS=98221***
MELLAT_USERNAME=user***
MELLAT_PASSWORD=80714***
MELLAT_TERMINAL_ID=747
ساخت callback route بانک
بعد از برگشت کاربر از بانک نیاز به یک route دارید و اون رو هم باید به بانک اعلام کنید که بعد از عملایت پرداخت کاربر روی اون route به سایت شما برگرده تا شما از وضعیت پرداخت با خبر بشید. برای این کار یک متد در کنترلر دلخواهتون بنویسید و براش یک route داخل مسیر route/web.php بسازید و یک اسم براش انتخاب کنید. به عنوان مثال:
Route::any('payment/callback', 'YourController@handleCallback')->name('payment.callback');
بعد از اون اسم route خودتون رو به .env اضافه کنید:
LARAPAY_PAYMENT_CALLBACK=payment.callback
با این کار لاراپی متوجه میشه که زمانی ارسال به بانک باید کدوم route رو به عنوان callback به بانک معرفی کنه. شما میتونید چندتا route مختلف داشته باشید (مثلا بانک ها رو تفکیک کنید) و زمان ارسال کاربر به بانک route مختلفی رو استفاده کنید ولی این تنظیم به صورت پیش فرض استفاده میشه.
استفاده
آماده سازی مدل
شما باید یک مدلی داشته باشید که پرداخت برای اون مدل انجام میشه. مثلا پروژه شما یک مدلی به اسم سفارش داره که قرار برای اون سفارش پرداخت انجام بشه. یا اینکه مدل کاربر میتونن اکانت خودش رو شارژ کنه که تو این حالت User میشه مدلی که قرار پرداخت براش ثبت بشه. برای این کار برای trait Payable تو کلاس مدلتون استفاده کنید. همچنین اگر سفارشتون مدل محاسبه قیمت ثابت داره، میتونید با پیاده سازی getAmount قیمتش رو به لاراپی برگردونید. درصورتی که قیمت مشخصی ندارید نیازی به این کار نیست. برای مثال:
use Tartan\Larapay\Payable;
class Order extends Model
{
use Payable;
public function getAmount(){
return intval($this->amount) * 10;
}
}
ساخت تراکنش
زمانی که کاربر شما اقدام به پرداخت میکنه، باید برای اون یک تراکنش ثبت کنید. مثلا کاربر سفارش خودش رو انتخاب میکنه و گزینه پرداخت رو میزنه. شما ابتدا سفارش رو پید میکنید و مثل مراحل زیر اقدام به ایجاد یک تراکنش می کنید:
use Tartan\Larapay\Models\Enum\Bank;
class BankController extends Controller
{
public function index()
{
//your logic and prepare your order
// ...
//if you implement getAmount() method you can set amount to null
$amount = 1200000; //Rial at least 1000
//order or user description
$description = 'I pay my order with Larapay <3';
//some additional data that you need store on transaction
$additionalData = [];
//create transaction
$transaction = $order->createTransaction(Bank::MELLAT, $amount, $description, $additionalData);
//auto submit bank form and transfer user to gateway
$autoSubmit = true;
//callback route name. if you set it on your .env file you can set this to null
$callbackRouteName = 'payment.callback';
//adapter config
$adapterConfig = [];
//generate bank form
$form = $transaction->generateForm($autoSubmit, $callbackRouteName, $adapterConfig);
}
}
شما ابتدا برای $order یک تراکنش میسازید. بعد از تراکنشتون میخواید که فرم بانک براتون درست کنه و بهتون برگردونه.
فرم ارسال به بانک
اگر دقت کرده باشید تمام سایت ها قبل از ارسال شما به بانک صفحه ای به شما نشون میدن که درحال انتقال به بانک هستید. شما هم باید همچین صفحه ای رو درست کنید و فرمی که تو مرحله قبل درست کردید رو داخل اون نشون بدید. پارامتر autoSubmit تو مرحله قبل مشخص میکنه که فرم اتوماتیک به سمت بانک پست بشه و اگر false باشه کاربر حتما باید دکمه انتقال به بانک رو بزنه.
داخل فایل view خودتون می تونید فرم رو این شکلی نمایش بدید:
<div>
{!! $form !!}
</div>
اگر دوست داشتید که فرمت فرم خروجی رو تغییر بدید میتونید از این مسیر نمونه فرم بانک خودتون رو عوض کنید: resources/views/vendor/larapy
بازگشت از بانک
بعد از اتمام مرحله پرداخت، کاربر به سمت route که در ابتدا ساخته بودیم هدایت میشه و اطلاعات تراکنش هم به این مسیر ارسال میشه. کاری که تو این مرحله می کنیم تایید وضعیت پرداخت هست. اگر تایید تراکنش با Exception رو به رو بشه یعنی پرداخت موفق نبوده و اگر هم که نه تراکنش در جواب اون به شما برمیگرده و از اون میتونید به مدل برسید:
use Illuminate\Http\Request;
use Tartan\Larapay\Facades\Larapay;
class YourController extends Controller
{
public function handleCallback(Request $request)
{
try{
$adapterConfig = [];
$transaction = Larapay::verifyTransaction($request, $adapterConfig);
$order = $transaction->model;
//transaction done. payment is successful
} catch (\Exception $e){
// transaction not complete!!!
// show error to your user
}
}
}
بعد از اینکه تراکنش با موفقیت انجام شد حالا باید سرویس خودتون رو به مشتری ارائه کنید. مثلا سفارشش رو به حالت پرداخت شده دربیارید. در صورتی که موفق به این کار نشدید، در صورتی که بانک شما قابلیت بازگشت وجه رو داشته باشه می تونید از این روش پول رو به کاربر برگردونید:
$transaction->reverseTransaction();
متد ها
مدلی که Paybel اضافه شده یکسری متد داره. برای مثال:
$order->transactions` : get all transactions of this model
$order->accomplishedTransactions`: get all accomplished transactions
$order->isPaid()`: return true if this model has at least one accomplished transaction
$order->paidAmount()`
همچنین تراکنش هم یکسری متد دارن که میتونید تو پروژه استفاده کنید:
$transaction->model`: return the model that create this transaction. for example `$order`
$transaction->reverseTransaction()`: reverse transaction and get back money to user. (if bank support reverse transaction)
$transaction->generateForm($autoSubmit = false, $callback = null)`: generate bank transfer form
$transaction->gatewayHandler()`: get gatewayHandler for advance use.
کلام آخر
تلاش ما این بوده که بتونیم ماژولی رو درست کنیم که تمام مشکلاتی که دربارش صحبت کردیم رو حل کنه. لاراپی در خیلی از پروژه ها در حاله استفاده هست و تراکنش های میلیونی داره. در صورتی که پیشنهادی دارید خوشحال میشیم روی گیت هاب پروژه با ما درمیون بذارید.
مطلبی دیگر از این انتشارات
صفحات خطای خود را با لاراول سفارشی کنید
مطلبی دیگر از این انتشارات
درباره Laravel Pipelines
مطلبی دیگر از این انتشارات
مقایسه Laravel vs Django... از دید یه لاراول کار که تازه رفته جنگو! بخش اول