Payment Gateway API

Introduction

This document is a guide and technical overview of how to create additional Payment Gateways for wpStoreCart 3, using the wpStoreCart Payment Gateway API. The wpStoreCart Payment Gateway API allows you to extend wpStoreCart so that it can accept payments through additional payment providers of your choice.

To effectively utilize this information, you will need to have intermediate experience with PHP & WordPress, as well as documentation from the payment provider regarding their payment API. It is also recommended that you have experience creating WordPress plugins, although this guide will also you walk you through the basics of creating a new WordPress plugin for your custom payment gateway. We also provide a barebones plugin for you to download to base your payment gateway off of. With that said, this document is intended for intermediate and above programmers. However, we do love feedback, and regardless of skill level, if you have any questions regarding the wpStoreCart Payment Gateway API, simply post in the comments below.

We will begin with a step by step tutorial, and will create a new WordPress/wpStoreCart plugin for our payment gateway. You should have a suitable testing machine with a local copy of WordPress to code with, as well as a code editor or IDE. I personally use NetBeans for PHP, but even Notepad or Emacs (I’ll take vi myself) will work. In the tutorial, I will code a payment gateway for PayPal (which is redundant because it’s already included in wpStoreCart 3) After the tutorial, we will follow it with a reference guide.

Programming Skill: Intermediate & above
Time Estimate: Varies depending on your payment gateway.
Skills Needed: PHP, HTML, Server to Server API knowledge, WordPress Hooks & Filters

Creating a Payment Gateway Plugin

Since the goal is to create a new payment gateway, something that wpStoreCart doesn’t already have, that means we need to keep our code separate from the main wpStoreCart plugin. The easiest way to make all this code portable and reusable, is to simply create our new payment gateway inside of a new WordPress plugin. That way, if we later need it on another site, it’s easy to use on any site. We can also redistribute it, and easily maintain it by making it a WordPress plugin. Once we’ve created the WordPress plugin, it’s only a matter of creating a few files, functions, classes, and hooking into action and filter hooks and we’ll be all done. However, each payment provider has a different API to interface with, and that is the one part of this whole process where this guide won’t be able to provide specific information. However, we are available for hire if you would like to pay us to code a custom payment gateway for you. With the sales pitch out of the way, let’s move onto creating our blank WordPress plugin:

Make a New WordPress Plugin

We’re going to begin our journey of creating a new payment gateway by starting with a fresh new WordPress plugin. To begin, let’s head over to our local test server’s WordPress plugin directory and create a new directory. For the sake of this tutorial, we’re going to name this plugin wpsc-payment-gateway-bb and so let’s name our new directory wpsc-payment-gateway-bb. Inside this directory, let’s create two files to begin with:

  • wpsc-payment-gateway-bb.php
  • readme.txt

Now we’ll need to edit both the files to put in the correct WordPress plugin headers, so that WordPress recognizes this as a plugin.

Editing wpsc-payment-gateway-bb.php

First, we’ll edit wpsc-payment-gateway-bb.php in our text editor/IDE. Paste this code into the files, then save it (keep it open though, because we will be doing more edits to this file shortly):


Editing readme.txt

Now, let’s edit the readme.txt file. You should adjust this according to your needs, as I am only providing a barebones readme.txt below. Feel free to close this file when you’re done. Here’s the barebones code to paste into your readme.txt file:

=== wpStoreCart 3+ Payment Gateway Barebones ===
Contributors: jquindlen
Donate link: http://wpstorecart.com/
Tags: wpStoreCart
Requires at least: 3.3.0
Tested up to: 3.5
Stable tag: 1.0.0

A barebones plugin to assist in creating payment gateways for wpStoreCart 3 powered stores.

== Description ==

A barebones plugin to assist in creating payment gateways for wpStoreCart 3 powered stores.

== Installation ==

Replace this with your installation instructions

== Frequently Asked Questions ==

Replace this with your FAQ

== Screenshots ==
 
1. A barebones plugin to assist in creating payment gateways for wpStoreCart 3 powered stores.

== Changelog ==

= 1.0.0 =
* First release!

== Upgrade Notice ==

= 1.0.0 =
* First release!

Activating Our New Plugin

Now that we have a basic plugin going, we can activate from the WordPress plugins admin page, like any other plugin. However, be aware that we will be editing this plugin, and if you happen to load a WordPress page while you’ve got an error in your code, it can deactivate your plugin or otherwise cause your site not to load until you fix the issue. This is another reason why you should only be doing this development on a local test server. When I develop, I always keep my in-development plugin loaded, and only refresh WordPress pages when I think the code is bug free.

So let’s go ahead and visit wp-admin > Plugins > Installed Plugins > wpStoreCart 3+ Payment Gateway Barebones > Activate

How to Add Admin Panel Options

Adding options and settings for your payment gateway is very simple. Simply create a function inside of wpsc-payment-gateway-bb.php that echoes out your options, like this:

/*
 * How to create payment gateway options on the wp-admin > wpStoreCart > Settings > Payment > tab:
 */
function myCustomFunction() {
    global $wpstorecart_settings_obj;

    $wpstorecart_settings_obj = new wpscSettings();
    $wpStoreCartOptions = $wpstorecart_settings_obj->getAdminOptions();

    echo '
    

Your Payment Gateway\'s Name

'.__('Option','wpstorecart').''.__('Description','wpstorecart').''.__('Value','wpstorecart').'

Accept AbcXyz Inc. Payments?

If set to Yes, customers can purchase during checkout using AbcXyz payment gateway.

    

'; }

and then hook into the Payment Settings page like this, using your function name:

add_action('wpsc_admin_payment_options_page', 'myCustomFunction');

Now there is still one thing left to do before this setting will work. We need to register the setting itself. In the example above, the setting is $wpStoreCartOptions['allowAbcXyz']

To add this, we follow the same steps above. Here’s our new function:

/**
 * How to save the custom settings you created for your payment gateway
 */
function myCustomSaveFunction() {
    global $wpstorecart_settings_obj, $wpdb;

    $wpstorecart_settings_obj = new wpscSettings();
    $wpStoreCartOptions = $wpstorecart_settings_obj->getAdminOptions();

    if(isset($_POST['allowAbcXyz'])) { // Here's where you update the value of the variable
        wpscCheckAdminPermissions(); // This insures that only wpStoreCart Managers can edit the settings
        $wpStoreCartOptions['allowAbcXyz'] = $wpdb->escape($_POST['allowAbcXyz']); // Changes the variable in the settings
        update_option('wpStoreCartAdminOptions', $wpStoreCartOptions);    
    }
}

we’ll hook this into the wpsc_admin_save_settings action hook.

add_action('wpsc_admin_save_settings', 'myCustomSaveFunction');

Note that in the example above, the default value will not be set until a wpStoreCart Manager clicks the Save Settings button. However, in many cases, you will need a default value to load up before that time. In that case, remove the default value code from the above function, and instead put it into a new function, like this:

/*
 * Default custom settings values samples
 */
function myCustomDefaultValuesFunction() {
    global $wpstorecart_settings_obj;

    $wpstorecart_settings_obj = new wpscSettings();
    $wpStoreCartOptions = $wpstorecart_settings_obj->getAdminOptions();
    
    if(!isset($wpStoreCartOptions['allowAbcXyz'])) { // If the setting hasn't been initialized previously, give it a default value
        $wpStoreCartOptions['allowAbcXyz'] = 'false'; // Default value.
        update_option('wpStoreCartAdminOptions', $wpStoreCartOptions);
    }    
}

We will tie this into the wpsc_admin action hook, like this:

add_action('wpsc_admin', 'myCustomDefaultValuesFunction');

Add Your Checkout Button

When a user has made it through checkout, and are ready to pay using your processor, you will need to provide a button for them to click on. Keeping with tradition, it’s time to create a new function. This function should output an input submit button, and it should definitely have the following two classes: “wpsc-button wpsc-checkout-button” Another important thing to take into consideration is the changing of the #paymentGateway field. You’ll need to use #paymentGateway value a little later to process the actual order. Here’s my example code, which I put inside of wpsc-payment-gateway-bb.php:

function myCustomCheckoutButtonFunction($output) {
    global $wpstorecart_settings_obj;

    $wpstorecart_settings_obj = new wpscSettings();
    $wpStoreCartOptions = $wpstorecart_settings_obj->getAdminOptions();    
    
    if($wpStoreCartOptions['allowAbcXyz']=='true') {
        $output .= '<input type="submit" value="AbcXyz" class="wpsc-button wpsc-checkout-button wpsc-checkout '.$wpStoreCartOptions['button_classes_checkout'].'" onclick=" jQuery(\'#paymentGateway\').val(\'AbcXyz\');" onsubmit=" jQuery(\'#paymentGateway\').val(\'AbcXyz\');">';
    }
    
    return $output;
}

and then, instead of an action hook, we attach this to a filter hook, like this:

add_filter('wpsc_final_checkout_buttons','myCustomCheckoutButtonFunction', 10, 1);

Extend the PaymentGateway Class

With our base plugin started, it’s now time to move into creating our payment gateway. First, let’s consult our payment provider’s documentation on their API. What we need to do will vary by payment gateway, but the general outline is this:

  • We pass the values from wpStoreCart to the Payment Gateway
  • The payment gateway handles the payment
  • The payment gateway communicates back to wpStoreCart whether payment was successful or not

So step 1 is we need to take the values from wpStoreCart and send it to the payment gateway. For many payment providers, this is done by simply submitting a form, using a GET or POST request. If the payment gateway you are coding uses this method, then your next step is to extend the PaymentGateway class to facilitate this. The PaymentGateway class is generic, and easily allows you to define the fields and the URL to submit the payment to your provider. Let’s explore how to set this up inside of wpsc-payment-gateway-bb.php:

include_once(WP_PLUGIN_DIR.'/wpstorecart/wpstorecart/payment/PaymentGateway.php');
class AbcXyz extends PaymentGateway {

    /**
	 * Initialize the Paypal gateway
	 *
	 * @param none
	 * @return void
	 */
	public function __construct()
	{
        parent::__construct();

        // Some default values of the class
		$this->gatewayUrl = 'https://www.paypal.com/cgi-bin/webscr';
		$this->ipnLogFile = 'paypal.ipn_results.log';

		// Populate $fields array with a few default
		$this->addField('rm', '2');           // Return method = POST
		$this->addField('cmd', '_xclick');
	}

    /**
     * Enables the test mode
     *
     * @param none
     * @return none
     */
    public function enableTestMode()
    {
        $this->testMode = TRUE;
        $this->gatewayUrl = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
    }

    /**
	 * Validate the IPN notification
	 *
	 * @param none
	 * @return boolean
	 */
	public function validateIpn() {
		// parse the paypal URL
		$urlParsed = parse_url($this->gatewayUrl);

		// generate the post string from the _POST vars
		$postString = '';

		foreach ($_POST as $field=>$value)
		{
			$this->ipnData["$field"] = $value;
			$postString .= $field .'=' . urlencode(stripslashes($value)) . '&';
		}

		$postString .="cmd=_notify-validate"; // append ipn command

		// open the connection to paypal
		$fp = fsockopen($urlParsed[host], "80", $errNum, $errStr, 30);

		if(!$fp)
		{
			// Could not open the connection, log error if enabled
			$this->lastError = "fsockopen error no. $errNum: $errStr";
			$this->logResults(false);

			return false;
		}
		else
		{
			// Post the data back to paypal

			fputs($fp, "POST $urlParsed[path] HTTP/1.1\r\n");
			fputs($fp, "Host: $urlParsed[host]\r\n");
			fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
			fputs($fp, "Content-length: " . strlen($postString) . "\r\n");
			fputs($fp, "Connection: close\r\n\r\n");
			fputs($fp, $postString . "\r\n\r\n");

			// loop through the response from the server and append to variable
			while(!feof($fp))
			{
				$this->ipnResponse .= fgets($fp, 1024);
			}

		 	fclose($fp); // close connection
		}

		if (eregi("VERIFIED", $this->ipnResponse))
		{
		 	// Valid IPN transaction.
		 	$this->logResults(true);
		 	return true;
		}
		else
		{
		 	// Invalid IPN transaction.  Check the log for details.
			$this->lastError = "IPN Validation Failed . $urlParsed[path] : $urlParsed[host]";
			$this->logResults(false);
			return false;
		}
	}
}

Processing the Cart & Payment

In the last step. wpStoreCart calculates everything you’ll need and provides the values you’ll need to pass to your payment gateway, using the global variable $wpscPaymentGateway, which is an array with the following data:

$wpscPaymentGateway['payment_gateway'] The payment gateway’s name, for example: paypal
$wpscPaymentGateway['success_permalink'] The URL to redirect customers to if payment succeeds
$wpscPaymentGateway['failed_permalink'] The URL to redirect customers to if payment fails
$wpscPaymentGateway['payment_gateway_item_count'] The number of unique products in the cart (does not take into account quantities, also note that variations and attributes are unique products and do increase this value.
$wpscPaymentGateway['cart_dbf'] The cart contents in database format: 0*0
$wpscPaymentGateway['cart_description'] A comma separated list of item names and quantity of the entire cart, for example: Item Name One (x2), Item Two
$wpscPaymentGateway['total_price'] The total price of the cart
$wpscPaymentGateway['total_shipping'] The total shipping for the cart
$wpscPaymentGateway['total_price_with_shipping'] The total price of the cart, including shipping charges
$wpscPaymentGateway['final_price'] The total price + the shipping price + calculated taxes
$wpscPaymentGateway['is_coupon_set'] False if no coupon has been set, true if there has been
$wpscPaymentGateway['discount_amount'] The amount to subtract from the total
$wpscPaymentGateway['discount_percent'] The percent to subtract from the total
$wpscPaymentGateway['is_donation'] False if not a donation, true if it is
$wpscPaymentGateway['order_tax'] Tax amount of $wpscPaymentGateway['total_price'] combined with $wpscPaymentGateway['total_shipping']
$wpscPaymentGateway['customer_user_id'] The WordPress user id of the customer, where 0 is a guest
$wpscPaymentGateway['customer_email'] The email of the customer
$wpscPaymentGateway['customer_username'] The display name of the customer. This is their username, not their actual names. Guests will include their IP address in this field.
$wpscPaymentGateway['order_id'] The unique key associated with this order. If you need to do additional MySQL queries with this order, note that this ID is the primary key of the wpstorecart_orders table.

Submitting To The Payment Gateway

After all that prep work, we’re at the end of the road. It’s time to take our custom payment gateway class that we created, and use it to submit the data that wpStoreCart has provided about the order to our payment provider. The primary way to do that is to use the addField method of the payment gateway object and feed it data from either $wpscPaymentGateway, $wpStoreCartOptions, or your own custom data.

For example, most payment gateways will want to know what URL to send your customer to if the payment is successful. In this case, PayPal has a field called return that it expects. Using the API reference table, we see that wpStoreCart provides a URL for successful payments in the global variable $wpscPaymentGateway['success_permalink'] so the following code

$myPaypal->addField('return', $wpscPaymentGateway['success_permalink']);  

However, that code needs to be in the right place. Again, we use an action hook

function process_AbcXyz_payments() {
    global $wpscPaymentGateway, $wpstorecart_settings_obj;

    $wpstorecart_settings_obj = new wpscSettings();
    $wpStoreCartOptions = $wpstorecart_settings_obj->getAdminOptions(); // Grabs the settings    
    
    if($wpscPaymentGateway['payment_gateway'] == 'AbcXyz') {  // This needs to match the value we set early in this code: onsubmit=" jQuery(\'#paymentGateway\').val(\'AbcXyz\');"

		$myPaypal = new AbcXyz(); // Create an instance of the AbcXyz class we just defined
		$myPaypal->addField('business', $wpStoreCartOptions['paypalemail']); // Specify your paypal email
		$myPaypal->addField('currency_code', $wpStoreCartOptions['currency_code']); // Specify the currency
		$myPaypal->addField('rm', '2'); // Return method = POST
		$myPaypal->addField('upload', '1');
		$myPaypal->addField('cancel_return', $wpscPaymentGateway['failed_permalink']);
		$myPaypal->addField('notify_url', $wpStoreCartOptions['paypalipnurl']); // Specify the url where paypal will send the IPN
		if($wpStoreCartOptions['paypaltestmode']=='true') { $myPaypal->enableTestMode(); } // Enable test mode if needed

		foreach ($wpscPaymentGateway['cart'] as $item) {
					$myPaypal->addField('item_name_' . $item['item_number'], $item['name']);
					$myPaypal->addField('amount_' . $item['item_number'], $item['price']);
					$myPaypal->addField('item_number_' . $item['item_number'], $item['item_number']);
					$myPaypal->addField('quantity_' . $item['item_number'], $item['qty']);
		}

		// Implement shipping here if needed
		if($wpscPaymentGateway['total_shipping'] > 0) {
			$myPaypal->addField('shipping_1', $wpscPaymentGateway['total_shipping']);
		}                    
		
		if($wpscPaymentGateway['is_donation'] == true) {
			$myPaypal->addField('cmd', '_donations');
		} else {
			$myPaypal->addField('cmd', '_cart');
		}

		if($wpscPaymentGateway['discount_amount'] > 0) {
			@$myPaypal->addField('discount_amount_cart', $wpscPaymentGateway['discount_amount']);
		}
		if($wpscPaymentGateway['discount_percent'] > 0) { //
			@$myPaypal->addField('discount_rate_cart', $wpscPaymentGateway['discount_percent']);
		}

		

		$myPaypal->addField('return', $wpscPaymentGateway['success_permalink']);                    
		
		// Specify any custom value, here we send the primkey of the order record
		$myPaypal->addField('custom', $wpscPaymentGateway['order_id']);

		// Tax
		if($wpscPaymentGateway['order_tax'] > 0) {
			$myPaypal->addField('tax_cart', $wpscPaymentGateway['order_tax']);
		}

		$myPaypal->submitPayment();
		
    }
}

and then we tie this function to our wpsc_process_payment_gateways() hook.

add_action('wpsc_process_payment_gateways', 'process_AbcXyz_payments');

Determining if the Payment Was Successful

The final thing that needs to be done before we can wrap everything up, is to figure out whether or not the payment succeeded.

This section is a work in progress, which I’ll finish before wpStoreCart 3 beta 1 is released.

Reference Guide

Available Variables

$wpscPaymentGateway['payment_gateway'] The payment gateway’s name, for example: paypal
$wpscPaymentGateway['success_permalink'] The URL to redirect customers to if payment succeeds
$wpscPaymentGateway['failed_permalink'] The URL to redirect customers to if payment fails
$wpscPaymentGateway['payment_gateway_item_count'] The number of unique products in the cart (does not take into account quantities, also note that variations and attributes are unique products and do increase this value.
$wpscPaymentGateway['cart_dbf'] The cart contents in database format: 0*0
$wpscPaymentGateway['cart_description'] A comma separated list of item names and quantity of the entire cart, for example: Item Name One (x2), Item Two
$wpscPaymentGateway['total_price'] The total price of the cart
$wpscPaymentGateway['total_shipping'] The total shipping for the cart
$wpscPaymentGateway['total_price_with_shipping'] The total price of the cart, including shipping charges
$wpscPaymentGateway['final_price'] The total price + the shipping price + calculated taxes
$wpscPaymentGateway['is_coupon_set'] False if no coupon has been set, true if there has been
$wpscPaymentGateway['discount_amount'] The amount to subtract from the total
$wpscPaymentGateway['discount_percent'] The percent to subtract from the total
$wpscPaymentGateway['is_donation'] False if not a donation, true if it is
$wpscPaymentGateway['order_tax'] Tax amount of $wpscPaymentGateway['total_price'] combined with $wpscPaymentGateway['total_shipping']
$wpscPaymentGateway['customer_user_id'] The WordPress user id of the customer, where 0 is a guest
$wpscPaymentGateway['customer_email'] The email of the customer
$wpscPaymentGateway['customer_username'] The display name of the customer. This is their username, not their actual names. Guests will include their IP address in this field.
$wpscPaymentGateway['order_id'] The unique key associated with this order. If you need to do additional MySQL queries with this order, note that this ID is the primary key of the wpstorecart_orders table.

Available Cart Variables

n = the cart item number. First item in cart is 1, for example $wpscPaymentGateway['cart'][3]['name'] is the 3rd item in the cart’s name.

$wpscPaymentGateway['cart'][n]['item_number'] The cart item number, starting with 1
$wpscPaymentGateway['cart'][n]['name'] The cart item’s name
$wpscPaymentGateway['cart'][n]['price'] The item’s price
$wpscPaymentGateway['cart'][n]['qty'] The quantity of this item in the cart

Action Hooks

wpsc_admin_payment_options_page() Echo out a table with the class of widefat, that has input elements for each setting your payment gateway will need.
wpsc_admin_save_settings() Using the $_POST global variable, save the options you previously created input elements for
wpsc_admin() Save default settings here
wpsc_process_payment_gateways() This hook is for sending data from wpStoreCart, to your payment gateway.

Filter Hooks

wpsc_final_checkout_buttons() Return a string with a button that sets the value of the #paymentGateway element.