Home » Resources » Documentation » Get Involved » Writing a New Payment Gateway

Writing a New Payment Gateway

Payment Gateways are an important part of an E-Commerce Website, there are many Gateway Providers. The trick is to find the one that suits your business needs. Once you’ve chosen a gateway, check to see if it is already integrated with the Wp-E-Commerce Plugin if not, this documentation will help you in making a Gateway Module.

Please note, this resource is intended for developers with a know how in PHP and mySQL and for developing gateway modules for Wp-E-Commerce 3.7 and up.

Parameters and required information

At the beginning of your script you must have these variables and fill them in with your new gateways information.

$nzshpcrt_gateways[$num]['name'] = 'My New Gateway';

This is the gateway name used in the front end of the site (checkout page)

$nzshpcrt_gateways[$num]['internalname'] = 'my_new_gateway';

This is the gateway name used internally
Naming convention is all small letters and no spaces

$nzshpcrt_gateways[$num]['function'] = 'gateway_my_new_gateway';

This is the name of the function called on execution (usually the function that talks to your gateway).
Naming convention is gateway_ followed by the internal name of your gateway, in this example my_new_gateway.

$nzshpcrt_gateways[$num]['form'] = "form_my_new_gateway";

This is the name of the function that returns a form within the admin section where you would provide information regarding your gateway and account.
Naming convention is form_ followed by the internal name of your gateway, in this example my_new_gateway.

$nzshpcrt_gateways[$num]['submit_function'] = "submit_my_new_gateway";

This is the name of the function used to validate and submit your form fields from the previous function (form_my_new_gateway)
Naming convention is submit_ followed by the internal name of your gateway, in this example my_new_gateway.

From the above code we can assume we will require at least 3 functions:

  • gateway_my_new_gateway($seperator, $sessionid)
  • form_my_new_gateway()
  • submit_my_new_gateway()

These three functions are the bare minimum needed to create a gateway, you can add more functions to allow cleaner more module code but they must all reside in the one file.

Functions

Starting with the easiest one:

form_my_new_gateway()

This function receives no parameters and returns a string with form elements ($output) within <tr> <td> </tr> <td>

tags, this is to make sure the fields appear within the admin section inside the table.

Note: There is no need for a <form> tag, as that is automatically done within the Wp-E-Commerce Plugin.

No doubt the gateway you chose to build will require at least a username and password, so as an example a basic submit function would look like this:

function form_my_new_gateway(){

$output ='<tr><td>';

$output.='<input name="my_new_gateway_username" type="text"/>';
$output.='';

$output.='<input name="my_new_gateway_password" type="text"/>';
$output.='';

$output .='</tr></td>';

return $output;

}

submit_my_new_gateway()

Now that you have a form, you must validate and save the content of the form into your WordPress setup. All gateways save their configuration details in the WordPress options functions.

function submit_my_new_gateway(){

if($_POST['my_new_gateway_username'] != null) {

update_option('my_new_gateway_username',
$_POST['my_new_gateway_username']);

}

if($_POST['my_new_gateway_password'] != null) {

update_option('my_new_gateway_password',
$_POST['my_new_gateway_password']);

}

return true;

}

gateway_my_new_gateway($seperator, $sessionid)

This function is where the communication between your website and the gateway happens. It receives two parameters $seperator and $sessionid.

$seperator is used to concatenate the information to pass through to your gateway

$sessionid is the unique identifier for each individual shopping cart log. Think of it this way, each time a user comes to your site and adds things to the cart a new $sessionid is created, when a transaction is put through and successfully sent to a gateway the $sessionid and the cart contents are stored in the purchase log, if the user leaves the site without purchasing anything in his cart then that session is destroyed/deleted.

Almost always gateways will provide documentation on how and what they require you to submit. We recommend using cURL as it is the most used and easily configured of the communication methods.

This example will use cURL to communicate with a fake gateway using the URL http://this.is.the.gateways.address

And will submit the following details:

  • my_new_gateway_username
  • my_new_gateway_password
  • Total Price of Shopping Cart
  • Total Amount for All Products (without tax and shipping)
  • Shipping Amount
  • Tax Amount
  • Billing Name
  • Billing Address
  • Billing Phone
  • Billing Email
  • Shipping Name
  • Shipping Address
  • Shipping Phone
  • All Products Purchased
function gateway_my_new_gateway($seperator, $sessionid){

//$wpdb is the database handle,
//$wpsc_cart is the shopping cart object

global $wpdb, $wpsc_cart;

//This grabs the purchase log id from the database
//that refers to the $sessionid

$purchase_log = $wpdb->get_row(
"SELECT * FROM `".WPSC_TABLE_PURCHASE_LOGS.
"` WHERE `sessionid`= ".$sessionid." LIMIT 1"
,ARRAY_A) ;

//This grabs the users info using the $purchase_log
// from the previous SQL query

$usersql = "SELECT `".WPSC_TABLE_SUBMITED_FORM_DATA."`.value,
`".WPSC_TABLE_CHECKOUT_FORMS."`.`name`,
`".WPSC_TABLE_CHECKOUT_FORMS."`.`unique_name` FROM
`".WPSC_TABLE_CHECKOUT_FORMS."` LEFT JOIN
`".WPSC_TABLE_SUBMITED_FORM_DATA."` ON
`".WPSC_TABLE_CHECKOUT_FORMS."`.id =
`".WPSC_TABLE_SUBMITED_FORM_DATA."`.`form_id` WHERE
`".WPSC_TABLE_SUBMITED_FORM_DATA."`.`log_id`=".$purchase_log['id']."
ORDER BY `".WPSC_TABLE_CHECKOUT_FORMS."`.`order`";

$userinfo = $wpdb->get_results($usersql, ARRAY_A);

//Now we will store all the information into an associative array
//called $data to prepare it for sending via cURL

//please note that the key in the array may need to be changed
//to work with your gateway (refer to your gateways documentation).

$data = array();

$data['USER']	= get_option('my_new_gateway_username');

$data['PWD'] 	= get_option('my_new_gateway_password');

$data['AMT']	= number_format($wpsc_cart->total_price,2);

$data['ITEMAMT']= number_format($wpsc_cart->subtotal,2);

$data['SHIPPINGAMT']= number_format($wpsc_cart->base_shipping,2);

$data['TAXAMT']= number_format($wpsc_cart->total_tax);

foreach((array)$userinfo as $key => $value){

if(($value['unique_name']=='billingfirstname')
    && $value['value'] != ''){

$data['BILLFIRSTNAME']	= $value['value'];

}

if(($value['unique_name']=='billinglastname')
    && $value['value'] != ''){

$data['BILLLASTNAME']	= $value['value'];

}

if(($value['unique_name']=='billingaddress')
    && $value['value'] != ''){

$data['BILLADDRESS']	= $value['value'];

}

if(($value['unique_name']=='billingemail')
    && $value['value'] != ''){

$data['BILLEMAIL']	= $value['value'];

}

if(($value['unique_name']=='billingphone')
    && $value['value'] != ''){

$data['BILLPHONE']	= $value['value'];

}

if(($value['unique_name']=='shippingfirstname')
    && $value['value'] != ''){

$data['SHIPFIRSTNAME']	= $value['value'];

}

if(($value['unique_name']=='shippinglastname')
    &&$value['value'] != ''){

$data['SHIPLASTNAME']	= $value['value'];

}

if(($value['unique_name']=='shippingaddress')
    && $value['value'] != ''){

$data['SHIPADDRESS']	= $value['value'];

}

if(($value['unique_name']=='shippingemail')
    && $value['value'] != ''){

$data['SHIPEMAIL']	= $value['value'];

}

if(($value['unique_name']=='shippingphone')
     && $value['value'] != ''){

$data['SHIPPHONE']	= $value['value'];

}

}

// Ordered Products

foreach($wpsc_cart->cart_items as $i => $Item) {

$data['PROD_NAME'.$i] = $Item->product_name;

$data['PROD_AMT'.$i] = number_format($Item->unit_price,2);

$data['PROD_NUMBER'.$i]	= $i;

$data['PROD_QTY'.$i] = $Item->quantity;

$data['PROD_TAXAMT'.$i]	= number_format($Item->tax,2);

}

//now we add all the information in the array into a long string

$transaction = "";

foreach($data as $key => $value) {

if (is_array($value)) {

foreach($value as $item) {

if (strlen($transaction) > 0) $transaction .= $seperator;

$transaction .= "$key=".urlencode($item);

}

} else {

if (strlen($transaction) > 0) $transaction .= $seperator;

$transaction .= "$key=".urlencode($value);

}

}

//Now we have the information we want to send to the gateway in a nicely formatted string we can setup the cURL

curl_setopt($connection,CURLOPT_URL,"http://this.is.the.gateways.address");

$useragent = 'WP e-Commerce plugin';

curl_setopt($connection, CURLOPT_SSL_VERIFYPEER, 0);

curl_setopt($connection, CURLOPT_SSL_VERIFYHOST, 0);

curl_setopt($connection, CURLOPT_NOPROGRESS, 1);

curl_setopt($connection, CURLOPT_VERBOSE, 1);

curl_setopt($connection, CURLOPT_FOLLOWLOCATION,0);

curl_setopt($connection, CURLOPT_POST, 1);

curl_setopt($connection, CURLOPT_POSTFIELDS, $transaction);

curl_setopt($connection, CURLOPT_TIMEOUT, 30);

curl_setopt($connection, CURLOPT_USERAGENT, $useragent);

curl_setopt($connection, CURLOPT_REFERER, "https://".$_SERVER['SERVER_NAME']);

curl_setopt($connection, CURLOPT_RETURNTRANSFER, 1);

$buffer = curl_exec($connection);

curl_close($connection);

/*

* This is the trickiest part, gateways send back their data in many different ways, please refer to your gateways documentation.

* So now we have passed the information to the gateway and have received information back from the gateway (stored in $buffer),
All we have left is to find out whether the transaction was accepted by the gateway or whether the transaction failed.

* This next bit of code was borrowed from the people at http://shopplugin.net/tour/ and their paypal pro module

*/

$_ = new stdClass();

$r = array();

$pairs = split("&",$buffer);

foreach($pairs as $pair) {

list($key,$value) = split("=",$pair);

if (preg_match("/(w*?)(d+)/",$key,$matches)) {

if (!isset($r[$matches[1]])) $r[$matches[1]] = array();

$r[$matches[1]][$matches[2]] = urldecode($value);

} else $r[$key] = urldecode($value);

}

$response->ack = $r['ACK'];
//with paypal Pro, ACK holds the status of the payment either
//'Success' 'SuccessWithWarning' and other error messages as well.
//All we need at this time is 'Success and SuccessWithWarning

$response->errorcodes = $r['L_ERRORCODE'];

$response->shorterror = $r['L_SHORTMESSAGE'];

$response->longerror = $r['L_LONGMESSAGE'];

$response->severity = $r['L_SEVERITYCODE'];

$response->timestamp = $r['TIMESTAMP'];

$response->correlationid = $r['CORRELATIONID'];

$response->version = $r['VERSION'];

$response->build = $r['BUILD'];

$response->transactionid = $r['TRANSACTIONID'];

$response->amt = $r['AMT'];

$response->avscode = $r['AVSCODE'];

$response->cvv2match = $r['CVV2MATCH'];

if($response->ack == 'Success' || $response->ack == 'SuccessWithWarning'){

//redirect to  transaction page and store in DB as a order with
//accepted payment

$sql = "UPDATE `".WPSC_TABLE_PURCHASE_LOGS.
"` SET `processed`= '2' WHERE `sessionid`=".$sessionid;

$wpdb->query($sql);

$transact_url = get_option('transact_url');

unset($_SESSION['WpscGatewayErrorMessage']);

header("Location: ".$transact_url.$seperator."sessionid=".$sessionid);

}else{

//redirect back to checkout page with errors

$sql = "UPDATE `".WPSC_TABLE_PURCHASE_LOGS.
"` SET `processed`= '5' WHERE `sessionid`=".$sessionid;

$wpdb->query($sql);

$transact_url = get_option('checkout_url');

$_SESSION['WpscGatewayErrorMessage'] =
 __('Sorry your transaction did not go through successfully, please try again.');

header("Location: ".$transact_url);

}

}

So there you have it that is the basic of making a gateway module for the Wp-E-Commerce Plugin. Save your file and place it in the merchants folder (wp-content/plugins/wp-e-commerce/merchants/). I recommend looking through the other files in the merchants folder as a reference as well. Hope that helps you on your way to making a great Online shop.

If you would like to submit your newly created gateway to Wp-E-Commerce to be included in future upgrades please submit it to dev@instinct.co.nz