From 6543a2f6c7277fb9527b8b8abec317519115666d Mon Sep 17 00:00:00 2001 From: Olusesan Ameye Date: Sat, 7 May 2022 23:20:17 -0400 Subject: [PATCH] Copying over from WrenchBoradWeb to new repository --- flutterwave-transfer-micro/.dockerignore | 3 + flutterwave-transfer-micro/.eslintrc | 209 ++++++++++++++++++ flutterwave-transfer-micro/.gitignore | 6 + flutterwave-transfer-micro/Dockerfile | 14 ++ flutterwave-transfer-micro/README.md | 47 ++++ flutterwave-transfer-micro/api/controller.js | 33 +++ flutterwave-transfer-micro/api/routes.js | 12 + flutterwave-transfer-micro/app/db.js | 47 ++++ flutterwave-transfer-micro/app/index.js | 10 + flutterwave-transfer-micro/app/logger.js | 61 +++++ flutterwave-transfer-micro/base64decoder.js | 9 + flutterwave-transfer-micro/base64encoder.js | 13 ++ flutterwave-transfer-micro/docker-compose.yml | 19 ++ flutterwave-transfer-micro/package.json | 46 ++++ flutterwave-transfer-micro/server.js | 151 +++++++++++++ .../service/transfer.js | 98 ++++++++ flutterwave-transfer-micro/swagger.js | 8 + flutterwave-transfer-micro/swagger.json | 62 ++++++ 18 files changed, 848 insertions(+) create mode 100644 flutterwave-transfer-micro/.dockerignore create mode 100644 flutterwave-transfer-micro/.eslintrc create mode 100644 flutterwave-transfer-micro/.gitignore create mode 100644 flutterwave-transfer-micro/Dockerfile create mode 100644 flutterwave-transfer-micro/README.md create mode 100644 flutterwave-transfer-micro/api/controller.js create mode 100644 flutterwave-transfer-micro/api/routes.js create mode 100644 flutterwave-transfer-micro/app/db.js create mode 100644 flutterwave-transfer-micro/app/index.js create mode 100644 flutterwave-transfer-micro/app/logger.js create mode 100644 flutterwave-transfer-micro/base64decoder.js create mode 100644 flutterwave-transfer-micro/base64encoder.js create mode 100644 flutterwave-transfer-micro/docker-compose.yml create mode 100644 flutterwave-transfer-micro/package.json create mode 100644 flutterwave-transfer-micro/server.js create mode 100644 flutterwave-transfer-micro/service/transfer.js create mode 100644 flutterwave-transfer-micro/swagger.js create mode 100644 flutterwave-transfer-micro/swagger.json diff --git a/flutterwave-transfer-micro/.dockerignore b/flutterwave-transfer-micro/.dockerignore new file mode 100644 index 0000000..eb6047c --- /dev/null +++ b/flutterwave-transfer-micro/.dockerignore @@ -0,0 +1,3 @@ + +node_modules +npm-debug.log diff --git a/flutterwave-transfer-micro/.eslintrc b/flutterwave-transfer-micro/.eslintrc new file mode 100644 index 0000000..76aaaa1 --- /dev/null +++ b/flutterwave-transfer-micro/.eslintrc @@ -0,0 +1,209 @@ +{ + "env": { + "es6": true, + "browser": true, + "node": true, + "meteor": true, + "mocha": true + }, + + "plugins": [], + + "ecmaFeatures": { + "arrowFunctions": true, + "binaryLiterals": true, + "blockBindings": true, + "classes": true, + "defaultParams": true, + "destructuring": true, + "experimentalObjectRestSpread": true, + "forOf": true, + "generators": true, + "globalReturn": true, + "jsx": true, + "modules": true, + "objectLiteralComputedProperties": true, + "objectLiteralDuplicateProperties": true, + "objectLiteralShorthandMethods": true, + "objectLiteralShorthandProperties": true, + "octalLiterals": true, + "regexUFlag": true, + "regexYFlag": true, + "restParams": true, + "spread": true, + "superInFunctions": true, + "templateStrings": true, + "unicodeCodePointEscapes": true + }, + + "rules": { + "array-bracket-spacing": [2, "always"], + "arrow-spacing": 2, + "block-scoped-var": 0, + "brace-style": [2, "1tbs", {"allowSingleLine": true}], + "callback-return": 2, + "comma-dangle": 0, + "comma-spacing": 0, + "comma-style": [2, "last"], + "complexity": 0, + "computed-property-spacing": [2, "never"], + "consistent-return": 0, + "consistent-this": 0, + "curly": [2, "all"], + "default-case": 0, + "dot-location": [2, "property"], + "dot-notation": 0, + "eol-last": 2, + "eqeqeq": 2, + "func-names": 0, + "func-style": 0, + "generator-star-spacing": [0, {"before": true, "after": false}], + "guard-for-in": 2, + "handle-callback-err": [2, "error"], + "id-length": 0, + "id-match": [2, "^(?:_?[a-zA-Z0-9]*)|[_A-Z0-9]+$"], + "indent": [2, 2, {"SwitchCase": 1}], + "init-declarations": 0, + "key-spacing": [2, {"beforeColon": false, "afterColon": true}], + "linebreak-style": 2, + "lines-around-comment": 0, + "max-depth": 0, + "max-len": [2, 300, 4], + "max-nested-callbacks": 0, + "max-params": 0, + "max-statements": 0, + "new-cap": 0, + "new-parens": 2, + "newline-after-var": 0, + "no-array-constructor": 2, + "no-bitwise": 0, + "no-caller": 2, + "no-catch-shadow": 0, + "no-class-assign": 2, + "no-cond-assign": 2, + "no-console": 1, + "no-const-assign": 2, + "no-constant-condition": 2, + "no-continue": 0, + "no-control-regex": 0, + "no-debugger": 1, + "no-delete-var": 2, + "no-div-regex": 2, + "no-dupe-args": 2, + "no-dupe-keys": 2, + "no-duplicate-case": 2, + "no-else-return": 2, + "no-empty": 2, + "no-empty-character-class": 2, + "no-empty-label": 2, + "no-eq-null": 0, + "no-eval": 2, + "no-ex-assign": 2, + "no-extend-native": 2, + "no-extra-bind": 2, + "no-extra-boolean-cast": 2, + "no-extra-parens": 0, + "no-extra-semi": 2, + "no-fallthrough": 2, + "no-floating-decimal": 2, + "no-func-assign": 2, + "no-implicit-coercion": 2, + "no-implied-eval": 2, + "no-inline-comments": 0, + "no-inner-declarations": [2, "functions"], + "no-invalid-regexp": 2, + "no-invalid-this": 0, + "no-irregular-whitespace": 2, + "no-iterator": 2, + "no-label-var": 2, + "no-labels": 0, + "no-lone-blocks": 2, + "no-lonely-if": 2, + "no-loop-func": 0, + "no-mixed-requires": [2, true], + "no-mixed-spaces-and-tabs": 2, + "no-multi-spaces": 2, + "no-multi-str": 2, + "no-multiple-empty-lines": 0, + "no-native-reassign": 0, + "no-negated-in-lhs": 2, + "no-nested-ternary": 0, + "no-new": 1, + "no-new-func": 0, + "no-new-object": 2, + "no-new-require": 2, + "no-new-wrappers": 2, + "no-obj-calls": 2, + "no-octal": 2, + "no-octal-escape": 2, + "no-param-reassign": 2, + "no-path-concat": 2, + "no-plusplus": 0, + "no-process-env": 0, + "no-process-exit": 0, + "no-proto": 2, + "no-redeclare": 2, + "no-regex-spaces": 2, + "no-restricted-modules": 0, + "no-return-assign": 2, + "no-script-url": 2, + "no-self-compare": 0, + "no-sequences": 2, + "no-shadow": 2, + "no-shadow-restricted-names": 2, + "no-spaced-func": 2, + "no-sparse-arrays": 2, + "no-sync": 0, + "no-ternary": 0, + "no-this-before-super": 2, + "no-throw-literal": 2, + "no-trailing-spaces": 2, + "no-undef": 2, + "no-undef-init": 2, + "no-undefined": 0, + "no-underscore-dangle": 0, + "no-unexpected-multiline": 2, + "no-unneeded-ternary": 2, + "no-unreachable": 2, + "no-unused-expressions": 0, + "no-unused-vars": [2, {"vars": "all", "args": "after-used"}], + "no-use-before-define": 0, + "no-useless-call": 2, + "no-var": 0, + "no-void": 2, + "no-warning-comments": 0, + "no-with": 2, + "object-curly-spacing": [0, "always"], + "object-shorthand": [2, "properties"], + "one-var": [2, "never"], + "operator-assignment": [2, "always"], + "operator-linebreak": [0, "after"], + "padded-blocks": 0, + "prefer-const": 0, + "prefer-reflect": 0, + "prefer-spread": 0, + "quote-props": [2, "as-needed"], + "quotes": [2, "single"], + "radix": 2, + "require-yield": 2, + "semi": [2, "always"], + "semi-spacing": [2, {"before": false, "after": true}], + "sort-vars": 0, + "space-after-keywords": [2, "always"], + "space-before-blocks": [2, "always"], + "space-before-function-paren": [2, {"anonymous": "always", "named": "never"}], + "space-in-parens": 0, + "space-infix-ops": [2, {"int32Hint": false}], + "space-return-throw-case": 2, + "space-unary-ops": [2, {"words": true, "nonwords": false}], + "spaced-comment": [2, "always"], + "strict": 0, + "use-isnan": 2, + "valid-jsdoc": 0, + "valid-typeof": 2, + "vars-on-top": 0, + "wrap-iife": 2, + "wrap-regex": 0, + "yoda": [2, "never", {"exceptRange": true}] + } +} diff --git a/flutterwave-transfer-micro/.gitignore b/flutterwave-transfer-micro/.gitignore new file mode 100644 index 0000000..5457631 --- /dev/null +++ b/flutterwave-transfer-micro/.gitignore @@ -0,0 +1,6 @@ +node_modules +*.log +config.json +.queues +*.txt +docs diff --git a/flutterwave-transfer-micro/Dockerfile b/flutterwave-transfer-micro/Dockerfile new file mode 100644 index 0000000..1db7516 --- /dev/null +++ b/flutterwave-transfer-micro/Dockerfile @@ -0,0 +1,14 @@ +FROM node:erbium + +# Create app directory +RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app + +# Install app dependencies +COPY package.json /usr/src/app/ +RUN npm install + +COPY . /usr/src/app + +CMD [ "npm", "start" ] + diff --git a/flutterwave-transfer-micro/README.md b/flutterwave-transfer-micro/README.md new file mode 100644 index 0000000..a4c92d4 --- /dev/null +++ b/flutterwave-transfer-micro/README.md @@ -0,0 +1,47 @@ +# flutterwave-transfer-micro +A microservice to handle flitterware payment services + +# Installation +* `git clone` this repository +* `cd` into the repository +* Build the docker image by `docker build -t flutterwave-transfer-micro .` + +# Run +* Set environment variables like `PORT` and `POSTGRE_URL`. Full list in the wiki. +* `docker run -p -e PORT= -e POSTGRE_URL= -e FLUTTERWAVE_API= -i -t flutterwave-transfer-micro` + +## Example configurations +* binding: 127.0.0.1:3000:3000/tcp +* app_port: 3000 +* postgre_url: postgresql://wrenchboard:wrenchboard@10.10.10.23:5432/wrenchboard +* flutterwave_config: eyJCYXNlQXBpVXJsIjoiaHR0cHM6Ly9hcGkuZmx1dHRlcndhdmUuY29tIiwiUHVibGljS2V5IjoiRkxXUFVCS19URVNULTU0YzkwMTQxYjAyODc4OWQ2NzEwNjdiZDcyZjc4MWE5LVgiLCJTZWNyZXRLZXkiOiJGTFdTRUNLX1RFU1QtYzdiYmM4NmQ3ZTcxMDAyNTRjNWU1YmJmMTYyYmYyYjItWCIsIkVuY3J5cHRpb25LZXkiOiJGTFdTRUNLX1RFU1RlOTQ3NGQ0ZTJjZTYifQ== + +## Example command + +``` +docker run -p 127.0.0.1:3000:3000/tcp \ + -e PORT=3000 \ + -e POSTGRE_URL='postgresql://wrenchboard:wrenchboard@10.10.10.23:5432/wrenchboard' \ + -e FLUTTERWAVE_API='eyJCYXNlQXBpVXJsIjoiaHR0cHM6Ly9hcGkuZmx1dHRlcndhdmUuY29tIiwiUHVibGljS2V5IjoiRkxXUFVCS19URVNULTU0YzkwMTQxYjAyODc4OWQ2NzEwNjdiZDcyZjc4MWE5LVgiLCJTZWNyZXRLZXkiOiJGTFdTRUNLX1RFU1QtYzdiYmM4NmQ3ZTcxMDAyNTRjNWU1YmJmMTYyYmYyYjItWCIsIkVuY3J5cHRpb25LZXkiOiJGTFdTRUNLX1RFU1RlOTQ3NGQ0ZTJjZTYifQ==' \ + -i -t flutterwave-transfer-micro +``` + +## Flutterwave config + +Either use a converniece script base64encoder.js or base64 CLI to encode the config: + +``` +echo '{ + "BaseApiUrl":"https://api.flutterwave.com", + "PublicKey":"FLWPUBK_TEST-54c90141b028789d671067bd72f781a9-X", + "SecretKey":"FLWSECK_TEST-c7bbc86d7e7100254c5e5bbf162bf2b2-X", + "EncryptionKey":"FLWSECK_TESTe9474d4e2ce6" +}' | base64 +``` + +# Test +`npm test` + + +--- + diff --git a/flutterwave-transfer-micro/api/controller.js b/flutterwave-transfer-micro/api/controller.js new file mode 100644 index 0000000..d32c1c9 --- /dev/null +++ b/flutterwave-transfer-micro/api/controller.js @@ -0,0 +1,33 @@ +'use strict'; + +const properties = require('../package.json') +const transfer = require('../service/transfer'); + +var controllers = { + about: function(req, res) { + var aboutInfo = { + name: properties.name, + version: properties.version + } + res.json(aboutInfo); + }, + postTransfer: function(req, res) { + transfer.create(req, res, function(err, dist) { + if (err) { + res.send(err); + } + res.json(dist); + }); + }, + getStatus: function(req, res) { + transfer.get(req, res, function(err, dist) { + if (err) { + res.send(err); + } + res.json(dist); + }); + }, +}; + +module.exports = controllers; + diff --git a/flutterwave-transfer-micro/api/routes.js b/flutterwave-transfer-micro/api/routes.js new file mode 100644 index 0000000..a5b5d63 --- /dev/null +++ b/flutterwave-transfer-micro/api/routes.js @@ -0,0 +1,12 @@ +'use strict'; + +const controller = require('./controller'); + +module.exports = function(app) { + app.route('/about') + .get(controller.about); + app.route('/create') + .post(controller.postTransfer); + app.route('/status/:id') + .get(controller.getStatus); +}; diff --git a/flutterwave-transfer-micro/app/db.js b/flutterwave-transfer-micro/app/db.js new file mode 100644 index 0000000..100fb30 --- /dev/null +++ b/flutterwave-transfer-micro/app/db.js @@ -0,0 +1,47 @@ +/** + * @file + * Configures the database connection + */ + +const { Pool, Client } = require('pg'); +const logger = require('./logger'); +//const connectionString = 'postgresql://wrenchboard:wrenchboard@10.10.10.23:5432/wrenchboard'; +const connectionString = process.env.POSTGRE_URL; +const postgres = new Pool({ + connectionString, +}); + +postgres.on('connect', client => { + logger.info('Connected to Database'); +}); + +postgres.on('acquire', client => { + logger.info('Client is checked out from the DB connection pool'); +}); + +postgres.on('remove', client => { + logger.info('Client is closed & removed from the DB connection pool'); +}); + +postgres.on('error', (err, client) => { + logger.error(err); +}); + +// Connect to PostgreSQL +postgres.connect((err, client, release) => { + logger.info(connectionString); + if (err) { + logger.error('Error acquiring client', err.stack); + return null; + } + client.query('SELECT NOW()', (err, result) => { + release(); + if (err) { + logger.error('Error executing query', err.stack); + return nul; + } + logger.info(result.rows); + }); +}); + +module.exports = postgres; \ No newline at end of file diff --git a/flutterwave-transfer-micro/app/index.js b/flutterwave-transfer-micro/app/index.js new file mode 100644 index 0000000..f6e1809 --- /dev/null +++ b/flutterwave-transfer-micro/app/index.js @@ -0,0 +1,10 @@ +/** + * @file + * Set up the app + */ +var _ = require('underscore'); +var db = require('./db'); + +module.exports = function () { + db(); +}; diff --git a/flutterwave-transfer-micro/app/logger.js b/flutterwave-transfer-micro/app/logger.js new file mode 100644 index 0000000..8b8d012 --- /dev/null +++ b/flutterwave-transfer-micro/app/logger.js @@ -0,0 +1,61 @@ +/** + * @file + * Defines logger for the microservice + */ + +var winston = require('winston'); +var Papertrail = require('winston-papertrail').Papertrail; +var serviceIdentifier = require('../package.json').name; + +var host = process.env.LOG_SERVICE_HOST; +var port = process.env.LOG_SERVICE_PORT; + +/** + * Class to provide logging facilities for the microservice + * @constructor + */ + +var Logger = function () { + + // Try to route logs to third party service + if (host && port) { + // Define our transport + var transport = new Papertrail({ + levels: { + debug: 0, + info: 1, + error: 3 + }, + colors: { + debug: 'blue', + info: 'green', + error: 'red' + }, + host, + port, + json: true, + colorize: true, + logFormat: (level, message) => { + return `[${serviceIdentifier}] ${level} : ${message}`; + } + }); + + // Handle exceptions + transport.exceptionsLevel = 'error'; + winston.handleExceptions(transport); + } + + this.info = winston.info; + this.error = winston.error; + this.debug = winston.debug; +}; + +module.exports = new Logger(); + + +/** + * @typedef {Object} Logger + * @property {function} info - Log in level `info` + * @property {function} error - Log in level `error` + * @property {function} debug - Log in level `debug` + */ diff --git a/flutterwave-transfer-micro/base64decoder.js b/flutterwave-transfer-micro/base64decoder.js new file mode 100644 index 0000000..a2d2b0c --- /dev/null +++ b/flutterwave-transfer-micro/base64decoder.js @@ -0,0 +1,9 @@ +'use strict'; + +let data = 'eyJQdWJsaWNLZXkiOiJGTFdQVUJLX1RFU1QtNTRjOTAxNDFiMDI4Nzg5ZDY3MTA2N2JkNzJmNzgxYTktWCIsIlNlY3JldEtleSI6IkZMV1NFQ0tfVEVTVC1jN2JiYzg2ZDdlNzEwMDI1NGM1ZTViYmYxNjJiZjJiMi1YIiwiRW5jcnlwdGlvbktleSI6IkZMV1NFQ0tfVEVTVGU5NDc0ZDRlMmNlNiJ9'; +let buff = new Buffer(data, 'base64'); +let text = buff.toString('ascii'); +let json = JSON.parse(text); + +console.log('"' + data + '" converted from Base64 to ASCII is "' + text + '"'); +console.log(json); diff --git a/flutterwave-transfer-micro/base64encoder.js b/flutterwave-transfer-micro/base64encoder.js new file mode 100644 index 0000000..cecea2e --- /dev/null +++ b/flutterwave-transfer-micro/base64encoder.js @@ -0,0 +1,13 @@ +'use strict'; + +let json = { + "BaseApiUrl":"https://api.flutterwave.com", + "PublicKey":"FLWPUBK_TEST-54c90141b028789d671067bd72f781a9-X", + "SecretKey":"FLWSECK_TEST-c7bbc86d7e7100254c5e5bbf162bf2b2-X", + "EncryptionKey":"FLWSECK_TESTe9474d4e2ce6" +}; +let data = JSON.stringify(json); +let buff = new Buffer(data); +let base64data = buff.toString('base64'); + +console.log('"' + data + '" converted to Base64 is "' + base64data + '"'); diff --git a/flutterwave-transfer-micro/docker-compose.yml b/flutterwave-transfer-micro/docker-compose.yml new file mode 100644 index 0000000..a7ca61a --- /dev/null +++ b/flutterwave-transfer-micro/docker-compose.yml @@ -0,0 +1,19 @@ +version: '3' +services: + flutterwave-transfer-micro: + build: + context: . + dockerfile: Dockerfile + restart: unless-stopped + image: registry.chiefsoft.net/flutterwave-transfer-micro:latest + volumes: + - ./:/app + - '/app/node_modules' + ports: + - 9086:3000 + environment: + - PORT=3000 + - POSTGRE_URL='postgresql://wrenchboard:wrenchboard@10.10.10.23:5432/wrenchboard' + - FLUTTERWAVE_API='eyJCYXNlQXBpVXJsIjoiaHR0cHM6Ly9hcGkuZmx1dHRlcndhdmUuY29tIiwiUHVibGljS2V5IjoiRkxXUFVCS19URVNULTU0YzkwMTQxYjAyODc4OWQ2NzEwNjdiZDcyZjc4MWE5LVgiLCJTZWNyZXRLZXkiOiJGTFdTRUNLX1RFU1QtYzdiYmM4NmQ3ZTcxMDAyNTRjNWU1YmJmMTYyYmYyYjItWCIsIkVuY3J5cHRpb25LZXkiOiJGTFdTRUNLX1RFU1RlOTQ3NGQ0ZTJjZTYifQ==' +volumes: + src: diff --git a/flutterwave-transfer-micro/package.json b/flutterwave-transfer-micro/package.json new file mode 100644 index 0000000..e58f626 --- /dev/null +++ b/flutterwave-transfer-micro/package.json @@ -0,0 +1,46 @@ +{ + "name": "flutterwave-transfer-micro", + "version": "0.0.4", + "description": "A microservice to handle flutterware payment services", + "main": "server.js", + "scripts": { + "generate-docs": "jsdoc ./api/*.js ./api/**/*.js ./app/*.js ./app/**/*.js ./service/*.js ./service/**/*.js -d docs", + "lint": "eslint ./ --ext .js", + "start": "node server.js", + "start:dev": "nodemon server.js", + "test": "npm run lint" + }, + "author": "Anatolii Okhotnikov ", + "dependencies": { + "axios": "^0.24.0", + "body-parser": "^1.19.0", + "express": "^4.17.1", + "openapi-types": "^10.0.0", + "pg": "8.7.1", + "request": "^2.88.2", + "swagger-autogen": "^2.17.2", + "swagger-jsdoc": "^6.1.0", + "swagger-ui-express": "^4.3.0", + "underscore": "^1.8.3", + "winston": "^2.3.1", + "winston-papertrail": "^1.0.4" + }, + "devDependencies": { + "eslint": "^1.10.3", + "jsdoc": "^3.4.3", + "nodemon": "^1.11.0" + }, + "repository": { + "type": "git", + "url": "ssh://git@gitlab.chiefsoft.net:10222/WrenchBoard/WrenchBoradWeb.git" + }, + "keywords": [ + "microservice", + "flutterwave", + "transfer" + ], + "bugs": { + "url": "https://gitlab.chiefsoft.net/WrenchBoard/WrenchBoradWeb/issues" + }, + "homepage": "https://gitlab.chiefsoft.net/WrenchBoard/WrenchBoradWeb/src/master/microservices/flutterwave-transfer-micro/README.md" +} diff --git a/flutterwave-transfer-micro/server.js b/flutterwave-transfer-micro/server.js new file mode 100644 index 0000000..834e26f --- /dev/null +++ b/flutterwave-transfer-micro/server.js @@ -0,0 +1,151 @@ +const express = require('express'); +const logger = require('./app/logger'); +const swaggerUI = require('swagger-ui-express'); +const swaggerJSDocs = require('swagger-jsdoc'); + +const port = process.env.PORT || 3000; + +const definition = { + "swagger": "2.0", + "info": { + "version": "0.0.4", + "title": "flutterwave-transfer-micro", + "description": "A microservice to handle flitterware payment services" + }, + "host": "localhost:3000", + "basePath": "/", + "tags": [], + "schemes": [ + "http" + ], + "consumes": ['application/json'], + "produces": ['application/json'], + "paths": { + "/about": { + "get": { + "tags": [], + "description": "About the microservice (service status)", + "parameters": [], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/create": { + "post": { + "tags": [], + "description": "Create new transfer", + "produces": [ + "application/json" + ], + "parameters": [{ + "name":"transfer", + "in": "body", + "description": "Transfer to create", + "required": true, + "type":"object", + "schema": { + "$ref": "#/definitions/NewTransfer" + }, + "example": { + "account_bank": "044", + "account_number": "0690000040", + "amount": 5500, + "narration": "Akhlm Pstmn Trnsfr xx007", + "currency": "NGN", + "reference": "akhlm-pstmnpyt-rfxx007_PMCKDU_1", + "debit_currency": "NGN" + } + }], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/status/{id}": { + "get": { + "tags": [], + "description": "Get transfer status", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, + "definitions": { + "NewTransfer": { + "type": "object", + "required": [ + "account_bank", + "account_number", + "amount", + "narration", + "currency", + "reference", + "debit_currency" + ], + "properties": { + "account_bank": { + "type": "string" + }, + "account_number": { + "type": "string" + }, + "amount": { + "type": "integer" + }, + "narration": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "debit_currency": { + "type": "string" + } + } + }, + } +}; + +const options = { + definition, + apis: ['./server.js'], +}; + +const swaggerSpec = swaggerJSDocs(options); + +const app = express(); + +app.get('/swagger.json', (req, res) => { + res.setHeader('Content-Type', 'application/json'); + res.send(swaggerSpec); +}); +app.use('/api-docs', swaggerUI.serve, swaggerUI.setup(swaggerSpec)); + +app.use(express.json()); +app.use(express.urlencoded()); + +const routes = require('./api/routes'); +routes(app); + +app.listen(port, "0.0.0.0", function() { + logger.info('***** Server started on port: ' + port + ' *****'); +}); diff --git a/flutterwave-transfer-micro/service/transfer.js b/flutterwave-transfer-micro/service/transfer.js new file mode 100644 index 0000000..3b3ac13 --- /dev/null +++ b/flutterwave-transfer-micro/service/transfer.js @@ -0,0 +1,98 @@ +'use strict'; + +const axios = require('axios'); +const request = require('request'); +const db = require('../app/db') +const logger = require('../app/logger'); + +// https://developer.flutterwave.com/reference/create-a-transfer +const flutterwaveConfigBuffer = new Buffer(process.env.FLUTTERWAVE_API, 'base64'); +const flutterwaveConfig = JSON.parse(flutterwaveConfigBuffer.toString('ascii')); + +var transfer = { + create: function(req, res, next) { + var url = flutterwaveConfig.BaseApiUrl + '/v3/transfers'; + var headersOpt = { + "Content-Type": "application/json", + "Authorization": "Bearer " + flutterwaveConfig.SecretKey, + }; + var data = { + "account_bank": req.body.account_bank, + "account_number": req.body.account_number, + "amount": req.body.amount, + "narration": req.body.narration, + "currency": req.body.currency, + "reference": req.body.reference, + "debit_currency": req.body.debit_currency + }; + var options = { + headers: headersOpt + }; + logger.info(url); + logger.info(options); + logger.info(data); + // https://blog.logrocket.com/5-ways-to-make-http-requests-in-node-js/ + // https://stackoverflow.com/questions/53846709/how-do-i-use-axios-within-expressjs + axios.post(url, data, options) + .then(data => { + res.json(data); + }) + .catch(err => { + logger.error(err.message); + //logger.error(err.stack); + logger.error(err.response.data); + //logger.error(err.response.headers); + res.send({ + status: "failure", + message: "Invalid response", + details: err.message, + code: err.response.status, + data: err.response.data + }); + }); + // TODO: Do we save the response in the DB? I assume: YES + db.query('SELECT NOW()', (err, res) => { + if (err) { + throw err; + } + logger.info('time:', res.rows[0]) + }); + }, + get: function(req, res, next) { + var url = flutterwaveConfig.BaseApiUrl + '/v3/transfers/' + req.params.id; + var headersOpt = { + "Authorization": "Bearer " + flutterwaveConfig.SecretKey, + }; + var options = { + headers: headersOpt + }; + logger.info(url); + axios.get(url, options) + .then(data => { + res.json(data); + }) + .catch(err => { + logger.error(err.message); + //logger.error(err.stack); + logger.error(err.response.data); + //logger.error(err.response.headers); + res.send({ + status: "failure", + message: "Invalid response", + details: err.message, + code: err.response.status, + data: err.response.data + }); + }); + // TODO: Do we save the response in the DB? I assume: YES + db.query('SELECT NOW()', (err, res) => { + if (err) { + throw err; + } + logger.info('time:', res.rows[0]) + }); + } +}; + +module.exports = transfer; + diff --git a/flutterwave-transfer-micro/swagger.js b/flutterwave-transfer-micro/swagger.js new file mode 100644 index 0000000..faaa0e8 --- /dev/null +++ b/flutterwave-transfer-micro/swagger.js @@ -0,0 +1,8 @@ +const swaggerAutogen = require('swagger-autogen')(); + +const outputFile = './swagger.json'; +const endpointsFiles = ['./api/routes.js'] + +swaggerAutogen(outputFile, endpointsFiles).then(() => { + require('./server.js') +}) diff --git a/flutterwave-transfer-micro/swagger.json b/flutterwave-transfer-micro/swagger.json new file mode 100644 index 0000000..6a53ab0 --- /dev/null +++ b/flutterwave-transfer-micro/swagger.json @@ -0,0 +1,62 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "REST API", + "description": "" + }, + "host": "localhost:3000", + "basePath": "/", + "tags": [], + "schemes": [ + "http" + ], + "consumes": [], + "produces": [], + "paths": { + "/about": { + "get": { + "tags": [], + "description": "", + "parameters": [], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/create": { + "post": { + "tags": [], + "description": "", + "parameters": [], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/status/{id}": { + "get": { + "tags": [], + "description": "", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, + "definitions": {} +} \ No newline at end of file