|
@@ -189,6 +189,21 @@ function generatePaymentSign(params, key) {
|
|
|
return crypto.createHash('md5').update(query, 'utf8').digest('hex')
|
|
return crypto.createHash('md5').update(query, 'utf8').digest('hex')
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+async function acquireCouponUsageLock(couponId) {
|
|
|
|
|
+ const lockKey = `coupon:usage:${couponId}`
|
|
|
|
|
+ const rows = await db.query('SELECT GET_LOCK(?, 5) AS ok', [lockKey])
|
|
|
|
|
+ return { lockKey, ok: Number(rows?.[0]?.ok || 0) === 1 }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+async function releaseCouponUsageLock(lockKey) {
|
|
|
|
|
+ if (!lockKey) return
|
|
|
|
|
+ try {
|
|
|
|
|
+ await db.query('SELECT RELEASE_LOCK(?)', [lockKey])
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ // 释放失败仅记录,不影响主流程
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
class CreateOrder extends API {
|
|
class CreateOrder extends API {
|
|
|
constructor() {
|
|
constructor() {
|
|
|
super()
|
|
super()
|
|
@@ -242,9 +257,34 @@ class CreateOrder extends API {
|
|
|
let discountAmount = 0
|
|
let discountAmount = 0
|
|
|
let couponId = null
|
|
let couponId = null
|
|
|
let appliedCouponCode = null
|
|
let appliedCouponCode = null
|
|
|
|
|
+ let couponLockKey = null
|
|
|
|
|
|
|
|
if (coupon_code && String(coupon_code).trim()) {
|
|
if (coupon_code && String(coupon_code).trim()) {
|
|
|
- const couponResult = await validateCoupon({
|
|
|
|
|
|
|
+ let couponResult = await validateCoupon({
|
|
|
|
|
+ code: coupon_code,
|
|
|
|
|
+ userUuid: uuid,
|
|
|
|
|
+ goodsId: goods_id,
|
|
|
|
|
+ goodsPrice: goods.price
|
|
|
|
|
+ })
|
|
|
|
|
+ if (!couponResult.ok) {
|
|
|
|
|
+ return res.json({ ...BaseStdResponse.ERR, msg: couponResult.msg })
|
|
|
|
|
+ }
|
|
|
|
|
+ finalPrice = couponResult.finalPrice
|
|
|
|
|
+ discountAmount = couponResult.discountAmount
|
|
|
|
|
+ couponId = couponResult.couponId
|
|
|
|
|
+ appliedCouponCode = couponResult.code
|
|
|
|
|
+
|
|
|
|
|
+ const lockRet = await acquireCouponUsageLock(couponId)
|
|
|
|
|
+ if (!lockRet.ok) {
|
|
|
|
|
+ return res.json({
|
|
|
|
|
+ ...BaseStdResponse.ERR,
|
|
|
|
|
+ msg: '优惠码校验繁忙,请稍后重试'
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ couponLockKey = lockRet.lockKey
|
|
|
|
|
+
|
|
|
|
|
+ // 拿到锁后重查一次,避免并发下单绕过“每人限用次数”
|
|
|
|
|
+ couponResult = await validateCoupon({
|
|
|
code: coupon_code,
|
|
code: coupon_code,
|
|
|
userUuid: uuid,
|
|
userUuid: uuid,
|
|
|
goodsId: goods_id,
|
|
goodsId: goods_id,
|
|
@@ -253,6 +293,7 @@ class CreateOrder extends API {
|
|
|
if (!couponResult.ok) {
|
|
if (!couponResult.ok) {
|
|
|
return res.json({ ...BaseStdResponse.ERR, msg: couponResult.msg })
|
|
return res.json({ ...BaseStdResponse.ERR, msg: couponResult.msg })
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
finalPrice = couponResult.finalPrice
|
|
finalPrice = couponResult.finalPrice
|
|
|
discountAmount = couponResult.discountAmount
|
|
discountAmount = couponResult.discountAmount
|
|
|
couponId = couponResult.couponId
|
|
couponId = couponResult.couponId
|
|
@@ -359,6 +400,8 @@ class CreateOrder extends API {
|
|
|
...BaseStdResponse.ERR,
|
|
...BaseStdResponse.ERR,
|
|
|
msg: "创建订单异常,请联系管理员"
|
|
msg: "创建订单异常,请联系管理员"
|
|
|
})
|
|
})
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ await releaseCouponUsageLock(couponLockKey)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|