I am attempting to integrate SagePay Inframe Server in to site of mine that uses Laravel as the framework. I have purchased an SSL certificate and everything works perfectly, except for the Notification response from Sagepay. I contacted their customer support and was emailed an old development toolkit for version 2.23 (apparently they have none for their latest protocol, take from that what you will), and much of the code is modified from that original (outdated) codebase.
In the last 3 weeks i have been attempting to create a set of functions within a controller (OrdersController) that deal with SagePays various POST sends / responses, in the hope that i can create a public library for Laravel so that nobody else need go through the hell of trying to integrate this nightmare of a system.
Currently my system registers the transaction correctly, from which a notificationURL is sent to Sagepay, I store the necessary VendorTxCode (i create) / VPSTxId and SecurityKey (sagepay created) fields required by Sagepay in my database, and my user is redirected within an iframe to enter their card details.
According to the documentation, after the user has inputted their details and proceeded with their transactions, a script should then check the Status / VendorTxCode / VPSTxId, and using these values withdraw the SecurityKey from the database. If the SecurityKey is non-existent, the user is redirected (using a RedirectURL) to a page specified by me to deal with the error.
I'll stop here, because at the moment i am not drawing the SecurityKey from the database and therefore it doesnt exist, and this is the precise problem - SagePay should from this point redirect the user to the /failure page, but it doesn't, instead it throws this generic error:
Error Code : 5006
Error Description : Unable to redirect to Vendor's web site. The Vendor failed to provide a RedirectionURL.
Now the strange thing here is that if i upload the same script (outside the Laravel / controller framework) to, for example, 'http://www.thisisanothersite/test/notification.php', and change the NotificationURL to reflect this, the iframe is redirected to the desired RedirectURL. If i load the script in my browser is shows the following (correct) response:
Status=INVALID RedirectURL=https://development.myproject.co.uk/sagepay/failure StatusDetail=Unable to find the transaction in our database.
However if i attempt to view the script from within the context of Laravel (so for example 'https://development.myproject.co.uk/sagepay/notification'), the script responds with the usual Illuminate exception handlers you would expect to see with a Laravel error.
My question is this: is there a way to do any of the following:
1) Is there a way to turn off the error handling associated with laravel for a single function so i get back the exact same message as i am getting when outside the Laravel context?
2) Create a stand-alone script within the context of Laravel, so i can use the database connectivity but access it as a standalone page (sagepay/notification.php) without the controller routing getting in the way?
The code i currently have in place for the above is as follows:
<?php
class OrdersController extends BaseController {
protected $layout = 'layouts.admin';
public function __construct(Order $order)
{
$this->order = $order;
}
public function notification() {
header("Content-type: text/plain");
$eoln = chr(13) . chr(10);
$strConnectTo = "TEST";
$strStatus=$this->cleanInput($_REQUEST["Status"],"Text");
$strVendorTxCode=$this->cleanInput($_REQUEST["VendorTxCode"],"VendorTxCode");
$strVPSTxId=$this->cleanInput($_REQUEST["VPSTxId"],"Text");
$strSecurityKey="";
$VendorTxCode = $strVendorTxCode;
$VPSTxId = $strVPSTxId;
$strSQL = Order::select('SecurityKey')->where('VendorTxCode', $VendorTxCode)->where('VPSTxId', $VPSTxId)->first();
if (strlen($strSQL->SecurityKey)==0)
{
ob_flush();
header("Content-type: text/html");
echo "Status=INVALID" . $eoln;
if ($strConnectTo=="LIVE") {
echo "RedirectURL=https://development.myproject.co.uk/sagepay/failure" . $eoln;
}
else {
echo "RedirectURL=https://development.myproject.co.uk/sagepay/failure" . $eoln;
}
echo "StatusDetail=Unable to find the transaction in our database." . $eoln;
exit();
}
else
{
// CODE TO DEAL WITH SUCCESS
}
}
}
And the routes are:
Route::any('sagepay/notification', 'OrdersController@notification');
Route::any('sagepay/failure', 'OrdersController@failure');
Route::resource('orders', 'OrdersController');
Apologies about the size of this question, but I am truly stumped here :/