From 903b3139053015b551ced82b0975f89a8260508c Mon Sep 17 00:00:00 2001 From: AlexanderC Date: Thu, 24 Jan 2019 18:01:57 +0200 Subject: [PATCH] Add Order payment command --- README.md | 10 ++++-- cli/index.js | 60 +++++++++++++++++++++++++++----- package-lock.json | 82 +++++++++++++++++++++++++++++++------------- package.json | 5 ++- src/entity/item.js | 16 ++------- src/index.js | 12 +++++++ src/transport/api.js | 8 +++++ 7 files changed, 145 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index dd1121d..457dcc7 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,12 @@ CLI Tool: ```bash alexanderc@MacBook-Pro:~/$ pt.md --help -pt.md [command] +pt.md Commands: pt.md configure Configure pt.md client pt.md list List current deliveries + pt.md pay [id] Pay for an order Options: --version Show version number [boolean] @@ -65,7 +66,6 @@ total = 1; items = [ { "isPaid": false, - "paymentURI": "https://pt.md/BeneficiarZone/TransactionJournal/CardPayOrder?id=123456", "rowNum": 1, "orderID": 123456, "orderDate": "2019-01-01T07:00:00.007Z", @@ -91,6 +91,12 @@ items = [ } ] */ + +// @TODO will be improved in future +const item = items[0]; +const paymentHTML = await pt.paymentPage(item.orderID); + +// ...save payment HTML to file and open it with a browser to get redirected to payment itself ``` ## Development diff --git a/cli/index.js b/cli/index.js index 2774b93..ab91533 100755 --- a/cli/index.js +++ b/cli/index.js @@ -4,8 +4,10 @@ const Configstore = require('configstore'); const { prompt } = require('enquirer'); const chalk = require('chalk'); const Table = require('terminal-table'); -const terminalLink = require('terminal-link'); const yargs = require('yargs'); +const tempfile = require('tempfile'); +const fs = require('fs-extra'); +const opn = require('opn'); const pkg = require('../package.json'); const Pt = require('../src/index'); const debug = require('../src/helper/debug')(__filename); @@ -46,7 +48,7 @@ function display(items) { table.push( [ - 'Paid', 'Id', 'Order Date', 'Status', 'Cell', 'Pickup Interval', 'Shop', 'Goods Name', 'Delivery Company', 'Actions', + 'Paid', 'Id', 'Order Date', 'Status', 'Cell', 'Pickup Interval', 'Shop', 'Goods Name', 'Delivery Company', ].map(col => chalk.gray(col)), ); @@ -71,12 +73,6 @@ function display(items) { deliveryCompanyName, ]; - if (!isPaid) { - row.push(terminalLink('Pay', item.paymentURI)); - } else { - row.push(chalk.blue('N/A')); - } - table.push(row); } @@ -174,6 +170,54 @@ yargs // eslint-disable-line } }, ) + .command( + 'pay [id]', + 'Pay for an order', + (yargs) => { // eslint-disable-line + return yargs + .positional('id', { + describe: 'Order ID to pay', + }) + .require('id', true); + }, + async (argv) => { + const conf = config(); + const { + id, + } = argv; + + const pt = Pt.create(); + + try { + debug(`Authorize with username:${conf.get('username')} and password:${conf.get('password') ? 'YES' : 'N/A'}`); + + await pt.authenticate(conf.get('username'), conf.get('password')); + } catch (err) { + error( + err, + 'Configure your pt.md client using "pt.md configure" command.', + ); + } + + try { + const paymentPageFile = tempfile('.html'); + + debug(`Fetching payment HTML for order "${id}" to "${paymentPageFile}"`); + + await fs.outputFile(paymentPageFile, await pt.paymentPage(id)); // eslint-disable-line + + await opn(`file://${paymentPageFile}`, { wait: false }); + + setTimeout(async () => { + debug(`Removing temporary file: "${paymentPageFile}"`); + + await fs.remove(paymentPageFile); + }, 3000); // @TODO figure out a smarter way + } catch (err) { + error(err, `It might be that the order "${id}" is missing.`); + } + }, + ) .command({ command: '*', handler() { yargs.showHelp(); } }) .help('h') .alias('h', 'help') diff --git a/package-lock.json b/package-lock.json index 8454cdd..29bf7b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -61,7 +61,8 @@ "ansi-escapes": { "version": "3.1.0", "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==" + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "dev": true }, "ansi-regex": { "version": "3.0.0", @@ -840,6 +841,16 @@ } } }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "requires": { + "graceful-fs": "4.1.15", + "jsonfile": "4.0.0", + "universalify": "0.1.2" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1098,6 +1109,11 @@ "has-symbols": "1.0.0" } }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -1137,6 +1153,14 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "4.1.15" + } + }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", @@ -1390,6 +1414,19 @@ "mimic-fn": "1.2.0" } }, + "open": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", + "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=" + }, + "opn": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", + "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", + "requires": { + "is-wsl": "1.1.0" + } + }, "optionator": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", @@ -1853,22 +1890,6 @@ "has-flag": "3.0.0" } }, - "supports-hyperlinks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz", - "integrity": "sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw==", - "requires": { - "has-flag": "2.0.0", - "supports-color": "5.4.0" - }, - "dependencies": { - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - } - } - }, "table": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/table/-/table-5.1.0.tgz", @@ -1881,13 +1902,18 @@ "string-width": "2.1.1" } }, - "terminal-link": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-1.2.0.tgz", - "integrity": "sha512-nkM6NjuohxfZGA/jkAnM1zl2qjhdm8vZTG0Q36t+5O6msGwZ/ieJW+XxbIlLpUBQEUeGswg4XiB/QhcEVI23Rg==", + "temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=" + }, + "tempfile": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", + "integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=", "requires": { - "ansi-escapes": "3.1.0", - "supports-hyperlinks": "1.0.1" + "temp-dir": "1.0.0", + "uuid": "3.3.2" } }, "terminal-table": { @@ -1949,6 +1975,11 @@ "crypto-random-string": "1.0.0" } }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -1963,6 +1994,11 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", diff --git a/package.json b/package.json index de50101..e5a7fd7 100644 --- a/package.json +++ b/package.json @@ -45,8 +45,11 @@ "debug": "^4.1.0", "deepmerge": "^2.2.1", "enquirer": "^2.3.0", + "fs-extra": "^7.0.1", + "open": "0.0.5", + "opn": "^5.4.0", "qs": "^6.6.0", - "terminal-link": "^1.2.0", + "tempfile": "^2.0.0", "terminal-table": "0.0.12", "yargs": "^12.0.5" } diff --git a/src/entity/item.js b/src/entity/item.js index 3582069..6f6cef8 100644 --- a/src/entity/item.js +++ b/src/entity/item.js @@ -62,25 +62,13 @@ class Item extends Base { return this.invoicePaymentStateID === 12990; } - /** - * Get payment URI - * @todo Decide to return payment URL anyway - */ - get paymentURI() { - if (this.isPaid) { - return null; - } - - return `https://pt.md/BeneficiarZone/TransactionJournal/CardPayOrder?id=${this.orderID}`; - } - /** * @inheritdoc */ toJSON() { - const { isPaid, paymentURI } = this; + const { isPaid } = this; - return Object.assign({ isPaid, paymentURI }, super.toJSON()); + return Object.assign({ isPaid }, super.toJSON()); } } diff --git a/src/index.js b/src/index.js index b040ffa..d77f5ae 100644 --- a/src/index.js +++ b/src/index.js @@ -66,6 +66,18 @@ class Pt { return response.data; } + /** + * Get payment page HTML + * @param {string} orderID + */ + async paymentPage(orderID) { + const paymentPage = await this.client.request('paymentPage'); + + const response = await paymentPage.send({ id: orderID }); + + return response.data; + } + /** * Create an instance of Pt */ diff --git a/src/transport/api.js b/src/transport/api.js index 287a8d2..f65cd8d 100644 --- a/src/transport/api.js +++ b/src/transport/api.js @@ -114,4 +114,12 @@ module.exports = { return response; }, }), + paymentPage: endpoint({ + method: 'get', + url: '/BeneficiarZone/TransactionJournal/CardPayOrder', + withCredentials: true, + params: { + id: null, + }, + }), };