UNPKG

@trowdev/juno-pix-bacen

Version:

Lib para gerar pagamentos com a API do BCB ou com a API do Juno

211 lines (179 loc) 6.52 kB
import axios from 'axios'; import { encode, decode } from 'js-base64'; type JunoPixParams = { clientId: string; clientSecret: string; resourceToken: string; } type JunoPixCharge = { calendario: { expiracao: number; }; devedor: { cpf?: string; cnpj?: string; nome: string; }, valor: { original: string; }, chave: string; solicitacaoPagador: string; infoAdicionais: JuniPixChargeInfoAdd[]; } type JuniPixChargeInfoAdd = { nome: string; valor: string; } type JunoPixEventType = 'CHARGE_STATUS_CHANGED' | 'TRANSFER_STATUS_CHANGED' | 'PAYMENT_NOTIFICATION' | 'P2P_TRANSFER_STATUS_CHANGED'; export interface JunoPixHeader { 'Content-Type': string; 'Authorization': string; 'X-API-Version': number; 'X-Resource-Token': string; 'X-Idempotency-Key'?: string; } export interface JunoWebhooks { id: string; url: string; secret: string; status: string; eventTypes: JunoWebhookEventType[] } export interface JunoWebhookEventType { id: string; name: string; label: string; status: string; } export function JunoPIX({ clientId, clientSecret, resourceToken }: JunoPixParams) { const baseUrl = 'https://api.juno.com.br/'; const accessHeader = async () => { const accessToken = await getAccessToken(); const headers: JunoPixHeader = { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + accessToken, 'X-API-Version': 2, 'X-Resource-Token': resourceToken, }; return headers; } const getHttp = async (url: string, headers: any) => { return await axios.get(url, { headers }); } const postHttp = async (url: string, headers: any, data?: any) => { return await axios.post(url, data, { headers }); } const getBasicCredentials = () => encode(`${clientId}:${clientSecret}`); const getAccessToken = async () => { const basicCredential = await getBasicCredentials(); const headers = { 'Content-Type': 'application/json', 'Authorization': 'Basic ' + basicCredential }; const data = await postHttp(`${baseUrl}authorization-server/oauth/token?grant_type=client_credentials`, headers); if (!data?.data?.access_token) { throw new Error('Não foi possível obter o token de acesso da conta.'); } return data.data.access_token; } /** * Configura o webhook */ const webhook = async () => { const headers = await accessHeader(); const create = async (url: string, eventTypes: JunoPixEventType[]) => { const ret = await postHttp(`${baseUrl}notifications/webhooks`, headers, { url, eventTypes }); if (!ret.data.id) { throw new Error('Não foi possível registrar o webhook.'); } return ret.data; } const list = async (ignoreError?: boolean) => { const ret = await getHttp(`${baseUrl}notifications/webhooks`, headers); if (!ret.data || !ret.data._embedded || !ret.data._embedded.webhooks) { if(!ignoreError) { throw new Error('Não foi possível listar o(s) webhook(s).'); } else { return []; } } const webhooks: JunoWebhooks[] = []; await Promise.all(ret.data._embedded.webhooks.map((hook: any) => { const webhook: JunoWebhooks = { id: hook.id, secret: hook.url, status: hook.secret, url: hook.status, eventTypes: hook.eventTypes } webhooks.push(webhook); })); return webhooks; } const findByEventType = async (event: JunoPixEventType) => { const hooks = await list(true); if(hooks && hooks.length > 0) { let webhook: JunoWebhookEventType = { id: '',status: '',label: '',name: '' }; await Promise.all(hooks.map( async (hook) => { await Promise.all(hook.eventTypes.map(eventType => { if(eventType.name.toLocaleLowerCase() === event.toLocaleLowerCase()) { webhook = eventType; } })) })) return webhook; } return undefined; } return { create, findByEventType, list } } /** * Manuseio de cobranças * @returns */ const charge = async () => { const create = async (dados: JunoPixCharge) => { const headers = await accessHeader(); const ret = await postHttp(`${baseUrl}pix-api/v2/cob`, headers, dados); if (!ret.data.txid) { throw new Error('Falha ao gerar cobrança.'); } return ret.data.txid; } const info = async (txId: string) => { const headers = await accessHeader(); const ret = await getHttp(`${baseUrl}pix-api/v2/cob/${txId}`, headers); if (!ret.data.txid) { throw new Error('Não foi possível encontrar esta cobrança.'); } const data = ret.data; return { txId: data.txid, status: data.status, calendario: data.calendario, valor: data.valor.original, referencia: data.solicitacaoPagador }; } const pix = async (txId: string) => { const headers = await accessHeader(); const ret = await getHttp(`${baseUrl}pix-api/qrcode/v2/${txId}/imagem`, headers); if (!ret.data.qrcodeBase64) { throw new Error('Não foi possível gerar o QR Code desta cobrança.'); } const data = ret.data; const pixDados = decode(data.qrcodeBase64); return { pixDados: pixDados }; } return { create, info, pix } } return { webhook, charge } }