| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- #!/usr/bin/env -S /usr/bin/node
- require("dotenv").config({ quiet: true });
- const decimal = require("decimal.js");
- const randomUUID = require("crypto").randomUUID;
- const DEBUG = false;
- const AUTH_URL =
- "https://genial-arquitetura-authentication.homolog.api.genial.systems";
- const COREBK_URL =
- "https://genial-arquitetura-corebank.homolog.api.genial.systems";
- const BAAS_URL = "https://gerador-arquitetura-baas.homolog.api.genial.systems";
- const OPS_URL = "https://genial-baas-operations.homolog.api.genial.systems";
- async function main() {
- const args = process.argv.slice(2);
- if (args.length === 0) return help();
- const cmd = args[0];
- const rest = args.slice(1);
- try {
- switch (cmd) {
- case "token": {
- const [ok, tok] = await getToken();
- if (!ok) return fail(tok);
- console.log(tok);
- break;
- }
- case "balance": {
- await Balance(rest[0]);
- break;
- }
- case "getkey": {
- if (rest.length < 1) return fail("Usage: getkey <pixKey>");
- await getKey(rest[0]);
- break;
- }
- case "decode": {
- if (rest.length < 1) return fail("Usage: decodeQrcode <qrcode>");
- await decodeQrcode(rest[0]);
- break;
- }
- case "payQr": {
- if (rest.length < 2)
- return fail("Usage: payQr <qrCodeCopyPaste> <value>");
- console.log(rest[0], rest[1]);
- await PayQr(rest[0], rest[1]);
- break;
- }
- case "qrcodeStatic": {
- await qrcodeStatic();
- break;
- }
- case "paykey": {
- if (rest.length < 2) return fail("Usage: payInit <pixKey> <value>");
- await PayInit(rest[0], rest[1]);
- break;
- }
- case "qrcodedynamic": {
- if (rest.length < 1) return fail("Usage: qrcode <value>");
- await QrCodeDynamic(rest[0]);
- break;
- }
- case "statusIn": {
- //not working on my machine
- if (rest.length < 1) return fail("Usage: statusIn <transactionId>");
- await StatusIn(rest[0]);
- break;
- }
- case "statusOut": {
- //not working on my machine
- if (rest.length < 1) return fail("Usage: statusOut <e2e>");
- await StatusOut(rest[0]);
- break;
- }
- case "refund": {
- if (rest.length < 1) return fail("Usage: refund <eventId> <value>");
- await Refund(rest[0], rest[1]);
- break;
- }
- default:
- help();
- return;
- }
- } catch (e) {
- fail(e.message || e);
- help();
- return;
- }
- }
- function help() {
- console.log(`Usage: genial-cli <command> [args]
- Commands:
- token
- balance <accountNumber>
- getkey <accountNumber> <pixKey>
- statusOut <instantPaymentId> <YYYY-MM-DD>
- statusIn <transactionId>
- qrcode <accountNumber> <value>
- payInit [value] [pixKey]
- pay <idempotencyId>
- payQr <accountNumber> <value> <qrCodeCopyPaste>
- refund <eventId> <value>
- preview <emv>
- boletoPay <taxId> <line> [description] [uuid]
- boletoGet <id>
- `);
- process.exit(1);
- }
- function fail(msg) {
- console.error("Error:", msg);
- process.exit(1);
- }
- /* =============== Auth =============== */
- async function getToken() {
- const url = `${AUTH_URL}/v1/authentication`;
- const options = {
- method: "POST",
- headers: {
- basic: process.env.TOKEN_BASIC,
- "X-ORIGEM": process.env.TOKEN_XORIGEM,
- },
- };
- try {
- if (DEBUG) {
- console.log("\nDEBUG callApi:", options.method, url);
- }
- const res = await fetch(url, options);
- const text = await res.text();
- if (DEBUG) {
- console.log("DEBUG getToken status:", res.status);
- console.log("DEBUG getToken body:", text);
- }
- if (res.status < 200 || res.status >= 300)
- return [false, { status: res.status, body: text }];
- const json = JSON.parse(text);
- if (!json.token) return [false, "No token in response"];
- return [true, json.token];
- } catch (e) {
- return [false, e.message];
- }
- }
- async function callApi(method, url, body) {
- const [ok, token] = await getToken();
- if (!ok) return [false, token];
- const headers = {
- Authorization: token,
- "X-ORIGEM": process.env.TOKEN_XORIGEM,
- };
- const options = { method, headers };
- if (method.toUpperCase() === "POST") {
- headers["Content-Type"] = "application/json";
- options.body = body ? JSON.stringify(body) : "";
- }
- if (DEBUG) {
- console.log("\nDEBUG callApi:", method, url);
- if (body) console.log("DEBUG body:", JSON.stringify(body));
- }
- try {
- const res = await fetch(url, options);
- const text = await res.text();
- if (DEBUG) {
- console.log("DEBUG status:", res.status);
- console.log("DEBUG raw:", text);
- }
- if (res.status < 200 || res.status >= 300)
- return [false, { status: res.status, body: text }];
- try {
- return [true, JSON.parse(text)];
- } catch {
- return [true, text];
- }
- } catch (e) {
- return [false, e.message];
- }
- }
- /**
- * @description
- * account 2 is me the user
- * account 1 is smartpay the receiver of the payment
- */
- /* =============== 1) Balance =============== done*/
- async function Balance(accountNumber) {
- //INFO: they share 2 acount to test, but idk if on prod only is gonna be one. ignore this, after i know the answer i will delete
- let account = process.env.ACCOUNT1;
- const url = `${COREBK_URL}/v1/core-banking/balance/1/${account}`;
- const [ok, out] = await callApi("GET", url);
- if (!ok) return fail(out);
- console.dir(out, { depth: null });
- }
- /* =============== 2) Dict Key =============== done*/
- async function getKey(pixKey) {
- const url = `${BAAS_URL}/v2/pix/key-account-partner/1/${process.env.ACCOUNT1}/${pixKey}`;
- const [ok, out] = await callApi("GET", url);
- if (!ok) return fail(out);
- console.dir(out, { depth: null });
- }
- /* =============== DECODE QRCODE =============== done*/
- async function decodeQrcode(qrcode) {
- const url = `https://gerador-arquitetura-baas.homolog.api.genial.systems/v1/pix/qrcode-decode?qrcode=${encodeURIComponent(
- qrcode
- )}`;
- const [ok, out] = await callApi("GET", url);
- if (!ok) return fail(out);
- console.dir(out, { depth: null });
- }
- /* =============== 8) Pay by QR =============== done*/
- async function PayQr(qrCodeCopyPaste, value) {
- const url = `${BAAS_URL}/v1/pix/copy-paste`;
- /**
- * debit is our account that is going to pay the qr code, need prod keys to do it correctly
- */
- const body = {
- qrCodeCopyPaste,
- value: Number(value),
- debit: {
- name: process.env.ACCOUNT2_NAME,
- agency: 1,
- account: process.env.ACCOUNT2,
- accountType: "CACC",
- },
- };
- console.log(body);
- const [ok, out] = await callApi("POST", url, body);
- if (!ok) return fail(out);
- console.dir(out, { depth: null });
- }
- /* =============== 2) QR Code Static =============== done*/
- async function qrcodeStatic() {
- const url = `${BAAS_URL}/v1/pix/qrcode-static/`;
- const body = {
- accountHolderName: process.env.ACCOUNT1_NAME,
- addressingKey: {
- key: process.env.ACCOUNT1_KEY,
- type: "EVP",
- },
- account: process.env.ACCOUNT1,
- agency: 1,
- // additionalInformation: "Pagamento de teste genial-cli" /**@optional */,
- // value: 10.0, /**@optional */
- };
- const [ok, out] = await callApi("POST", url, body);
- if (!ok) return fail(out);
- console.dir(out, { depth: null });
- }
- /* =============== 3) Status OUT (PAC008) =============== NEED TO CHECK*/
- async function StatusOut(e2e) {
- const url = `${OPS_URL}/v1/cashout/${encodeURIComponent(e2e)}`;
- const [ok, out] = await callApi("GET", url);
- if (!ok) return fail(out);
- console.dir(out, { depth: null });
- }
- /* =============== 4) Status IN (PAC002) =============== NEED TO CHECK*/
- async function StatusIn(transactionId) {
- const url = `${OPS_URL}/v1/cashin/end-to-end-id/${encodeURIComponent(
- transactionId
- )}`;
- const [ok, out] = await callApi("GET", url);
- if (!ok) return fail(out);
- console.dir(out, { depth: null });
- }
- /* =============== 6) Init Pix by Key (PAC008 Start) =============== done */
- /**
- *
- * @param pixKey
- * @param value
- * @returns confirmed idempotencyId [@description we need to create the idempotencyId on our side to confirm the payment later ]
- */
- async function PayInit(pixKey, value) {
- const url = `${BAAS_URL}/v1/pix/send/initialization`;
- const body = {
- debit: {
- name: process.env.ACCOUNT1_NAME,
- agency: 1,
- account: process.env.ACCOUNT1,
- accountType: "CACC",
- },
- credit: {
- key: pixKey,
- },
- value: String(value),
- idempotencyId: randomUUID(),
- };
- var [ok, out] = await callApi("POST", url, body);
- if (!ok) return fail(out);
- console.dir(out, { depth: null });
- if (out?.data?.idempotencyId) {
- console.log("idempotencyId:", out.data.idempotencyId);
- }
- var [ok, reply] = await paykey(out.data.idempotencyId);
- if (!ok) return fail(reply);
- console.dir(reply, { depth: null });
- }
- /* =============== 7) Pay by Idempotency (PAC008) =============== done */
- /**
- *
- * @param idempotencyId
- * @param payinfo
- * @returns
- */
- async function paykey(idempotencyId, payinfo) {
- const url = `${BAAS_URL}/v1/pix/send/confirmed`;
- const body = {
- idempotencyId: idempotencyId,
- ignorePaymentDuplication: false,
- // additionalInformation: payinfo, /**@optional */
- };
- const [ok, out] = await callApi("POST", url, body);
- if (!ok) return fail(out);
- if (DEBUG) console.log("Payment confirmed for idempotencyId:", idempotencyId);
- return [true, out];
- }
- /* =============== 9) Refund (PAC004) =============== worked*/
- async function Refund(eventId, value) {
- const url = `${BAAS_URL}/v1/pix/return`;
- const body = {
- value: value,
- returnReasonCode: "MD06",
- eventId: eventId,
- };
- const [ok, out] = await callApi("POST", url, body);
- if (!ok) return fail(out);
- console.dir(out, { depth: null });
- }
- async function QrCodeDynamic(value) {
- const url = `${BAAS_URL}/v2/qrcode/dynamic?agency=1&account=${process.env.ACCOUNT1}`;
- const body = {
- items: [
- {
- addressingKey: {
- key: process.env.ACCOUNT1_KEY,
- type: "EVP",
- },
- accountHolderName: process.env.ACCOUNT1_NAME,
- accountHolderCity: "SAO PAULO",
- dynamicQRCodeType: "IMMEDIATE",
- immediate: {
- expiration: 36000,
- paymentValue: {
- documentValue: value,
- showPaymentValueInQrCode: true,
- //"cashback": {
- //"cashbackType": "WITHDRAW",
- //"value": 0,
- //"allowValueChange": true,
- //"withdrawProviders": {
- //"agentModality": "string",
- //"serviceProvider": "string"
- //}
- //}
- },
- payerInformation: {
- cpfCnpj: "37812511871",
- name: "gustavo lopes",
- validatePayerInformation: true,
- },
- receiverInformation: {
- taxId: process.env.DOCUMENT_NUMBER,
- name: process.env.ACCOUNT1_NAME,
- tradeName: process.env.ACCOUNT1_NAME,
- },
- },
- payerRequestInformation: "TESTE SOLICITAÇÃO AO PAYER",
- //"additionalInformation": [
- //{
- //"name": "string",
- //"content": "string",
- //"showToPayer": true
- //}
- //],
- //"itemId": "string",
- //"receiverTxId": "CTXXXXXXXXXXXX999999995800"
- },
- ],
- };
- const [ok, out] = await callApi("POST", url, body);
- if (!ok) return fail(out);
- console.dir(out, { depth: null });
- }
- /* =============== 10) Preview Pagamento (BOLETO) =============== did not test*/
- async function Preview(emv) {
- const url = `${BAAS_URL}/v1/payments/preview`;
- const body = { emv };
- const [ok, out] = await callApi("POST", url, body);
- if (!ok) return fail(out);
- console.dir(out, { depth: null });
- }
- /* =============== 11) Boleto Pay =============== did not test*/
- async function BoletoPay(taxId, line, description, uuid) {
- const url = `${BAAS_URL}/v1/payments/boleto`;
- const body = {
- taxId,
- description: description || "Pagamento de boleto",
- line,
- uuid: uuid || `BOL-${Date.now()}`,
- };
- const [ok, out] = await callApi("POST", url, body);
- if (!ok) return fail(out);
- console.dir(out, { depth: null });
- }
- /* =============== 12) Boleto Get by Id =============== did not test*/
- async function BoletoGet(id) {
- const url = `${BAAS_URL}/v1/payments/boleto/${encodeURIComponent(id)}`;
- const [ok, out] = await callApi("GET", url);
- if (!ok) return fail(out);
- console.dir(out, { depth: null });
- }
- main();
|