Steve Vincent
Steve Vincent

Reputation: 199

Curl and Sagepay

I'm having a lot of trouble integrating Sagepay InFrame Server with PHP, as there are no integration kits available for the new protocol (v3). I have the old kits for v2.23 but much of the code therein is deprecated.

At the moment the only way i have been successful in retrieving an OK status from the Sagepay Server servers is to have a form with the collection of hidden values required by Sagepay, including the cryptography field, and using the server URL as the form action. This gives me a status of 'OK' and the SecurityKey etc in the browser tab, but its not much use in the browser tab as i need that POST response back on my server, not on theirs.

For this i opted for curl. I hold the return values for curl_exec in a variable called $rawresponse, and dump the response after each attempt, and as it stands $rawresponse is returning as a false boolean:

$curlSession = curl_init();

curl_setopt ($curlSession, CURLOPT_URL, $url);
curl_setopt ($curlSession, CURLOPT_HEADER, 0);
curl_setopt ($curlSession, CURLOPT_POST, 1);
$data['Crypt'] = new CurlFile('filename.png', 'image/png', 'filename.png');
curl_setopt ($curlSession, CURLOPT_POSTFIELDS, $data);
curl_setopt($curlSession, CURLOPT_RETURNTRANSFER,1); 
curl_setopt($curlSession, CURLOPT_TIMEOUT,30); 
curl_setopt($curlSession, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curlSession, CURLOPT_SSL_VERIFYHOST, 0);

$rawresponse = curl_exec($curlSession);

Now as you can see here I am having to force the Crypt value to be of type CurlFile, which is what i think is breaking the request, however if i dont do that i get the following error:

"The usage of the @filename API for file uploading is deprecated. Please use the CURLFile class instead"

I can only ascertain from this that the cryptography is being mistaken for a file (possibly because the string starts with @), and to counter this im trying to force it to be an image.

So my question is this - is there a particular way to use CurlFile so cryptography strings can be understood? Is there a better way of integrating this functionality with Sagepay that anyone knows about? It really is a very confusing system, and the good documentation is let down by a complete lack of example.

Upvotes: 0

Views: 894

Answers (1)

Steve Vincent
Steve Vincent

Reputation: 199

Apologies for this, I was building the string the wrong way. Just in case anyone has a similar problem in the future i'll paste the code that works for me:

public function registerTransaction()
{
    $VPSProtocol = urlencode($_POST['VPSProtocol']);
    $TxType = urlencode($_POST['TxType']);
    $Vendor = urlencode($_POST['Vendor']);
    $VendorTxCode = urlencode($_POST['VendorTxCode']);
    $Currency = urlencode($_POST['Currency']);
    $Amount = urlencode($_POST['Amount']);
    $NotificationURL = urlencode($_POST['NotificationURL']);
    $Description = urlencode($_POST['Description']);
    $BillingSurname = urlencode($_POST['BillingSurname']);
    $BillingFirstnames = urlencode($_POST['BillingFirstnames']);
    $BillingAddress1 = urlencode($_POST['BillingAddress1']);
    $BillingCity = urlencode($_POST['BillingCity']);
    $BillingPostCode = urlencode($_POST['BillingPostCode']);
    $BillingCountry = urlencode($_POST['BillingCountry']);
    $DeliverySurname = urlencode($_POST['DeliverySurname']);
    $DeliveryFirstnames = urlencode($_POST['DeliveryFirstnames']);
    $DeliveryAddress1 = urlencode($_POST['DeliveryAddress1']);
    $DeliveryCity = urlencode($_POST['DeliveryCity']);
    $DeliveryPostCode = urlencode($_POST['DeliveryPostCode']);
    $DeliveryCountry = urlencode($_POST['DeliveryCountry']);

    $url = "?VPSProtocol=" . $VPSProtocol;
    $url .= "&TxType=" . $TxType;
    $url .= "&Vendor=" . $Vendor;
    $url .= "&VendorTxCode=" . $VendorTxCode;
    $url .= "&Currency=" . $Currency;
    $url .= "&Amount=" . $Amount;
    $url .= "&NotificationURL=" . $NotificationURL;
    $url .= "&Description=" . $Description;
    $url .= "&BillingSurname=" . $BillingSurname;
    $url .= "&BillingFirstnames=" . $BillingFirstnames;
    $url .= "&BillingAddress1=" . $BillingAddress1;
    $url .= "&BillingCity=" . $BillingCity;
    $url .= "&BillingPostCode=" . $BillingPostCode;
    $url .= "&BillingCountry=" . $BillingCountry;
    $url .= "&DeliverySurname=" . $DeliverySurname;
    $url .= "&DeliveryFirstnames=" . $DeliveryFirstnames;
    $url .= "&DeliveryAddress1=" . $DeliveryAddress1;
    $url .= "&DeliveryCity=" . $DeliveryCity;
    $url .= "&DeliveryPostCode=" . $DeliveryPostCode;
    $url .= "&DeliveryCountry=" . $DeliveryCountry;

    $strPurchaseURL = "https://test.sagepay.com/gateway/service/vspserver-register.vsp";
    $arrResponse = $this->requestPost($strPurchaseURL, $url);
    dd($arrResponse);
}


public function requestPost($url, $data){
    // Set a one-minute timeout for this script
    set_time_limit(60);

    // Initialise output variable
    $output = array();

    // Open the cURL session
    $curlSession = curl_init();

    curl_setopt ($curlSession, CURLOPT_URL, $url);
    curl_setopt ($curlSession, CURLOPT_HEADER, 0);
    curl_setopt ($curlSession, CURLOPT_POST, 1);
    curl_setopt ($curlSession, CURLOPT_POSTFIELDS, $data);
    curl_setopt($curlSession, CURLOPT_RETURNTRANSFER,1); 
    curl_setopt($curlSession, CURLOPT_TIMEOUT,30); 
    curl_setopt($curlSession, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($curlSession, CURLOPT_SSL_VERIFYHOST, 2);

    $rawresponse = curl_exec($curlSession);
    dd($rawresponse);
    //Store the raw response for later as it's useful to see for integration and understanding 
    $_SESSION["rawresponse"]=$rawresponse;
    //Split response into name=value pairs
    $response = preg_split(chr(10), $rawresponse);
    // Check that a connection was made
    if (curl_error($curlSession)){
        // If it wasn't...
        $output['Status'] = "FAIL";
        $output['StatusDetail'] = curl_error($curlSession);
    }

    // Close the cURL session
    curl_close ($curlSession);

    // Tokenise the response
    for ($i=0; $i<count($response); $i++){
        // Find position of first "=" character
        $splitAt = strpos($response[$i], "=");
        // Create an associative (hash) array with key/value pairs ('trim' strips excess whitespace)
        $output[trim(substr($response[$i], 0, $splitAt))] = trim(substr($response[$i], ($splitAt+1)));
    } // END for ($i=0; $i<count($response); $i++)

    // Return the output
    return $output;
} // END function requestPost()

Upvotes: 1

Related Questions