LemonStand Documentation

Developing payment modules

LemonStand payment modules are classes defined in PHP scripts located in the modules/shop/payment_types directory. Technically payment module classes belong to the Shop module. You can develop your own payment module classes in order to provide LemonStand integration with specific payment gateways. Non-native payment modules can be distributed separately from the LemonStand Shop module. It allows you to share payment modules with other LemonStand users.

Structure of a payment module

Payment module classes should extend the Shop_PaymentType class. This abstract PHP class contains all methods sufficient for developing any payment module. By overriding methods of this base class you can add specific features to your payment module.

There is a naming convention, which allows LemonStand to load payment module classes automatically. Payment module class names should have the following structure: Shop_ModuleName_Payment. The Shop_ prefix and the _Payment suffix are required. Between the prefix and suffix you use any suitable name, describing a module. For example, in this article we will demonstrate the process of developing a payment module for the Beanstream payment gateway. This gateway has two integration options - the basic HTTP method and the advanced method, also called the server-to-server method. A suitable class name for the Beanstream basic integration method is Shop_Beanstream_Basic_Payment.

Each payment module class should be defined in a separate file, with the name matching the class name it contains, written in lower case. If the class name was the Shop_Beanstream_Basic_Payment, a corresponding file name, would be shop_beanstream_basic_payment.php.

Aside from the payment module PHP file, payment modules can also have a directory, with name matching the module PHP file name. The directory should be located in the same directory with the module PHP file, i.e. in the modules/shop/payment_types directory. If a payment module class name is shop_beanstream_basic_payment.php, than the corresponding module directory name is shop_beanstream_basic_payment. Module directories can contain HTML and XML files required for the module. Below is a screenshot of the modules/shop/payment_types directory. On the screenshot you can see some payment module PHP files and corresponding directories.

Types of the payment gateway integration

There are two generic types of payment integration methods. The redirection method implies a payment form located on the payment gateway server. When a customer clicks the Pay button on your store, he is redirected away from the store to the secure payment form hosted on the payment gateway server. PayPal Standard and Authorize.Net Simple Integration Method are examples of the redirection integration approach.

With another integration method, which is sometimes called the server-to-server integration method, the payment form is located on your own server. When a customer clicks the Pay button, the payment module sends a request to the payment gateway in background, and then displays the transaction registration result to the customer. Customers do not leave your website, and the method provides more consistent user experience. PayPal Pro and Authorize.net Advanced Integration Method are examples of the server-to-server integration.

You can implement both integration methods with LemonStand payment modules. Actually, most of the existing LemonStand payment modules have two versions, corresponding the redirection and server-to-server integration. If you are going to implement both integration methods for a single payment gateway, you will need to develop two different classes. For example, for the Beanstream payment gateway there are two payment module classes: Shop_Beanstream_Basic_Payment and Shop_Beanstream_ServerToServer_Payment.

You can find the Beanstream payment modules which we refer in this article in the following files:

  • /modules/shop/payment_types/shop_beanstream_basic_payment.php - Beanstram basic (redirection) integration method.
  • /modules/shop/payment_types/shop_beanstream_servertoserver_payment.php - Beanstram server-to-server integration method.

Common payment module functions

Regardless of what specific integration type (redirection or server-to-server) a payment module implements, there is a number of common function each payment module should provide. Firstly, each module should provide the information about itself - the payment gateway name, and payment module description. Also each module should have a configuration form, which LemonStand administrators will use for creating a payment method and setting module-specific parameters. All required payment module functions should be implemented as specific class metho[ds, which we are describing below.

Defining a payment module class

Below is a partial declaration of the payment module class, which implements the Beansream Basic integration. The code defines the class and a method which returns the module specific information.

<?
  class Shop_Beanstream_Basic_Payment extends Shop_PaymentType
  {
    public function get_info()
    {
      return array(
        'name'=>'Beanstream Basic Integration',
        'description'=>'A basic HTTP POST integration. The customer’s browser will be pointed to the Beanstream server at the time of processing.'
      );
    }
  }
?>

The get_info() method should be declared in all payment modules. The method should return an array containing the module name and description. This information will be presented in the Add Payment Method form in the Administration Area:

The resulting array can also contain elements specific for the redirection and server-to-server integration methods. We will explain the possible array elements in corresponding articles.

Building the payment module configuration form

Another required payment module class method is the build_config_ui(). This method builds the module configuration form and it is similar to the define_form_fields() method of the model class, which we described in the Forms article. In this method you can add tabs and fields to the module configuration form. All field values are saved automatically and you can access them inside the payment processing code. In this method you should add only module-specific fields, for example fields for API user name and password. All fields which are common for all payment modules, for example payment method name, description and checkboxes for selecting countries the method is applicable for, are added by LemonStand automatically. The set of fields depends on specific payment gateway and you need to refer to your payment gateway API description in order to find out which configuration fields you need to create on the configuration form.

Below is a definition of the build_config_ui() method of the Beanstream Basic Integration payment module.

public function build_config_ui($host_obj, $context = null)
{
  if ($context !== 'preview')
  {
    $host_obj->add_field('merchant_id', 'Merchant ID')->tab('Configuration')->renderAs(frm_text)->
      comment('Include the 9-digit Beanstream ID number here.', 'above')->validation()->fn('trim')->
      required('Please provide Merchant ID.');
  }

  $host_obj->add_field('transaction_type', 'Transaction Type')->tab('Configuration')->renderAs(frm_dropdown)->
    comment('The type of credit card transaction you want to perform.', 'above');
  
  $host_obj->add_field('order_status', 'Order Status')->tab('Configuration')->renderAs(frm_dropdown)->
    comment('Select status to assign the order in case of successful payment.', 'above', true);
}

The method receives 2 parameters - the Active Record object, which should be used for adding form fields, and a form context. If the form context value is preview, the method should not create any form fields which contain API user names or passwords, because the payment gateway preview form is available in read-only mode from the Order Preview page. The condition in the beginning of the example code excludes the Merchant ID field from the Preview form. For example, below is the preview form of the PayPal Standard payment module, which LemonStand administrators can access from the Shop/Orders/Order Preview page.

The example code creates 3 fields on the configuration form - Merchant ID, Transaction Type and Order Status. The Merchant Id field is a gateway-specific field, which is required in order to register a transaction on the Beanstream payment gateway. The Transaction Type field is also a gateway-specific field. It allows to choose a specific operation to be applied to a credit card. Many payment gateways allow to specify a transaction type in the transaction registration request. The Order Status field allows to select a status the order should be sent after successful transaction registration. With rare exception you will need to create this form field on all payment module forms. Below is a screenshot of the Configuration tab of the module configuration form:

To add fields to the configuration form, the code inside the build_config_ui() method should call the add_field() method of the object, passed in the first method parameter. This method has two parameters - the field identifier and the field title. Field identifiers should be compatible with PHP variable names - they should not contain spaces, and they can contain only Latin characters and numbers. Using the optional third parameter you can specify a field placement on the form. Allowed parameter values are left, right and full (it is a default value).

The add_field() method returns an object of the [link]Db_FormFieldDefinition[/link] class, which you can use for configuring a field appearance and validation rules. The renderAs() method allows to specify a preferable control type for a field. You can find a list of possible control types in the [link]Db_FormFieldDefinition[/link] class description.

The code above sets the drop-down control type for the order_status and transaction_type form fields. For each drop-down field there has to be defined a method returning a list of options. The method name should have the following structure: get_field_name_options. Thus, for the order_status and transaction_type valid method names are get_order_status_options and get_transaction_type_options. The methods should have a single parameter with default value -1. Below is an example of the both methods:

public function get_transaction_type_options($current_key_value = -1)
{
  $options = array(
    'PA'=>'Pre-authorization',
    'P'=>'Purchase'
  );
  
  if ($current_key_value == -1)
    return $options;

  return isset($options[$current_key_value]) ? $options[$current_key_value] : null;
}

public function get_order_status_options($current_key_value = -1)
{
  if ($current_key_value == -1)
    return Shop_OrderStatus::create()->order('name')->find_all()->as_array('name', 'id');

  return Shop_OrderStatus::create()->find($current_key_value)->name;
}

The methods return arrays of available options as associative arrays with indexes matching option identifiers and values matching option titles. For example, the get_transaction_type_options() method, which returns a list of options for the Transaction Type field, returns the following array:

array(
  'PA'=>'Pre-authorization',
  'P'=>'Purchase'
);

The array key values (PA and P) correspond the Beanstream API documentation for possible transaction types. LemonStand renders this field as a drop-down menu with options corresponding the array elements:

Methods which return option lists, should check the method parameter value. If the parameter value is equal to -1, a method should return all possible options. If the parameter value is not -1, the method should try to find an option corresponding the parameter value, and return the option name (title). You can find conditions examining the $current_key_value parameter value in the code examples above.

Validating the configuration form data

All payment module classes should override the validate_config_on_save() method. Inside this method a module can check configuration field values before the configuration is saved to the database. The method has a single parameter - an object, with fields matching form fields defined in the build_config_ui() method. The method should be implemented even if you are not going to perform any parameter validation. In this case you can leave it empty. Below is a code example, which checks the merchant_id field:

public function validate_config_on_save($host_obj)
{
  if ($host_obj->merchant_id == 'some_false_value')
    $host_obj->field_error('merchant_id', 'Please specify a valid value in the Merchant Id field.');
}

Processing gateway response

Another method which must be implemented in all payment method classes is the process_payment_form(). This method is called by LemonStand when it receives a response from a payment gateway. We will describe the method implementation for the redirection and server-to-server integration types in the corresponding articles.

Initializing the configuration form field values

You can initialize values of the configuration form fields using the init_config_data() optional method. The values will be applied when a payment method based on your payment module is created. The method receives a single parameter, which you can use for setting values to fields defined in the build_config_ui() method. Example:

public function init_config_data($host_obj)
{
  $host_obj->merchant_id = '000000';
}

Disallowing an order status deletion

If your payment method configuration form has the Order Status field, you should disallow LemonStand administrators to delete an order status the payment method refers to, in order to keep the system integrity. The status_deletion_check() method is called by LemonStand each time when somebody tries to delete an order status on the System/Order Route page. You can implement the method in the following way:

public function status_deletion_check($host_obj, $status)
{
  if ($host_obj->order_status == $status->id)
    throw new Phpr_ApplicationException('This status cannot be deleted because it is used in the Beanstream Basic payment method.');
}

Payment form partial templates

Each payment gateway should provide a payment form partial template file, containing a payment form which will be displayed on the front-end store. When LemonStand finds a new payment module, it creates a new partial from the template file. The partial name depends on a payment module name. For example, for the Beanstream Basic payment module, LemonStand creates a partial with the "payment:beanstream_basic" name. Store developers can modify payment partials for styling purposes.

The payment form partial is automatically rendered by LemonStand when the render_payment_form() method is called from the Pay page. The partial template file should have the front_end_partial.htm name and should be placed to the payment method directory, which we mentioned earlier in the Structure of a payment module section of this article.

Please note that LemonStand creates partials from template files only once, if it cannot find a payment partial for a specific payment method. LemonStand never updates contents of existing payment form partials, allowing LemonStand administrators to customize them. During the payment module development process, if you need to update a payment form partial content, you may need to delete the corresponding partial manually (on the CMS/Partials page), and then update the partial template file. Then LemonStand will re-create the partial from the template file as soon as you open the Pay page.

We will describe the template files content for redirection and server-to-server integration methods in the following articles:

Next: Redirection integration method
Previous: Developing LemonStand modules
Return to Extending LemonStand

Comments

No comments posted so far.

Add your comment

Loading form...