Browse Source

✨ feat: 增加商品信息获取接口

Pchen. 11 months ago
parent
commit
bb021374bc

+ 78 - 0
apis/Goods/Admin/AddGoods.js

@@ -0,0 +1,78 @@
+const API = require("../../../lib/API");
+const db = require("../../../plugin/DataBase/db");
+const AccessControl = require("../../../lib/AccessControl");
+const { BaseStdResponse } = require("../../../BaseStdResponse");
+
+// 添加/编辑商品
+class AddProduct extends API {
+    constructor() {
+        super()
+
+        this.setPath('/Admin/Goods')
+        this.setMethod('POST')
+    }
+
+    async onRequest(req, res) {
+
+        let {
+            uuid,
+            session,
+            id,
+            name,
+            state,
+            content,
+            price,
+            num,
+            lepao_count,
+            ic_count
+        } = req.body
+
+        if ([uuid, session, name, state, content, price, num, lepao_count, ic_count].some(value => value === '' || value === null || value === undefined))
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER
+            })
+
+        // 检查 session
+        if (!await AccessControl.checkSession(uuid, session))
+            return res.status(401).json({
+                ...BaseStdResponse.ACCESS_DENIED
+            })
+
+        // 检查权限
+        let permission = await AccessControl.getPermission(uuid)
+        if (!permission.includes("admin") && !permission.includes("product"))
+            return res.json({
+                ...BaseStdResponse.PERMISSION_DENIED
+            })
+
+        let sql, r
+        const time = new Date().getTime()
+
+        if (!id) {
+            sql = 'INSERT INTO goods (name, create_user, create_time, state, content, price, lepao_count, ic_count) VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
+            r = await db.query(sql, [name, uuid, time, state, content, price, lepao_count, ic_count])
+        } else {
+            sql = 'UPDATE goods SET name = ?, update_user = ?, update_time = ?, state = ?,  content = ?, price = ?, lepao_count = ?, type = ? WHERE id = ?'
+            r = await db.query(sql, [name, uuid, time, state, content, price, lepao_count, ic_count, id])
+        }
+
+        try {
+            if (r && r.affectedRows > 0) {
+                res.json({
+                    ...BaseStdResponse.OK
+                })
+            } else {
+                res.json({ ...BaseStdResponse.ERR, endpoint: 7894378, msg: '编辑商品失败!数据库错误!请检查参数是否正确' })
+            }
+        } catch (err) {
+            this.logger.error(`编辑商品失败!${err.stack}`)
+            res.json({
+                ...BaseStdResponse.ERR,
+                msg: "编辑商品失败!",
+            });
+        }
+    }
+
+}
+
+module.exports.AddProduct = AddProduct;

+ 57 - 0
apis/Goods/Admin/DeleteGoods.js

@@ -0,0 +1,57 @@
+const API = require("../../../lib/API");
+const db = require("../../../plugin/DataBase/db");
+const AccessControl = require("../../../lib/AccessControl");
+const { BaseStdResponse } = require("../../../BaseStdResponse");
+
+// 删除产品
+class DeleteProduct extends API {
+    constructor() {
+        super();
+
+        this.setPath('/Admin/Goods')
+        this.setMethod('DELETE')
+    }
+
+    async onRequest(req, res) {
+        let { uuid, session, id } = req.body
+
+        if ([uuid, session, id].some(value => value === '' || value === null || value === undefined))
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER
+            })
+
+        // 检查 session
+        if (!await AccessControl.checkSession(uuid, session))
+            return res.status(401).json({
+                ...BaseStdResponse.ACCESS_DENIED
+            })
+
+        // 检查权限
+        let permission = await AccessControl.getPermission(uuid)
+        if (!permission.includes("admin") && !permission.includes("product"))
+            return res.json({
+                ...BaseStdResponse.PERMISSION_DENIED
+            })
+
+        let sql = 'DELETE FROM goods WHERE id = ?'
+        let r = await db.query(sql, [id])
+
+        try {
+            if (r && r.affectedRows > 0) {
+                res.json({
+                    ...BaseStdResponse.OK
+                })
+            } else {
+                res.json({ ...BaseStdResponse.ERR, endpoint: 7894378, msg: '删除商品失败!数据库错误' })
+            }
+        } catch (err) {
+            this.logger.error(`删除商品失败!${err.stack}`)
+            res.json({
+                ...BaseStdResponse.ERR,
+                msg: "删除商品失败!",
+            });
+        }
+    }
+}
+
+module.exports.DeleteProduct = DeleteProduct;

+ 83 - 0
apis/Goods/Admin/GetGoods.js

@@ -0,0 +1,83 @@
+const API = require("../../../lib/API");
+const db = require("../../../plugin/DataBase/db");
+const AccessControl = require("../../../lib/AccessControl");
+const { BaseStdResponse } = require("../../../BaseStdResponse");
+
+// 获取产品
+class GetProduct extends API {
+    constructor() {
+        super();
+
+        this.setPath('/Admin/Product')
+        this.setMethod('GET')
+    }
+
+    async onRequest(req, res) {
+        let {
+            uuid,
+            session,
+            id
+        } = req.query
+
+        if ([uuid, session, id].some(value => value === '' || value === null || value === undefined))
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER
+            })
+
+        // 检查 session
+        if (!await AccessControl.checkSession(uuid, session))
+            return res.status(401).json({
+                ...BaseStdResponse.ACCESS_DENIED
+            })
+
+        // 检查权限
+        let permission = await AccessControl.getPermission(uuid)
+        if (!permission.includes("admin") && !permission.includes("product"))
+            return res.json({
+                ...BaseStdResponse.PERMISSION_DENIED
+            })
+
+        let sql = `
+            SELECT
+                a.id,
+                a.name,
+                a.state,
+                a.content,
+                a.price,
+                a.views,
+                a.num,
+                a.ic_count,
+                a.lepao_count,
+                a.create_time,
+                a.update_time,
+                u1.username AS create_user,
+                u2.username AS update_user
+            FROM
+                goods a
+            LEFT JOIN
+                users u1
+            ON
+                a.create_user = u1.uuid
+            LEFT JOIN
+                users u2
+            ON
+                a.update_user = u2.uuid
+            WHERE a.id = ?
+        `
+
+        let rows = await db.query(sql, [id])
+
+        if (!rows || rows.length === 0)
+            return res.json({
+                ...BaseStdResponse.MISSING_FILE,
+                msg: '获取商品失败!'
+            })
+
+        res.json({
+            ...BaseStdResponse.OK,
+            data: rows
+        })
+    }
+}
+
+module.exports.GetProduct = GetProduct;

+ 117 - 0
apis/Goods/Admin/GetGoodsList.js

@@ -0,0 +1,117 @@
+const API = require("../../../lib/API");
+const db = require("../../../plugin/DataBase/db");
+const AccessControl = require("../../../lib/AccessControl");
+const { BaseStdResponse } = require("../../../BaseStdResponse");
+
+// 获取商品列表
+class GetProductList extends API {
+    constructor() {
+        super();
+        this.setPath('/Admin/Product/List');
+        this.setMethod('post');
+    }
+
+    async onRequest(req, res) {
+        let { uuid, session, pagesize, current, keyword } = req.body;
+
+        if ([uuid, session, pagesize, current].some(value => value === '' || value === null || value === undefined))
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER
+            })
+
+        // 校验分页参数
+        if (isNaN(pagesize) || pagesize <= 0 || isNaN(current) || current <= 0) {
+            return res.json({
+                ...BaseStdResponse.ERR,
+                msg: '参数错误'
+            })
+        }
+
+        // 计算分页的 offset
+        const offset = (current - 1) * pagesize
+
+        // 检查 session
+        if (!await AccessControl.checkSession(uuid, session))
+            return res.status(401).json({
+                ...BaseStdResponse.ACCESS_DENIED
+            })
+
+        // 检查权限
+        let permission = await AccessControl.getPermission(uuid)
+        if (!permission.includes("admin") && !permission.includes("product"))
+            return res.json({
+                ...BaseStdResponse.PERMISSION_DENIED
+            })
+
+        let sql = `
+            SELECT
+                a.id,
+                a.name,
+                a.state,
+                a.price,
+                a.num,
+                a.ic_count,
+                a.lepao_count,
+                a.views,
+                a.create_time,
+                a.update_time,
+                u1.username AS create_user,
+                u2.username AS update_user
+            FROM
+                goods a
+            LEFT JOIN
+                users u1 ON a.create_user = u1.uuid
+            LEFT JOIN
+                users u2 ON a.update_user = u2.uuid
+            WHERE 1=1
+        `
+
+        let countSql = `
+            SELECT COUNT(*) AS total
+            FROM goods a
+            WHERE 1 = 1
+        `
+
+        let params = []
+        let countParams = []
+
+        if (keyword) {
+            sql += ` AND a.name LIKE ?`
+            countSql += ` AND a.name LIKE ?`
+            params.push(`%${keyword}%`)
+            countParams.push(`%${keyword}%`)
+        }
+
+        sql += `
+            ORDER BY 
+                a.id DESC
+            LIMIT ? OFFSET ? 
+            `
+        params.push(String(pagesize), String(offset))
+
+        let rows = await db.query(sql, params);
+        let countResult = await db.query(countSql, countParams)
+
+        if (!rows || !countResult)
+            return res.json({
+                ...BaseStdResponse.MISSING_FILE,
+                msg: '获取产品失败!'
+            })
+
+        let total = countResult[0].total
+        const totalPages = Math.ceil(total / pagesize)
+
+        res.json({
+            ...BaseStdResponse.OK,
+            data: rows,
+            pagination: {
+                current: current,
+                pagesize: pagesize,
+                total: total,
+                totalPages: totalPages
+            }
+        })
+    }
+}
+
+module.exports.GetProductList = GetProductList;

+ 52 - 0
apis/Goods/GetGoods.js

@@ -0,0 +1,52 @@
+const API = require("../../lib/API");
+const db = require("../../plugin/DataBase/db");
+const { BaseStdResponse } = require("../../BaseStdResponse");
+
+// 获取产品
+class GetProduct extends API {
+    constructor() {
+        super();
+
+        this.setPath('/Goods')
+        this.setMethod('GET')
+    }
+
+    async onRequest(req, res) {
+        let { id } = req.query
+
+        if ([id].some(value => value === '' || value === null || value === undefined))
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER
+            })
+
+            let sql = `
+            SELECT
+                id,
+                name,
+                content,
+                price,
+                num
+            FROM
+                goods 
+            WHERE id = ? AND state = 1
+        `
+
+        let rows = await db.query(sql, [id])
+
+        if (!rows || rows.length === 0)
+            return res.json({
+                ...BaseStdResponse.MISSING_FILE,
+                msg: '获取商品详情失败!'
+            })
+
+        res.json({
+            ...BaseStdResponse.OK,
+            data: rows
+        })
+
+        sql = 'UPDATE goods SET views = views + 1 WHERE id = ?'
+        await db.query(sql, [id])
+    }
+}
+
+module.exports.GetProduct = GetProduct;

+ 99 - 0
apis/Goods/GetGoodsList.js

@@ -0,0 +1,99 @@
+const API = require("../../lib/API");
+const db = require("../../plugin/DataBase/db");
+const { BaseStdResponse } = require("../../BaseStdResponse");
+
+// 获取产品列表
+class GetProductList extends API {
+    constructor() {
+        super();
+
+        this.setPath('/Goods/List')
+        this.setMethod('post')
+    }
+
+    async onRequest(req, res) {
+        let { keyword, pagesize, current } = req.body;
+
+        if ([pagesize, current].some(value => value === '' || value === null || value === undefined))
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER
+            })
+
+        // 校验分页参数
+        if (isNaN(pagesize) || pagesize <= 0) {
+            return res.json({
+                ...BaseStdResponse.ERR,
+                msg: '参数错误'
+            })
+        }
+
+        if (isNaN(current) || current <= 0) {
+            return res.json({
+                ...BaseStdResponse.ERR,
+                msg: '参数错误'
+            })
+        }
+
+        // 计算分页的 offset
+        const offset = (current - 1) * pagesize
+
+        let sql = `
+            SELECT
+                id,
+                name,
+                price,
+                num
+            FROM
+                goods
+            WHERE state = 1 
+        `
+
+        let countSql = `
+            SELECT COUNT(*) AS total
+            FROM goods
+            WHERE 1 = 1
+        `
+
+        let params = []
+        let countParams = []
+
+        if (keyword) {
+            sql += ` AND name LIKE ?`
+            countSql += ` AND name LIKE ?`
+            params.push(`%${keyword}%`)
+            countParams.push(`%${keyword}%`)
+        }
+
+        sql += `
+            ORDER BY 
+                id DESC
+            LIMIT ? OFFSET ?;
+        `
+        params.push(String(pagesize), String(offset))
+
+        let rows = await db.query(sql, params)
+        let countResult = await db.query(countSql, countParams)
+
+        if (!rows || !countResult)
+            return res.json({
+                ...BaseStdResponse.ERR,
+                msg: '获取商品失败!'
+            })
+
+        let total = countResult[0].total
+        const totalPages = Math.ceil(total / pagesize)
+
+        res.json({
+            ...BaseStdResponse.OK,
+            data: rows,
+            pagination: {
+                current: current,
+                pagesize: pagesize,
+                total: total,
+                totalPages: totalPages
+            }
+        })
+    }
+}
+
+module.exports.GetProductList = GetProductList;

+ 50 - 13
apis/Order/CallBack.js

@@ -20,10 +20,11 @@ class CallBack extends API {
         } = req.query
 
         // 参数校验
-        if ([pid, trade_no, out_trade_no, type, name, money, trade_status, sign, sign_type].some(v => v === undefined))
+        if ([pid, trade_no, out_trade_no, type, name, money, trade_status, sign, sign_type].some(v => v === undefined)) {
             return res.json({
                 ...BaseStdResponse.MISSING_PARAMETER
             })
+        }
 
         // 签名校验
         const rawParams = {
@@ -33,34 +34,70 @@ class CallBack extends API {
         const preSignStr = sortedKeys.map(key => `${key}=${rawParams[key]}`).join('&') + `&key=${PAYMENT_KEY}`
         const localSign = crypto.createHash('md5').update(preSignStr, 'utf8').digest('hex')
 
-        if (localSign !== sign)
-            return res.json({
-                ...BaseStdResponse.ERR,
-                msg: '签名验证失败'
-            })
+        if (localSign.toLowerCase() !== sign.toLowerCase()) {
+            this.logger.error(`签名校验失败,订单号:${out_trade_no}`)
+            return res.send('签名验证失败')
+        }
 
-        // 判断支付状态
+        // 支付未成功,标记为失败
         if (trade_status !== 'TRADE_SUCCESS') {
-            const sql = 'UPDATE orders SET \`state\` = 2, pay_id = ? WHERE orderId = ?'
+            const sql = 'UPDATE orders SET state = 3, pay_id = ? WHERE orderId = ?'
             await db.query(sql, [trade_no, out_trade_no])
+            return res.send('fail')
         }
-            
+
         try {
-            // 更新订单状态
-            const sql = 'UPDATE orders SET \`state\` = 1, pay_type = ?, pay_id = ? WHERE orderId = ? AND \`state\` = 0'
+            // 更新订单状态为已支付(state=1)
+            let sql = 'UPDATE orders SET state = 1, pay_type = ?, pay_id = ? WHERE orderId = ? AND state = 0'
             const result = await db.query(sql, [type, trade_no, out_trade_no])
 
             if (result.affectedRows > 0) {
+                // 查询订单与商品信息
+                sql = `
+                    SELECT 
+                        g.lepao_count,
+                        g.ic_count,
+                        a.create_user
+                    FROM 
+                        orders a
+                    LEFT JOIN 
+                        goods g 
+                    ON 
+                        a.goods_id = g.id
+                    WHERE 
+                        a.orderId = ?
+                `
+                const rows = await db.query(sql, [out_trade_no])
+                if (!rows || rows.length !== 1) {
+                    this.logger.error(`订单商品信息异常,订单号:${out_trade_no}`)
+                    await db.query('UPDATE orders SET state = 4 WHERE orderId = ?', [out_trade_no])
+                    return res.send('fail')
+                }
+
+                const { lepao_count, ic_count, create_user } = rows[0]
+
+                // 更新用户剩余次数
+                sql = 'UPDATE users SET lepao_count = lepao_count + ?, ic_count = ic_count + ? WHERE uuid = ?'
+                const updateUser = await db.query(sql, [lepao_count, ic_count, create_user])
+                if (!updateUser || updateUser.affectedRows !== 1) {
+                    this.logger.error(`更新用户失败,UUID: ${create_user}`)
+                    await db.query('UPDATE orders SET state = 4 WHERE orderId = ?', [out_trade_no])
+                    return res.send('fail')
+                }
+
+                sql = 'UPDATE orders SET state = 2 WHERE orderId = ?'
+                await db.query(sql, [out_trade_no])
+
                 return res.send('success')
             } else {
+                this.logger.warn(`订单不存在或已处理,订单号:${out_trade_no}`)
                 return res.send('订单不存在或已处理')
             }
         } catch (err) {
-            this.logger.error(`支付回调异常:${err.stack}`)
+            this.logger.error(`支付回调处理异常:${err.stack}`)
             return res.send('服务器错误')
         }
     }
 }
 
 module.exports.CallBack = CallBack
-