UNPKG

@jackiemacklein/nettz-utils

Version:

Serviços de imagem, e-mail, códigos de barras, utilitários numéricos e componentes React para apps Node.js com TypeScript

131 lines (130 loc) 6.28 kB
"use strict"; /** * @author Jackiê Macklein * @company Onside tecnologia/Nettz * @copyright Todos direitos reservados. * @description Cliente HTTP para API SuperTEF (listar POS, solicitar e consultar pagamentos). * Documentação: https://supertef.apidog.io/ */ Object.defineProperty(exports, "__esModule", { value: true }); exports.createSuperTefClient = createSuperTefClient; const errors_1 = require("./errors"); const types_1 = require("./types"); function sleep(ms, signal) { return new Promise((resolve, reject) => { if (signal === null || signal === void 0 ? void 0 : signal.aborted) { reject(new DOMException("Aborted", "AbortError")); return; } const t = setTimeout(() => { signal === null || signal === void 0 ? void 0 : signal.removeEventListener("abort", onAbort); resolve(); }, ms); const onAbort = () => { clearTimeout(t); signal === null || signal === void 0 ? void 0 : signal.removeEventListener("abort", onAbort); reject(new DOMException("Aborted", "AbortError")); }; signal === null || signal === void 0 ? void 0 : signal.addEventListener("abort", onAbort); }); } async function readResponseBody(res) { try { return await res.text(); } catch { return ""; } } function createSuperTefClient(config) { var _a, _b, _c, _d; const baseUrl = ((_a = config.baseUrl) !== null && _a !== void 0 ? _a : types_1.SUPERTEF_DEFAULT_BASE_URL).replace(/\/$/, ""); const timeoutMs = (_b = config.timeoutMs) !== null && _b !== void 0 ? _b : 30000; const fetchFn = (_c = config.fetchImpl) !== null && _c !== void 0 ? _c : fetch; const paymentLookupUsesQueryParam = (_d = config.paymentLookupUsesQueryParam) !== null && _d !== void 0 ? _d : true; async function request(path, init) { var _a, _b; const url = `${baseUrl}${path.startsWith("/") ? path : `/${path}`}`; const controller = new AbortController(); const t = setTimeout(() => controller.abort(), (_a = init === null || init === void 0 ? void 0 : init.timeoutMs) !== null && _a !== void 0 ? _a : timeoutMs); try { const res = await fetchFn(url, { ...init, signal: (_b = init === null || init === void 0 ? void 0 : init.signal) !== null && _b !== void 0 ? _b : controller.signal, headers: { Accept: "application/json", Authorization: `Bearer ${config.token}`, ...((init === null || init === void 0 ? void 0 : init.body) ? { "Content-Type": "application/json" } : {}), ...init === null || init === void 0 ? void 0 : init.headers, }, }); const text = await readResponseBody(res); if (!res.ok) { throw new errors_1.SuperTefApiError(`SuperTEF HTTP ${res.status} ${res.statusText}`, res.status, text); } if (!text || text.trim() === "") { return undefined; } try { return JSON.parse(text); } catch { throw new errors_1.SuperTefApiError("SuperTEF resposta não é JSON válido", res.status, text); } } finally { clearTimeout(t); } } return { baseUrl, async listPos(params) { const search = new URLSearchParams(); if ((params === null || params === void 0 ? void 0 : params.cliente_chave) != null && params.cliente_chave !== "") { search.set("cliente_chave", params.cliente_chave); } if ((params === null || params === void 0 ? void 0 : params.page) != null && `${params.page}` !== "") { search.set("page", String(params.page)); } const q = search.toString(); return request(q ? `/pos?${q}` : "/pos"); }, async requestPayment(body) { return request("/pagamentos", { method: "POST", body: JSON.stringify(body), }); }, async getPaymentByUniqueId(paymentUniqueId) { const path = paymentLookupUsesQueryParam ? `/pagamentos/by-uniqueid?${new URLSearchParams({ payment_uniqueid: String(paymentUniqueId), }).toString()}` : `/pagamentos/by-uniqueid/${encodeURIComponent(String(paymentUniqueId))}`; return request(path); }, async pollPaymentUntilFinal(paymentUniqueId, options) { var _a, _b, _c; const intervalMs = (_a = options === null || options === void 0 ? void 0 : options.intervalMs) !== null && _a !== void 0 ? _a : 4000; const maxAttempts = (_b = options === null || options === void 0 ? void 0 : options.maxAttempts) !== null && _b !== void 0 ? _b : 120; const requirePaid = (_c = options === null || options === void 0 ? void 0 : options.requirePaid) !== null && _c !== void 0 ? _c : true; const signal = options === null || options === void 0 ? void 0 : options.signal; /** 4 Pago, 5 Cancelado/Erro — documentação SuperTEF */ const isTerminal = (d) => d.payment_status === 4 || d.payment_status === 5; let last = await this.getPaymentByUniqueId(paymentUniqueId); let attempts = 0; while (!isTerminal(last) && attempts < maxAttempts) { await sleep(intervalMs, signal); last = await this.getPaymentByUniqueId(paymentUniqueId); attempts += 1; } if (!isTerminal(last)) { throw new errors_1.SuperTefApiError(`SuperTEF: pagamento ${paymentUniqueId} não atingiu status final após ${attempts + 1} consulta(s)`, 408, JSON.stringify(last)); } if (requirePaid && last.payment_status !== 4) { throw new errors_1.SuperTefApiError(`SuperTEF: pagamento ${paymentUniqueId} não foi concluído com sucesso (status ${last.payment_status})`, 422, JSON.stringify(last)); } return last; }, }; }