├── .idea ├── misc.xml ├── vcs.xml ├── .gitignore ├── modules.xml └── nodejs-webhook.iml ├── database └── index.js ├── .gitignore ├── app ├── controllers │ ├── index.js │ └── paymentController.js └── models │ └── payment.js ├── index.js ├── client-notification ├── package.json ├── model.js └── index.js ├── package.json └── readme.md /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /database/index.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose") 2 | 3 | mongoose.connect("mongodb://localhost:27017/webhookjs", { 4 | useNewUrlParser: true, 5 | useUnifiedTopology: true, 6 | }) 7 | mongoose.Promise = global.Promise 8 | module.exports = mongoose -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store* 3 | Icon? 4 | ._* 5 | 6 | # Windows 7 | Thumbs.db 8 | ehthumbs.db 9 | Desktop.ini 10 | 11 | # Linux 12 | .directory 13 | *~ 14 | 15 | 16 | # npm 17 | node_modules 18 | package-lock.json 19 | *.log 20 | *.gz 21 | client-notification/node-modules/* -------------------------------------------------------------------------------- /app/controllers/index.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs") 2 | const path = require("path") 3 | 4 | module.exports = (app) => { 5 | fs.readdirSync(__dirname) 6 | .filter((file) => file.indexOf(".") != 0 && file !== "index.js") 7 | .forEach((file) => require(path.resolve(__dirname, file))(app)) 8 | } -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/nodejs-webhook.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const bodyParser = require('body-parser'); 3 | const morgan = require('morgan'); 4 | 5 | const app = express(); 6 | 7 | app.use(morgan("dev")); 8 | app.use(bodyParser.urlencoded({ extended: false })) 9 | app.use(bodyParser.json()); 10 | 11 | require("./app/controllers/index")(app) 12 | 13 | app.listen(9000, () => { 14 | console.log("Node-Webhook has been stated at: http://localhost:9000"); 15 | }) -------------------------------------------------------------------------------- /client-notification/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client-notification", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.19.0", 14 | "express": "^4.17.1", 15 | "mongoose": "^5.9.22", 16 | "morgan": "^1.10.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-webhook", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.19.0", 14 | "express": "^4.17.1", 15 | "fs": "0.0.1-security", 16 | "mongoose": "^5.9.22", 17 | "morgan": "^1.10.0", 18 | "node-webhooks": "^1.4.2", 19 | "path": "^0.12.7" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/models/payment.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("../../database") 2 | 3 | const PaymentSchema = new mongoose.Schema({ 4 | title: { 5 | type: String, 6 | required: true, 7 | }, 8 | value: { 9 | type: Number, 10 | required: true 11 | }, 12 | status: { 13 | type: Boolean, 14 | default: false, 15 | }, 16 | createdAt: { 17 | type: Date, 18 | default: Date.now, 19 | }, 20 | }) 21 | 22 | const Payment = mongoose.model("Payment", PaymentSchema) 23 | 24 | module.exports = Payment -------------------------------------------------------------------------------- /client-notification/model.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const PaymentSchema = new mongoose.Schema({ 4 | title: { 5 | type: String, 6 | required: true, 7 | }, 8 | value: { 9 | type: Number, 10 | required: true 11 | }, 12 | status: { 13 | type: Boolean, 14 | default: false, 15 | }, 16 | createdAt: { 17 | type: Date, 18 | default: Date.now, 19 | }, 20 | }) 21 | 22 | const Payment = mongoose.model("Payment", PaymentSchema) 23 | 24 | module.exports = Payment -------------------------------------------------------------------------------- /client-notification/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const bodyParser = require('body-parser'); 3 | const morgan = require('morgan'); 4 | const mongoose = require('mongoose'); 5 | 6 | const Model = require('./model'); 7 | 8 | const app = express(); 9 | 10 | app.use(morgan("dev")); 11 | app.use(bodyParser.urlencoded({ extended: false })) 12 | app.use(bodyParser.json()); 13 | 14 | mongoose.connect('mongodb://localhost:27017/webhookjs-client', { useNewUrlParser: true, useUnifiedTopology: true }); 15 | 16 | app.post('/webhook-client', async(req, res) => { 17 | console.log('Inside Callback hook', req.body) 18 | const { data } = req.body 19 | await Model.create(data) 20 | return res.status(200).end(); 21 | }); 22 | 23 | app.listen(8005, () => { 24 | console.log("Client has been stated at: http://localhost:8005"); 25 | }) -------------------------------------------------------------------------------- /app/controllers/paymentController.js: -------------------------------------------------------------------------------- 1 | const express = require("express") 2 | const Payment = require('../models/payment') 3 | const webhooks = require('node-webhooks'); 4 | 5 | const router = express.Router(); 6 | 7 | router.get("/", async(req, res) => { 8 | try { 9 | const paymentsList = await Payment.find({}) 10 | return res.send({ data: paymentsList }) 11 | } catch (err) { 12 | return res.status(400).send({ message: "payment list failed", error: err }) 13 | } 14 | }) 15 | 16 | router.post("/", async(req, res) => { 17 | try { 18 | const payment = await Payment.create(req.body) 19 | if(payment){ 20 | const hooks = registerHooks(); 21 | hooks.trigger('callback_hook', { msg: "new payment created", data: payment}); 22 | } 23 | return res.send({ payment }) 24 | } catch (err) { 25 | return res.status(400).send({ message: "payment create failed", error: err }) 26 | } 27 | }) 28 | 29 | const registerHooks = () => { 30 | return new webhooks({ 31 | db: { 32 | 'callback_hook': ['http://localhost:8005/webhook-client'] 33 | } 34 | }); 35 | } 36 | 37 | module.exports = (app) => app.use("/payments", router) -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Projeto Webhook em NodeJS 2 | 3 | O projeto em questão para fins de estudo tem por objetivo 4 | a construção de uma API de pagamentos que 5 | deve notificar um determinado cliente (também construído em NodeJS). 6 | 7 | Esta notificação deve ocorrer quando um novo pagamento for adicionado 8 | ao projeto utilizando o endpoint: 9 | ``` 10 | POST /payments HTTP/1.1 11 | Host: localhost:9000 12 | Content-Type: application/json 13 | 14 | { 15 | "title": "Cobranca simples volume 1", 16 | "value": 59.90 17 | } 18 | ``` 19 | 20 | O cliente que representa um outro sistema deve receber 21 | o recurso criado e armazenar no banco de dados 22 | da aplicação cliente (representada pela base `webhookjs-client`). 23 | 24 | As informações serão repassadas no formato abaixo 25 | para o cliente a ser notificado: 26 | 27 | ``` 28 | { 29 | "msg": "new payment created", 30 | "data": { 31 | "status": false, 32 | "_id": "5f07524eea6d6524e892a629", 33 | "title": "Cobranca simples volume 1", 34 | "value": 59.9, 35 | "createdAt": "2020-07-09T17:22:22.970Z", 36 | "__v": 0 37 | } 38 | } 39 | ``` 40 | 41 | ## Diretórios e Arquivos 42 | 43 | - Para rodar a aplicação da API: `node index.js`. 44 | - A aplicação cliente está dentro de client-notification. 45 | - Para rodar a aplicação cliente: `cd client-notification` e `node index.js`. 46 | - Configurações de banco de dados da API estão em database. 47 | - Demais arquivos como controllers e rotas estão alocados dentro de app. 48 | 49 | 50 | ## Conclusão 51 | Este repositorio está sendo mantido para estudos caso tenha alguma duvida favor entrar em contato pelo leandro.souara.web@gmail.com --------------------------------------------------------------------------------