|
|
@@ -0,0 +1,126 @@
|
|
|
+const API = require("../../lib/API.js")
|
|
|
+const db = require("../../plugin/DataBase/db.js")
|
|
|
+const { BaseStdResponse } = require("../../BaseStdResponse.js")
|
|
|
+const AccessControl = require("../../lib/AccessControl.js")
|
|
|
+const crypto = require('crypto')
|
|
|
+const config = require('../../config.json')
|
|
|
+
|
|
|
+function generateOrderId() {
|
|
|
+ const now = new Date()
|
|
|
+ const pad = (n, w = 2) => n.toString().padStart(w, '0')
|
|
|
+ return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}`
|
|
|
+ + `${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`
|
|
|
+ + `${pad(now.getMilliseconds(), 3)}`
|
|
|
+}
|
|
|
+
|
|
|
+function generatePaymentSign(params, key) {
|
|
|
+ const sorted = Object.keys(params).sort();
|
|
|
+ const query = sorted.map(k => `${k}=${params[k]}`).join('&') + `&key=${key}`;
|
|
|
+ return crypto.createHash('md5').update(query, 'utf8').digest('hex');
|
|
|
+}
|
|
|
+
|
|
|
+class CreateOrder extends API {
|
|
|
+ constructor() {
|
|
|
+ super()
|
|
|
+ this.setPath('/Order/CreateOrder')
|
|
|
+ this.setMethod('POST')
|
|
|
+ }
|
|
|
+
|
|
|
+ async onRequest(req, res) {
|
|
|
+ const { uuid, session, goods_id, pay_type } = req.body
|
|
|
+
|
|
|
+ if ([uuid, session, goods_id, pay_type].some(v => v === '' || v === null || v === undefined)) {
|
|
|
+ return res.json({
|
|
|
+ ...BaseStdResponse.MISSING_PARAMETER,
|
|
|
+ endpoint: 1513126
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ const sessionValid = await AccessControl.checkSession(uuid, session)
|
|
|
+ if (!sessionValid) {
|
|
|
+ return res.status(401).json({
|
|
|
+ ...BaseStdResponse.ACCESS_DENIED
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 查询商品信息
|
|
|
+ const goodsSql = 'SELECT name, price, num, state FROM goods WHERE id = ?'
|
|
|
+ const goodsRows = await db.query(goodsSql, [goods_id])
|
|
|
+
|
|
|
+ if (!goodsRows || goodsRows.length !== 1) {
|
|
|
+ return res.json({
|
|
|
+ ...BaseStdResponse.ERR,
|
|
|
+ msg: '商品不存在',
|
|
|
+ endpoint: 1513126
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ const goods = goodsRows[0]
|
|
|
+ if (goods.num < 1 || goods.state !== 1) {
|
|
|
+ return res.json({
|
|
|
+ ...BaseStdResponse.ERR,
|
|
|
+ msg: '商品已下架或库存不足',
|
|
|
+ endpoint: 1513126
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ const createTime = new Date().getTime()
|
|
|
+ const orderId = generateOrderId()
|
|
|
+
|
|
|
+ const insertSql = `
|
|
|
+ INSERT INTO orders (orderId, create_user, create_time, goods_id, price, pay_type)
|
|
|
+ VALUES (?, ?, ?, ?, ?, ?)
|
|
|
+ `
|
|
|
+ const insertParams = [orderId, uuid, createTime, goods_id, goods.price, pay_type]
|
|
|
+ const result = await db.query(insertSql, insertParams)
|
|
|
+
|
|
|
+ const updateSql = 'UPDATE goods SET num = num - 1 WHERE id = ?'
|
|
|
+ await db.query(updateSql, [goods_id])
|
|
|
+
|
|
|
+ if (result && result.affectedRows > 0) {
|
|
|
+ const paymentConfig = config.pay
|
|
|
+
|
|
|
+ const payParams = {
|
|
|
+ pid: paymentConfig.pid,
|
|
|
+ type: pay_type,
|
|
|
+ out_trade_no: orderId,
|
|
|
+ notify_url: config.url + '/Order/CallBack',
|
|
|
+ return_url: paymentConfig.return_url,
|
|
|
+ name: goods.name,
|
|
|
+ money: goods.price.toFixed(2),
|
|
|
+ sitename: paymentConfig.sitename
|
|
|
+ }
|
|
|
+
|
|
|
+ const sign = generatePaymentSign(payParams, paymentConfig.key);
|
|
|
+ payParams.sign = sign
|
|
|
+ payParams.sign_type = 'MD5'
|
|
|
+
|
|
|
+ // 构造支付URL
|
|
|
+ const queryString = new URLSearchParams(payParams).toString();
|
|
|
+ const payUrl = `${paymentConfig.url}?${queryString}`;
|
|
|
+
|
|
|
+ return res.json({
|
|
|
+ ...BaseStdResponse.OK,
|
|
|
+ id: orderId,
|
|
|
+ payUrl
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ return res.json({
|
|
|
+ ...BaseStdResponse.ERR,
|
|
|
+ msg: '创建订单失败!请联系客服',
|
|
|
+ endpoint: 7894378
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (err) {
|
|
|
+ this.logger.error(`创建订单失败!${err.stack}`)
|
|
|
+ return res.json({
|
|
|
+ ...BaseStdResponse.ERR,
|
|
|
+ msg: "创建订单失败!请联系客服",
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+module.exports.CreateOrder = CreateOrder
|