From 85b48c7a6336221c08bcf6276f4c1233a33e99a0 Mon Sep 17 00:00:00 2001 From: Rodrigo Rodriguez Date: Mon, 31 Jul 2023 15:06:47 -0300 Subject: [PATCH] new(payment.gblib): #354 QRcode for payments. --- .../basic.gblib/services/DialogKeywords.ts | 19 +++- .../services/KeywordsExpressions.ts | 10 ++ .../basic.gblib/services/SystemKeywords.ts | 97 ++++++++++++++----- 3 files changed, 100 insertions(+), 26 deletions(-) diff --git a/packages/basic.gblib/services/DialogKeywords.ts b/packages/basic.gblib/services/DialogKeywords.ts index fff0012a..3a946600 100644 --- a/packages/basic.gblib/services/DialogKeywords.ts +++ b/packages/basic.gblib/services/DialogKeywords.ts @@ -1171,20 +1171,29 @@ export class DialogKeywords { const { min, user } = await DialogKeywords.getProcessInfo(pid); const element = filename._page ? filename._page : filename.screenshot ? filename : null; let url; + let nameOnly; + + // Web automation. if (element) { const gbaiName = DialogKeywords.getGBAIPath(min.botId); const localName = Path.join('work', gbaiName, 'cache', `img${GBAdminService.getRndReadableIdentifier()}.jpg`); + nameOnly = Path.basename(localName); await element.screenshot({ path: localName, fullPage: true }); url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', Path.basename(localName)); GBLog.info(`BASIC: WebAutomation: Sending the file ${url} to mobile ${mobile}.`); - } else if (filename.url) { - url = filename.url; - } + } + + // GBFILE object. + else if (filename.url) { + url = filename.url; + nameOnly = Path.basename(filename.localName); + } // Handles Markdown. + else if (filename.indexOf('.md') > -1) { GBLog.info(`BASIC: Sending the contents of ${filename} markdown to mobile ${mobile}.`); const md = await min.kbService.getAnswerTextByMediaName(min.instance.instanceId, filename); @@ -1203,6 +1212,8 @@ export class DialogKeywords { } else { url = filename } + + nameOnly = filename; } if (url) { @@ -1213,7 +1224,7 @@ export class DialogKeywords { const contentType = mime.lookup(url); reply['attachments'] = []; reply['attachments'].push({ - name: filename, + name: nameOnly, contentType: contentType, contentUrl: `data:${contentType};base64,${base64Image}` }); diff --git a/packages/basic.gblib/services/KeywordsExpressions.ts b/packages/basic.gblib/services/KeywordsExpressions.ts index a7d35b37..aa01c4f3 100644 --- a/packages/basic.gblib/services/KeywordsExpressions.ts +++ b/packages/basic.gblib/services/KeywordsExpressions.ts @@ -253,6 +253,16 @@ export class KeywordsExpressions { keywords[i++] = [/^\s*next *$/gim, '}']; + keywords[i++] = [ + /^\s*((?:[a-z]+.?)(?:(?:\w+).)(?:\w+)*)\s*=\s*pay\s*(.*)/gim, + ($0, $1, $2, $3) => { + const params = this.getParams($2, ['orderId', 'customerName', 'ammount']); + + return ` + ${$1} = await sys.pay({pid: pid, ${params}})`; + } + ]; + keywords[i++] = [ /^\s*do while +(.*)/gim, function (input, group1) { diff --git a/packages/basic.gblib/services/SystemKeywords.ts b/packages/basic.gblib/services/SystemKeywords.ts index a70de30b..e6e00664 100644 --- a/packages/basic.gblib/services/SystemKeywords.ts +++ b/packages/basic.gblib/services/SystemKeywords.ts @@ -154,22 +154,22 @@ export class SystemKeywords { if (date) { return array ? array.sort((a, b) => { - const c = new Date(a[memberName]); - const d = new Date(b[memberName]); - return c.getTime() - d.getTime(); - }) + const c = new Date(a[memberName]); + const d = new Date(b[memberName]); + return c.getTime() - d.getTime(); + }) : null; } else { return array ? array.sort((a, b) => { - if (a[memberName] < b[memberName]) { - return -1; - } - if (a[memberName] > b[memberName]) { - return 1; - } - return 0; - }) + if (a[memberName] < b[memberName]) { + return -1; + } + if (a[memberName] > b[memberName]) { + return 1; + } + return 0; + }) : array; } } @@ -181,23 +181,21 @@ export class SystemKeywords { if (Array.isArray(data)) { isObject = Object.keys(data[1]) !== null; - } - else { + } else { isObject = true; } if (isObject || JSON.parse(data) !== null) { - // Copies data from JSON format into simple array. if (!Array.isArray(data)) { // If data is a single object, wrap it in an array data = [data]; } - + // Ensure that keys is an array of strings representing the object keys const keys = Object.keys(data[0]); - + if (headers) { output[0] = []; @@ -210,7 +208,6 @@ export class SystemKeywords { output.push({ gbarray: '0' }); } - for (let i = 0; i < data.length; i++) { output[i + 1] = []; for (let j = 0; j < keys.length; j++) { @@ -234,7 +231,6 @@ export class SystemKeywords { * @see http://tabulator.info/examples/5.2 */ private async renderTable(pid, data, renderPDF, renderImage) { - if (data.length && !data[1]) { return null; } @@ -661,7 +657,6 @@ export class SystemKeywords { const filter = await DialogKeywords.getOption({ pid, name: 'filter' }); if (filter) { - // Creates id row. body.values[0][0] = 'id'; @@ -1121,7 +1116,7 @@ export class SystemKeywords { } } - const outputArray = await DialogKeywords.getOption({ pid, name:"output" }); + const outputArray = await DialogKeywords.getOption({ pid, name: 'output' }); if (table.length === 1) { GBLog.info(`BASIC: FIND returned no results (zero rows).`); @@ -1877,5 +1872,63 @@ export class SystemKeywords { await client.v2.tweet(text); GBLog.info(`Twitter Automation: ${text}.`); } -} + public async pay({ pid, orderId, customerName, ammount }) { + const { min, user } = await DialogKeywords.getProcessInfo(pid); + + const gbaiName = DialogKeywords.getGBAIPath(min.botId); + + const merchantId = min.core.getParam(min.instance, 'Merchant ID', null); + const merchantKey = min.core.getParam(min.instance, 'Merchant Key', null); + + if (!merchantId || !merchantKey) { + throw new Error('Payment not configured in .gbot.'); + } + + const apiUrl = 'https://apisandbox.cieloecommerce.cielo.com.br/1/sales/'; + const requestId = GBAdminService.generateUuid(); + + GBLog.info(`GBPay: ${requestId}, ${orderId}, ${ammount}... `); + + const requestData = { + MerchantOrderId: orderId, + Customer: { + Name: customerName + }, + Payment: { + Type: 'qrcode', + Amount: ammount, + Installments: 1, + Capture: false, + Modality: 'Debit' + } + }; + + const response = await fetch(apiUrl, { + method: 'POST', + body: JSON.stringify(requestData), + headers: { + 'Content-Type': 'application/json', + MerchantId: merchantId, + MerchantKey: merchantKey, + RequestId: requestId + } + }); + + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + const data = await response.json(); + + // Prepare an image on cache and return the GBFILE information. + + const buf = Buffer.from(data.Payment.QrCodeBase64Image, 'base64'); + const localName = Path.join('work', gbaiName, 'cache', `qr${GBAdminService.getRndReadableIdentifier()}.png`); + Fs.writeFileSync(localName, buf, { encoding: null }); + const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', Path.basename(localName)); + + GBLog.info(`GBPay: ${data.MerchantOrderId} OK: ${url}.`); + + return { localName: localName, url: url, data: buf, text: data.Payment.QrCodeString }; + } +}