Paylink Integrations Paylink PHP / cURL Skeleton Example

Server environment, languages, extensions and libraries

Language / extension   Version Notes
PHP 5 >= 5.2.0  
libcurl >= 7.10.5  
PECL json >=  1.2.0  
PECL hash >= 1.1  

Constants

//
//  The following constant values are used in this integration sample.
//
//  Depending on the nature of the Merchant Application, it may be
//  more appropriate to represent them as part of the global configuration
//  for the application so that it can be amended independently of the
//  program code.
//
define('MERCHANT_ID', "<merchant_id>");
define('LICENCE_KEY', "<licence_key>");

Configure the Paylink Transaction

Construct the Paylink Transaction Request

Payment Transaction basic configuration

//
//  Construct an associative array for the Payment Transaction Request,
//  and assign it to the $request variable.
//
$request = array();

//
//  Assign values to the mandatory fields of the Payment Transaction Request
//  and any optional fields as required. 
//
$request['merchantid'] = MERCHANT_ID;
$request['licenceKey'] = LICENCE_KEY;
$request['test'] = "true";
$request['identifier'] = "php-integration-test";
$request['amount'] = 5000;

Payment Transaction processing configuration

//
//  Assign the host, application path and application endpoint values
//  to temporary variables to enable reuse.
//
$host = $_SERVER['HTTP_HOST'];
$applicationPath = $_SERVER['PHP_SELF'];
$applicationEndpoint = $host.$applicationPath;

//
//  Construct an associative array for the Payment Transaction configuration,
//  and assign it to the $request associative array with the index 'config'.
//
$request['config'] = array();

//
//  Assign values to the relevant fields of the Payment Transaction configuration
//  associative array to guide processing and Merchant Application integration by
//  the Paylink Payment Form and the Paylink server.
//
$request['config']['postback_policy'] = 'async';
$request['config']['postback'] = 'http://'.$applicationEndpoint.'?postback=false';
$request['config']['redirect_success'] = 'http://'.$applicationEndpoint.'?success';
$request['config']['redirect_failure'] = 'http://'.$applicationEndpoint.'?failure';

Issue the Paylink Transaction Request

//
//  Generate a JSON representation of the $request associative array
//  using PECL json.
//
$jsonEncodedRequest = json_encode($request);

//
//  Open a temporary stream for the purpose of collecting verbose connection
//  information generated by cURL. This is useful for tracing into SSL
//  certificate-related connectivity issues.
//
$curl_stderr = fopen('php://temp', 'w+');

//
//	Initialise an associative array containing the configuration required
//  for the cURL-based request.
//
$curl_opts = array(
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $jsonEncodedRequest,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => array(
                'Accept: application/json',
                'Content-Type: application/json;charset=UTF-8',
                'Content-Length: '.strlen($jsonEncodedRequest)
            ),
        CURLOPT_VERBOSE => true,
        CURLOPT_STDERR => $curl_stderr
    );
 
//
//  Initialise the cURL request.
//
$ch = curl_init('https://secure.citypay.com/paylink3/create');
 
//
//	Configure the cURL request with the configuration provided
//  by the associative array.
//
curl_setopt_array($ch, $curl_opts);

// 
//	Open the cURL request and receive the response (if any)
//
$httpsResponse = curl_exec($ch);

Process the Paylink Transaction Response

Main control flow

//
//  If cURL is unable to complete the HTTP request for whatever reason,
//  it will return FALSE (which may be tested using the PHP empty function).
//
//  If the cURL HTTP request was completed and the response generated is
//  not empty -
//
if (!empty($httpsResponse))
{
	//
	//	Close and dispose of the temporary stream used to receive connection-
	//  related output generated by cURL in the course of processing the
	//  HTTP request.
	//
	fclose($curl_stderr);

    //
    //  Get the HTTP response code received from the remote server and, if
	//  necessary, any further diagnostic or process-related information
	//	from the cURL request object.
    //
    $httpsResponseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    //
    //	Close the cURL request object to release system resources associated
	//	with it.
    //
    curl_close($ch);

    //
    //  If the HTTP POST request was reported as having been
    //  successfully completed by the Paylink server -
    //
    if ($httpsResponseCode == 200)
    {    
        //
        //  1. De-serialize the JSON formatted message body to
        //     form an object, of an anonymous class, structured
        //     to contain properties that mirror those of the
        //     JSON packet.
        //
        $decodedResponse = json_decode(httpsResponse);
        
        //
        //  2.  Process the Payment Transaction Response.
        //
        if ($decodedResponse->result == 0x01)
        {
            //
		    //  The Paylink server has generated and returned a Payment Token
            //  and a URL to which the Customer Browser may be referred to
            //  complete the Payment Transaction using the Paylink Payment Form.
            //
            $token = $decodedResponse->id;
            $url = $decodedResponse->url;
            
            //
            //  TODO: Redirect Customer Browser to Paylink Payment Form (see below)
            //
            //  OR
            //
            //  TODO: Embed link to Paylink Payment Form in HTTP Response (see below)
            //
        }
        else
        {
            //
            //  The Paylink server has encountered Payment Transaction Request
            //  authentication, validation or other upstream errors while processing
            //  the Payment Transaction Request.
            //
            //  TODO: Handle Payment Transaction Request processing errors (see below)
            //
        }		
    }
	else
	{
        //
        //  The Paylink server has generated a HTTP response code that
        //  indicates that an error has occurred.
        //
        //  TODO: Handle Payment Transaction Request non-200 HTTP response codes (see below)
        //
	}
}
else
{
   	//
	//	Move the file pointer associated with the temporary stream used to
	//  receive connection processing output generated by cURL back to the
	//  start of the file.
	//
    rewind($curl_stderr);
 
	//
	//	Get the contents of the temporary stream used to receive connection
	//	processing output generated by cURL.
	//
    $req_stderr = stream_get_contents($curl_stderr, 4096);
 
	//
	//	Close the dispose of the temporary stream used to receive connection 
	//  processing output generated by cURL.
	//
    fclose($curl_stderr);
 
    //
    //  Obtain any diagnostic information from the cURL request object.
    //
    $req_errno = curl_errno($ch);
    $req_error = curl_error($ch);

    //
    //	Close the cURL request object to release system resources associated
	//	with it.
    //
    curl_close($ch);

	//
    //  TODO: Handle cURL HTTP connection error and log any relevant
    //        diagnostic information to a log file, as appropriate.
    //  
}

Redirect or link

Redirect Customer Browser to Paylink Payment Form

$result = http_redirect($url, array(), false, HTTP_REDIRECT_POST);

Embed link to Paylink Payment Form in HTTP Response

print('<p><a href="'
        .$url
        .'">Click here for the Paylink Payment Form</p>'
    );

Handle Payment Transaction Request processing errors

//
//  Paylink has generated errors
//
print('<p>decodedResponse</p>');
print($decodedResponse);

Handle Payment Transaction Request non-200 HTTP response codes

//
//  HTTP 1.1 Status codes that may be accepted and handled by
//  the Merchant Application, either specifically if required
//  or generally.
//
switch ($httpsResponseCode)
{
    //
    //  HTTP 1.1 Client Error status codes.
    //
    case 400:  // "400 Bad Request"
    case 401:  // "401 Unauthorised"
    case 403:  // "403 Forbidden"
    case 404:  // "404 Not Found"
    case 408:  // "408 Request Timeout"
        //
        //  HTTP 1.1 Status codes that may foreseeably be returned by the
        //  Paylink server and which may require specific handling by the
        //  Merchant Application.
        //
        //  TODO: Log error or raise an exception indicating that an
        //  error relating to the availability of the Merchant Application,
        //  or the resources made available by the Paylink server has
        //  occurred. 
        //
        break;
 
    case 402:  // "402 Payment Required"
    case 405:  // "405 Method Not Allowed"
    case 407:  // "407 Proxy Authentication Required"     
    case 406:  // "406 Not Acceptable"
    case 409:  // "409 Conflict"
    case 410:  // "410 Gone"
    case 411:  // "411 Length Required"
    case 412:  // "412 Precondition Failed"
    case 413:  // "413 Request Entity Too Large"
    case 414:  // "414 Request-URI Too Long"
    case 415:  // "415 Unsupported Media Type"
    case 416:  // "416 Requested Range Not Satisfiable"
    case 417:  // "417 Expectation Failed"
        //
        //  HTTP 1.1 Status codes that are unlikely to be returned by the
        //  Paylink server and which may only require general handling
        //  by the Merchant Application.
        //
        //  TODO: Log error or raise an exception indicating that an
        //  error relating to the availability of the Merchant Application,
        //  or the resources made available by the Paylink server has
        //  occurred. 
        //
        break;
 
    //
    //  HTTP 1.1 Server Error status codes.
    //
    case 500:  // "500 Internal Server Error"
    case 501:  // "501 Not Implemented"
    case 502:  // "502 Bad Gateway"
    case 503:  // "503 Service Unavailable"
    case 504:  // "504 Gateway Timeout"
        //
        //  HTTP 1.1 Status codes that may foreseeably be returned by the
        //  Paylink server and which may require specific handling by the
        //  Merchant Application.
        //
        //  TODO: Log error or raise an exception indicating that an
        //  error relating to the availability of the Merchant Application,
        //  or the resources made available by the Paylink server has
        //  occurred. 
        //
        break;
}

Handle the Postback RPC

//
//  Get the message body accompanying the incoming HTTP POST request,
//  using a call to file_get_contents in conjunction with the PHP
//  "php://input" read-only I/O stream.
//
$postback = file_get_contents("php://input");
if ($postback === FALSE)
{
    //
    //  TODO: Raise an exception that no message body accompanied the
    //  incoming HTTP POST request.
    //
}
    
//
//  De-serialize the JSON formatted message body contents to form
//  an object, of an anonymous class, structure to contain properties
//  that mirror those of the JSON packet.  
//
$jsonPostback = json_decode($postback);
if ($jsonPostback == NULL)
{
    //
    //  TODO: Raise an exception that the message body could not be parsed
	//  as a JSON formatted string.
    //
}
    
//
//  Check whether the Payment Transaction was authorised.
//
if ($jsonPostback->authorised === "true")
{
    //
    //	TODO: Mark the relevant customer invoice as "authorised".
    //
}
else
{
    //
    //  TODO: Mark the relevant customer invoice as "declined".
    //
}

//
//  Return a HTTP 200 OK response code to the Paylink server.
//
http_response_code(200);
flush();
    
//
//  TODO: Perform any post HTTP response actions that.
//

Handle the Customer Browser Redirection

On success

//
//  1.  Mandatory: check integrity of redirection payload (see below)
//
//  2.  Recommended: compare certain Payment Transaction data provided in the
//      redirection payload with the known state of the Payment Transaction
//      provided to the Merchant Application through the Postback RPC (see above).
//
if ($_POST['authorised'] == "true")
{
    //
    //  Advise the Customer of any purchase references, or anticipated delivery
    //  date for the product or service purchased. 
    //
}
else
{
    //
    //  Raise an exception: there is a mismatch between the reported state of
    //  the Payment Transaction according to the redirection payload and the
    //  redirection endpoint provided to the application by the Paylink server.
    //
}

On failure

//
//  1.  Mandatory: check integrity of redirection payload (see below)
//
//  2.  Recommended: compare certain Payment Transaction data provided in the
//      redirection payload with the known state of the Payment Transaction
//      provided to the Merchant Application through the Postback RPC (see above).
//
if ($_POST['authorised'] != "true")
{
   //
   //   Advise the Customer that the Payment Transaction was declined and,
   //   if appropriate, give the customer an opportunity to contact the
   //   the Merchant to report any problems or to facilitate manual handling
   //   of the Payment Transaction.
   //
}
else
{
    //
    //  Raise an exception: there is a mismatch between the reported state
    //  of the Payment Transaction according to the redirection payload and
    //  the redirection endpoint provided to the application by the Paylink
    //  server.
    //
}

Checking the integrity of redirection payload

//
//  The Customer Browser Redirection from the Paylink Payment Form to the
//  Merchant Application is performed through a POST operation to the
//  relevant redirection endpoint.
//
//  If the Payment Transaction has been configured to return the parameters
//  of the authorised or otherwise declined Payment Transaction, the parameters
//  are provided in URL encoded form which PHP processes to generate the
//  $_POST associative array. 
//
//  Note
//
//  Verification of the payload forwarded to the Merchant Application via
//  the Customer Browser Redirection is performed by reference to the licence
//  key [licencekey] used for the Payment Transaction which is not transmitted
//  back to the Merchant Application indirectly via the Customer Browser.
//
$digestSource = $_POST['authcode']
    .$_POST['amount']
    .$_POST['errorcode']
    .$_POST['merchantid']
    .$_POST['transno']
    .$_POST['identifier']
    .LICENCE_KEY;


//
//  Encode the digest source as a UTF-8 encoded string.
//
$digestSource_utf8 = utf8_encode($digestSource);

//
//  Calculate the SHA256 hash for the UTF-8 encoded digest source
//  to generate a byte array containing the result.
//
$digest_sha256 = hash('sha256', $digestSource_utf8, true);
 
//
//  Encode the SHA256 hash value to a Base64 encoded string.
//
$digest_sha256_base64 = base64_encode($digest_sha256);
    
//
//  Compare the Base64 encoded SHA256 hash value calculated by the
//  Merchant Application to the Base64 encoded SHA256 hash value
//  accompanying the Payment Transaction parameters. 
//    
if ($_POST['sha256'] == $digest_sha256_base64)
{
    //
    //  Data subject to validation using a cryptographic hash function
    //  matches the data sent by the Paylink server for indirect delivery
    //  via the Customer Browser.  
    //
}
else
{
    //
    //  Data subject to validation using a cryptographic hash function
    //  does not match the data sent by the Paylink server for indirect
    //  delivery via the Customer Browser.  
    //
}

 

 

+44 (0)1534 884000