A gateway module allows to connect a third party payment gateway, configure settings, and interface of the payment form, as well as payment procedure on the User side. Besides, the payment module implements invoice generation and payment processing. You may add a custom payment procedure depending on your specific needs: either redirect clients to a gateway web-site to make payments, or generate invoices and wait for him to pay for his order.

How it works


The payment procedure in BILLmanager includes the following steps:

  1. The module is installed 
  2. The module is connected to a payment gateway 
  3. A client makes payment 
  4. A clients pays the invoice
  5. The system credits or cancels the payment 

You can install the module manually (if it is a list of files) or from repository using the package manager. Once installed, you can choose a payment gateway when adding a payment method in BILLmanager.

Every module requests a list of supported features and required parameters from BILLmanager.  This operation is performed each time BILLmanager starts and allows to improve BILLmanager performance, exclude unsupported calls, and define behavior of BILLmanager forms when the client makes a new payment.

Module structure


A payment gateway module consists of two to unlimited number of files. The main files are  XML description, and the main script that sends the module configuration to BILLmanager. Alternatively, two CGI scripts can be used: to redirect a client to the gateway web-site, and receive payment status change notifications from the gateway.

You can add additional files if needed (for example, files that handle additional forms, verify payment parameters, print invoices, check payment statuses, etc.).

The following is a standard list of files (their paths are relative to the location of BILLmanager installation directory):


  • etc/xml/billmgr_mod_pmXXX.xml - XML description of the payment module. 
  • paymethods/pmXXX - main script 
  • cgi/XXXpayment - payment script. Optional file which can have any name 
  • cgi/XXXresult - notification processing script. Optional file which can have any name
  • cgi/XXXrecurring - recurring payment activation script. An optional file which can have any name 
  • cgi/XXXrecurringresult - recurring payments notifications script.  An optional file, which can have any name  

XXX is the name of your payment method in the Latin alphabet letters. If the name of the main module contains a file extension, it will be included into the name. For example, if your script name is pmpay.php, the module name will be pay.php,  rather than pay

XML description


A file name can look like the following -   billmgr_mod_pmXXX.xml, where XXX is a module name. The file is copied into the etc/xml directory relative to the BILLmanager installation directory.  The file contains description of the  module   (it is described as a plugin) and additional forms and messages. 


The example of the XML file:

<?xml version="1.0" encoding="UTF-8"?>
<mgrdata>
  <plugin name="XXX">
    <group>payment_method</group>
    <msg name="desc_short" lang="en">XXX module</msg>
    <msg name="desc_full" lang="en">XXX module</msg>
  </plugin>

  <metadata name="paymethod.edit.XXX" type="form">
    <form>
      <page name="methodprops">
        <field name="prop1">
          <input name="prop1" required="yes" type="text" />
        </field>
        <field name="prop2">
          <input name="prop2" private="yes" required="yes" type="text" />
        </field>
      </page>
      <page name="recurring">
        <field name="recurring">
         <input type="checkbox" name="recurring">
           <if value="off" hide="recurringprop1"/>
           <if value="off" hide="recurringprop2"/>
         </input>
        </field>
        <field name="recurringprop1">
          <input name="recurringprop1" required="yes" type="text" />
        </field>
        <field name="recurringprop2">
          <input name="recurringprop2" private="yes" required="yes" type="text" />
        </field>
      </page>
      <page name="refundpage">
        <field name="allowrefund">
         <input type="checkbox" name="allowrefund">
           <if value="off" hide="refundprop1"/>
           <if value="off" hide="refundprop2"/>
         </input>
        </field>
        <field name="refundprop1">
          <input name="refundprop1" required="yes" type="text" />
        </field>
        <field name="refundprop2">
          <input name="refundprop2" private="yes" required="yes" type="text" />
        </field>
      </page>
    </form>
  </metadata>

  <metadata name="payment.edit.xxx" type="form">
    <form>
      <field name="payment_prop">
        <input type="text" name="payment_prop" required="yes"/>
      </field>
    </form>
  </metadata>

  <metadata name="paymethod.transfer.XXX" type="form">
    <form>
      <field name="param">
        <input type="text" name="param" required="yes"/>
      </field>
    </form>
  </metadata>

  <lang name="en">
    <messages name="label_paymethod">
      <msg name="pmXXX">XXX module</msg>
      <msg name="module_pmXXX">XXX module</msg>
    </messages>

    <messages name="paymethod.edit.XXX">
      <msg name="prop1">Prop 1</msg>
      <msg name="hint_prop1">Hint for prop 1</msg>
      <msg name="prop2">Prop 2</msg>
      <msg name="hint_prop2">Hint for prop 2</msg>

      <msg name="recurringprop1">Recurring prop 1</msg>
      <msg name="hint_recurringprop1">Hint for recurring prop 1</msg>
      <msg name="recurringprop2">Recurring prop 2</msg>
      <msg name="hint_recurringprop2">Hint for recurring prop 2</msg>

      <msg name="refundprop1">Refund prop 1</msg>
      <msg name="hint_refundprop1">Hint for refund prop 1</msg>
      <msg name="refundprop2">Refund prop 2</msg>
      <msg name="hint_refundprop2">Hint for refund prop 2</msg>
    </messages>

    <messages name="paymethod.transfer.XXX">
      <msg name="param">Param</msg>
      <msg name="hint_param">Hint param</msg>
    </messages>

    <messages name="payment.edit.XXX">
      <msg name="payment_prop">Prop</msg>
      <msg name="hint_payment_prop">Hint for prop</msg>
      <msg name="placeholder_payment_prop">prop</msg>
    </messages>
  </lang>

  <lang name="ru">
     <messages name="label_paymethod">
      <msg name="pmXXX">XXX module</msg>
      <msg name="module_pmXXX">XXX module</msg>
    </messages>

    <messages name="paymethod.edit.XXX">
      <msg name="prop1">Property 1</msg>
      <msg name="hint_prop1">Hint for property 1</msg>
      <msg name="prop2">Property 2</msg>
      <msg name="hint_prop2">Hint for property 2</msg>
    </messages>

    <messages name="paymethod.transfer.XXX">
      <msg name="param">Parameter</msg>
      <msg name="hint_param">Hint for parameter</msg>
    </messages>

    <messages name="payment.edit.XXX">
      <msg name="payment_prop">Property</msg>
      <msg name="hint_payment_prop">Hint for property</msg>
      <msg name="placeholder_payment_prop">Property</msg>
    </messages>
  </lang>
</mgrdata>
XML

The <plugin> section describes the module.  The name property matches the payment module name. The section may contain the group element with the payment_method value indicating that this module is used for payment methods, and several msg elements.  The lang property defines a language associated with the message, the name attribute may have the following values:  

  • desc_short - a brief description of the module which is displayed in BILLmanager payment form. 
  • desc_full - a full description of the module which is displayed in the list of installed modules in COREmanager. 

The metadata section paymethod.edit.XXX handles additional fields of the module that are displayed when you add or configure the payment module. It is formed according to the standard description of XML forms. Take the note of the location of fields in the  <page name="methodprops"></page> section for correct location of fields on BILLmanager forms. The only difference from the standard description is the private attribute which forbids to output this attribute in the XML when printing an invoice based on that payment.   It is used for security information , such as password or secret key.  Recurring and refundpage pages describe configuration of recurring payments and refunds correspondingly. 

The metadata  section payment.edit.xxx' handles additional fields that a client can see when making a payment. It is described according to standard description of XML form.

The metadata  section paymethod.transfer.XXX handles additional fields that are displayed when making refund.It is described according to standard description of XML form.

The lang section contains translations of form fields according to the standard scheme of translation description. The <messages name="label_paymethod"> section specifies the module name in a list of payment methods.

Main script


The main script sends information about the functions that the module support to BILLmanager and handles those functions. BILLmanager executes the script file with the following parameters:  

paymethods/pmxxx --command cmd [--payment id [--amount amnt]]
XML

where

  • cmd - a command
  • id - payment id
  • amnt - amount in payment method currency (it used in case of refunds or transfer)

The --command parameter can have the following values:

  • config - module configuration request. The module will send the following XML to the standard output:
<?xml version="1.0" encoding="UTF-8"?>
<doc>
  <feature>
    <refund>on</refund>
    <transfer>on</transfer>
    <recurring>on</recurring>
    <redirect>on</redirect>
    <noselect>on</noselect>
    <notneedprofile>on</notneedprofile>
    <pmtune>on</pmtune>
    <pmvalidate>on</pmvalidate>
    <crtune>on</crtune>
    <crvalidate>on</crvalidate>
    <crset>on</crset>
    <crdelete>on</crdelete>
    <rftune>on</rftune>
    <rfvalidate>on</rfvalidate>
    <rfset>on</rfset>
    <rctune>on</rctune>
    <rcvalidate>on</rcvalidate>
    <rcset>on</rcset>
    <rcpay>on</rcpay>
    <tftune>on</tftune>
    <tfvalidate>on</tfvalidate>
    <tfset>on</tfset>
  </feature>
  <param>
    <payment_script>/mancgi/qiwipullpayment.php</payment_script>
    <recurring_script>/mancgi/qiwipullrecurringpayment.php</recurring_script>
    <recurring_type></recurring_script>
  </param>
</doc>
XML

The feature branch contains features supported by the module. If a feature is not supported, do not send it to stdout.

The following is a list of possible values:

    • refund -  payments can be cancelled and refunded.  If this feature is not supported,  the ftune, rfvalidate, rfset commands may not be handled
    • transfer - funds can be transferred from a payment system's account into a client's account. If this feature is not supported, the ftunerfvalidaterfset commands may not be handled
    • recurring - support of recurring payments. If this feature is not supported,  the recurring_script and recurring_type parameters may not be specified
    • redirect - a client will be redirected to a payment gateway to complete the payment. 
    • noselect - payment method won't be available to clients. This value is used if a client doesn't need to create invoice in BILLmanager.
    • notneedprofile - payment does not require a payer. However, if the payment method is associated with a company, the client will be asked to create or select a payer. 
    • pmtune - payment method configuration form requires additional actions. See the pmtune command for more details
    • pmvalidate - call the module to verify values when saving parameters of the payment method.  
    • crtune - payment form requires additional actions. See the crtune command for more details.  
    • crvalidate - call the  module to verify values when saving parameters that the client enters. 
    • crset - it is specified if the module is required to complete additional actions or if a clients is not redirected to the payment system site to complete his payment. We recommend that you add this feature, if the client needs provide any data when making a payment
    • crdelete - the client needs to perform  additional actions on the payment system side to delete the payment correctly
    • rftune - similar to crtune,  in the case of refund.
    • rfvalidate - similar to crvalidate, in the case of refund 
    • rfset - clients can be refunded. Calling this command will perform operations required for refund.  
    • rctune - similar to crtune, if the recurring payments option is enabled 
    • rcvalidate - similar to crvalidate,  if the recurring payments option is enabled 
    • rcset - similar to crset, when a client activates the recurring payment option. It is used to set up recurring payments on the payment gateway side.
    • rcpay - it is called when creating a recurring payment in BILLmanager. It is used to set up recurring payments on the payment gateway side.
    • rcdelete - the client needs to perform  additional actions on the payment system side to delete the auto payment correctly
    • tftune - similar to crtune, in the case of funds transfer 
    • tfvalidate - similar to  crvalidate, in the case of funds transfer 
    • tfset - mandatory feature for fund transfer. Calling this command will perform operations required for funds transfer.  

The param branch contains parameters of the payment method. Supported parameters:

    • payment_script - the path to the payment redirect script relative to BILLmanager installation domain
    • recurring_script - the path to the redirect script for recurring payments confirmation 
    • recurring_type - the bit mask of supported options of recurring options: 
      • 1 - a new payment is created for every service 
      • 2 - a new payment is created for several services 
      • 7 - a new payment is created for all services 
      • 8 -  the maximum amount must be specified for the payment
      • 20 - a client must be redirected to a payment gateway for recurring payment confirmation
      • 21 - a client should perform additional operations for payment confirmation 
  • pmtune - change the payment method form. The form XML is sent to the stdin. The script  returns the modified XML to the stdout
  • pmvalidate - check values in the payment method form. The XML with values from the form is sent to the stdin. The script returns the XML containing error description or an empty XML to its standard output. 
  • crtune - change the payment form. The payment form XML is sent to the stdin. The script  returns the modified XML to the stdout
  • crvalidate - check values in the payment form. The XML with values from the form is sent to standard input, and then the script returns the XML containing error description or empty XML to its standard output.
  • crset - it is called when clicking OK on the payment form. The parameter sends id of the required payment. Data that the client enters are already kept in the database
  • crdelete - it is called when clicking Delete in the list of payments. The parameter sends id of the payment to be deleted.  
  • rftune - edit the refund form. The refund XML is sent to the stdin and the script  returns the modified XML to its standard output
  • rfvalidate - check values in the refund method form. The XML with values from the form is sent to stdin and the script returns the XML containing error description or empty XML to its stdput.
  • rfset - it is called when clicking OK the refund form. The XML with information about new or existing payment for refund, amount to be refunded, cause, and payment method parameters is sent to the stdin. 
  • tftune - change the transfer form. The transfer form XML is sent to the stdin and the script returns the modified XML to its standard output. 
  • tfvalidate - check values provided for funds transfer. The XM containing values from the form is sent to the stdin, and the XML containing error description or empty XML is sent to the stdout.  
  • tfset - it is called when clicking OK on the transfer form. The XML with information about payment, amount to be transferred, and payment method parameters are sent to stdin. The script returns the XML with information about transfer payment, amount to be transferred, and payment method are sent to its standard output.
  • rcdelete - it is called when disabling an auto-payment. The auto-payment profile id to be deleted is sent. 

You can find an example of the script at the end of this article.

CGI scripts


CGI scripts are optional elements of the payment module. You don't need to specify them, if the logic is described in the main module.

The module may have several CGI scripts:

  • payments
  • payment status change notifications 
  • other scripts that a payment system may require 

In general, CGI scripts can locate on a different server, IP address or domain, depending on the needs of the module developer and/or payment system requirements. 

Following are the examples of two scripts: payment redirect and payment status change notification

Payment redirect 

BILLmanager retrieves the address of the payment redirect script along with the module data when calling the module for the fist time. The most common way is to generate and send a form with required parameters automatically. The form looks like the following: 

<html>
  <head>
    <meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
    <link rel='shortcut icon' href='billmgr.ico' type='image/x-icon' />
    <script language='JavaScript'>
      function submit() {
        document.frm.submit();
      }
    </script>
  </head>
  <body onload='submit()'>
    <form name='frm' action='https://paysystem/url' method='post'>
      <input type='hidden' name='shop_id' value='1'>
      <input type='hidden' name='amount' value='1.00'>
    </form>
  </body>
</html>
HTML

The elid parameter with payment id is always sent to the  redirect script. Using the payment.info feature you can obtain all the data to generate a payment form. The XML that the function returns (you can use JSON if needed) looks like the following:  

<doc>
  <payment>                                                   <!-- payment information  -->
    <id>1</id>                                                <!-- payment id -->
    <subaccount>1</subaccount>                                <!-- client account id -->
    <paymethod>1</paymethod>                                  <!-- payment method id -->
    <recipient/>                                              <!-- payee id (company). Company data if any, will be also added into the function output -->
    <sender/>                                                 <!-- payer id who is making payment. Payer data if any, will be also added into the function output -->
    <subaccountamount>1.00</subaccountamount>                 <!-- payment amount converted into the payment method currency  -->
    <status>2</status>                                        <!-- payment status -->
    <number>pfx/1</number>                                    <!-- payment number -->
    <paymethodamount>1.00</paymethodamount>                   <!-- payment amount converted into the payment method currency -->
    <currency>126</currency>                                  <!-- currency id -->
    <externalid/>                                             <!-- payment external id; it can be saved by the payment.setpaid function -->
    <description>Advanced payment</description>               <!-- purpose of payment  -->
    <remote_ip>127.0.0.1</remote_ip>                          <!-- IP address that the payment is made from -->
    <manager_url>https://localhost:1500/billmgr</manager_url> <!-- URL BILLmanager that was open when making the payment -->
    <phone>7 000 0000000</phone>                              <!-- additional parameter of the payment specified in the module XML -->
    <useremail>email@example.com</useremail>                  <!-- email of the user who made the payment -->
    <paymethod>                                               <!-- payment method information -->
      <id>1</id>                                              <!-- payment method id -->
      <name>XXX</name>                                        <!-- payment method name -->
      <active>on</active>                                     <!-- status -->
      <minamount>0.00</minamount>                             <!-- minimum payment amount -->
      <maxamount/>                                            <!-- maximum payment amount -->
      <autoclearperiod/>                                      <!-- period to delete due invoices -->
      <currency>126</currency>                                <!-- payment method currency id -->
      <profiletype>1,2,3</profiletype>                        <!-- types of payers who can use this payment method -->
      <commissionamount>0.00</commissionamount>               <!-- commission -->
      <commissionpercent>0</commissionpercent>                <!-- payment commission in % -->
      <module>pmXXX</module>                                  <!-- module name -->
    </paymethod>
    <currency>                                                <!-- payment currency -->
      <id>126</id>                                            <!-- currency id from the list -->
      <name>Russian Ruble</name>                              <!-- name -->
      <iso>RUB</iso>                                          <!-- ISO currency code-->
      <code>643</code>                                        <!-- ISO numerical cod -->
      <active>on</active>                                     <!-- status -->
    </currency>
    <project>                                                 <!-- provider information  -->
      <id>1</id>                                              <!-- id -->
      <name>ISPsystem</name>                                  <!-- name -->
      <notifyemail>email@example.com</notifyemail>            <!-- email for notifications -->
    </project>
    <items>                                                   <!-- invoice items; if associated with a service, it contains ordered services, otherwise - purpose payment -->
      <item>                                                  <!-- invoice item -->
        <name>Advanced payment</name>                         <!-- name-->
        <locale_name>Advanced payment</locale_name>           <!-- name in user localisation -->
        <amount>1.00</amount>                                 <!-- item subtotal -->
      </item>
    </items>
  </payment>
</doc>
XML

Additional parameters that clients provide when making a payment are also added to the payment node. Parameters of the payment method are added to the paymethod node. We recommend that you use this method rather than sending requests directly to the BILLmanager database. 

You can find the example of the redirect script at the end of this article. 

Payment status change notifications

A script that handles  payment status change notifications must perform the following operations: 

  • Select the payment id (from BILLmanager) from the data sent by  the payment system.
  • Receive information related to that payment from the database, or execute the ''payment.info'' function to get information about the payment and payment method parameters. 
  • Compare the data from the payment system with those kept in BILLmanager.
  • Verify the control sign of the received data with the secret key (the most common way of data verification). 
  • Change the payment status in BILLmanager based on the data received above. 
  • Inform the payment system about successful or failed incoming request, if needed.

You can find the example of the script at the end of this article

 BILLmanager functions


  • payment.info - information about a payment, the elid parameter - payment id
  • payment.setfraud - set the payment status as "Fraud"; parameters:
    • elid - payment id
    • info - additional information 
    • externalid - payment id in the payment gateway
  • payment.setinpay - set the payment status as "Paid"; parameters:
    • elid - payment id
    • info - additional information
    • externalid - payment id in the payment gateway
  • payment.setnopay - set the payment status as "Not paid"; parameters:
    • elid - payment id
    • info - additional information
    • externalid - payment id in the payment gateway
  • payment.setpaid - credit the payment; parameters:
    • elid - payment id
    • info - additional information
    • externalid - payment id in the payment gateway
  • payment.success - successful payment page; parameters:
    • elid - payment id
    • module - integration module name
  • payment.fail - payment error page, parameters:
    • elid - payment id
    • module - integration module name

Refund pages


To return your clients back to BILLmanager after they make a payment, you can use custom CGI scripts, static html pages, or BILLmanager standard functions:

  • payment.success - successful payment page, the elid parameters - payment id
  • payment.fail - failed payment page, the elid - parameters - payment id

To add additional information into the forms, add more description to the corresponding function:

<metadata name="payment.XXX.fail" type="form">
  <form>
    <field name="fail_description" noname="yes" formwidth="yes">
      <textdata name="fail_description"/>
    </field>
  </form>
</metadata>

 <metadata name="payment.XXX.success" type="form">
  <form> 
    <field name="success_description" noname="yes" formwidth="yes">
      <textdata name="success_description"/>
    </field>
  </form>
</metadata>

<lang name="en">
  <messages name="payment.XXX.fail">
    <msg name="fail_description">Fail</msg>
  </messages>
  <messages name="payment.XXX.success">
    <msg name="success_description">Success</msg>
  </messages>
</lang>
<lang name="ru">
  <messages name="payment.XXX.fail">
    <msg name="fail_description">Error</msg>
  </messages>
  <messages name="payment.XXX.success">
    <msg name="success_description">Success</msg>
  </messages>
</lang>
XML

Example


The following is the example of the QIWI payment method through the PULL(REST) protocol 

PHP

The module contains four main files:

  • etc/xml/billmgr_mod_pmqiwipull.php.xml - XML description 
  • paymethods/pmqiwipull.php - main script 
  • cgi/qiwipullpayment.php - redirect CGI script 
  • cgi/qiwipullresult.php -  notifications from the payment gateway

The additional file with useful functions::

  • include/php/bill_util.php

You can download the file a https://github.com/ISPsystemLLC/billmanager/blob/master/tar/qiwipull.tar.gz, or view the list of files at https://github.com/ISPsystemLLC/billmanager/

The bill_util.php function

!!!Before adding the bill_util.php file into your script, be sure to define the __MODULE__ macro to form a log file name. It will look like this:

set_include_path(get_include_path() . PATH_SEPARATOR . "/usr/local/mgr5/include/php"); 
define('__MODULE__', "pmXXX"); 
require_once 'bill_util.php';
XML

The bill_util.php file delivers the following functions:

  • Debug($str) - outputs $str into the log as additional information
  • Error($str) -  outputs $str as an error message
  • LocalQuery($function, $param, $auth = NULL) - executes $function in BILLmanager and sends parameters from the $param array, and the session id from $auth to this function.
  • HttpQuery($url, $param, $requesttype = "POST", $username = "", $password = "", $header = array("Accept: application/xml")) - sends a request to the $url with parameters from $param. The file uses $requesttype as a request type and authentication data from $username and $password. Additional headings can be also sent to $header
  • CgiInput($skip_auth = false) - receives the array of script parameters in the request or data POST. $skip_auth receives the auth parameter from cookie, if it is not present in the data received.
  • ClientIp() - get the IP address from which the script was called
  • class Error - error class imitating behavior similar to COREmanager errors.

C++ (using BILLmanager libraries)

Starting from version 5.58.0 you can use BILLmanager header files to develop custom processing modules. Beside a simplified example, you can look into examples in the BILLmanager developer package - billmanager-[BILLmanager version]-devel, example:


yum install billmanager-standard-devel
XML
You can find the examples in the following directory:
/usr/local/mgr5/src/examples
XML

C++

You can find the example of the module at https://github.com/ISPsystemLLC/interkassa. The module is based on custom components described in the articles How to build custom components and Lower-level interaction, C++ plug-ins.

See also:

Module structure

The module consists of two mandatory files pminterkassa.cpp - the code of the main executable file of the payment method, and xml/billmgr_mod_pminterkassa.xml - XML description of the module.

The module also includes two CGI scripts for redirect to a processing center, and receipt of successful payments notifications.