Jak podpiąć płatności talerzykowe (Node.js)?

Obsługa płatności talerzykowych po stronie serwera

Obsługę płatności talerzykowych należy rozpocząć od zainstalowania frameworku Sails.js (instrukcja), utworzenia aplikacji Sails.js i zainstalowaniu w niej modułu Node.js – billon: sudo npm install billon --save Po zainstalowaniu modułu obsługującego płatność w wygenerowanej przez „Sails.js” strukturze plików należy utworzyć w katalogu „/api/services/” plik (usługę) o nazwie np. „plates.js”:

var billon = require("billon");
var myShop = new billon.Payment();
var alpha = 10; // cena za najtańszy artykuł, np. 1 gr (liczba dziesiątych części grosza)
var beta = 100; // cena za drugi artykuł, np. 10 gr
var gamma = 200; // cena za trzeci artykuł, np. 20 gr
var delta = 500; // cena za czwarty artykuł, np. 50 gr
var epsilon = 1000; // cena za najdroższy artykuł, np. 1 zł
myShop.user(function (requestData, cb)
{
   cb(requestData.user);
}).products(function (requestData, cb)
{
   cb(requestData.itemsId);
}).product(function (requestData, itemId, cb)
{
   switch (itemId)
   { // lista artykułów - produktów, ustawianie artykułu według typu talerzyka jest niezalecane w przypadku taryf składających się z mniejszej liczby talerzyków
      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) 
{ // wywołanie metody niewymagane, jeśli dla wszystkich produktów określono parametr "quantity"
   cb(item);
}).paymentTitle(function (requestData, items, delivery, cb) 
{
   return cb("Tytuł płatności");
}).plates(function(requestData, cb)
{ // ustawienie cen, brak argumentu lub liczba 0 usuwa talerzyk z taryfy
   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", // nazwa użytkownika węzła Corporate Node
       address: "http://213.189.38.34:20891" // adres i port węzła Corporate Node
    });*/ // komunikacja bezpośrednio z węzłem Corporate Node
}).currency(function(requestData, cb)
{ // kod ISO 4217 waluty, metoda niewymagana, domyślnie "PLN"
   cb('PLN');
}).maxTotalAmount(function(requestData, cb)
{ // maksymalna suma płatności w serii wyrażona w dziesiątych częściach grosza, metoda niewymagana
   cb(10000);
}).duration(function(requestData, cb)
{ // czas trwania serii płatności w sekundach, metoda wymagana, aby seria miała nie zerową długość czasu trwania
   cb(3600);
}).maxPaymentsInSeries(function(requestData, cb)
{ // maksymalna liczba płatności w serii, metoda niewymagana
   cb(10);
}).platePayment(function(requestData, cb)
{ // ustawienie identyfikatora serii i rodzaju talerzyka
   cb(requestData.seriesId, requestData.type);
}).merchantBrandName(function(requestData, cb)
{ // ustawienie brandu, metoda niewymagana, domyślnie domena strony, na której wykonywane są płatności
   cb('Nazwa brandu');
}).onReceivedPlatePaymentSeriesStatus(function (response)
{ // zdarzenie odpowiedzi węzła Corporate Node w tracie operacji akceptacji serii, metoda niewymagana
   console.log(response);
   if (response.status == 'SERIES_ACCEPTED' || response.status == 'TRANSFERRING' || response.status == 'TRANSFERING')
   {
      console.log('Seria płatności zakceptowana');
   }
}).onAcceptedPlatePaymentSeries(function (paymentData)
{ // zdarzenie zaakceptowanej serii płatności, metoda niewymagana
   console.log(paymentData);
}).onFinishedPayment(function (items, delivery_option, document, requestData)
{ // zdarzenie ukończonej płatności, metoda niewymagana
   console.log(document);
   console.log(requestData);
   if (requestData.itemsId.constructor === Array)
   {
      for (var i = 0; i < requestData.itemsId; ++i)
      { // tutaj można wykonać operację po pomyślnie dokonanym zakupie artykułu - produktu
         console.log(requestData.itemsId[i]);
      }
   }
}).onRequestSend(function (requestName, parameters, requestResponse, error)
{ // zdarzenie wysłania operacji SOAP, metoda niewymagana
   console.log('Wiadomość SOAP: ', requestName);
   console.log('Parametry wiadomości: ', parameters);
   console.log('Odpowiedź węzła Corporate Node: ', requestResponse);
   console.log('Błąd przy wysyłaniu: ', error);
});
module.exports = myShop;

Kiedy już posiadamy skonfigurowany serwer i usługę Sails.js, trzeba utworzyć kontroler, aby mógł się on skomunikować z użytkownikiem strony WWW:

sails generate controller Plates

W katalogu „api/controllers” powstanie plik „PlatesController.js”, w którym należy obsłużyć komunikację do danego adresu i powiązać ją z usługą „plates.js”, którą wcześniej utworzyliśmy. Przykład pliku „PlatesController.js”:

module.exports = {
  list: function(req, res)
  { // metoda wysyłającą ustawioną listę cen, walutę, 
    // limit czasu trwania serii, maksymalną sumę płatności w serii i nazwę brandu
    plates.tariff(res);
  },
  initiate: function(req, res)
  { // metoda inicjująca start serii płatności
    plates.platePaymentSeriesStart(req, res);
  },
  pay: function(req, res)
  { // metoda inicjująca płatność
    plates.paymentInitiation(req, res);
  },
  status: function(req, res)
  { // metoda nasłuchująca
    plates.paymentStatus(req.body.taskId || req.query.taskId, function(response)
    {
      res.json(response);
    });
  }
};

Podpięcie płatności talerzykowych na stronach internetowych

W celu podpięcia płatności do strony internetowej należy skorzystać ze skryptów JavaScript Billon:

<div id="button-container-1"></div>
<script src="//showroom.billongroup.com/lib/js/billon.js"></script>
<script src="//showroom.billongroup.com/lib/js/billon-agent.js"></script>
<script src="//showroom.billongroup.com/lib/js/billon-object.js"></script>
<script src="//showroom.billongroup.com/lib/js/billon-user.js"></script>
<script src="//showroom.billongroup.com/lib/js/billon-plates.js"></script>
<script>
   billon.plates({
      connection: new billon.agent("http://billon.info:1401/plates"), // adres wskazujący na kontroler Sails.js obsługujący płatność (w tym przypadku PlatesController)
      lang: 'pl', // język "pl" lub "en", domyślnie "en"
      plateButtonAddress: "https://showroom.billongroup.com/lib/screen/plate-button/index.html", // w przypadku problemów z niepokazywaniem przycisków, w przypadku braku problemów pominąć
      plateDialogAddress: "https://showroom.billongroup.com/lib/screen/plate-dialog/index.html", // w przypadku problemów z niepokazywaniem okna dialogowego, w przypadku braku problemów pominąć
      skipAnotherUser: false, // opcjonalne - pominięcie kroku wyboru innego użytkownika niż wykryty, domyślnie krok nie jest pomijany
      disableButtonsTitle: false, // opcjonalne - domyślne niedodawanie tytułu (etykiety) z ceną do przycisków, domyślnie tytuły są ustawiane
      tariff: {
         address: 'list', // nazwa parametru kontrolera, gdzie wywoływana jest metoda "tariff"
         displayedCurrency: '', // wyświetlana waluta, 
                                   // domyślnie kwoty są sformatowana według kodu ISO 4217 waluty ustawionej za pomocą serwerowego modułu Node.js 'billon' i ustawień regionalnych użytkownika, 
                                   // jeśli nie ustawiono parametru "displayedCurrencyBefore" i gdy są wyższe lub równe 1 lub nie ustawiono parametru, 
                                   // przy ustawionym parametrze "displayCurrencyBefore" jako symbol waluty używany jest kod ISO 4217 waluty ustawionej za pomocą modułu Node.js 'billon'
         displayCurrencyBefore: false, // czy wyświetlać walutę przed liczbą, 
                                    // domyślnie symbol z parametru "displayedCurrency" doklejany jest na końcu liczby
         centSign: ' gr', // symbol waluty dla setnej części podstawowej jednostki pieniężnej wyświetlany dla cen o wartości poniżej tej jednostki, 
                    // domyślnie stosowany jest symbol, jak dla wyższych cen
         displayCentSignBefore: false // czy wyświetlać symbol waluty ustawiony w parametrze "centSign" przed liczbą, domyślnie ten symbol doklejany jest na końcu liczby
      },
      series: {
         request: {
            address: 'initiate', // nazwa parametru kontrolera, gdzie wywoływana jest metoda "platePaymentSeriesStart"
            data: function (user) 
            {
              return {
                user: user
              };
            }
         },
         listenResponse: function (response, user)
         {
            if (response.status == "SERIES_ACCEPTED" || response.status == "TRANSFERRING" || response.status == "TRANSFERING")
            { // zapis identyfikatora serii i nazwy użytkownika Billon, w tym przypadku w Local Storage
               localStorage.setItem("seriesId", response.taskId);
	       localStorage.setItem("user", JSON.stringify(user));
            }
         }
      },
      paymentRequest: {
         address: 'pay', // nazwa parametru kontrolera, gdzie wywoływana jest metoda "paymentInitiation"
         data: function()
         { // odczyt zapisanego wcześniej identyfikatora serii i nazwy użytkownika Billon, w tym przypadku z Local Storage
            try
            {
               return {
                  seriesId: localStorage.getItem("seriesId"),
                  user: JSON.parse(localStorage.getItem("user"))
               };
            }
            catch (e)
            {
               return {};
            }
         }
      },
      listen: {
         address: "status", // nazwa parametru kontrolera, gdzie wywoływana jest metoda "paymentStatus"
         data: function (requestResponse) 
         {
           return {
             taskId: requestResponse.taskId
           };
         }
      },
      buttons: [ // tablica przycisków
      {
         place: document.getElementById('button-container-1'), // element HTML, w którym ma być umieszczony przycisk
         type: 'alpha', // można podać 0 zamiast 'alpha' - typ przycisku
         disableTitle: false, // opcjonalne - nieustawianie tytułu przycisku z ceną,
                              // domyślnie brana pod uwagę jest globalna opcja "DisableButtonsTitle"
         requestData: function(type)
         {
            return {
               type: type,
               itemsId: [1] // tablica identyfikatorów produktów
            }
         },
         listenResponse: function(response)
         { // metoda opcjonalna
            switch (response.status)
            {
               case "FINISHED_OK":
                  // zdarzenie pomyślnej zapłaty przyciskiem
                  break;
               case "FINISHED_ERR_USER_REJECTED": // brak możliwości płatności w ramach zapamiętanej serii
                  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":
                  // zdarzenie pomyślnej zapłaty przyciskiem
                  break;
               case "FINISHED_ERR_USER_REJECTED": // brak możliwości płatności w ramach zapamiętanej serii
                  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":
                  // zdarzenie pomyślnej zapłaty przyciskiem
                  break;
               case "FINISHED_ERR_USER_REJECTED": // brak możliwości płatności w ramach zapamiętanej serii
                  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":
                  // zdarzenie pomyślnej zapłaty przyciskiem
                  break;
               case "FINISHED_ERR_USER_REJECTED": // brak możliwości płatności w ramach zapamiętanej serii
                  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":
                  // zdarzenie pomyślnej zapłaty przyciskiem
                  break;
               case "FINISHED_ERR_USER_REJECTED": // brak możliwości płatności w ramach zapamiętanej serii
                  localStorage.setItem("seriesId", null);
		  localStorage.setItem("user", JSON.stringify(null));
            }
         }
      }]
   });
</script>
Czy ten artykuł jest dla Ciebie pomocny? Tak Nie 1

Jak możemy pomóc?