{"version":3,"file":"index.mjs","sources":["../src/helpers.js","../src/webSocket.js","../src/index.js"],"sourcesContent":["const NAME = '%c Pagar.Me Bifrost ';\nconst BACKGROUND = 'background:#f26722 ; padding: 2px; border-radius: 2px;  color: #fff ';\n\nexport function required(name, param) {\n  if (param === undefined) {\n    throw new Error(`Parâmetro obrigatório ${name} não declarado.`);\n  }\n\n  return param;\n}\n\nexport function logInfo(msg) {\n  console.log(NAME, BACKGROUND, msg); // eslint-disable-line no-console\n}\n\nexport function logError(msg) {\n  console.error(NAME, BACKGROUND, msg); // eslint-disable-line no-console\n}\n\n/**\n * Add spaces to match the max screen length\n * @param {string} text\n * @param {number} maxChar\n * @returns {string}\n */\nexport function addSpaces(text, maxChar) {\n  return text\n    .split('')\n    .concat(...Array(maxChar).fill(' '))\n    .slice(0, maxChar)\n    .join('');\n}\n\nexport default {\n  required,\n  logInfo,\n  logError,\n  addSpaces,\n};\n","/* eslint-disable no-underscore-dangle */\nimport { logInfo, required } from './helpers';\n\nconst privateVariables = {\n  request: {\n    listDevices: 1,\n    initialize: 2,\n    process: 4,\n    finish: 5,\n    displayMessage: 6,\n    status: 7,\n    closeContext: 8,\n  },\n  response: {\n    unknownCommand: 0,\n    devicesListed: 1,\n    initialized: 2,\n    alreadyInitialized: 3,\n    processed: 4,\n    finished: 5,\n    messageDisplayed: 6,\n    status: 7,\n    contextClosed: 8,\n    error: 9,\n  },\n  paymentMethods: {\n    credit: 1,\n    debit: 2,\n  },\n  errorStrings: {\n    errorContextString: 'Device already in use by context ',\n    errorInitialize: 'An error has occured with the [Initialize] request. See the log and contact the support.',\n    errorOperationErrored: 'Transaction Errored',\n    errorOperationFailed: 'Error: 43',\n    errorOperationCanceled: 'Transaction Canceled',\n    catastroficError: 'Error: 14',\n  },\n  ws: null,\n  timeout: null,\n  close: true,\n  timeoutConn: null,\n};\n\nfunction _connect(host, payload) {\n  if (privateVariables.ws === null) {\n    privateVariables.ws = new WebSocket(host);\n  } else if (privateVariables.ws.readyState === 2 || privateVariables.ws.readyState === 3) {\n    _disconnect();\n    privateVariables.ws = new WebSocket(host);\n  }\n\n  return new Promise((resolve, reject) => {\n    try {\n      _timeout();\n\n      const sendRequest = () => {\n        _clearTimeout();\n        privateVariables.ws.send(JSON.stringify(payload));\n        _timeout(60000);\n      }\n\n      if (privateVariables.ws.readyState === 0) {\n        privateVariables.ws.onopen = () => {\n          sendRequest();\n        };\n      } else if (privateVariables.ws.readyState === 1) {\n        sendRequest();\n      }\n\n      privateVariables.ws.onmessage = (evtMsg) => {\n        _clearTimeout();\n        resolve(JSON.parse(evtMsg.data));\n      };\n\n      privateVariables.ws.onerror = (evtError) => {\n        _clearTimeout();\n        if (evtError) reject(evtError);\n      };\n    } catch (e) {\n      reject(e);\n    }\n  });\n}\n\nfunction _disconnect() {\n  privateVariables.ws.close();\n  privateVariables.ws = null;\n}\n\nfunction _clearTimeout() {\n  privateVariables.close = false;\n  clearTimeout(privateVariables.timeoutConn);\n}\n\nfunction _timeout(time = 10000) {\n  privateVariables.close = true;\n  privateVariables.timeoutConn = setTimeout(() => {\n    if (privateVariables.close) {\n      privateVariables.ws.close();\n    } else {\n      _clearTimeout();\n    }\n  }, time);\n}\n\nclass BifrostWebSocket {\n  constructor({ contextId, baudRate, debug, host }) {\n    this.debug = debug || false;\n    this.contextId = required('contextId', contextId);\n    this.baudRate = baudRate || 115200;\n    this._connected = false;\n    this.devices = [];\n    this._host = host || 'wss://localhost:2000/mpos';\n    this._amount = 0;\n    this._method = '';\n    this.lastRequest = null;\n  }\n\n  debugLog(message) {\n    if (this.debug) {\n      logInfo(message);\n    }\n  }\n\n  classError(message) {\n    this.debugLog((typeof message === 'object') ? message.text : message);\n    throw new Error(message);\n  }\n\n  get amount() {\n    return this._amount; // eslint-disable-line\n  }\n\n  get connected() {\n    return (this._connected);\n  }\n\n  set amount(value) {\n    if (typeof value === 'number' && value <= 0) {\n      throw new Error('Não é possível definir um valor menor ou igual a zero.');\n    } else {\n      this._amount = parseFloat(value) * 100;\n    }\n  }\n\n  get method() {\n    return this._method;\n  }\n\n  set method(value) {\n    if (typeof value === 'string') {\n      if (Object.keys(privateVariables.paymentMethods)\n        .includes(value)) {\n        this._method = value;\n      }\n    } else if (typeof value === 'number') {\n      if (privateVariables.paymentMethods.find(p => p === value)) {\n        this._method = Object.keys(privateVariables.paymentMethods)\n          .find(k => privateVariables.paymentMethods[k] === value);\n      }\n    } else {\n      throw new Error('Método de pagamento não permitido.');\n    }\n  }\n\n  defineRequest(value) {\n    if (value === undefined) this.lastRequest = null;\n    if (this.lastRequest !== null) {\n      this.classError('Não é possível fazer requisições asíncronas, termine uma ação antes de executar a outra.');\n    }\n\n    if (typeof value === 'number') this.lastRequest = value;\n  }\n\n  /**\n   * Terminate the context of the PinPad device\n   * @param {string} contextId = null - Optional ContextId to be terminated\n   * @returns {Promise<*>}\n   */\n  async closePinPadContext(contextId) {\n    try {\n\n      this.debugLog('Fechando contexto do Serviço Bifrost.');\n      this.defineRequest(privateVariables.request.closeContext);\n      await _connect(this._host, {\n        request_type: privateVariables.request.closeContext,\n        context_id: contextId || this.contextId,\n      });\n      this._connected = false;\n      this.defineRequest();\n      return Promise.resolve(true);\n    } catch (error) {\n      this.defineRequest();\n      return Promise.reject(error);\n    } finally {\n      await _disconnect();\n    }\n  }\n\n  /**\n   * @typedef {object} PinPadDevice\n   * @property {string} id - Device ID\n   * @property {number} kind - Device Kind\n   * @property {string} manufacturer - Device Manufacturer\n   * @property {string} name - Device name\n   * @property {string} port - Device Port\n   */\n  /**\n   * Get the connected devices on the serial port (COM)\n   * @returns {Promise<Array.<PinPadDevice>>}\n   */\n  async getPinPadDevices() {\n    try {\n      this.debugLog('Buscando lista de dispositivos do sistema.');\n      this.defineRequest(privateVariables.request.listDevices);\n      const responseData = await _connect(this._host, {\n        request_type: privateVariables.request.listDevices,\n        context_id: this.contextId,\n      });\n      this.debugLog(responseData);\n      this.devices = responseData.device_list;\n      this.defineRequest();\n      return Promise.resolve(this.devices);\n    } catch (error) {\n      this.defineRequest();\n      return Promise.reject(error);\n    }\n  }\n\n  /**\n   * @typedef {object} PinPadInitializerParameters\n   * @property{string} encryptionKey\n   * @property {number} simpleInitialize = null\n   * @property {number} timeoutMilliseconds = null\n   */\n  /**\n   * Start the PinPan hardware\n   * @param {PinPadInitializerParameters} params\n   * @param {number} deviceIndex = 0 - Index of the device in the devices Array.\n   */\n  async initialize(params, deviceIndex = 0) {\n    try {\n      this.debugLog(`Conectando ao PinPad ${this.devices[deviceIndex].id}.`);\n      this.defineRequest(privateVariables.request.initialize);\n      const response = await _connect(this._host, {\n        request_type: privateVariables.request.initialize,\n        context_id: this.contextId,\n        initialize: {\n          device_id: this.devices[deviceIndex].id,\n          encryption_key: params.encryptionKey,\n          baud_rate: this.baudRate,\n          simple_initialize: params.simpleInitialize,\n          timeout_milliseconds: params.timeoutMilliseconds,\n        },\n      });\n      if (this.lastRequest === privateVariables.request.initialize) {\n        this.defineRequest();\n        if (response.response_type === privateVariables.response.initialized) {\n          this._connected = true;\n          return this.debugLog(`PinPad ${this.devices[deviceIndex].id} inicializado com sucesso.`);\n        }\n\n        if (response.response_type === privateVariables.response.alreadyInitialized) {\n          this.debugLog('Serviço Bifrost já inicializado, reiniciando a conexão.');\n          await this.closePinPadContext(response.context_id);\n          await this.initialize({\n            encryptionKey: params.encryptionKey,\n            baud_rate: this.baudRate,\n            simpleInitialize: params.simpleInitialize,\n            timeoutMilliseconds: params.timeoutMilliseconds,\n          }, 0);\n          return false;\n        }\n\n        if (response.response_type === privateVariables.response.error && privateVariables.errorStrings.errorInitialize) {\n          const nextDevice = (deviceIndex + 1);\n\n          if (nextDevice > this.devices.length) {\n            await _disconnect();\n            this.classError('Não foi possível inicial a conexão com nenhum dispositivo.');\n          } else {\n            this.debugLog('Dispositivo selecionado não é válido, inicializando novamente com próximo dispositivo da lista.');\n            await this.initialize({\n              encryptionKey: params.encryptionKey,\n              baud_rate: this.baudRate,\n              simpleInitialize: params.simpleInitialize,\n              timeoutMilliseconds: params.timeoutMilliseconds,\n            }, nextDevice);\n            return false;\n          }\n        }\n\n        if (response.error === privateVariables.errorStrings.catastroficError) {\n          this.classError('Erro catastrófico no sistema. Por favor, reinicialize o PinPad e o Serviço do Bifrost');\n          _disconnect();\n          return false;\n        }\n\n        if (response.error && response.error.includes(privateVariables.errorStrings.errorContextString)) {\n          this.debugLog('Serviço Bifrost com contexto diferente do definido na classe.');\n          const context = response.error.split(privateVariables.errorStrings.errorContextString)[1];\n          if (await this.closePinPadContext(context)) {\n            await this.initialize({\n              encryptionKey: params.encryptionKey,\n              baud_rate: this.baudRate,\n              simpleInitialize: params.simpleInitialize,\n              timeoutMilliseconds: params.timeoutMilliseconds,\n            }, 0);\n          }\n\n          return false;\n        }\n      }\n      return response;\n    } catch (error) {\n      return Promise.reject(error);\n    } finally {\n      this.defineRequest();\n    }\n  }\n\n  /**\n   * @typedef {object} BifrostServiceStatus\n   * @property {boolean} connected - Is device connected\n   * @property {string} contextId - Device Context\n   * @property {string} connectedDeviceId - Connected Device Id\n   */\n  /**\n   * Get the Bifrost Service Status\n   * @returns {Promise<BifrostServiceStatus>}\n   */\n  async getPinPanStatus() {\n    try {\n      this.debugLog('Buscando status do serviço Bifrost.');\n      this.defineRequest(privateVariables.request.status);\n      const responseData = await _connect(this._host, {\n        request_type: privateVariables.request.status,\n        context_id: this.contextId,\n      });\n      logInfo(responseData);\n      return Promise.resolve({\n        connected: !!responseData.status.code,\n        contextId: responseData.context_id,\n        connectedDeviceId: responseData.status.connected_device_id,\n      });\n    } catch (error) {\n      return Promise.reject(error);\n    } finally {\n      this.defineRequest();\n    }\n  }\n\n  /**\n   * Display a message on the PinPad Device\n   * @param message\n   * @returns {Promise<*>}\n   */\n  async displayMessageOnPinPadScreen(message) {\n    try {\n      this.debugLog(`Mostrando \"${message}\" no display do PinPad.`);\n      this.defineRequest(privateVariables.request.displayMessage);\n      const responseData = await _connect(this._host, {\n        request_type: privateVariables.request.displayMessage,\n        context_id: this.contextId,\n        display_message: {\n          message,\n        },\n      });\n      return Promise.resolve(responseData);\n    } catch (error) {\n      return Promise.reject(error);\n    } finally {\n      this.defineRequest();\n    }\n  }\n\n  /**\n   * @typedef {object} PaymentStartObject\n   * @property {number} amount\n   * @property {string} method = 'credit'|'debit'\n   */\n  /**\n   * Start the payment process by setting the amount and method.\n   * @param {PaymentStartObject} params\n   */\n  startPayment(params) {\n    try {\n      this.amount = params.amount;\n      this.method = params.method || privateVariables.paymentMethods.credit;\n    } catch (error) {\n      throw new Error(error);\n    }\n  }\n\n  /**\n   * @typedef {object} PinPadProcessedCardReturn\n   * @property {string} card_hash\n   * @property {string} card_holder_name\n   * @property {number} error_code\n   * @property {boolean} is_online_pin\n   * @property {number} payment_method\n   * @property {number} status\n   */\n  /**\n   * Send the payment request to the PinPad and start the\n   * payment process of it.\n   * @returns {Promise<Object.<PinPadProcessedCardReturn>>}\n   */\n  async startPaymentProcess() {\n    try {\n      this.debugLog(`Iniciando processo de pagamento. Venda via ${this.method}, valor ${this.amount / 100}`);\n      this.defineRequest(privateVariables.request.process);\n\n      const response = await _connect(this._host, {\n        request_type: privateVariables.request.process,\n        context_id: this.contextId,\n        process: {\n          amount: this.amount,\n          magstripe_payment_method: this.method,\n        },\n      });\n\n      if (this.lastRequest === privateVariables.request.process) {\n        if (response.error === privateVariables.errorStrings.errorOperationCanceled) {\n          const error = {\n            text: 'Operação cancelada pelo usuário.',\n            type: 'cardCanceled',\n          };\n          this.debugLog(error.text);\n          return Promise.reject(error);\n        }\n\n        if (\n          response.error === privateVariables.errorStrings.errorOperationErrored\n          || response.error === privateVariables.errorStrings.errorOperationFailed\n        ) {\n          const error = {\n            text: 'Aconteceu algum erro na operação, tente novamente.',\n            type: 'operationError',\n          };\n          this.debugLog(error.text);\n          return Promise.reject(error);\n        }\n\n        if (response.response_type === privateVariables.response.processed) {\n          return Promise.resolve(response.process);\n        }\n      }\n    } catch (error) {\n      return Promise.reject(error);\n    } finally {\n      this.defineRequest();\n    }\n  }\n\n  /**\n   * Finish the payment process of the PinPad\n   * @param {string} code\n   * @param {string} emvData\n   * @returns {Promise<*>}\n   */\n  async finishPaymentProcess(code, emvData) {\n    try {\n      this.debugLog(`Finalizando a venda via ${this.method}`);\n      this.defineRequest(privateVariables.request.finish);\n      return await _connect(this._host, {\n        request_type: privateVariables.request.finish,\n        context_id: this.contextId,\n        finish: {\n          success: !!(code && emvData),\n          response_code: code || '0000',\n          emv_data: emvData || '000000000.0000',\n        },\n      });\n    } catch (error) {\n      return Promise.reject(error);\n    } finally {\n      this.defineRequest();\n    }\n  }\n}\n\nexport default BifrostWebSocket;\n","/* eslint-disable no-underscore-dangle */\nimport { required, logError, addSpaces } from './helpers';\nimport BifrostWebSocket from './webSocket';\n\n/**\n * Show the error on not connected PinPad\n */\nfunction notConnected() {\n  throw new Error('PinPad não foi inicializado. Por favor, inicie o PinPad antes de executar outro comando.');\n}\n\n/**\n * @class PagarMeTEF\n * @constructor PagarMeConstructor\n */\nclass PagarMeBifrost {\n  /**\n   * Class Constructor\n   * @param {Object.<PagarMeConstructor>} params\n   */\n  /**\n   * @typedef {Object} PagarMeConstructor\n   * @property {boolean} debug\n   * @property {string} host\n   * @property {string} contextId\n   * @property {number} baudRate\n   * @property {string} encryptionKey\n   * @property {number} pinPadMaxCharLine\n   * @property {number} pinPadMaxChar\n   * @property {number} pinPanDisplayLines\n   */\n  constructor(params) {\n    try {\n      this.baudRate = params.baudRate || 115200;\n      this.contextId = required('contextId', params.contextId);\n      this.encryptionKey = required('encryptionKey', params.encryptionKey);\n      this.pinPadMaxCharLine = params.pinPadMaxCharLine || 16;\n      this.pinPadMaxChar = params.pinPadMaxChar || 32;\n      this.pinPanDisplayLines = params.pinPanDisplayLines || 2;\n\n      const constructorOptions = {\n        debug: params.debug || false,\n        contextId: this.contextId,\n        host: params.host || 'wss://localhost:2000/mpos',\n      };\n\n      this.__bifrost__ = new BifrostWebSocket(constructorOptions);\n    } catch (error) {\n      logError(error, true);\n    }\n  }\n\n  get connected() {\n    return this.__bifrost__.connected;\n  }\n\n  /**\n   * Initialize the PinPad\n   * @returns {Promise<boolean>}\n   */\n  async initialize() {\n    try {\n      await this.__bifrost__.getPinPadDevices();\n      await this.__bifrost__.initialize({ encryptionKey: this.encryptionKey });\n      return Promise.resolve(true);\n    } catch (error) {\n      return Promise.reject(error);\n    }\n  }\n\n  /**\n   * Terminate the PinPad\n   * @returns {Promise<Boolean>}\n   */\n  async terminate() {\n    return new Promise((resolve, reject) => {\n      if (this.connected) {\n        this.__bifrost__.closePinPadContext()\n          .then(() => {\n            resolve(true);\n          })\n          .catch((e) => {\n            reject(e);\n          });\n      } else {\n        notConnected();\n      }\n    });\n  }\n\n  /**\n   * Restart the PinPad\n   * @returns {Promise<boolean>}\n   */\n  async restart() {\n    try {\n      await this.terminate();\n      return this.initialize();\n    } catch (error) {\n      return Promise.reject(error);\n    }\n  }\n\n  /**\n   * Get the PinPad Status\n   * @returns {Promise<Object.<BifrostServiceStatus>>}\n   */\n  async status() {\n    try {\n      if (!this.connected) notConnected();\n      return this.__bifrost__.getPinPanStatus();\n    } catch (error) {\n      return Promise.reject(error);\n    }\n  }\n\n  /**\n   * Display a message on the PinPad\n   * @param {string|array} message - A message string or an array of messages.\n   * @returns {Promise<String>}\n   */\n  async showMessage(message) {\n    try {\n      if (!this.connected) notConnected();\n      const tefMaxCharLine = this.pinPadMaxCharLine;\n      const tefMaxChar = this.pinPadMaxChar;\n      let formattedMessage = '';\n\n      if (Array.isArray(message)) {\n        formattedMessage = message\n          .slice(0, this.pinPanDisplayLines)\n          .map(m => addSpaces(m, tefMaxCharLine))\n          .join('');\n      }\n\n      if (typeof message === 'string') {\n        formattedMessage = addSpaces(message, tefMaxChar);\n      }\n\n      await this.__bifrost__.displayMessageOnPinPadScreen(formattedMessage);\n      return Promise.resolve(formattedMessage);\n    } catch (error) {\n      return Promise.reject(error);\n    }\n  }\n\n  /**\n   * Start the payment process\n   * @param {number} amount\n   * @param {string|number} method = 'credit'|'debit'|1|2\n   * @returns {Promise<Object.<PinPadProcessedCardReturn>>}\n   */\n  async payment(amount, method) {\n    try {\n      if (!this.connected) notConnected();\n      this.__bifrost__.startPayment({ amount, method });\n      const processedPayment = await this.__bifrost__.startPaymentProcess();\n\n      return Promise.resolve(processedPayment);\n    } catch (error) {\n      logError(error);\n      await this.showMessage(error.text);\n      setTimeout(async () => {\n        await this.finish();\n        await this.terminate();\n        setTimeout(async () => {\n          await this.initialize();\n        }, 2000);\n      }, 2000);\n      return Promise.reject(error);\n    }\n  }\n\n  /**\n   * @typedef {object} PinPadFinishParameters\n   * @property {number} timeout - Timeout in MS between the execution of messages\n   * @property {string|array} messages - An string or an Array of messages\n   * @property {string} code\n   * @property {string} emvData\n   */\n  /**\n   * Finish the PinPad payment process.\n   * @param {PinPadFinishParameters} params\n   * @returns {Promise<*>}\n   */\n  async finish(params = {}) {\n    try {\n      if (!this.connected) notConnected();\n      const code = params.code || '';\n      const emvData = params.emvData || '';\n      const timeOut = params.timeout || 2000;\n      const messages = params.messages || null;\n      const processed = await this.__bifrost__.finishPaymentProcess(code, emvData);\n\n      if (Array.isArray(messages)) {\n        messages.forEach((message, index) => {\n          setTimeout(async () => {\n            await this.showMessage(message);\n          }, timeOut * (index + 1));\n        });\n      }\n\n      if (typeof messages === 'string') {\n        setTimeout(async () => {\n          await this.showMessage(messages);\n        }, timeOut);\n      }\n\n      return Promise.resolve(processed);\n    } catch (error) {\n      return Promise.reject(error);\n    }\n  }\n}\n\nexport default PagarMeBifrost;\n"],"names":["NAME","BACKGROUND","required","name","param","undefined","Error","logInfo","msg","console","log","logError","error","addSpaces","text","maxChar","split","concat","Array","fill","slice","join","body","then","result","f","args","i","arguments","length","Promise","resolve","apply","this","e","reject","finalizer","bind","value","direct","thrown","recover","privateVariables","request","listDevices","initialize","process","finish","displayMessage","status","closeContext","response","unknownCommand","devicesListed","initialized","alreadyInitialized","processed","finished","messageDisplayed","contextClosed","paymentMethods","credit","debit","errorStrings","errorContextString","errorInitialize","errorOperationErrored","errorOperationFailed","errorOperationCanceled","catastroficError","ws","timeout","close","timeoutConn","_connect","host","payload","WebSocket","readyState","_disconnect","_timeout","sendRequest","_clearTimeout","send","JSON","stringify","onopen","onmessage","evtMsg","parse","data","onerror","evtError","clearTimeout","time","setTimeout","BifrostWebSocket","contextId","baudRate","debug","_connected","devices","_host","_amount","_method","lastRequest","message","debugLog","_typeof","classError","defineRequest","_this","request_type","context_id","_this2","responseData","device_list","params","deviceIndex","_this3","id","device_id","encryption_key","encryptionKey","baud_rate","simple_initialize","simpleInitialize","timeout_milliseconds","timeoutMilliseconds","response_type","closePinPadContext","nextDevice","includes","context","_this4","connected","code","connectedDeviceId","connected_device_id","_this5","display_message","amount","method","_this6","magstripe_payment_method","type","emvData","_this7","success","response_code","emv_data","parseFloat","Object","keys","find","p","k","notConnected","pinPadMaxCharLine","pinPadMaxChar","pinPanDisplayLines","constructorOptions","__bifrost__","getPinPadDevices","catch","terminate","getPinPanStatus","tefMaxCharLine","tefMaxChar","formattedMessage","isArray","map","m","displayMessageOnPinPadScreen","startPayment","startPaymentProcess","processedPayment","showMessage","timeOut","messages","finishPaymentProcess","forEach","index"],"mappings":"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"}