1. Home
  2. Libraries for webmasters
  3. Server-side scripts

Server-side scripts

To begin, install the framework Sails.js (guide), create a Sails.js application and install the Node.js module “billon”: sudo npm install billon --save After installing the module ‘billon’, create a file in ‘/api/services/’ a service, for example ‘MyShop.js’. ‘MyShop.js’ should begin with an import of the Billon library and creation of a payment object:

var billon = require('billon'); 
var myShop = new billon.Shop();

Next, call the configuration functions for the newly created payment object, which receive ‘requestData’ as a parameter (it is an object sent for the user’s browser via the POST method) and then return correctly formatted data to the object as a callback. At the end of your ‘MyShop.js’ file, make the payment object:

module.exports = myShop;

Configuration methods

Configuration methods return a reference to their object. An example of a product purchase payment service (payment for product):

var billon = require("billon");
var myShop = new billon.Shop();
myShop.user(function (requestData, cb)
{
   cb(requestData.user);
}).products(function (requestData, cb)
{
   cb(requestData.itemsId);
}).product(function (requestData, itemId, cb)
{
   if (itemId == 16)
   { // the number of thousandth parts of the basic monetary unit
       cb(2000); // eg. 2 pounds
   }
   else if (itemId == 17) 
   {
       cb({
          "amount_gross": 1.2 // eg. 1.2 pounds
       });
   }
   else if (itemId == 18) 
   {
       cb({
          "item_id": "18",
          "item_name": "eBook",
          "quantity": 1,
          "unit_type": "pcs.",
          "unit_price_net": 0.24,
          "amount_net": 0.24,
          "amount_discount_net": 0,
          "vat": {
             "percent": 23,
             "amount": 0.06
          },
          "amount_gross": 0.3
       });
   }
   else if (itemId == 30)
   {
       KeyCode.find({}).exec(function (err, found)
       {
          return cb({
             "item_id": "30",
             "item_name": "Access Code",
             "quantity": 1,
             "unit_type": "pcs.",
             "unit_price_net": 0.81,
             "amount_net": 0.81,
             "amount_discount_net": 0,
             "vat": {
                "percent": 23,
                "amount": 0.19
             },
          "amount_gross": 1,
          KeyCodes: found});
       });
  }
}).productBillon(function (requestData, item, cb) 
{ // not required method
   cb(item);
}).productDelivery(function (requestData, items, cb) 
{ // not required method
   cb({
        "delivery_id": "",
	"delivery_description": "",
	"delivery_kind": "",
	"delivery_price_net": "0",
	"vat": {
		"percent": "0",
		"amount": "0"
	},
	"delivery_price_gross": "0",
	"estimated_delivery_date": "0"
   });
}).productDownload(function (requestData, items, delivery, document, cb)
{
   if (items[0].item_id == 18) 
   {
      cb(["http://sklep3.billon.net.pl/downloadFiles/eBook.pdf"]);
   }
   else if (items[0].item_id == 30)
   {
      var downloads = [];
      if (items[0] && items[0].KeyCodes && items[0].KeyCodes.length > 0)
      {
        var key = _.find(items[0].KeyCodes, function (keycode)
        {
            return keycode.Status === "available";
        });
        if (key)
        {
            downloads.push(key);
            return cb(downloads);
        }
      }
      cb({err: true});
   }
   cb(false);
}).currency(function (requestData, cb)
{
   cb('GBP');
}).paymentTitle(function (requestData, items, delivery, cb) 
{
    cb('Payment title');
}).app24(function (requestData, items, delivery, cb)
{
cb("eyJhkGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c3VyIjp7ImlkIjoyNSwic2FsdCI6IjEyZWVkMzQwLTM2NGUtMThNjgyN1hNDM5zA1MiOjEh0OTCJpYXQiDk0NjF9Q1M.zeWXG7Nyr3PFVhb4HRgLi5rh8fLZx41VHySHWUStIzc"); // API key of the user of a service "billon.me"
    /*cb({
       Name: "billonpayments4",
       Address: "http://213.189.38.34:20891"
    });*/ // direct communication with the application 24/7
}).merchant(function (requestData, items, delivery, cb)
{ // not required method
   cb({
      "company": {
		"name": "Default",
		"NIP": "",
		"REGON": "",
		"KRS": ""
      },
      "person": {
		"first_name": "Default",
		"last_name": "",
		"PESEL": ""
      },
      "address": {
		"street": "Default",
		"city": "Default",
		"zip": "00-000",
		"country": ""
       },
       "fax": "",
       "www": "",
       "email": ""
   });
}).documentParse(function (requestData, document, cb)
{ // not required method
   cb(false);
}).onFinishedPayment(function (items, delivery_option, document, requestData)
{
   console.log(document);
   console.log(document.additionalInfo);
   console.log(document.taskId); // since version no. 2.3 of the module 'billon'
}).onRequestSend(function (requestName, parameters, requestResponse, error)
{ // the event of sending SOAP request, not required method
   console.log('SOAP request: ', requestName);
   console.log('Parameters of request: ', parameters);
   console.log('Response of the app: ', requestResponse);
   console.log('Error while sending: ', error);
});
module.exports = myShop;

A specific type of payment used to purchase the product is the plate payments. Example of a service of a donation (payment for amount):

var billon = require("billon");
var myShop = new billon.Shop();
myShop.paymentTitle(function (requestData, items, delivery, cb) 
{
   return cb("Donation");
}).app24(function (requestData, param1, param2, cb)
{
cb("eyJhkGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c3VyIjp7ImlkIjoyNSwic2FsdCI6IjEyZWVkMzQwLTM2NGUtMThNjgyN1hNDM5zA1MiOjEh0OTCJpYXQiDk0NjF9Q1M.zeWXG7Nyr3PFVhb4HRgLi5rh8fLZx41VHySHWUStIzc"); // API key of the user of the service "billon.me"
    /*cb({
       Name: "billonpayments4",
       Address: "http://213.189.38.34:20891"
    });*/ // direct communication with the application 24/7
}).merchant(function (requestData, items, delivery, cb) 
{ // not required method
    return cb({
        "company": {
	        "name": "",
                "NIP": "",
                "REGON": "",
                "KRS": ""
        },
        "person": {
                "first_name": "Default",
                "last_name": "",
                "PESEL": ""
        },
        "address": {
                "street": "Default",
                "city": "Default",
                "zip": "00-000",
                "country": ""
        },
        "fax": "",
        "www": "",
        "email": ""
     }); 
}).documentParse(function(requestData, document, cb) { 
     cb(document); // not required method
}).onFinishedPayment(function (items, delivery_option, document, requestData) { 
     console.log(document);
     console.log(document.additionalInfo);
     console.log(document.taskId); // in version no. 2.3 of the module 'billon'
}).onRequestSend(function (requestName, parameters, requestResponse, error) 
{ // the event of sending SOAP request, not required method
     console.log('SOAP request: ', requestName);
     console.log('Parameters of request: ', parameters);
     console.log('Response of the app: ', requestResponse);
     console.log('Error while sending: ', error);
}); 
module.exports = myShop;

1. user

In the function serving as a parameter of the ‘user’ method, the function ‘cb’ should be called with the object ‘peerLocation’ as parameter. The object should be the user’s location, automatically checked by ‘billon-user.js’ if there is Billon running on the user’s device. If not, it is an object with one property: ‘userName’. The method does not apply to donations made using the method ‘donateInitiation’ where user`s ‘peerLocation’ object is retrieved from the parameter ‘user’ of JSON structure that is the parameter of the request of the controller from the webpage. The donation amount expressed in the number of thousandth parts of the basic monetary unit is passed in a similar way through the parameter ‘amount’ which is the parameter of the request. Example request:

myShop.user(function (requestData, cb)
{
  /* Example value of variable 'requestData.user':
  {
    "userName": "test", // Required
    ... // Other optional parameters for faster user searching
  }
  */
  cb(requestData.user);
});

2. products

This method should pass an array of product ids. The method does not apply to the donations. The method is not required in version no. 2.4 of the module. Example request:

myShop.products(function (requestData, cb) 
{
  /* Example value of variable 'requestData.itemsId':
  [
    1,
    2,
    3
  ]
  */
  cb(requestData.itemsId);
});

3. product

The function serving as a parameter of the ‘product’ method should have the parameter ‘id’ of a product or a price expressed in a number of the thousandth parts of the basic monetary unit. and should pass an object with product data. The data will be available in the user’s browser to display information about the product which is being purchased. A simple product or price shall be set using this method in the case of not using the method ‘products’. Example request:

myShop.product(function (requestData, itemId, cb) 
{
  if (itemId == 16)
  { // the number of thousandth parts of the basic monetary unit
    cb(2000); // eg. 2 pounds
  }
  else if (itemId == 17) 
  {
    cb({
          "amount_gross": 1.2 // eg. 1.2 pounds
    });
  }  
  else if (itemId === 26) 
  {
    cb({
      "item_id": "26",
      "item_name": "Footwear",
       "quantity": 1,
      "unit_type": "szt",
      "unit_price_net": 64.96,
      "amount_net": 64.96,
      "amount_discount_net": 0,
      "vat": {
        "percent": 23,
        "amount": 14.94
      },
      "amount_gross": 79.9,
      "requestInvoiceData": "OPTIONAL", // optional invoice data
      "requestDeliveryData": "OBLIGATORY" // obligatory invoice data
      // default value in both above cases: 'NOT_NEEDED' - needless data
    });
  }
  else if (itemId === 30)
  {
    KeyCode.find({Service: 'games'}).exec(function (err, found)
    { // sale access codes
      return cb({
        "item_id": "30",
        "item_name": "Access Code",
        "quantity": 1,
        "unit_type": "szt",
        "unit_price_net": 0,81,
        "amount_net": 0,81,
        "amount_discount_net": 0,
        "vat": {
          "percent": 23,
          "amount": 0.19
        },
        KeyCodes: found});
    });
  }
});

The product can be a unique access code. Module ‘billon’ can select codes and set them as used on its own. To use the code necessary to create Sails.js model KeyCode. The required attributes of this model are:

  • „Value” – code;
  • „Status” – code status, który which can take values available, sold and blocked.

Example of model KeyCode.js:

module.exports = {
  connection: 'database_connection',
  tableName: 'KeyCodes',
  autoPK: true,
  attributes: {
	Value: {
	    type: "string",
	    required: true,
	    unique: true,
	    size: 255
},
	Status: {
	    type: "string",
            enum: [
               'available' // codes possible to buy
               'blocked', // codes blocked during the transaction
               'sold', // sold codes
               'used' // optional custom value preventing from code purchase
            ], 
            defaultsTo: 'available'
        },
        Service: { // optional custiom attribute of code
	   type: "string",
	   size: 255
        }
  }
};

It is recommended to check the availability of codes single-handedly.

4. productBillon

The method ‘productBillon’ is different from the previous method in that it requires the parameters to be formatted in a way that complies with Billon API. Example request:

myShop.productBillon(function (requestData, item, cb) 
{
  cb(item);
});

5. productDelivery

In this method there should be a delivery method specified by the customer. Method is optional. It does not apply to payments for online products or donations. Example request:

myShop.productDelivery(function (requestData, items, cb) 
{
  // The structure of the object delivery options below.
  cb({
    "delivery_id": "",
    "delivery_description": "",
    "delivery_kind": "",
    "delivery_price_net": "0",
    "vat": {
      "percent": "0",
      "amount": "0"
    },
    "delivery_price_gross": "0",
    "estimated_delivery_date": "0"
  });
});

6. productDownload

This method applies only to products which can be downloaded and codes. In the case of downloadable products the link that is to be given to buyer after payment should be set in the method for a given parcel (parameter ‘items’) of products. In the case of the access codes, use the code below. Codes and downloadable products are supported by script ‘billon-loadingBar.js but not supported by ‘billon-plates.js’ intended for plate payments and by ‘billon-paymentDialog.js’. Example request:

myShop.productDownload(function (requestData, items, delivery, document, cb)
{
  // Example in which a product with "id" 18 is downloadable from a fixed link
  // and a product with "id" 30 is returned as code below 
  if (items[0].item_id == 18)
  {
    return cb(["http://sklep3.billon.net.pl/downloadFiles/eBook.pdf"]);
  }
  else if (items[0].item_id == 30)
  {
    var downloads = [];
    if (items[0] && items[0].KeyCodes && items[0].KeyCodes.length > 0)
    {
        var key = _.find(items[0].KeyCodes, function (keycode)
        {
            return keycode.Status === "available";
        });
        if (key)
        {
            downloads.push(key);
            // UsedKeyCode = key.Value; - code save to prevoulsy created variable
            return cb(downloads);
        }
    }
    cb({err: true});
  }
  cb(false);
});

7. currency

In this method you can specify the currency, using ISO 4217 format. This method is optional. The default currency is ‘PLN’. Example request:

myShop.currency(function (requestData, cb)
{
   cb('EUR');
});

8. paymentTitle

Method used for setting payment title. Example request:

myShop.paymentTitle(function (requestData, items, delivery, cb) 
{
  cb("Code");
});

9. app24

This method specifies the address of a 24/7 service which handles payments. API key of the user of the service ‘billon.me’, which can be copied from a settings page, or the object with username with which the application 24/7 is signed in and address on which the application 24/7 listens for incoming requests can be given. You can include your loadbalancing functionality here. Example request:

myShop.app24(function (requestData, items, delivery, cb)
{
    cb("eyJhkGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c3VyIjp7ImlkIjoyNSwic2FsdCI6IjEyZWVkMzQwLTM2NGUtMThNjgyN1hNDM5zA1MiOjEh0OTCJpYXQiDk0NjF9Q1M.zeWXG7Nyr3PFVhb4HRgLi5rh8fLZx41VHySHWUStIzc"); // API key of the user of the service 'billon.me'
    /*cb({
       Name: "billonpayments4",
       Address: "http://213.189.38.34:20891"
    });*/ // an object that contains the name and the IP address (and port) of the application 24/7 - direct communication with the application 24/7
});

10. merchant

This methods shows your data in the user’s app. The data has to be formatted according to Billon API standards. The method is optional. Example request:

myShop.merchant(function (requestData, items, delivery, cb)
{
  cb({
    "company": {
      "name": "Default",
      "NIP": "",
      "REGON": "",
      "KRS": ""
    },
    "person": {
      "first_name": "Default",
      "last_name": "",
      "PESEL": ""
    },
    "address": {
      "street": "Default",
      "city": "Default",
      "zip": "00-000",
      "country": ""
    },
    "fax": "",
    "www": "",
    "email": ""
  });
});

11. documentParse

This method is used for non-standard parsing of the payment document. The method is optional.

myShop.documentParse(function (requestData, document, cb)
{   
  // If the method "cb" is being called with the parameter "false", the document will not be parsed.
  cb(false);   
});

12. merchantBrandName

This method sets the name of the brand, which is by default the domain of the page on which payment is made:

myShop.merchantBrandName(function(requestData, cb)
{
   cb('Name of brand');
});

13. plates

Using this method, you can set the price of plates. These prices apply at the time of the call of methods ‘platePaymentSeriesStart’ and ‘platesList’ in Sails.js controller. Example of use with previously set values:

myShop.plates(function(requestData, cb)
{
   cb(alpha * 1000, beta * 1000, gamma * 1000, delta * 1000, epsilon * 1000); // multiplying the price to the number of thousandths of a basic monetary unit 
}); // method 'cb' can be called with fewer arguments, number 0 also removes a plate from the tariff

14. maxTotalAmount

This method is used to set the maximum amount of the plate payments in series. The method is applicable at the time of the call of method ‘platePaymentSeriesStart’ in Sails.js controller. The sum is expressed in the number of thousandths of a basic monetary unit:

myShop.maxTotalAmount(function(requestData, cb)
{
   cb(10000); // np. 10 zł
})

15. duration

Using this method, you need to set the duration of the series the plate payments in seconds. The method is applicable at the time of the call of method ‘platePaymentSeriesStart’ in Sails.js controller. Example:

myShop.duration(function(requestData, cb)
{
   cb(3600);
})

16. maxPaymentsInSeries

This method can be called with an argument being a function that calls a function of its second argument with the maximum number of payments in a series of the plate payments. The method is applicable at the time of the call of method ‘platePaymentSeriesStart’ in Sails.js controller. Example:

myShop.maxPaymentsInSeries(function(requestData, cb)
{
   cb(10);
})

17. platePayment

This method is used to define the payment as plate one. The argument of this method is a function that calls a function of its first argument with two arguments: an identifier of series and the type of plate (PLATE_ALPHA, PLATE_BETA, PLATE_GAMMA, PLATE_DELTA or PLATE_EPSILON). An example of using the values set the script in the browser:

myShop.platePayment(function(requestData, cb)
{
   cb(requestData.seriesId, requestData.type);
});

Note: If the number of plates is less than five, a type of a plate can be changed by client-side script „billon-plates.js”.

18. onReceivedPlatePaymentSeriesStatus

This method is used to handle the status returned by 24/7 application during the operation of acceptance of the plate payments series. The method is applicable at the time of the call of method ‘platePaymentSeriesStart’ in Sails.js controller.

myShop.onReceivedPlatePaymentSeriesStatus(function (response)
{ 
   console.log(response); // message returned by 24/7 application
   console.log(response.status); // returned status
});

19. onAcceptedPlatePaymentSeries

Using this method, you can handle the event of acceptance the plate payments series on the server side. The method is applicable at the time of the call of method ‘platePaymentSeriesStart’ in Sails.js controller.

myShop.onAcceptedPlatePaymentSeries(function (paymentData)
{
   // event handler of acceptance of payments series here
});

20. onFinishedPayment

The most important method for Billon integration on your website. It specifies what happens when the operation is successfully completed. You can, for example, display a ”success” screen and / or send a confirmation email to your customer. Example request:

myShop.onFinishedPayment(function (items, delivery, purchaseDocument, requestData) 
{
  // "purchaseDocument" is an object that contains all invoice data concerning the transaction which was a success.
  console.log(purchaseDocument);
  if (purchaseDocument.additionalInfo)
  {
    var additionalInfo = JSON.parse(purchaseDocument.additionalInfo);
    if (additionalInfo.actual_amount)
    {
      console.log(additionalInfo.actual_amount); // actual amount paid by user
    }
    // console.log(UsedKeyCode); - previously used variable, eg. purchased code 
  }
  if (purchaseDocument.taskId)
  {
    console.log(purchaseDocument.taskId); // the task identifier in version no. 2.3 of the module 'billon'
  }
});

21. onRequestSend

This method handles the event of sending SOAP request to 24/7 app and receiving or not receiving a response. The method can be useful to create logs of SOAP communication or perform some operation in case of a failure of the payment. Example request:

myShop.onRequestSend(function (requestName, parameters, requestResponse, error)
{
   console.log('SOAP request: ', requestName);
   console.log('Parameters of request: ', parameters);
   console.log('Response of the app: ', requestResponse);
   console.log('Error while sending: ', error); // the errors from 24/7 app are being passed by the argument 'requestResponse'
});

Communicating with a WWW user

If there is a Sails.js app configured, you can create a controller for communicating with users. Create a new controller “PaymentController.js” in your app for example: sails generate controller Payment In it, we will service all communication associated with your your payment services. Below is an example of a PaymentController.js, using appropriate Billon methods and sending data to the user’s browser.

module.exports = {
  // Initiating payment
  initiate: function(req, res)
  {
    MyShop.paymentInitiation(req, res);
  },
  // Tracking operation progress
  status: function(req, res)
  {
    MyShop.paymentStatus(req.body.taskId || req.query.taskId, function(response)
    {
      res.json(response);
    });
  },
  // Handling a donation
  donate: function(req, res)
  {
    MyShop.donateInitiation(req, res);
  }
};

With our controller defined, you can use scripts for browsers ‘billon-<module>.js or a WebSocket to communicate with your Sails.js controller.

Was this article helpful to you? Yes No

How can we help?