I'm trying to integrate PayHere payment gateway to my site which is built with Laravel 5.5. So as their documentation I have integrate their api as below. I'm testing with sandbox credentials in live sever .In here what I do is first pass the payment details via a <from>
(as in their documentation )
.So when I make a transaction it works as it should be and I receive the success mail from the payment gateway too.
But my problem is that I cant fetch the notification which send from the payment gateway to check the payment status of my payment to update the db. So I have wrote a simple code to check the payment status code . ( 2 - success / 0 - pending / -1 - canceled / -2 -failed / -3 -charged-back )
So could anyone please help me to solve this. Please refer below sample codes that I have written to test the payment gateway which is in a live server
CheckOutController
public function notifyUrl(Request $request){
//As their documentation
$merchant_id = $request -> input('merchant_id');
$order_id = $request -> input('order_id');
$payhere_amount = $request -> input('payhere_amount');
$payhere_currency = $request -> input('payhere_currency');
$status_code = $request -> input('status_code');
$md5sig = $request -> input('md5sig');
$merchant_secret = 'xxxxxxxxxxxxxxxxxxxx'; // Replace with your Merchant Secret (Can be found on your PayHere account's Settings page)
$local_md5sig = strtoupper (md5 ( $merchant_id . $order_id . $payhere_amount . $payhere_currency . $status_code . strtoupper(md5($merchant_secret)) ) );
// return $status_code;
if (($local_md5sig === $md5sig) AND ($status_code == 2) ){
$newStatus = new Status();
$newStatus ->status= 2;
$newStatus ->save();
}elseif(($local_md5sig === $md5sig) AND ($status_code == 0) ){
$newStatus = new Status();
$newStatus ->status= 0;
$newStatus ->save();
}elseif(($local_md5sig === $md5sig) AND ($status_code == -1) ){
$newStatus = new Status();
$newStatus ->status= -1;
$newStatus ->save();
}elseif(($local_md5sig === $md5sig) AND ($status_code == -2) ){
$newStatus = new Status();
$newStatus ->status= -2;
$newStatus ->save();
}elseif(($local_md5sig === $md5sig) AND ($status_code == -3) ){
$newStatus = new Status();
$newStatus ->status= -3;
$newStatus ->save();
}else{
$newStatus = new Status();
$newStatus ->status= 'Fail';
$newStatus ->save();
}
}
public function cancelUrl(){
return redirect()->route('shop.home');
}
public function returnUrl(){
return redirect()->route('shop.cart');
}
Routes
$router //**using POST method hens they pass data via this url**
-> post ( 'payment/notify' , 'CheckOutController@notifyUrl' )
-> name ( 'shop.notifyUrl' ) ;
$router
-> get ( 'payment/cancelUrl' , 'CheckOutController@cancelUrl' )
-> name ( 'shop.cancelUrl' ) ;
$router
-> get ( 'payment/returnUrl' , 'CheckOutController@returnUrl' )
-> name ( 'shop.returnUrl' ) ;
Checkout Form Sample taken from their documentation
<form method="post" action="https://sandbox.payhere.lk/pay/checkout" >
<input type="hidden" name="merchant_id" value="000000"> <!-- Replace your Merchant ID -->
<input type="hidden" name="return_url" value="{{route ( 'shop.returnUrl' )}}">
<input type="hidden" name="cancel_url" value="{{route ( 'shop.cancelUrl' )}}">
<input type="hidden" name="notify_url" value="{{route ( 'shop.notifyUrl' )}}">
<input hidden type="text" name="order_id" value="xxxxx">
<input hidden type="text" name="items" value="xxxxxx">
<input hidden type="text" name="currency" value="LKR">
<input hidden type="text" name="amount" value="5000.0">
<br><br>Customer Details</br></br>
<input type="text" name="first_name" value="xxxxx">
<input type="text" name="last_name" value="xxxx">
<input type="text" name="email" value="xxxx">
<input type="text" name="phone" value="xxxx">
<input type="text" name="address" value=" xxxxx / xxxxxx/ xxxxxx/ Sri Lanka">
<input type="text" name="city" value="Colombo">
<input type="hidden" name="country" value="Sri Lanka">
</form>
Update 01 (As @RicardoAlbear said )
Thanks to the help from payhere I was able to fix my issue. The problem was I have not excluded the CSRF for my payhere notification url.So that laravel automatically reject the data passed through the notification url. So what I did was just added * (accept all the url s . Also we can specify the url like 'www.exapmle.com/payhere/nofity') and now its working. So the issue is that we need to exclude CSRF for payhere notify url. @RecardoAlbear thank you very much for your support. I was able to grab lot of new things from your comment. Thanks
For future references payhere can be integrate as follow in Laravel
Exclud CSRF protection from app\Http\Middleware\VerifyCsrfToken.php
<?php
namespace App\Http\Middleware ;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware ;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array
*/
//I have used * - means that it allows for all the url. But you can specify excluded url s as you wanted
protected $except = [
'*', //this exclude all urls
'www.exapmle.com/payhere/nofity'
] ;
}