const router = require('express').Router() const { ok, fail } = require('../lib/response') const { requireUser } = require('../middleware/auth') const { requireAdmin } = require('../middleware/auth') const { getSettings } = require('../lib/settings-cache') const subscriptionDao = require('../dao/subscription.dao') const logDao = require('../dao/log.dao') const wrap = fn => (req, res, next) => fn(req, res, next).catch(next) const PLANS = { trial: { amount: 0, days: 7 }, monthly: { amount: 99, days: 30 }, yearly: { amount: 899, days: 365 } } router.get('/subscription/plans', wrap(async (req, res) => { const settingsDao = require('../dao/settings.dao') const settings = await settingsDao.getAll() res.json(ok({ plans: [ { key: 'monthly', name: '月卡', price: Number(settings.monthly_price) || PLANS.monthly.amount, days: 30 }, { key: 'yearly', name: '年卡', price: Number(settings.yearly_price) || PLANS.yearly.amount, days: 365 }, { key: 'trial', name: '试用', price: 0, days: Number(settings.trial_days) || 7 } ] })) })) router.get('/subscription', requireUser, wrap(async (req, res) => { const sub = await subscriptionDao.findActive(req.user.user_id) const trialUsed = await subscriptionDao.findTrial(req.user.user_id) if (!sub) return res.json(ok({ status: 'inactive', plan: 'none', remaining_days: 0, trial_used: !!trialUsed })) res.json(ok({ status: sub.remaining_days > 0 ? 'active' : 'expired', plan: sub.plan, start_time: sub.start_time, expire_time: sub.expire_time, remaining_days: sub.remaining_days, trial_used: !!trialUsed })) })) router.post('/subscription/purchase', requireUser, wrap(async (req, res) => { const plan = req.body.plan || req.body.plan_type if (!PLANS[plan]) return res.json(fail(2001, 'invalid plan')) const orderId = 'ORD' + Date.now() res.json(ok({ order_id: orderId, payment_params: {}, plan, amount: PLANS[plan].amount })) })) router.post('/subscription/mock-purchase', requireUser, wrap(async (req, res) => { const config = require('../config') if (config.nodeEnv === 'production') return res.json(fail(2001, 'not available in production')) const plan = req.body.plan || req.body.plan_type if (!PLANS[plan] || plan === 'trial') return res.json(fail(2001, 'invalid plan')) const p = PLANS[plan] const orderId = 'MOCK' + Date.now() await subscriptionDao.purchase(req.user.user_id, plan, p.amount, orderId, p.days) await logDao.write({ user_id: req.user.user_id, action: 'subscription_mock_purchase', detail: '模拟购买: ' + plan, ip: req.ip }) const sub = await subscriptionDao.findActive(req.user.user_id) res.json(ok({ status: 'active', plan, remaining_days: sub ? sub.remaining_days : p.days })) })) router.post('/subscription/trial', requireUser, wrap(async (req, res) => { const usedTrial = await subscriptionDao.findTrial(req.user.user_id) if (usedTrial) return res.json(fail(2001, '已使用过试用')) const activeSub = await subscriptionDao.findActive(req.user.user_id) if (activeSub) return res.json(fail(2001, '已有有效订阅')) const settings = await getSettings() const trialDays = Number(settings.trial_days) || 7 await subscriptionDao.createTrial(req.user.user_id, undefined, trialDays) res.json(ok({ status: 'active', plan: 'trial', remaining_days: trialDays })) })) // Temporary: admin-only until payment integration router.post('/subscription/verify', requireAdmin, wrap(async (req, res) => { const userId = req.body.user_id if (!userId) return res.json(fail(2001, 'user_id required')) const plan = req.body.plan || req.body.plan_type || 'monthly' if (!PLANS[plan]) return res.json(fail(2001, 'invalid plan')) const p = PLANS[plan] await subscriptionDao.purchase(userId, plan, p.amount, req.body.order_id || 'ORD' + Date.now(), p.days) await logDao.write({ admin_id: req.admin.admin_id, action: 'subscription_verify', detail: '订阅生效: ' + plan + ' user:' + userId, ip: req.ip }) const sub = await subscriptionDao.findActive(userId) res.json(ok({ status: 'active', plan, remaining_days: sub ? sub.remaining_days : p.days })) })) module.exports = router