fix: payment security hardening — 3 CRITICAL + 3 HIGH
CRITICAL fixes: - C1: Notify amount validation now unconditional (was skippable if amount field missing) - C2: Sync endpoint validates payer_total against order amount before activation - C3: Order ID uses crypto.randomBytes(6) instead of Math.random (collision-safe) HIGH fixes: - H1: Payment endpoints rate limited to 5/min per IP - H2: Max 5 pending orders per user, reject new ones until completed/cancelled - H3: Purchase endpoint returns error (not mock) when wxpay unconfigured in production Also fixed: - Notify handler asserts Buffer body, rejects non-Buffer (L3) - Notify error response is generic, no internal message leak (M1) - Private key cached in memory after first read (L2) - Fixed duplicate paymentOrderDao const declaration
这个提交包含在:
@@ -42,10 +42,20 @@ app.use((req, res, next) => {
|
||||
next()
|
||||
})
|
||||
|
||||
const paymentLimiter = rateLimit({
|
||||
windowMs: 60 * 1000,
|
||||
max: 5,
|
||||
standardHeaders: true,
|
||||
legacyHeaders: false,
|
||||
message: { code: 2001, message: 'too_many_attempts' }
|
||||
})
|
||||
|
||||
app.use('/api/v1/auth/login', userLoginLimiter)
|
||||
app.use('/api/v1/admin/login', adminLoginLimiter)
|
||||
app.use('/api/v1/user/avatar', uploadLimiter)
|
||||
app.use('/api/v1/user/phone', uploadLimiter)
|
||||
app.use('/api/v1/subscription/purchase', paymentLimiter)
|
||||
app.use('/api/v1/payment/orders', paymentLimiter)
|
||||
|
||||
// WeChat Pay callback — must be before authMiddleware (no JWT)
|
||||
app.post('/api/v1/payment/wechat/notify', require('./routes/payment-notify'))
|
||||
|
||||
在新工单中引用
屏蔽一个用户