The Pancake Gateway System

@todo gateway variables

@todo generate_payment_form is AFTER client_fields were requested, so $this->get_client_field() can be used

@todo generate_payment_form can return false with $this->error() or array of $data if payment was completed then and there or string

The basics

A Pancake Gateway is simply a file that acts as the middle man between Pancake and any payment gateway, located in system/pancake/modules/gateways/models. To start a new gateway, create a file in that folder. Name it gatewayname_m.php (eg. paypal_m.php). Here's the basic structure of a gateway:

<?php
class Gatewayname_m extends Gateway {
	public $title = 'Gatewayname (as viewed by the admin on the settings page)';
	public $frontend_title = 'Gateway name (as viewed by the client when paying)';

	public function __construct() {
		parent::__construct(__CLASS__);
	}

	public function generate_payment_form($unique_id, $item_name, $amount, $success,
	$cancel, $notify, $currency_code, $invoice_number) {

	}

	public function process_cancel($unique_id) {

	}

	public function process_success($unique_id) {

	}

	public function process_notification($unique_id) {

	}

}
?>

Fairly simple, right? Now, let me tell you a bit about what those functions do, and how you're supposed to handle them.

__construct()

This is where you can define what configuration fields you need for your gateway, and load necessary payment gateway code. PayPal, for example, needs the merchant account's email address, so this is how it looks like for PayPal:

parent::__construct(__CLASS__);
$this->fields = array('paypal_email' => 'PayPal Email');
$this->load->library('paypal_lib');

$this->fields is just an array containing all your gateway's configuration fields, in a field name => label format. It's pretty simple. The third line simply loads code that helps us deal with PayPal. Your payment gateway might have an SDK, or a set of files that you should use, that help make integration easier. You should load those in __construct(), so you can access their functionality anywhere in your Pancake Gateway.

generate_payment_form($unique_id, $item_name, $amount, $success, $cancel, $notify, $currency_code, $invoice_number)

This function is called when a client wants to pay using your gateway. You are given the partial payment's unique ID (not the same as an invoice's unique ID), the item name (eg. "Invoice #xxx"), the amount to pay, the URL to the success page, the cancel page and the payment notification page, the currency code (three-letter code, like EUR, GBP or USD), and the invoice number. This function is required to return a <form> with whatever hidden fields are necessary to send the user to the payment gateway, and a submit button. That's it. Nothing special. Pancake will then use some magic to automatically submit that form and thus redirect the user to the payment gateway.

process_cancel($unique_id)

This function is called when the gateway sends the user to the cancel URL (as set in generate_payment_form()). It is not required to return anything, it's just giving you a chance to do whatever processing you feel you have to.

process_success($unique_id)

This function is called when the gateway sends the user to the success URL (as set in generate_payment_form()). It is not required to return anything, but if it returns an array in the same format as process_notification() is expected to return, it'll use that as the payment notification. This is useful for gateways that don't send payment notifications, choosing instead to pass the payment information when the user is returning to the success URL.

process_notification($unique_id)

This function is called when the gateway calls the notification URL (as set in generate_payment_form()). It is required to return an array in the following format:

return array(
    'txn_id' => '', // the gateway transaction ID
    'payment_gross' => 0, // the amount paid, rounded to 2 decimal places
    'transaction_fee' => 0, // the fee charged by the gateway, rounded to 2 decimal places
    'payment_date' => time(), // a UNIX timestamp for the payment date
    'payment_status' => 'Completed', // One of: Completed/Pending/Refunded/Unpaid
    'item_name' => '', // the item name (passed to the gateway in generate_payment_form())
    'is_paid' => true, // true or false, depending on whether payment was successful or not
);

Gateway::complete_payment($unique_id, $gateway, $data)

In most cases, you should not have to call this function, but some gateways may send you payment notifications that contain the details of multiple transactions. In those situations, you might need to manually tell Pancake to process a payment. That's what this function is here for.

The $unique_id is the partial payment's unique ID (not the same as an invoice's unique ID). $gateway is the name of your gateway's file, without the extension (eg. gatewayname_m). $data is an array in the format that process_notification() is expected to return.

That's it!

Now you know pretty much everything there is to know about Pancake Payment Gateways. It couldn't be simpler, right? If you have any difficulties, feel free to start a free support ticket. If you didn't understand something, send an email to bruno@pancakeapp.com RIGHT NOW. I'll help you out. If you think I missed something, or that there's things that could be improved, you should email me at bruno@pancakeapp.com. If you've got ideas, suggestions, feedback of any kind, or if you just want to tell me that I'm awesome, feel free to email me, too. Just bear in mind that flattering me will not get you free beer. Kay, now that's out in the open. Anyway, go make some Pancake Gateways, now!

P.S. (Oh, I forgot something.)

If you think your gateway is cool, and you want to make sure it'll always work with Pancake, send its files to support@pancakeapp.com. We'll integrate it into the Pancake core, and keep it updated so it won't ever break.