设置节点 js 服务器以侦听 webhook 并发布到数据库时出现问题



大家早上好,我在设置服务器来侦听 webhook 数据并将其发布到数据库时遇到了一些困难。我主要是前端的,所以其中一些对我来说有点新。所以我有一个在snipcart上建立的熟食网站。我有一台收据打印机,可以查询 api 并打印出新订单。所以我想要的是一个服务器来侦听 webhook 并将信息存储在数据库中。我已经把它放在了正确侦听 webhook 的地方,但它拒绝发布到数据库。 下面是 app.js 文件中的代码。

'use strict';

require('./config/db');

const express = require('express');
const bodyParser = require('body-parser');
const fetch = require('node-fetch');

const app = express();
var routes = require('./api/routes/apiRoutes');
routes(app);
let orderToken;
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
app.listen(process.env.PORT || 8080);

app.post('/hook', (req, res) => {
orderToken = req.body.content.token;
console.log(orderToken);
const secret = "snipcart api key";
const apiFetch = async function(){

};
let buffered = new Buffer.from(secret);
let base64data = buffered.toString('base64');
const start = async function(){

const request = await fetch('https://app.snipcart.com/api/orders/'+orderToken, {
headers: {
'Authorization': `Basic ${base64data}`,
'Accept': 'application/json'
}
});
const result = await request.json();
console.log(result);
};
start();
res.status(200).end();
});

app.get('/', (req, res) => {
res.send('hello world')
});

这是我的 apiController.js 文件中的代码


const mongoose = require('mongoose'),
Order = mongoose.model('apiModel');

// listAllOrders function - To list all orders
exports.listAllOrders = (req, res) => {
api.find({}, (err, api) => {
if (err) {
res.status(500).send(err);
}
res.status(200).json(api);
});
};
// createNewOrder function - To create new Order
exports.createNewOrder = (req, res) => {
let  newApi = new api (req.body);
newApi.save((err, api) => {
if (err) {
res.status(500).send(err);
}
res.status(201).json(api);
});
};
// deleteOrder function - To delete order by id
exports.deleteOrder = async ( req, res) => {
await  api.deleteOne({ _id:req.params.id }, (err) => {
if (err) {
return res.status(404).send(err);
}
res.status(200).json({ message:"Order successfully deleted"});
});
};

和我的 apiModel.js文件


const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ApiSchema = new Schema({
customerName: {
type:String,
required:true
},
customerPhone: {
type:String,
required:true
},
name: {
type:String,
required:true
},
orderNumber: {
type:String,
required:true
},
price: {
type:String,
required:true
},
customFields: {
type:Array,
required:false
},
});
module.exports = mongoose.model("apiModel", ApiSchema);

api路由.js



module.exports = function(app){
var orderList = require('../controllers/apiController');

app
.route('/orders')
.get(orderList.listAllOrders)
.post(orderList.createNewOrder);

app
.route('/order/:id')
.delete(orderList.deleteOrder);

};

和我的数据库.js


const mongoose = require("mongoose");
//Assign MongoDB connection string to Uri and declare options settings
var  uri = "<mongodb atlas info> 
retryWrites=true&w=majority";
// Declare a variable named option and assign optional settings
const  options = {
useNewUrlParser:  true,
useUnifiedTopology:  true
};
// Connect MongoDB Atlas using mongoose connect method
mongoose.connect(uri, options).then(() => {
console.log("Database connection established!");
},
err  => {
{
console.log("Error connecting Database instance due to:", err);
}
});

这是我需要放入数据库的示例响应

{
"token": "93c4604e-35ac-4db7-b3f1-2871476e9e6a",
"creationDate": "2013-10-22T20:54:40.377Z",
"modificationDate": "2013-10-22T20:55:45.617Z",
"status": "Processed",
"paymentMethod": "CreditCard",
"invoiceNumber": "SNIP-1427",
"email": "geeks@snipcart.com",
"cardHolderName": "Geeks Snipcart",
"creditCardLast4Digits": "4242",
"billingAddressName": "Geeks Snipcart",
"billingAddressCompanyName": "Snipcart",
"billingAddressAddress1": "4885 1ere Avenue",
"billingAddressAddress2": null,
"billingAddressCity": "Quebec",
"billingAddressCountry": "CA",
"billingAddressProvince": "QC",
"billingAddressPostalCode": "G1H2T5",
"billingAddressPhone": "1-877-301-4813",
"notes": null,
"shippingAddressName": "Geeks Snipcart",
"shippingAddressCompanyName": "Snipcart",
"shippingAddressAddress1": "4885 1ere Avenue",
"shippingAddressAddress2": null,
"shippingAddressCity": "Quebec",
"shippingAddressCountry": "CA",
"shippingAddressProvince": "QC",
"shippingAddressPostalCode": "G1H2T5",
"shippingAddressPhone": "1-877-301-4813",
"shippingAddressSameAsBilling": true,
"finalGrandTotal": 287.44,
"shippingFees": 10,
"shippingMethod": "Shipping",
"items": [
{
"uniqueId": "1aad3398-1260-419c-9af4-d18e6fe75fbf",
"id": "1",
"name": "Un poster",
"price": 300,
"quantity": 1,
"url": "http://snipcart.com",
"weight": 10,
"description": "Bacon",
"image": "",
"customFieldsJson": "[]",
"stackable": true,
"maxQuantity": null,
"totalPrice": 300,
"totalWeight": 10
},
...
],
"taxes": [
{
"taxName": "TPS",
"taxRate": 0.05,
"amount": 12.5,
"numberForInvoice": ""
},
{
"taxName": "TVQ",
"taxRate": 0.09975,
"amount": 24.94,
"numberForInvoice": ""
},
...
],
"rebateAmount": 0,
"subtotal": 310,
"itemsTotal": 300,
"grandTotal": 347.44,
"totalWeight": 10,
"hasPromocode": true,
"totalRebateRate": 20,
"promocodes": [
{
"code": "PROMO",
"name": "PROMO",
"type": "Rate",
"rate": 20,
},
...
],
"willBePaidLater": false,
"customFields": [
{
"name":"Slug",
"value": "An order"
},
...
],
"paymentTransactionId": null,
}

我不需要放在数据库中的所有信息,只需要一些关键项目,如客户姓名、电话号码和订单信息。 但是如果订单中有多个项目,我需要它考虑到这一点并添加订单中的所有项目。 这是我需要集成的打印机的文档 https://star-m.jp/products/s_print/CloudPRNTSDK/Documentation/en/index.html 将不胜感激你们能给我的任何帮助。谢谢!

Snipcart会将webhook发送给您endpoint以进行不同的events。我建议您首先通过eventNamefilterevent,因为您只想侦听order.completed事件。之后,从请求消息的body,您可以提取将位于req.body.content.items中的items。您可以从可用信息中获取所需的信息,并仅将其存储在数据库中。

试试这个:

app.post('/hook', (req, res) => {
if (req.body.eventName === 'order.completed') {
const customer_name = req.body.content.cardHolderName;
const customer_phone req.body.content.billingAddressPhone;
const order_number = req.body.content.invoiceNumber;

let items = [];
req.body.content.items.forEach((item) => {
items.push({
name: item.name,
price: item.price,
quantity: item.quantity,
id: item.uniqueId
});
})

// Now store in database
apiFetch.create({
customerName: customer_name,
customerPhone: customer_phone
name: customer_name,
orderNumber: order_number 
customFields: items 
}).then(()=>{
res.status(200).json({success:true});
}, (error)=>{
console.log('ERROR: ', error);
})

}
};

最新更新