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 == 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) 
{
   cb(item);
}).productDelivery(function (requestData, items, cb) 
{
   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('EUR');
}).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)
{
   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)
{
   cb(false);
}).onFinishedPayment(function (items, delivery_option, document, requestData)
{
   console.log(document);
   console.log(document.additionalInfo);
}).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");
}).product(function(itemId, cb)
{
   return cb(false);
}).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) 
{
    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);
}).onFinishedPayment(function (items, delivery_option, document, requestData)
{
   console.log(document);
   console.log(document.additionalInfo);
}).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’.

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.

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 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.

Example request:

myShop.product(function (requestData, itemId, cb) 
{
  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) 
{
  // Since the data was in the correct format in the last method, we pass the same item object.
  cb(item);
});

5. productDelivery

In this method there should be a delivery method specified by the customer. 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 specife 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.

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.

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 
  }
});

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?