Проблема с настройкой сервера node js для прослушивания веб-перехватчика и публикации в базе данных

Доброе утро всем, мне немного сложно настроить сервер для прослушивания данных веб-перехватчиков и их публикации в базе данных. Я в основном занимаюсь фронтендом, поэтому кое-что из этого для меня немного ново. Итак, у меня есть веб-сайт гастронома, который я построил на snipcart. У меня есть принтер чеков, который запрашивает API и распечатывает новые заказы. Итак, мне нужен сервер, который будет прослушивать веб-перехватчик и хранить информацию в базе данных. Я получил его там, где он правильно слушает веб-перехватчик, но он отказывается отправлять сообщения в базу данных. Вот код в файле 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);

apiRoutes.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);


};

и мой db.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": "[email protected]",
    "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 Буду признателен за любую помощь, которую вы все можете мне оказать. Спасибо!


person Marcus Martin    schedule 29.03.2021    source источник


Ответы (1)


Snipcart отправит вам webhook endpoint для разных events. Я бы посоветовал вам сначала filter прослушать event по eventName, потому что вы хотите прослушивать только событие order.completed. После этого из body сообщения запроса вы можете извлечь items, который будет в req.body.content.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);
      })
    
   }

};
person Nenad Milosavljevic    schedule 04.04.2021