Quickstart

Overview

This guide explains how to organise payment processing via Payment Page. So that the form would open from the web service and return customers to this web service. And so that you could use tested and quick solutions—with clear instructions, libraries, and code examples And so that you could use programming solutions in one of the three popular programming languages—PHP, Python, or Java.



If you are interested in something else, there are other options available.

Figure: Other options

  • To learn how to generate payment links for opening Payment Page, you can figure out how to work with them either manually via Dashboard or automatically via Gate.
  • To get deep understanding of the workflow and the capabilities of the work with Payment Page, you can see this article.
  • To address other things relevant to you, you can to refer to other sections (for example, starting here) and contact the ecommpay specialists.

With that, let’s get started.

Brief theory

Projects and keys

The work with the ecommpay payment platform can be compared to using hotel services: to check into a hotel, you need a room and a key for this room, and to start working with the platform, you need a project and a key for this project. And like in case of hotel rooms, there can be different number of projects for one client—for different aims and purposes—and each project requires its own key.

Usually, to work with the platform, having one test and one production project is enough. This case is typical and is used as the basis within the Quickstart guide. If for some reason you need more projects, this should be discussed with the key account manager, but still you can start with one test project.

To start working with the platform, you need a project and a key for this project. If the identifier (project_id) and the secret key (secret_key) of the test project have been already obtained, you can prepare them for use and proceed with this article. Otherwise, you can get the access to the test project and return to this article.

Workflow

For Payment Page to open correctly, the collection of parameters, signature generation, and the form opening should be set up. Along with that, it is important that data signing (which requires the secret key) is performed on the server side of the web service and the payment form opening—on the client side of the web service. Additionally, for the timely monitoring of results, setting up the server side to receive callbacks from the payment platform can be helpful.

This is an overall workflow.

  Web service front end Web service back end In the payment platform
1 Creating an order. Collecting payment parameters and sending them to the web service back end (for signing the parameters)
2 Submitting additional parameters (if relevant) and signing them, then sending the information to the front end
3 Creating the request for opening Payment Page and sending it to the payment platform
4 Accepting the request, preparing and displaying the form to the customer, processing the customer actions and the payment, after that sending the callback with the payment result information and returning the customer to the web service
5

Accepting the callback with the payment result information and updating the order status

6 Displaying the payment information to the customer and the information about the customer further actions (if such actions are required, for example, for the product delivery)

Generally, this workflow scheme on the client and server sides of the web service can be implemented in a number of ways. This article—for the convenient and quick launch of the work with Payment Page—describes all necessary procedures with the application of ready-to-use components (such as SDKs) and code examples to their fullest extent. Still it is always possible to combine our ready-to-use components with your solutions.

Parameters for opening the form

To display the payment form to the customer, in the simplest case, you just need to decide on the parameters of the payment amount and currency and add the following three identifiers to these two parameters: the identifier of the project, the payment, and the customer. In total, this makes up five required parameters. (And signing these parameters is technically required.)

Table 1. Required parameters
Parameter Description

project_id
integer

Project identifier. Together with the key, it is provided by ecommpay and should be precisely specified even in test requests. Otherwise, this is going to look as if you are trying to enter someone else's hotel room and the payment platform reacts accordingly. from the payment platform.
Example: 57123

payment_id
string

Payment identifier. It can have random values but always should be unique within the project used. Otherwise, an error occurs from the web service.
Example: payment_443

payment_amount
integer

Payment amount. In test requests it can be a random amount, while in real ones the amount should correspond to the amount of the order. The amount is specified in minor currency units.
Example: 1815 (for the amount of 18.15)

payment_currency
string

Payment currency code. It is specified in the three-letter ISO 4217 alpha-3 format. Test requests can contain any of the applicable codes, while every real request should contain the code of the currency in which the payment is being initiated.
The currency codes are provided in the corresponding reference.

Example: EUR

customer_id
string

Customer identifier. It can have random values and be reused in different requests, however, the identifier of every real customer should exactly match the account of this very customer in the web service and be unique within the project. Otherwise, there can occur different issues that also concern displaying to the customer saved payment data of another customer.
Example: customer_112

How to collect these parameters (as well as which of them should be specified on the client and on the server side of the web service) is for you to decide (with regards to your web service architecture and other factors). For the initial few times of opening the payment form, it is not necessary to automate the collection of parameters, you can deal with this after the primary testing of the payment form operation. There is just one thing left to mention—in addition to the required parameters, you can use other parameters, for managing the payment form look and behavior; but since it is better to use these parameters after setting up the standard Payment Page opening, they are substantially described further.

Basic implementation

Variants of working with the form

The work of the web service functions with the payment form and callbacks can be implemented in different ways, which include creating in-house solutions and applying the CMS modules. Within this article, we consider the two variants of implementation implementing the work of the web service functions with the payment form and callbacks:

  • with the use of the SDKs from ecommpay on the server side of the web service;
  • with the use of the ready-to-use code from ecommpay on the server side of the web service.

You can choose among these variants, with regards to their differences, at your discretion. The SDKs can make the work with other programming languages a little easier and more available (full information about working with the SDKs is provided in a separate section). The work with the code examples can be a little more transparent and flexible in terms of embedding them in your own solutions (as well as when working with signatures). Still both variants are quite quick and complete, and you can choose any of them.

Along with that, whatever variant of the server functions implementation is used, within this article, we look at different variants of the payment form opening on the client side of the web service, including the usage of libraries from ecommpay. In general, this is what should be done for the implementation.

Web service back end Web service front end
  • link the libraries (when using SDKs)
  • ensure the submission of additional parameters (the relevant ones)
  • ensure data signing
  • ensure the receipt of callbacks
  • link the libraries (if relevant)
  • ensure the collection of parameters (the relevant ones)
  • ensure the form opening

The collection of parameters and submission of additional ones, as said in the brief theory overview, can be implemented in various ways (for the primary testing, manual implementation is possible) which are up to you. Other actions are regarded further.

Work with SDK

Linking and setting up.

Figure: PHP

1 Linking SDK

  1. If this has not been done previously, download, install, and set up the dependency manager Composer (https://getcomposer.org/).
  2. Use the operating system command line to open the directory with the web service source code and execute the following command composer require ecommpay/paymentpage-sdk.
  3. Include the script autoload.php into the web service source code.
// linking libraries
require` __DIR__.'../../vendor.autoload.php';

 

2 Ensuring data signing

Only then, when the values for all necessary parameters are defined, this data can be collected on the server side of the web service and the signature and the URL for opening the payment form can be generated. Here is an example of how to do this.

// Generating the signature and the link 

// creating the object of the Payment class and specifying the project and payment identifires
$payment = new ecommpay Payment('57123', 'payment_443');

// specifying other required parameters
$payment->setPaymentAmount(1815)->setPaymentCurrency('EUR'); // payment amount and currency
$payment->setCustomerId('customer_112'); // customer identifier

// creating the object of the Gate class and specifying the secret key
$gate = new ecommpay\Gate('<secret_key>');

// generating the link for opening the payment form
$url = $gate->getPurchasePaymentPageUrl($payment);

 

3 Setting up the receipt of callbacks

To keep track of the payment results and other significant information, you can set up receiving and processing program callbacks sent from the payment platform. This is done in three steps:

  1. Define and specify the URL for receiving callbacks by the web service within the project (at first, one URL can be specified, and then there can be several ones for various events). This can be done via Dashboard in the Projects section with the use of the Callbacks tab tools.
  2. Set up the integrity validation and parsing of the callbacks, which are sent to the specified URL, with the use of the SDK.
  3. Set up sending of synchronous HTTP responses with the information about the callbacks receipt: 200 OK if the signature is correct and 400 Bad Request if the signature is incorrect.
// Working with callbacks

// creating the object of the Gate class and specifying the secret key
$gate = new ecommpay\Gate('<secret_key>');

// creating the object of the Callback class and parsing the JSON string
// with the callback data ($data), with the data integrity validation
$callback = $gate->handleCallback($data);

// using methods for receiving information
Callback::getPaymentId();        // receiving the payment identifier
Callback::getPaymentStatus();    // receiving the payment status
Callback::getPayment();          // receiving all information from the callback

The payment statuses used in the payment platform are described in a separate section, and the information about callbacks and their usage is provided in a separate article. It should be noted that when a purchase is not confirmed by the customer in the payment form, it is not registered in the payment platform (thus does not have any status as well).

The information retrieved from the callbacks can be used for promptly updating the statuses of the orders in the web service, informing customers, and for other purposes—according to the web service operation model.

Figure: Python

1 Linking SDK

  1. If this has not been done previously, download, install, and set up the package-management system—pip (https://pip.pypa.io/en/stable/).
  2. Use the operating system command line to open the directory with the web service source code and execute the following command pip install ecommpay-sdk.
  3. Include the libraries from the SDK into the web service source code.
# Linking libraries
from payment_page_sdk.gate import Gate
from payment_page_sdk.payment import Payment

 

2 Ensuring data signing

Only then, when the values for all necessary parameters are defined, this data can be collected on the server side of the web service and the signature and the URL for opening the payment form can be generated. Here is an example of how to do this.

# Generating the signature and the link 

# creating the object of the Payment class and specifying the project and payment identifires
payment = Payment('57123', 'payment_443')

# specifying other required parameters
payment.payment_amount = 1815 # payment amount
payment.payment_currency = 'EUR' # payment currency
payment.customer_id = 'customer_112' # customer identifier

# creating the object of the Gate class and specifying the secret key
gate = Gate('<secret_key>')

# generating the link for opening the payment form
payment_url = gate.get_purchase_payment_page_url(payment)

 

3 Setting up the receipt of callbacks

To keep track of the payment results and other significant information, you can set up receiving and processing program callbacks sent from the payment platform. This is done in three steps:

  1. Define and specify the URL for receiving callbacks by the web service within the project (at first, one URL can be specified, and then there can be several ones for various events). This can be done via Dashboard in the Projects section with the use of the Callbacks tab tools.
  2. Set up the integrity validation and parsing of the callbacks, which are sent to the specified URL, with the use of the SDK.
  3. Set up sending of synchronous HTTP responses with the information about the callbacks receipt: 200 OK if the signature is correct and 400 Bad Request if the signature is incorrect.
# Working with callbacks

# creating the object of the Gate class and specifying the secret key
gate = Gate('<secret_key>')

# creating the object of the Callback class and parsing the JSON string
# with the callback data (data), with the data integrity validation
callback = gate.handle_callback(data)

# using methods for working with callbacks
callback.get_payment_id()        # receiving the payment identifier
callback.get_payment_status()    # receiving the payment status
callback.get_payment()           # receiving all information from the callback

The payment statuses used in the payment platform are described in a separate section, and the information about callbacks and their usage is provided in a separate article. It should be noted that when a purchase is not confirmed by the customer in the payment form, it is not registered in the payment platform (thus does not have any status as well).

The information retrieved from the callbacks can be used for promptly updating the statuses of the orders in the web service, informing customers, and for other purposes—according to the web service operation model.

Figure: Java

1 Linking SDK

  1. If this has not been done previously, download the SDK for Java and aggregate the SDK files in a JAR file.
  2. If your project directory with the web service source code does not contain a libs directory, create one and move the JAR file to the libs directory.
  3. Include the JAR file into the web service source code.

 

2 Ensuring data signing

Only then, when the values for all necessary parameters are defined, this data can be collected on the server side of the web service and the signature and the URL for opening the payment form can be generated. Here is an example of how to do this.

// Generating the signature and the link 

// creating the object of the Payment class and specifying the project and payment identifires
Payment payment = new Payment('57123', "payment_443");

// specifying other required parameters
payment
    .setParam(Payment.PAYMENT_AMOUNT, 1815) // payment amount
    .setParam(Payment.PAYMENT_CURRENCY, "EUR") // payment currency
    .setParam(Payment.CUSTOMER_ID, "customer_112") // customer identifier

// creating the object of the Gate class and specifying the secret key
Gate gate = new Gate("<secret_key>");

// generating the link for opening the payment form
String paymentUrl = gate.getPurchasePaymentPageUrl(payment);

 

3 Setting up the receipt of callbacks

To keep track of the payment results and other significant information, you can set up receiving and processing program callbacks sent from the payment platform. This is done in three steps:

  1. In the payment platform, define and specify the URL for receiving callbacks by the web service within the project (at first, one URL can be specified, and then there can be several ones for various events). This can be done via Dashboard in the Projects section with the use of the Callbacks tab tools.
  2. Set up the integrity validation and parsing of the callbacks, which are sent to the specified URL, with the use of the SDK.
  3. Set up sending of synchronous HTTP responses with the information about the callbacks receipt: 200 OK if the signature is correct and 400 Bad Request if the signature is incorrect.
// Working with callbacks

// creating the object of the Gate class and specifying the secret key
Gate gate = new Gate("<secret_key>");

// creating the object of the Callback class and parsing the JSON string
// with the callback data (data), with the data integrity validation
Callback callback = gate.handleCallback(data);

// using methods for working with callbacks
callback.getPaymentId();        // receiving the payment identifier
callback.getPaymentStatus();    // receiving the payment status
callback.getPayment();          // receiving all information from the callback

The payment statuses used in the payment platform are described in a separate section, and the information about callbacks and their usage is provided in a separate article. It should be noted that when a purchase is not confirmed by the customer in the payment form, it is not registered in the payment platform (thus does not have any status as well).

The information retrieved from the callbacks can be used for promptly updating the statuses of the orders in the web service, informing customers, and for other purposes—according to the web service operation model.

Work with code

Embedding and using.

Figure: PHP

1 Ensuring data singing

// Coding the algorithm
class Signer
{
    const ALGORITHM = 'sha512';
    const ITEMS_DELIMITER = ';';
    const MAXIMUM_RECURSION_DEPTH = 3;
 
 
    /**
     * Generate signature
     *
     * @param array $params
     * @param string $secretKey
     * @param array $ignoreParamKeys
     * @param bool $doNotHash
     * @param bool $useUnlimitedRecursionDepth
     *
     * @return string
     */
    public static function sign(array $params, string $secretKey, array $ignoreParamKeys = [], bool $doNotHash = false, bool $useUnlimitedRecursionDepth = false): string
    {
        $paramsPrepared = self::getParamsToSign($params, $ignoreParamKeys, 1, '', $useUnlimitedRecursionDepth);
        $stringToSign = implode(self::ITEMS_DELIMITER, $paramsPrepared);
 
        return $doNotHash
            ? $stringToSign
            : base64_encode(hash_hmac(self::ALGORITHM, $stringToSign, $secretKey, true));
    }
 
    /**
     * Get parameters to sign
     *
     * @param array $params
     * @param array $ignoreParamKeys
     * @param int $currentLevel
     * @param string $prefix
     * @param bool $useUnlimitedRecursionDepth
     *
     * @return array
     */
    private static function getParamsToSign(
        array  $params,
        array  $ignoreParamKeys = [],
        int    $currentLevel = 1,
        string $prefix = '',
        bool   $useUnlimitedRecursionDepth = false
    ): array
    {
        $paramsToSign = [];
 
        foreach ($params as $key => $value) {
            if (in_array($key, $ignoreParamKeys, true)) {
                continue;
            }
 
            $paramKey = ($prefix ? $prefix . ':' : '') . $key;
 
            if (is_object($value)) {
                $value = get_object_vars($value);
            }
 
            if (is_array($value)) {
                if (!$useUnlimitedRecursionDepth && ($currentLevel >= self::MAXIMUM_RECURSION_DEPTH)) {
                    $paramsToSign[$paramKey] = (string)$paramKey . ':';
                } else {
                    $subArray = self::getParamsToSign($value, $ignoreParamKeys, $currentLevel + 1, $paramKey, $useUnlimitedRecursionDepth);
                    $paramsToSign = array_merge($paramsToSign, $subArray);
                }
            } else {
                if (is_bool($value)) {
                    $value = $value ? '1' : '0';
                } else {
                    $value = (string)$value;
                }
 
                $paramsToSign[$paramKey] = (string)$paramKey . ':' . $value;
            }
        }
 
        if ($currentLevel == 1) {
            ksort($paramsToSign, SORT_NATURAL);
        }
 
        return $paramsToSign;
    }


// Usage example

// specifying the secret key and the parameters for opening the payment form
$secretKey = "jwfbfjhewbrw33383kr3js9d987";
 
$params = [
    'project_id' => 57123,     
    'payment_amount' => 1815,
    'payment_currency' => 'EUR',
    'customer_id' => 'customer_112',
    'payment_id' => 'payment_443',
];
 
// generating the signature
$params['signature'] = Signer::sign($params, $secretKey);
 
// receiving the link for opening the payment form
$uriParams = http_build_query($params);
$link = implode('?', ['https://paymentpage.ecommpay.com/payment', $uriParams]);

 

2 Ensuring the receipt of callbacks

To keep track of the payment results and other significant information, you can set up receiving and processing program callbacks sent from the payment platform. This is done in three steps:

  1. In the payment platform, define and specify the URL for receiving callbacks by the web service within the project (at first, one URL can be specified, and then there can be several ones for various events). This can be done via Dashboard in the Projects section with the use of the Callbacks tab tools.
  2. Set up the integrity validation and parsing of the callbacks, which are sent to the specified URL, with the use of the SDK.
  3. Set up sending of synchronous HTTP responses with the information about the callbacks receipt: 200 OK if the signature is correct and 400 Bad Request if the signature is incorrect.
// Working with callbacks. The example of comparing the received
// signature to the generated one

require_once 'Signer.php';

$secretKey = '<secret_key>';

$requestBody = '{
       "project_id": 57123,
       "payment": {
           "id": "payment_443",
           "type": "purchase",
           "status": "success",
           "date": "2022-03-03T10:50:29+0000",
           "method": "card",
           "sum": {
               "amount": 1815,
               "currency": "EUR"
           },
           "description": "Test payment"
       },
       "customer": {
           "id": "customer_112",
           "ip": "127.0.0.1",
           "phone": "+60-3-xxxx-xxxx",
           "email": "jane.doe@testmail.com"
       },
       "operation": {
           "id": 15788000002076,
           "type": "sale",
           "status": "success",
           "date": "2022-03-03T10:50:29+0000",
           "sum_initial": {
               "amount": 1815,
               "currency": "EUR"
           },
           "code": "0",
           "message": "Success"
       },
       "signature": "zwoFECy7H+WZFziw9IgR9031Uu878TuIv3dhFyHvCuvzIdRAzDQA=="
   }';

$requestBodyArray = json_decode($requestBody, true);

$actualSignature = $requestBodyArray['signature'];
unset($requestBodyArray['signature']);
$expectedSignature = Signer::sign($requestBodyArray, $secretKey);

print_r('Actual signature: ' . $actualSignature . PHP_EOL);
print_r('Expected signature: ' . $expectedSignature . PHP_EOL);

if ($expectedSignature === $actualSignature) {
    print_r('Signatures are equal');
} else {
    print_r('Signatures are not equal');
}

print_r(PHP_EOL);

The payment statuses used in the payment platform are described in a separate section, and the information about callbacks and their usage is provided in a separate article. It should be noted that when a purchase is not confirmed by the customer in the payment form, it is not registered in the payment platform (thus does not have any status as well).

The information retrieved from the callbacks can be used for promptly updating the statuses of the orders in the web service, informing customers, and for other purposes—according to the web service operation model.

Figure: Python

1 Ensuring data singing

# Coding the algorithm
import hmac
import base64
import hashlib
 
 
class Signer:
    def getSign(self, params, key):
        byteKey = key.encode()
        paramsPrepared = self.getParamsToSign(params)
        toSignString = ';'.join(paramsPrepared.values())
        hmacObj = hmac.new(byteKey, toSignString.encode(), hashlib.sha512)
 
return base64.b64encode(hmacObj.digest())
 
def getParamsToSign(self, params, currentLevel = 1, prefix = '', useUnlimitedRecursionDepth = False):
        paramsToSign = dict()
 
for paramKey in params.keys():
 
newParamKey = (prefix + ':' if prefix else '') + paramKey
 
if isinstance(params[paramKey], (dict)):
                if useUnlimitedRecursionDepth is False and (currentLevel >= 3):
                    paramsToSign[newParamKey] = newParamKey + ':'
                else:
                    subDict = self.getParamsToSign(params[paramKey], currentLevel + 1, newParamKey, useUnlimitedRecursionDepth)
                    paramsToSign.update(subDict)
            else:
                if isinstance(params[paramKey], (bool)):
                    value = '1' if params[paramKey] == True else '0'
                else:
                    value = str(params[paramKey])
 
paramsToSign[newParamKey] = str(newParamKey + ':' + value)
 
sortedParams = dict()
 
for key in sorted(paramsToSign.keys()):
            sortedParams[key] = paramsToSign[key]
 
return sortedParams


# Usage example

# specifying the secret key and the parameters for opening the payment form
import urllib.parse
import Signer
 
params = {
    'project_id': 57123, 
    'payment_amount': 1815,
    'payment_currency': 'EUR',
    'customer_id': 'customer_112',
    'payment_id': 'payment_443',
}

# Generating signature
signer = Signer.Signer()
 
params['signature'] = signer.getSign(params, '<secret_key>')
 
print(params['signature'])

# creating the signature
jointParams = urllib.parse.urlencode(params)
 
link = '?'.join(['https://paymentpage.ecommpay.com/payment', jointParams])

 

2 Ensuring the receipt of callbacks

To keep track of the payment results and other significant information, you can set up receiving and processing program callbacks sent from the payment platform. This is done in three steps:

  1. In the payment platform, define and specify the URL for receiving callbacks by the web service within the project (at first, one URL can be specified, and then there can be several ones for various events). This can be done via Dashboard in the Projects section with the use of the Callbacks tab tools.
  2. Set up the integrity validation and parsing of the callbacks, which are sent to the specified URL, with the use of the SDK.
  3. Set up sending of synchronous HTTP responses with the information about the callbacks receipt: 200 OK if the signature is correct and 400 Bad Request if the signature is incorrect.
# Working with callbacks. The example of comparing the received
# signature to the generated one

from Signer import Signer
import base64

secretKey = '<secret_key>'
params = {
    "project_id": 57123,
    "payment": {
        "id": "payment_443",
        "type": "purchase",
        "status": "success",
        "date": "2022-03-03T10:50:29+0000",
        "method": "card",
        "sum": {
            "amount": 1815,
            "currency": "EUR"
        },
        "description": "Gagarin set"
    },
    "customer": {
        "id": "customer_112",
        "ip": "127.0.0.1",
        "phone": "+60-3-xxxx-xxxx",
        "email": "jane.doe@testmail.com"
    },
    "operation": {
        "id": 15788000002076,
        "type": "sale",
        "status": "success",
        "date": "2022-03-03T10:50:29+0000",
        "sum_initial": {
            "amount": 1815,
            "currency": "EUR"
        },
        "code": "0",
        "message": "Success"
    },
    "signature": "zwoFECy7H+WZFziw9IgR90SEmC+o3qXD7OIaHqgQuqcSwBC09W6yQA=="
}

signer = Signer()
actualSign = params['signature']
del params['signature']
expectedSign = signer.getSign(params, secretKey).decode()

print('Actual signature:' + actualSign)
print('Expected signature:' + expectedSign)

if (expectedSign == actualSign):
    print('Signature is correct')
else:
    print('Signature is incorrect')

The payment statuses used in the payment platform are described in a separate section, and the information about callbacks and their usage is provided in a separate article. It should be noted that when a purchase is not confirmed by the customer in the payment form, it is not registered in the payment platform (thus does not have any status as well).

The information retrieved from the callbacks can be used for promptly updating the statuses of the orders in the web service, informing customers, and for other purposes—according to the web service operation model.

Figure: Java

1 Ensuring data signing

// Coding the algorithm
const CryptoJS = require('crypto-js'); // npm install crypto-js
 
class Signer {
    getSign(params, key) {
        const paramsPrepared = this.getParamsToSign(params, 1);
 
const joinedString = Object.values(paramsPrepared).join(';');
 
const hash = CryptoJS.HmacSHA512(joinedString, key);
 
return hash.toString(CryptoJS.enc.Base64);
    }
 
getParamsToSign(params, currentLevel = 1, prefix = '', useUnlimitedRecursionDepth = false) {
        let paramsToSign = {};
        let value = '';
 
let keys = Object.keys(params);
        let key = '';
        for (let i = 0; i < keys.length; i++) {
            key = keys[i];
 
let paramKey = (prefix ? prefix + ':' : '') + key;
 
if (typeof params[key] === 'object') {
                if (!useUnlimitedRecursionDepth && (currentLevel >= 3)) {
                    paramsToSign[paramKey] = paramKey + ':';
                } else {
                    let subParams = this.getParamsToSign(params[key], currentLevel + 1, paramKey, useUnlimitedRecursionDepth);
 
Object.assign(paramsToSign, subParams);
                }
            } else {
                if (typeof params[key] === "boolean") {
                    value = params[key] === true ? '1' : '0';
                } else {
                    value = params[key].toString();
                }
 
paramsToSign[paramKey] = paramKey + ':' + value;
            }
        }
 
let orderedKeys = Object.keys(paramsToSign).sort();
 
let ordered = {};
 
for (let k = 0; k < orderedKeys.length; k++) {
            ordered[orderedKeys[k]] = paramsToSign[orderedKeys[k]];
        }
 
return ordered;
    }
}
 
module.exports = Signer;


// Usage example

// specifying the secret key and the parameters for opening the payment form
const signer  = require('./Signer');
 
let params = {
    'project_id': 57123,
    'payment_amount': 1815,
    'payment_currency': 'EUR',
    'customer_id': 'customer_112',
    'payment_id': 'payment_443',
};

// generating signature
params['signature'] = (new signer()).getSign(params, '<secret_key>');

// receiving the link for opening the payment form
const uriParams = Object.keys(params).sort().reduce(
    (paramsArray, key) => {
        paramsArray.push(key + '=' + encodeURIComponent(params[key]));
        return paramsArray;
    },
    []
);
const link = ['https://paymentpage.ecommpay.com/payment', uriParams.join('&')].join('?');

 

2 Ensuring the receipt of callbacks

To keep track of the payment results and other significant information, you can set up receiving and processing program callbacks sent from the payment platform. This is done in three steps:

  1. In the payment platform, define and specify the URL for receiving callbacks by the web service within the project (at first, one URL can be specified, and then there can be several ones for various events). This can be done via Dashboard in the Projects section with the use of the Callbacks tab tools.
  2. Set up the integrity validation and parsing of the callbacks, which are sent to the specified URL, with the use of the SDK.
  3. Set up sending of synchronous HTTP responses with the information about the callbacks receipt: 200 OK if the signature is correct and 400 Bad Request if the signature is incorrect.
// Working with callbacks. The example of comparing the received
// signature to the generated one

const signer = require('./Signer');

const secretKey = '<secret_key>';

const params = {
    "project_id": 57123,
    "payment": {
        "id": "payment_443",
        "type": "purchase",
        "status": "success",
        "date": "2022-03-03T10:50:29+0000",
        "method": "card",
        "sum": {
            "amount": 1815,
            "currency": "EUR"
        },
        "description": "Gagarin set"
    },
    "customer": {
        "id": "customer_112",
        "ip": "127.0.0.1",
        "phone": "+60-3-xxxx-xxxx",
        "email": "jane.doe@testmail.com"
    },
    "operation": {
        "id": 15788000002076,
        "type": "sale",
        "status": "success",
        "date": "2022-03-03T10:50:29+0000",
        "sum_initial": {
            "amount": 1815,
            "currency": "EUR"
        },
        "code": "0",
        "message": "Success"
    },
    "signature": "zwoFECy7H+WZFziw9IgR90SHvCuvqXD7OIaHqgQuqcSwBC09W6yQA=="
};

const actualSignature = params['signature'];
delete params.signature;
const expectedSignature = (new signer()).getSign(params, secretKey);

console.log('Actual: ' + actualSignature);
console.log('Expected: '+expectedSignature);

if (actualSignature == expectedSignature) {
    console.log('Signatures is correct');
} else {
    console.log('Signature is incorrect');
}

The payment statuses used in the payment platform are described in a separate section, and the information about callbacks and their usage is provided in a separate article. It should be noted that when a purchase is not confirmed by the customer in the payment form, it is not registered in the payment platform (thus does not have any status as well).

The information retrieved from the callbacks can be used for promptly updating the statuses of the orders in the web service, informing customers, and for other purposes—according to the web service operation model.

Actions on the client side

Payment Page can be opened on the client side of the web service in various ways, and to get the feel of them, you can try several options even within the Quickstart guide.

The easiest option is to open the payment form in a separate browser tab.

Figure: Opening in a separate browser tab

To open the payment form as a separate HTML page, you should use the link obtained during signature generation. The link has the format of https://paymentpage.ecommpay.com/payment?<parameters> where <parameters> is a data string containing the names and values of the parameters.

In this case, the HTTP request with the use of the GET method can look as follows:

GET
/payment?payment_currency=EUR&project_id=42&payment_amount=1000&
customer_id=123&payment_id=4438&signature=AE5hmtzdP0Dt7qGTg... HTTP/1.1

Host: https://paymentpage.ecommpay.com

To use other options—opening the payment form in a modal window and in an iframe element—you need to link the two libraries: CSS for the form to be displayed correctly and JavaScript for the form to open. This is done via adding the links to the libraries in the header of the web service HTML page.

Figure: Linking libraries

<head>
...
// linking the CSS library
<link rel="stylesheet" href="https://paymentpage.ecommpay.com/shared/merchant.css" /> 

// linking the JavaScript library
<script type="text/javascript" src="https://paymentpage.ecommpay.com/shared/merchant.js">
</script>
...
</head>

For opening the payment form with the help of the JavaScript library, the signed set of parameters in the form of the JavaScript object should be used. The set can be formed by way of parsing the link received when the data was signed (in the PHP language, you can use the parse_url and parse_str functions for this) or using the server code for generating the signature (without generating the link) and adding the signature to other parameters.

After linking the libraries and dealing with the parameters, you can try opening the form.

Figure: Opening in a modal window

For Payment Page to open in a modal window with a button click on the web service page, the bind method of the JavaScript EPayWidget object can be used. When accessing this object, you should specify the button identifier (pay_button_id), the object with the parameters for opening Payment Page (configObj), and the HTTP method for sending requests (method):

EPayWidget.bind('pay_button_id',            // button identifier
                { payment_id: 'payment_443',         // payment identifier
                  payment_amount: 1815,              // payment amount
                  payment_currency: 'EUR',           // payment currency code
                  project_id: 57123,                 // project identifier
                  customer_id: 'customer_112',       // customer identifier
                  signature: 'YWb6Z20ByxpQ30hfTI' }, // signature
                 'post') // HTTP method

Figure: Opening directly on the page, in the iframe element

For Payment Page to open in the iframe element with a button click on the web service page, as with the modal window, the bind method of the JavaScript EPayWidget object can be used. When accessing this object, you should specify the button identifier (pay_button_id), the object with the parameters for opening Payment Page (configObj) which also contains the identifier of the element in which the payment form should be displayed (target_element), and the HTTP method for sending requests (method):

EPayWidget.bind('pay_button_id',             // button identifier
                { payment_id: 'payment_443',          // payment identifier
                  payment_amount: 1815,               // payment amount
                  payment_currency: 'EUR',            // payment currency code
                  project_id: 57123,                  // project identifier
                  customer_id: 'customer_112',        // customer identifier
                  signature: 'YWb6Z20ByxpQ30hfTI' },  // signature
                  target_element: 'widget-container', // element identifer
                 'post') // HTTP-method 

For the primary introduction, these opening options can suffice. If you need a more tailored approach, refer to the documentation and contact our specialists.

Testing

When the payment form is opened in the production mode, it is intended to be used by the customer. In the test mode, you can put yourself in the customer's shoes and test various purchase scenarios as if you were paying for something. The key question here—what credentials should be specified?

In the test project, there are two available types of payment credentials: special test credentials, which allow to test predefined payment scenarios, and random realistic credentials, which allow to additionally test the payment form operation in various cases.

For bare minimum testing (to process payments according to the shortest scenarios, without the emulation of the 3‑D Secure authentication), use the following numbers of test cards:

  • 4000 0000 0000 0077—for a purchase to be processed;
  • 4111 1111 1111 1111—for a purchase to be declined.


For the purposes of the more comprehensive testing, it is possible to use extended test data for card payments (including scenarios with the 3‑D Secure authentication) and various alternative payments, as well as random data including the credentials of cards, wallets, and other payment instruments. This is safe since all data in the test and the production environment is protected equally, although in the test environment there are no actual payments taking place.

After testing and ensuring the correct work with the form, the basic functions for purchase processing can be considered implemented, and when desired, you can move on to various additional aspects, which can be helpful at the initial stages of working with the payment platform, and to launching the solution operation.

Additional aspects

Monitoring of payment processing

After processing several test payments, you can explore how to monitor the overall payment situation. For this, use the register and the payment information tabs in Dashboard.

With questions about working with this interface, and about other issues, refer to the documentation and contact our specialists.

Refunds

When needed to refund a purchase, Dashboard can be used as well. When testing the work with the payment form, you can try to make full and partial refunds via the payment information tabs.

To delve into the topic about working with refunds, including mass refunds, you can use the separate article. Besides, knowing about refunds via Gate can be useful.

UX capabilities of the form

The work with Payment Page can be supplemented by various capabilities that include managing the form’s look and behavior—for example, setting the relevant language, filtering payment methods, or managing the ways of returning the customer to the web service. Some of such capabilities can be set up only via the ecommpay specialists, others can be applied without the anyone’s involvement, just via Dashboard or by sending additional parameters in the requests for opening Payment Page.

For testing the Payment Page operation, we recommend that you try the following:

  • Customise the payment form with the help of the Payment Page Designer.

    For this, in the Projects section of the Dashboard interface, use the tools of the Payment Page Designer tab (for more information, see Customisation).

  • Try opening the payment form in different languages.

    For opening Payment Page in a specific language, this language code (in the two-letter ISO 639-1 alpha-2 format) should be sent as the value of the corresponding parameter—language_code. The list of the languages supported by ecommpay is provided here.

  • Return the customer to the web service after payment processing.

    After the payment processing and depending on the payment result, the customer can be returned to different pages of the web service. The URLs of such pages can be specified in the Projects section of the Dashboard interface (in the Redirect URLs tab) or sent in certain requests as the values of the parameters merchant_success_url and merchant_fail_url.

  • Apply the capabilities to suit your needs.

    The information about different capabilities is provided in the overview and in the specialised section, and the list of the parameters for opening the form is provided in the separate article. All questions, as usual, can be forwarded to our specialists.

Launch

After implementing the basic functions, testing various capabilities, and defining the scenarios of the work with Payment Page relevant for you, you can start launching the production project. It is important that by this time all organisational issues have been resolved—in this case, the technical issues come down to configuring the project settings on the payment platform side and beginning to use the identifier and the key of the production project.

Good luck!