Introduction

This guide is an introduction to creating payment gateways in X-Cart.

In this article, we will create the simplest PHP script that will emulate the work of a payment gateway, and then we will create an integration with this self-designed “payment gateway”.

Table of Contents

Self-designed payment gateway

Since payment gateways often change their API, and we want to keep this guide relevant as long as possible, we will create a test PHP script that will emulate the work of a payment gateway. This test script will be able to accept two parameters via POST request:

  1. returnURL will define where customer must be redirected to after a successful transaction (all our transactions will be successful in our scenario);
  2. transactionID will define the transaction number.

The output of this script will be a redirect of a customer to the returnURL passed in the request. This returnURL will be appended with transactionID submitted and status=Paid parameters. For example, if we submit a request with the following parameters:

  1. returnURL = http://example.com?target=main
  2. transactionID = 10

we will be redirected to http://example.com?target=main&transactionID=10&status=Paid URL.

We will create this “payment gateway” script as the <X-Cart>/payment.php file with the following content: 

<?php

$location = $_POST['returnURL'] . '&transactionID=' . $_POST['transactionID'] . '&status=Paid';

header('Location: ' . $location);
die();

Payment gateway module implementation

We start the creation of the payment gateway by creating an empty module with the developer ID Tony and the module ID PaymentDemo. Then, we create the file <X-Cart>/classes/XLite/Module/Tony/PaymentDemo/Model/Payment/Processor/DemoPayment.php with the following content: 

<?php

namespace XLite\Module\Tony\PaymentDemo\Model\Payment\Processor;

class DemoPayment extends \XLite\Model\Payment\Base\WebBased
{
    protected function getFormURL()
    {
        return \XLite::getInstance()->getShopURL() . 'payment.php';
    }

    protected function getFormFields()
    {
        return array(
            'transactionID' => $this->transaction->getPublicTxnId(),
            'returnURL' => $this->getReturnURL('transactionID'),
            );
    }

    public function processReturn(\XLite\Model\Payment\Transaction $transaction)
    {
        parent::processReturn($transaction);

        $result = \XLite\Core\Request::getInstance()->status;

        $status = ('Paid' == $result)
            ? $transaction::STATUS_SUCCESS
            : $transaction::STATUS_FAILED;

        $this->transaction->setStatus($status);
    }
}

and this class describes our payment gateway integration.

Let us have a closer look at its implementation:

  1. Our class extends the class \XLite\Model\Payment\Base\WebBased, because our payment gateway is a typical web-form payment gateway, i.e. the shopping cart will redirect the customer to the payment form (in our case, payment.php), the customer will input their credit card details there (we skip this step as payment.php will accept all orders), and then the payment gateway will redirect the customer back to the shopping cart. Depending on the order status passed alongside with redirecting the customer to the shopping cart, the shopping cart will either show a Thank you page or Your transaction is failed error message.
  2. The getFormURL() method defines where we are going to submit the request. In our case, it should be your store’s URL + payment.php.

  3. The getFormFields() method defines what fields we are going to submit to the URL defined in the getFormURL() method. In our case, we are going to submit the transactionID param with the value returned from the getPublicTxnId() method (public transaction ID is a character-digit string that will identify this transaction) and the returnURL param generated by the getReturnURL() method.

  4. The getReturnURL() method generates a return URL for the current transaction. If it is called as getReturnURL(false), it will generate the cart.php?target=payment_return URL. If it is called as getReturnURL('transactionID'), then the result will be cart.php?target=payment_return&txn_id_name=transactionID. Since our payment gateway will append our return URL with the transactionID parameter, the actual return URL to which the customer is redirected will be cart.php?target=payment_return&txn_id_name=transactionID&transactionID=a1b2c3d4.
  5. Once X-Cart receives a request at the URL cart.php?target=payment_return&txn_id_name=transactionID&transactionID=a1b2c3d4, it will try to identify the transaction that needs to be updated. X-Cart will have a look at the txn_id_name parameter, and since its value is transactionID, X-Cart will find out that transaction ID is stored in the transactionID parameter and will have a look at the transactionID=a1b2c3d4 parameter. Finally, it will find out that the needed transaction is identified by the ID a1b2c3d4 and will look for it in the database.
  6. When the transaction object is found, X-Cart will run our payment gateway’s processReturn() method passing this transaction object as an argument to it: 

        public function processReturn(\XLite\Model\Payment\Transaction $transaction)
        {
            parent::processReturn($transaction);
    
            $result = \XLite\Core\Request::getInstance()->status;
    
            $status = ('Paid' == $result)
                ? $transaction::STATUS_SUCCESS
                : $transaction::STATUS_FAILED;
    
            $this->transaction->setStatus($status);
        }
    

    This method analyzes the request received, and if the request contains the status=Paid parameter, then we will mark this transaction as successful: 

    $this->transaction->setStatus($status);
    

Our payment integration is ready and now we only need to register this payment gateway in the system. For that, we create the file <X-Cart>/classes/XLite/Module/Tony/PaymentDemo/install.yaml with the following content: 

XLite\Model\Payment\Method:
  - service_name: DemoPayment
    class: Module\Tony\PaymentDemo\Model\Payment\Processor\DemoPayment
    type: C
    translations:
      - code: en
        name: Demo Payment

Now the YAML file contains all the needed information about this payment method:

  1. class field defines what PHP class describes this payment method. In our case, it is the class we have just created above.

  2. type = C defines that this payment method is a credit card one. Other possible values are: “A”, which refers to all-in-one solutions like Paypal Standard, where you do not need to specify credit card info directly, and “O”, which refers to Offline payment methods.

  3. translation section defines that our payment method will be called Demo Payment in English.

For payment methods that have country restrictions based on the merchant’s location, be sure to add information about these restrictions to the YAML file. The format is as follows: 

XLite\Model\Payment\Method:
 - service_name: AuthorizeNet SIM
   countries: [US, CA]
   exCountries: [US, CA]
  • The field countries provides a list of codes of allowed merchant countries. If a country is listed in this field, it means that merchants from this country may register an account with the payment system and use this payment method to accept payments on their website. If the field is blank, it means that the payment method is available in all countries (In this case, the field countries may be omitted from the YAML file).
  • The field exCountries provides a list of exceptions. It means that merchants from all countries - except for the ones listed in this field - may register an account and use this method. If there are no exceptions, the field may be omitted.

Your YAML file will probably contain just one of the above fields.

The list of allowed countries / exceptions in the YAML file will be used to filter payment methods in the payment method selection popup in the admin area.

Once the YAML file has been created, do not forget to push it to the database.

The mod is completed, and we need to re-deploy the store in order to test it in action.

We should go to the Store setup > Payment methods section in the Admin area, click the Add payment method button there, search for the keyword Demo in the given form and then add the Demo Payment method by clicking the Add button:

After the payment method has been added, you need to enable it by clicking this icon:

Now we need to go to the storefront, add some products to cart and go to checkout. You will see the Demo Payment method there:

Finally, click the Place Order button and submit the order. You should see the Thank you page, and the status of this new order should be set to Paid.

Module pack

You can download this module example from here: https://dl.dropboxusercontent.com/u/23858825/Tony-PaymentDemo-v5_1_0.tar

Module example (with the settings page) for X-Cart v5.2.x: Tony-PaymentDemo-v5_2_0.tar

Module example (with the settings page) for X-Cart v5.3.x: XCExample-Payment-v5_3_0.tar