1. Home
  2. Libraries for webmasters
  3. Plate payments
  4. How to hook plate payments (Node.js)?

How to hook plate payments (Node.js)?

Server-side plate payment processing

To begin support plate payments, 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 that supports payments a file (service) named eg. ‘plates.js’ must be created in file structure generated by ‘Sails.js’ in catalog ‘/api/services/’:

var billon = require("billon");
var myShop = new billon.Payment();
var alpha = 10; // the cheapest article, number of thousandths of a basic monetary unit, eg. 1p
var beta = 100; // a price of the second article, eg. 10p
var gamma = 200; // a price of the third article, eg. 20p
var delta = 500; // a price of the fourth article, eg. 50p
var epsilon = 1000; // a price of the most expensive article, eg. 1 pound
myShop.user(function (requestData, cb)
{
   cb(requestData.user);
}).products(function (requestData, cb)
{
   cb(requestData.itemsId);
}).product(function (requestData, itemId, cb)
{
   switch (itemId)
   { // a list of articles - products, article setting according to the type of the plate is not recommended in case of tariffs consisting of a smaller number of plates
      case 1:
          cb(alpha);
       break;
       case 2:
          cb(beta);
       break;
       case 3:
          cb(gamma);
       break;
       case 4:
          cb(delta);
       break;
       case 5:
          cb(epsilon);
       break;
   }
}).productBillon(function (requestData, item, cb) 
{ // call of the method not required if parameter 'quantity' is defined for all products
   cb(item);
}).paymentTitle(function (requestData, items, delivery, cb) 
{
   return cb("Payment title");
}).plates(function(requestData, cb)
{ // price setting, the lack of an argument or number 0 removes a plate from the tariff
   cb(alpha, beta, gamma, delta, epsilon);
}).cNode(function (requestData, items, delivery, cb)
{
cb("eyJhkGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c3VyIjp7ImlkIjoyNSwic2FsdCI6IjEyZWVkMzQwLTM2NGUtMThNjgyN1hNDM5zA1MiOjEh0OTCJpYXQiDk0NjF9Q1M.zeWXG7Nyr3PFVhb4HRgLi5rh8fLZx41VHySHWUStIzc"); // API key użytkownika serwisu "billon.me"
    /*cb({
       name: "billonpayments4", // CNode username
       address: "http://213.189.38.34:20891" // address and port of CNode
    });*/ // direct communication with CNode
}).currency(function(requestData, cb)
{ // ISO 4217 currency code, not required method, 'PLN' by default
   cb('GBP');
}).maxTotalAmount(function(requestData, cb)
{ // the maximum sum payment in the series expressed in thousandths of a basic monetary unit, not required method
   cb(10000);
}).duration(function(requestData, cb)
{ // the duration of a series of payments in seconds, the required method in order that the series has a non-zero length of duration
   cb(3600);
}).maxPaymentsInSeries(function(requestData, cb)
{ // the maximum number of payments in the series, not required method
   cb(10);
}).platePayment(function(requestData, cb)
{ // setting of series identifier and kind of plate 
   cb(requestData.seriesId, requestData.type);
}).merchantBrandName(function(requestData, cb)
{ // setting of brand, not required method, domain of the page on which payment is executed by default
   cb('Nazwa brandu');
}).onReceivedPlatePaymentSeriesStatus(function (response)
{ // event of CNode response during the proces of the acceptance of the series, not reqiured method
   console.log(response);
   if (response.status == 'SERIES_ACCEPTED' || response.status == 'TRANSFERRING' || response.status == 'TRANSFERING')
   {
      console.log('The series of payment accepted');
   }
}).onAcceptedPlatePaymentSeries(function (paymentData)
{ // event of acceptance of the series, not required method
   console.log(paymentData);
}).onFinishedPayment(function (items, delivery_option, document, requestData)
{ // event of finished payment, not required method
   console.log(document);
   console.log(requestData);
   if (requestData.itemsId.constructor === Array)
   {
      for (var i = 0; i < requestData.itemsId; ++i)
      { // a operation can be performed here after successfully finished purchase of article - product
         console.log(requestData.itemsId[i]);
      }
   }
}).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;

Once you have configured the server and Sails.js service, you need to create a controller to be able to communicate with the user on a webpage

sails generate controller Plates

A file ‘PlatesController.js’, in which the communication to given address must be handled and associated with previously created service ‘plates.js’, will be created in catalog ‘api/controllers’. Example of file ‘PlatesController.js’:

module.exports = {
  list: function(req, res)
  { // method that outputs the list of prices, the currency, the limit of the duration of the series,
    // the maximum amount of the payments in the series and merchant brand name
    plates.tariff(res);
  },
  initiate: function(req, res)
  { // method that initiate start of series of payment
    plates.platePaymentSeriesStart(req, res);
  },
  pay: function(req, res)
  { // method that initiates payment
    plates.paymentInitiation(req, res);
  },
  status: function(req, res)
  { // listening method
    plates.paymentStatus(req.body.taskId || req.query.taskId, function(response)
    {
      res.json(response);
    });
  }
};

Taking plate payments on webpages

Use JavaScript Billon scripts for taking the plate payments on a webpage:

<div id="button-container-1"></div>
<script src="//cdn.billon.pro/js/billon.js"></script>
<script src="//cdn.billon.pro/js/billon-agent.js"></script>
<script src="//cdn.billon.pro/js/billon-object.js"></script>
<script src="//cdn.billon.pro/js/billon-user.js"></script>
<script src="//cdn.billon.pro/js/billon-plates.js"></script>
<script>
   billon.plates({
      connection: new billon.agent("http://billon.info:1401/plates"), // address pointing to Sails.js controller that supports payment (in this case PlatesController)
      lang: 'en', // language 'en' or 'pl', 'en' by default
      plateButtonAddress: "https://cdn.billon.pro/screen/plate-button/index.html", // in the case of not showing buttons, skip in the case of the lack of problems
      plateDialogAddress: "https://cdn.billon.pro/screen/plate-dialog/index.html", // in the case of not showing dialog, skip in the case of the lack of problems
      skipAnotherUser: false, // optional - omission of the step of of choosing another user than detected, the step is not skipped by default
      disableButtonsTitle: false, // optional - default not adding title (tooltip) with the price to the buttons, the titles are being set by default
      tariff: {
         address: 'list', // name of controller parameter where method 'tariff' is being called
         displayedCurrency: '£', // displayed currency, ISO 4217 currency code set with Node.js module 'billon' by default
                              // if a parameter 'displayedCurrencyBefore' is not set and the amounts greater than or equal to 1 or a parameter 'centSign' is not set, 
                              // they are formatted by default according to ISO 4217 currency code set with Node.js module 'billon' and user's locale, 
                              // ISO 4217 currency code set with server payment module is used as sign of currency by default, when 'displayCurrencyBefore' is set
         displayCurrencyBefore: true, // displaying the sign of currency before the number, 
                                    // the sign from the parameter 'displayedCurrency' is appended to the number at the end by default
         centSign: 'p', // sign of currency for the hundredth part of the basic monetary unit displayed for the price lower than this unit, 
                    // the sign is used as for higher prices by default
         displayCentSignBefore: false // displaying the sign of currency set in parameter 'centSign' before number, this sign is appended to the number at the end by default
      },
      series: {
         request: {
            address: 'initiate', // name of controller parameter where method 'platePaymentSeriesStart' is being called
            data: function (user) 
            {
              return {
                user: user
              };
            }
         },
         listenResponse: function (response, user)
         {
            if (response.status == "SERIES_ACCEPTED" || response.status == "TRANSFERRING" || response.status == "TRANSFERING")
            { // save of identifier of series and Billon username, in this case in Local Storage
               localStorage.setItem("seriesId", response.taskId);
	       localStorage.setItem("user", JSON.stringify(user));
            }
         }
      },
      paymentRequest: {
         address: 'pay', // name of controller parameter where method 'paymentInitiation' is being called
         data: function()
         { // reading previously saved identifier of series and Billon username, in this case from Local Storage
            try
            {
               return {
                  seriesId: localStorage.getItem("seriesId"),
                  user: JSON.parse(localStorage.getItem("user"))
               };
            }
            catch (e)
            {
               return {};
            }
         }
      },
      listen: {
         address: "status", // name of controller parameter where method 'paymentStatus' is being called
         data: function (requestResponse) 
         {
           return {
             taskId: requestResponse.taskId
           };
         }
      },
      buttons: [ // array of buttons
      {
         place: document.getElementById('button-container-1'), // HTML element in which the button is to be placed
         type: 'alpha', // 0 can by given instead of 'aplha' - type of the button
         disableTitle: false, // optional - not setting the title of the button with the price,
                              // the global option 'DisableButtonsTitle' is acted on by default
         requestData: function(type)
         {
            return {
               type: type,
               itemsId: [1] // array of identifiers of products
            }
         },
         listenResponse: function(response)
         { // optional method
            switch (response.status)
            {
               case "FINISHED_OK":
                  // event of successfully purchase with the button
                  break;
               case "FINISHED_ERR_USER_REJECTED": // a lack of possibility to pay within the stored series
                  localStorage.setItem("seriesId", null);
		  localStorage.setItem("user", JSON.stringify(null));
            }
         }
      },
      {
         place: document.getElementById('button-container-2'),
         type: 'beta',
         requestData: function(type)
         {
            return {
               type: type,
               itemsId: [2]
            }
         },
         listenResponse: function(response)
         {
            switch (response.status)
            {
               case "FINISHED_OK":
                  // event of successfully purchase with the button
                  break;
               case "FINISHED_ERR_USER_REJECTED": // a lack of possibility to pay within the stored series
                  localStorage.setItem("seriesId", null);
		  localStorage.setItem("user", JSON.stringify(null));
            }
         }
      },
      {
         place: document.getElementById('button-container-3'),
         type: 'gamma',
         requestData: function(type)
         {
            return {
               type: type,
               itemsId: [3]
            }
         },
         listenResponse: function(response)
         {
            switch (response.status)
            {
               case "FINISHED_OK":
                  // event of successfully purchase with the button
                  break;
               case "FINISHED_ERR_USER_REJECTED": // a lack of possibility to pay within the stored series
                  localStorage.setItem("seriesId", null);
		  localStorage.setItem("user", JSON.stringify(null));
            }
         }
      },
      {
         place: document.getElementById('button-container-4'),
         type: 'delta',
         requestData: function(type)
         {
            return {
               type: type,
               itemsId: [4]
            }
         },
         listenResponse: function(response)
         {
            switch (response.status)
            {
               case "FINISHED_OK":
                  // event of successfully purchase with the button
                  break;
               case "FINISHED_ERR_USER_REJECTED": // a lack of possibility to pay within the stored series
                  localStorage.setItem("seriesId", null);
		  localStorage.setItem("user", JSON.stringify(null));
            }
         }
      },
      {
         place: document.getElementById('button-container-5'),
         type: 'epsilon',
         requestData: function(type)
         {
            return {
               type: type,
               itemsId: [5]
            }
         },
         listenResponse: function(response)
         {
            switch (response.status)
            {
               case "FINISHED_OK":
                  // event of successfully purchase with the button
                  break;
               case "FINISHED_ERR_USER_REJECTED": // a lack of possibility to pay within the stored series
                  localStorage.setItem("seriesId", null);
		  localStorage.setItem("user", JSON.stringify(null));
            }
         }
      }]
   });
</script>
Was this article helpful to you? Yes No

How can we help?