Skip to content
This repository has been archived by the owner on Jul 3, 2024. It is now read-only.
/ node-siba Public archive

Utility library that creates a SIBA webservice request without coupling with HTTP/SOAP clients.

License

Notifications You must be signed in to change notification settings

rafaelrpinto/node-siba

Repository files navigation

node-siba

Build Status Coverage Status Code Climate Dependencies

Utility library that creates a SIBA web service request without coupling with HTTP/SOAP clients.

Motivation

This project's goal is to facilitate the integration with SIBA, the Portuguese border control system for foreigns seeking accommodation in Portugal (Hotels or Alojamento Local). More info at SIBA's Portal.

Since each project may make HTTP requests using different libraries/versions this project is limited to generating the web service SOAP request and the model involved in the task.

Installation

yarn add node-siba

or

npm install node-siba

Usage

This module exports two functions: buildSIBAXMLRequest and parseSIBAXMLResponse.

The following builds the SOAP XML request:

import { buildSIBAXMLRequest, GuestDocumentType } from "node-siba";

const bulletin = {
  number: 1,
  issueDate: new Date(),
  hotelUnit: {
    nipc: "121212121",
    establishment: "00",
    accessKey: "999999999",
    name: "A Hotel",
    abbreviation: "ABV",
    address: "An address",
    location: "A Location",
    zipCode: "4050",
    zipZone: "175",
    phone: "999888777",
    fax: "299888777",
    contactName: "A Name",
    contactEmail: "email@test.com"
  },
  guests: [
    {
      firstName: "John",
      surname: "Doe",
      nationality: "AFG",
      birthDate: new Date("2009-01-01T10:00:00Z"),
      birthPlace: "A place",
      checkInDate: new Date("2019-01-01T10:00:00Z"),
      checkOutDate: new Date("2019-01-03T10:00:00Z"),
      countryOfResidence: "AFG",
      placeOfResidence: "A place",
      document: {
        number: "ABCD1234",
        issuingCountry: "AFG",
        type: GuestDocumentType.PASSPORT
      }
    },
    {
      firstName: "Mary",
      surname: "Anne",
      nationality: "AFG",
      birthDate: new Date("2009-01-01T10:00:00Z"),
      birthPlace: "A place",
      checkInDate: new Date("2019-01-01T10:00:00Z"),
      checkOutDate: new Date("2019-01-03T10:00:00Z"),
      countryOfResidence: "AFG",
      placeOfResidence: "A place",
      document: {
        number: "1234ABCD",
        issuingCountry: "AFG",
        type: GuestDocumentType.PASSPORT
      }
    }
  ]
};

const soapRequest = buildSIBAXMLRequest(bulletin);
console.log(soapRequest);

Console output:

<Envelope xmlns="http://www.w3.org/2003/05/soap-envelope">
   <Header/>
   <Body>
      <EntregaBoletinsAlojamento xmlns="http://sef.pt/">
         <UnidadeHoteleira>121212121</UnidadeHoteleira>
         <Estabelecimento>00</Estabelecimento>
         <ChaveAcesso>999999999</ChaveAcesso>
         <Boletins>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48TW92aW1lbnRvQkFMIHhtbG5zPSJodHRwOi8vc2VmLnB0L0JBd3MiPjxVbmlkYWRlX0hvdGVsZWlyYT48Q29kaWdvX1VuaWRhZGVfSG90ZWxlaXJhPjEyMTIxMjEyMTwvQ29kaWdvX1VuaWRhZGVfSG90ZWxlaXJhPjxFc3RhYmVsZWNpbWVudG8+MDA8L0VzdGFiZWxlY2ltZW50bz48Tm9tZT5BIEhvdGVsPC9Ob21lPjxBYnJldmlhdHVyYT5BQlY8L0FicmV2aWF0dXJhPjxNb3JhZGE+QW4gYWRkcmVzczwvTW9yYWRhPjxMb2NhbGlkYWRlPkEgTG9jYXRpb248L0xvY2FsaWRhZGU+PENvZGlnb19Qb3N0YWw+NDA1MDwvQ29kaWdvX1Bvc3RhbD48Wm9uYV9Qb3N0YWw+MTc1PC9ab25hX1Bvc3RhbD48VGVsZWZvbmU+OTk5ODg4Nzc3PC9UZWxlZm9uZT48RmF4PjI5OTg4ODc3NzwvRmF4PjxOb21lX0NvbnRhY3RvPkEgTmFtZTwvTm9tZV9Db250YWN0bz48RW1haWxfQ29udGFjdG8+ZW1haWxAdGVzdC5jb208L0VtYWlsX0NvbnRhY3RvPjwvVW5pZGFkZV9Ib3RlbGVpcmE+PEJvbGV0aW1fQWxvamFtZW50bz48QXBlbGlkbz5Kb2huPC9BcGVsaWRvPjxOb21lPkRvZTwvTm9tZT48TmFjaW9uYWxpZGFkZT5BRkc8L05hY2lvbmFsaWRhZGU+PERhdGFfTmFzY2ltZW50bz4yMDA5LTAxLTAxVDEwOjAwOjAwLjAwMFo8L0RhdGFfTmFzY2ltZW50bz48TG9jYWxfTmFzY2ltZW50bz5BIHBsYWNlPC9Mb2NhbF9OYXNjaW1lbnRvPjxEb2N1bWVudG9fSWRlbnRpZmljYWNhbz5BQkNEMTIzNDwvRG9jdW1lbnRvX0lkZW50aWZpY2FjYW8+PFBhaXNfRW1pc3Nvcl9Eb2N1bWVudG8+QUZHPC9QYWlzX0VtaXNzb3JfRG9jdW1lbnRvPjxUaXBvX0RvY3VtZW50bz5QPC9UaXBvX0RvY3VtZW50bz48RGF0YV9FbnRyYWRhPjIwMTktMDEtMDFUMTA6MDA6MDAuMDAwWjwvRGF0YV9FbnRyYWRhPjxEYXRhX1NhaWRhPjIwMTktMDEtMDNUMTA6MDA6MDAuMDAwWjwvRGF0YV9TYWlkYT48UGFpc19SZXNpZGVuY2lhX09yaWdlbT5BRkc8L1BhaXNfUmVzaWRlbmNpYV9PcmlnZW0+PExvY2FsX1Jlc2lkZW5jaWFfT3JpZ2VtPkEgcGxhY2U8L0xvY2FsX1Jlc2lkZW5jaWFfT3JpZ2VtPjwvQm9sZXRpbV9BbG9qYW1lbnRvPjxFbnZpbz48TnVtZXJvX0ZpY2hlaXJvPjE8L051bWVyb19GaWNoZWlybz48RGF0YV9Nb3ZpbWVudG8+MjAxOS0wMS0yNFQyMDowMzo0NS4wNjJaPC9EYXRhX01vdmltZW50bz48L0VudmlvPjwvTW92aW1lbnRvQkFMPg==</Boletins>
      </EntregaBoletinsAlojamento>
   </Body>
</Envelope>

With the request built it's possible to call SIBA's web service using any HTTP client, ex:

import {
  buildSIBAXMLRequest,
  parseSIBAXMLResponse,
  GuestDocumentType
} from "node-siba";
const fetch = require("node-fetch");

const bulletin = {
  // same structure as the example above
};

// generates the SOAP Envelope
const body = buildSIBAXMLRequest(bulletin);

// calls SIBA's dev environment using fetch (could be done with axios, request, etc)
const response = await fetch(
  "https://siba.sef.pt/bawsdev/boletinsalojamento.asmx",
  {
    body,
    method: "post",
    headers: {
      "Content-Type": "text/xml",
      SOAPAction: "http://sef.pt/EntregaBoletinsAlojamento"
    }
  }
);
const xmlResponse = await response.text();

// Parses the XML response into an object
const sibaREsponse = parseSIBAXMLResponse(xmlResponse);

console.log(sibaREsponse);

SIBA's response object has the following structure:

interface SIBAResponse {
  isSuccess: boolean;
  code: string;
  errorLine?: string;
  errorMessage?: string;
}