فهرست محتوا
متاسفانه درگاه های بانکهای ایرانی بر اساس یک پرتوکل و api یکسان ساخته نشده اند که این ضعف باعث شده برای ارتباط با هر درگاهی نیازمند به مطالعه دقیق api و مستندات آن باشید که معمولا قطعه کد های بوجود آمده علاوه بر داشتن quality پایین و عدم پایداری ، ضعف های امنیتی نیز خواهد داشت . با اینکه تمامی درگاه های بانک های ایرانی زیر پوشش شاپرک فعالیت میکنند اما هیچ کدام از نظر کد و منطق با دیگری یکسان نیست !
حتی یک مشکل امنیتی هم در تمامی درگاهای بانک های ایرانی وجود داره که پس از اتمام خرید ، کاربر و اطلاعات خرید (نتایج !!!!) همزمان به وبسایت پذیرنده هدایت و ارسال می شوند !!!. که یک کار خیلی مسخره و میتونم بگم ناشی از بیـسوادی بانکدارهاست !!! به هر روی متاسفانه در سالیان متمادی این مشکل امنیتی وجود داشته و تاکنون اقدامی برای حل آن صورت نگرفته !
بگذریم ;
پکیجی که قصد داریم امروز به شما معرفی کنیم پکیج ارتباط با درگاه بانک های ایرانی با نام Gateway می باشد که توسط تیم لارابوک برای لاراول پیاده سازی شده است و این پکیج از پکیج دیگری با نام poolport مشتق شده است اما قسمت های مختلفی از آن بهبود یافته است و برای فریمورک لاراول پیاده سازی شده است . لازم به ذکر است این پکیج همچنان در مرحله توسعه می باشد و در صورتی اینکه خطا یا مشکل امنیتی درآن مشاهده کردید میتوانید از قسمت issue ما را مطلع سازید تا در سریعترین زمان آن را مرتفع نماییم .
در حال حاضر امکان ارتباط با بانک های زیر وجود دارد:
بانک های عضو شاپرک :
ملت
ملی (سداد)
پارسیان
پاسارگاد
سامان
بانک های واسط :
پیلاین
جهان پی
زرین پال
که متاسفانه اخیرا مطلع شدیم به دلیل اعمال محدودیت از سوی بانک مرکزی ، برخی بانک های واسط ذکر شده فیلتر شده اند .
مراحل نصب :
ابتدا دستور زیر را در ترمینال وارد نمایید
1 |
composer require larabook/gateway |
سپس به مسیر config/app.php بروید و تغییرات زیر را ایجاد نمایید :
1 2 3 4 5 6 7 8 9 10 |
'providers' => [ ... LarabookirGatewayGatewayServiceProvider::class, // <-- add this line at the end of provider array ],
'aliases' => [ ... 'Gateway' => LarabookirGatewayGateway::class, // <-- add this line at the end of aliases array ] |
توجه داشته باشید پس از اعمال دستورات بالا ، دسترسی به سرویس gateway از طریق فاساد و service container برای شما فراهم خواهد شد.
دستور آرتیسان زیر را در ترمینال اجرا نمایید تا فایل های مورد نیاز در پروژه ایجاد گردند :
1 |
php artisan vendor:publish --provider="LarabookirGatewayGatewayServiceProvider" |
نکته : اگر دستور بالا خطا داد ، کوتیشن ها (“) رو از قسمت پارامتر حذف کنید و مجددا تست کنید .
و سپس برای ایجاد جداول :
1 |
php artisan migrate |
همچنین شما میتوانید نام جدول تراکنش ها را در فایل تنظیمات در مسیر config/gateway.php تغییر نمایید .
سپس فایل config/gateway.php را باز کنید و سپس اطلاعات درگاهتان را در آن وارد نمایید .
شما میتوانید از چند روش به سرویس gateway دسترسی پیداکنید (Facade , Service container) :
1 2 3 4 |
Gateway::make(new Mellat()); // روش یک Gateway::mellat(); // روش دو app('gateway')->make(new Mellat()); // روش سه app('gateway')->mellat(); // روش چهار |
بجای کلمه “Mellat” میتوانید از اسامی بانک های دیگر نیز استفاده نمایید :
- MELLAT
- SADAD
- PARSIAN
- PASARGAD
- ZARINPAL
نمونه ساده هدایت کاربر به بانک : ابتدا یک route از نوع get به منظور هدایت کاربر به بانک ایجاد میکنیم .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Route::get('request',function(){ try {
$gateway = Gateway::mellat(); $gateway->setCallback(url('callback/from/bank')); $gateway->price(1000)->ready(); $refId = $gateway->refId(); $transID = $gateway->transactionId();
// Your code here
return $gateway->redirect();
} catch (Exception $e) {
echo $e->getMessage(); } }); |
نکاتی که در این قسمت باید به آنها توجه داشت :
- با استفاده از متد price میتوانید مقدار هزینه را به ریال وارد کنید. توجه کنید که در تمام درگاهها این مقدار باید به ریال وارد شود.
- پس از تنظیم هزینه باید متد
ready
را فراخوانی کنید. این متد چک میکند که آیا همه چیز برای متصل شدن به درگاه آماده است یا خیر. - پس از فراخوانی متد
ready
میتوانید به درگاهredirect
کنید. اما در کد بالا مشاهده میکنید که ما ابتدا مقدارrefId
را دریافت کرده و سپس به درگاه تغییر مسیر میدهیم. مقدار ref id یک مقداری است که هر درگاه برای هر عملیات پرداخت در نظر میگرد. - در صورت وقوع هر نوع خطا پکیج
Exception
برمیگرداند، به همین دلیل شما حتما باید کدهای مربوط به پکیج را در بلاک{}try{}catch
قرار دهید.
ودر مرحله بعد یک route از نوع ANY برای دریافت نتایج از بانک ایجاد نمایید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Route::any('callback/from/bank',function(){ try {
$gateway = Gateway::verify(); $trackingCode = $gateway->trackingCode(); $refId = $gateway->refId(); $cardNumber = $gateway->cardNumber();
// عملیات خرید با موفقیت انجام شده است // در اینجا کالا درخواستی را به کاربر ارائه میکنم
} catch (Exception $e) {
echo $e->getMessage(); } }); |
نکاتی که در این قسمت باید به آنها توجه داشت :
- برای تایید اینکه آیا کاربر مبلغ مورد نظر را پرداخت کرده است یا خیر، باید متد
verify
را فراخوانی کنید. در صورتی که کاربر مبلغ مورد نظر را پرداخت نکرده باشد، و یا هر نوع مشکلی در انجام تایید پرداخت بوجود آمده باشد، پکیجException
برمیگرداند و مانع اجرا شدن کدهای بعدی خواهد شد. - متد
trackingCode
برای گرفتن شماره رهگیری است. - متد
refId
برای گرفتن مقدار ref id است. - متد
cartNumber
برای گرفتن شماره کارت کاربر است. توجه کنید که این متد در بعضی از درگاهها به دلیل پشتیبانی نکردن درگاه، مقدار خالی برمیگرداند.
Exceptions
در زمان بازگشت کاربر به سایت، ممکن است Exceptionهای مختلفی رخ بدهد:
- کاربر ممکن است برای دومین یا چندمین بار سعی بر ارسال داده از طرف بانک به سایت داشته باشد (
RetryException
) - ممکن است اطلاعات بازگشتی درست نباشد و در اینجا ممکن است چنین درگاههی در سایت موجود نباشد (
PortNotFoundException
) - ممکن است اطلاعات بازگشتی به سایت درست نباشد و در اینجا ممکن است آدرس بازگشت به سایت اشتباه باشد (
InvalidRequestException
) - ممکن است اطلاعات بازگشتی به سایت درست نباشد و در اینجا ممکن است چنین رکورد پرداختی موجود نباشد. (
NotFoundTransactionException
) - ممکن است کاربر از انجام پرداخت منصرف شده باشد. (
Exception
) - در اینجا Exception ها بدون درج مسیر کامل کلاس و namespace ایجاد شده اند . پس حتما با دستور use فضای نام (namespace) را لود کنید .
همچنین شما میتوانید تمام این Exceptionها را به صورت زیر Handle کنید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
try {
$gateway = Gateway::verify(); $trackingCode = $gateway->trackingCode(); $refId = $gateway->refId(); $cardNumber = $gateway->cardNumber();
// Your code here
} catch (RetryException $e) { echo $e->getMessage(); } catch (PortNotFoundException $e) { echo $e->getMessage(); } catch (InvalidRequestException $e) { echo $e->getMessage(); } catch (NotFoundTransactionException $e) { echo $e->getMessage(); } catch (Exception $e) { echo $e->getMessage(); } |
موفق و سربلند باشید
دیدگاه ها (0)