Running Zarinpal Gateway version4 on Laravel framework version 5.5

one of the most common things using in a web developer is a gateway for making money from customers.

Zarinpal is a famous gateway in Persian guys but the biggest problem of this gateway is lake document when releasing new API.

for implement Laravel by using Zarinpal, I Found the Shetabit composer.

text
composer require shetabit/payment

but this composer isn’t compatible with the new version of Zarinpal and my Laravel version. so I’m using a traditional way to connect Zarinpal into Laravel.

Running Zarinpal Gateway on Laravel framework
“needing fast way connection the payment to the gateway”, My boss screams at me. therefore ignoring the composer and deploy traditionally.

I’m submit Shetabit githaub issues and they answer me at below link. but unfortunately I don’t have time to check them.

stay with me to build payment in Laravel v5.5 with Zarinpal Gateway API version4

Database

3 tables are needed in this project. package price, invoice, and status payment need to store in the database and using as different roles.

php artisan make:migration packageprices

add the structure of the database in up part

php
Schema::create('packageprices', function (Blueprint $table) {
php
$table->increments('id');
php
$table->string('name');
php
$table->integer('price')->unsigned();
php
$table->integer('oldprice')->unsigned();
php
$table->string('hour');
php
$table->timestamps();
text
});
php
Schema::create('transactions', function (Blueprint $table) {
php
$table->increments('id');
php
$table->string('trackingCode');
php
$table->integer('price')->unsigned();
php
$table->integer('user_id')->unsigned();
php
$table->integer('packageprice_id')->unsigned();
php
$table->integer('statustransaction_id')->unsigned();
php
$table->string('bankName')->nullable();
php
$table->string('Authority')->nullable();
php
$table->string('zarinpalStatus')->nullable();
php
$table->string('zarinpalErrorMessage')->nullable();
php
$table->string('zarinpalError')->nullable();
php
$table->string('zarinpalRefID')->nullable();
php
$table->string('zarinpalStatusFinal')->nullable();
php
$table->string('zarinpalErrorMessageFinal')->nullable();
php
$table->string('zarinpalErrorFinal')->nullable();
php
$table->string('zarinpalFinalcardhash')->nullable();
php
$table->string('zarinpalFinalcardpan')->nullable();
php
$table->string('zarinpalFinalfeetype')->nullable();
php
$table->string('zarinpalfee')->nullable();
php
$table->timestamps();
text
});
php
Schema::create('statustransactionses', function (Blueprint $table) {
php
$table->increments('id');
php
$table->string('name');
php
$table->timestamps();
text
});

Migrate

php artisan migrate

and for back to previwe step

php artisan migrate:rollback

Model

make 3 models base on commands below:

php artisan make:model Packageprice — migration

php artisan make:model Statustransactionse — migration

php artisan make:model Transaction — migration

Controller

in this project on need only one controller

php artisan make:controller PaymentController — resource

Initial request with Zarinpal

for making connections to Zarinpal need to send a request to get the Authority code in the controller.

php
$error = array(
text
"-1" => "اطلاعات ارسال شده ناقص است.",
text
"-2" => "IP و يا مرچنت كد پذيرنده صحيح نيست",
text
"-3" => "با توجه به محدوديت هاي شاپرك امكان پرداخت با رقم درخواست شده ميسر نمي باشد",
text
"-4" => "سطح تاييد پذيرنده پايين تر از سطح نقره اي است.",
text
"-11" => "درخواست مورد نظر يافت نشد.",
text
"-12" => "امكان ويرايش درخواست ميسر نمي باشد.",
text
"-21" => "هيچ نوع عمليات مالي براي اين تراكنش يافت نشد",
text
"-22" => "تراكنش نا موفق ميباشد",
text
"-33" => "رقم تراكنش با رقم پرداخت شده مطابقت ندارد",
text
"-34" => "سقف تقسيم تراكنش از لحاظ تعداد يا رقم عبور نموده است",
text
"-40" => "اجازه دسترسي به متد مربوطه وجود ندارد.",
text
"-41" => "اطلاعات ارسال شده مربوط به AdditionalData غيرمعتبر ميباشد.",
text
"-42" => "مدت زمان معتبر طول عمر شناسه پرداخت بايد بين 30 دقيه تا 45 روز مي باشد.",
text
"-54" => "درخواست مورد نظر آرشيو شده است",
text
"100" => "عمليات با موفقيت انجام گرديده است.",
text
"101" => "عمليات پرداخت موفق بوده و قبلا PaymentVerification تراكنش انجام شده است.",
text
);
php
$uuid = uniqid();
php
$transaction = Transaction::create([
text
'trackingCode' => $uuid,
php
'price' => $pakageprice->price,
php
'user_id' => $user->id,
php
'packageprice_id' => $pakageprice->id,
text
'statustransaction_id' => 1,
text
'bankName' => 'زرین پال'
text
]);
text
try {
php
$data = array('merchant_id' => 'Your code',
php
'amount' => $transaction->price * 10,
text
'callback_url' => 'url',
php
'mobile' => $user->mobile,
php
'email' => $user->email,
text
'description' => $uuid
text
);
php
$jsonData = json_encode($data);
php
$ch = curl_init('https://api.zarinpal.com/pg/v4/payment/request.json');
php
curl_setopt($ch, CURLOPT_USERAGENT, 'ZarinPal Rest Api v4');
php
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
php
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
php
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
php
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
text
'Content-Type: application/json',
php
'Content-Length: ' . strlen($jsonData)
text
));
php
$result = curl_exec($ch);
php
$err = curl_error($ch);
php
$result = json_decode($result, true);
text
curl_close($ch);
php
$code = $result['data']['code'];
php
$errorMessage = "";
php
if (array_key_exists("{$code}", $error)) {
php
$errorMessage = $error["{$code}"];
text
} else {
php
$errorMessage = "خطای نامشخص هنگام اتصال به درگاه زرین پال";
text
}
php
$transaction->Authority = $result['data']['authority'];
php
$transaction->zarinpalStatus = $result['data']['message'];
php
$transaction->zarinpalErrorMessage = $errorMessage;
php
$transaction->zarinpalError = $err;
php
$transaction->save();
php
if ($err) {
php
$transaction->Authority = $result['data']['authority'];
php
$transaction->zarinpalStatus = $result['data']['message'];
php
$transaction->zarinpalErrorMessage = $errorMessage;
php
$transaction->zarinpalError = $err;
php
$transaction->save();
text
}
php
if($transaction AND !empty($result['data']["authority"]) ){
php
return Redirect::to("
https://www.zarinpal.com/pg/StartPay/" . $result['data']["authority"]);
text
}
text
}catch (Exception $ex) {
php
$transaction->Authority = NULL;
php
$transaction->zarinpalStatus = 'خطا در ارتباط اولیه';
php
$transaction->zarinpalErrorMessage = 'خطا در ارتباط اولیه';
php
$transaction->zarinpalError = 'error';
php
$transaction->save();
php
$request->session()->flash('warning', 'خطا در ارتباط با زرین پال');
php
return redirect()->back();
text
}

after this code user is going to zaripal gateway.

Running Zarinpal Gateway on Laravel framework

next step Zarinpal callback to your callback address. so create call back address in the router.php and payment must confirm in the controller. if payment not confirms, the money will come back to the customer.

callback method in controller:

get Autority by get method.

php
$Authority = NULL;
php
$Status = NULL;
php
if (isset($_GET['Authority']) OR isset($_GET['Status'])) {
php
$Authority = $_GET['Authority'];
$Status = $_GET['Status'];
text
}

if your using nginx set below configure to get data.

nginx
location / {
nginx
try_files $uri $uri/ /index.php?$args;
text
}

in controller verify the zarinpal transaction

php
if (!empty($Authority) AND !empty($Status)) {
php
if($Status == 'OK')
text
{
php
$errorMessagesZarinpal = array(
text
"-1" => "اطلاعات ارسال شده ناقص است.",
text
"-2" => "IP و يا مرچنت كد پذيرنده صحيح نيست",
text
"-3" => "با توجه به محدوديت هاي شاپرك امكان پرداخت با رقم درخواست شده ميسر نمي باشد",
text
"-4" => "سطح تاييد پذيرنده پايين تر از سطح نقره اي است.",
text
"-11" => "درخواست مورد نظر يافت نشد.",
text
"-12" => "امكان ويرايش درخواست ميسر نمي باشد.",
text
"-21" => "هيچ نوع عمليات مالي براي اين تراكنش يافت نشد",
text
"-22" => "تراكنش نا موفق ميباشد",
text
"-33" => "رقم تراكنش با رقم پرداخت شده مطابقت ندارد",
text
"-34" => "سقف تقسيم تراكنش از لحاظ تعداد يا رقم عبور نموده است",
text
"-40" => "اجازه دسترسي به متد مربوطه وجود ندارد.",
text
"-41" => "اطلاعات ارسال شده مربوط به AdditionalData غيرمعتبر ميباشد.",
text
"-42" => "مدت زمان معتبر طول عمر شناسه پرداخت بايد بين 30 دقيه تا 45 روز مي باشد.",
text
"-54" => "درخواست مورد نظر آرشيو شده است",
text
"100" => "عمليات با موفقيت انجام گرديده است.",
text
"101" => "عمليات پرداخت موفق بوده و قبلا PaymentVerification تراكنش انجام شده است.",
text
);
php
$transaction = Transaction::where('Authority', $Authority)
php
->first();
php
if(empty($transaction->id))
text
{
php
$error = True;
php
$message = "خطا تراکنشی یافت نشد ";
php
return view('/callback')->with('message', $message)->with('error' , $error);
text
}
php
if($transaction->statustransaction_id != 1)
text
{
php
$error = True;
php
$message = "خطا این تراکنش قبلا در سیستم تعیین تکلیف شده است ";
php
return view('/callback')->with('message', $message)->with('error' , $error);
text
}
php
$data = array(
text
'merchant_id' => 'Your Code',
text
'authority' => $Authority,
php
'amount' => $transaction->price * 10,
text
);
php
$jsonData = json_encode($data);
php
$ch = curl_init('https://api.zarinpal.com/pg/v4/payment/verify.json');
php
curl_setopt($ch, CURLOPT_USERAGENT, 'ZarinPal Rest Api V4');
php
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
php
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
php
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
php
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
text
'Content-Type: application/json',
php
'Content-Length: ' . strlen($jsonData)
text
));
php
$result = curl_exec($ch);
php
$err = curl_error($ch);
text
curl_close($ch);
php
$result = json_decode($result, true);
php
if(isset($result['errors']['code']))
text
{
php
$transaction->zarinpalErrorMessageFinal = $result['errors']['code'];
php
$transaction->zarinpalErrorFinal = $result['errors']['message'];
php
$transaction->statustransaction_id = 2;
php
$transaction->save();
php
$error = True;
php
$message = ".خطا از سمت زرین پال. "."عملیات با شکست روبه رو شد".$result['errors']['message'];
php
return view('callback')->with('message', $message)->with('error' , $error);
text
}
text
else
text
{
php
$code = $result['data']['code'];
php
$errorMessage = "";
php
if (array_key_exists("{$code}", $errorMessagesZarinpal)) {
php
$errorMessage = $errorMessagesZarinpal["{$code}"];
text
} else {
php
$errorMessage = "خطای نامشخص هنگام اتصال به درگاه زرین پال";
php
if (isset($result['data']['code']) AND $result['data']['code'] == '100')
text
{
php
$transaction->zarinpalErrorMessageFinal = $result['data']['code'];
php
$transaction->zarinpalStatusFinal = $result['data']['message'];
php
$transaction->statustransaction_id = 3;
php
$transaction->zarinpalRefID = $result['data']['ref_id'];
php
$transaction->zarinpalFinalcardhash = $result['data']['card_hash'];
php
$transaction->zarinpalFinalcardpan =$result['data']['card_pan'];
php
$transaction->zarinpalFinalfeetype = $result['data']['fee_type'];
php
$transaction->zarinpalfee =$result['data']['fee'];
php
$transaction->save();
php
$error = False;
php
$message = "پرداخت با موفقیت انجام شد. شد پیگیری".$result['data']['ref_id']."
    ";
php
$message.= "  -  ";
php
$message.= $packageprice->hour." ساعت حساب کاربری شما شارژ شد";
php
return view('/callback')->with('message', $message)->with('error' , $error);
text
}
php
else if (isset($result['data']['code']) AND $result['data']['code'] == '101')
text
{
php
$error = True;
php
$message = "تراکنش شما در سیستم قبلا ثبت شده است و کد پیگیری :".$result['data']['ref_id'];
php
return view('/customer/payment/paymentcallbakzarinpall')->with('message', $message)->with('error' ,
$error);
text
}
text
}
text
}
text
else{ //Status is NOK
php
$error = True;
php
$message = "زرین پال اعلام می کند که تراکنش شما موفقیت آمیز نبوده است ";
php
return view('callback')->with('message', $message)->with('error' , $error);
text
}
text
}else // no Authority get
text
{
php
$error = True;
php
$message = "خطا ورود به صورت غیر مجاز ";
php
return view('/callback')->with('message', $message)->with('error' , $error);
text
}

Zarinal Api Response

error in connection

text
array:2 [▼
text
"data" => []
text
"errors" => array:3 [▼
text
"code" => -51
text
"message" => "Session is not valid, session is not active paid try."
text
"validations" => []
text
]
text
]

successful API response

text
array:2 [▼
text
"data" => array:7 [▼
text
"code" => 100
text
"message" => "Paid"
text
"card_hash" => "code"
text
"card_pan" => "card"
text
"ref_id" => integer
text
"fee_type" => "Merchant"
text
"fee" => 0
text
]
text
"errors" => []
text
]

I would like to use these line by object oriented Class but composer class has problem with this version of Zarinpal Gateway.