139 行
4.2 KiB
JavaScript
139 行
4.2 KiB
JavaScript
var db = require('../../common/db')
|
|
var auth = require('../../common/auth')
|
|
var log = require('../../common/log')
|
|
var RESPONSE = require('../../common/response').RESPONSE
|
|
var ERROR_CODES = require('../../common/response').ERROR_CODES
|
|
|
|
exports.main_handler = async function (event) {
|
|
try {
|
|
var method = event.httpMethod || 'GET'
|
|
var path = event.path || ''
|
|
var body = parseBody(event)
|
|
|
|
if (method === 'GET' && path === '/api/v1/subscription') {
|
|
return await getSubscription(event)
|
|
}
|
|
if (method === 'POST' && path === '/api/v1/subscription/purchase') {
|
|
return await purchaseSubscription(event, body)
|
|
}
|
|
if (method === 'POST' && path === '/api/v1/subscription/verify') {
|
|
return await verifyPayment(event, body)
|
|
}
|
|
|
|
return RESPONSE.error(ERROR_CODES.PARAM_ERROR.code, 'unknown route')
|
|
} catch (err) {
|
|
console.error('subscription error:', err)
|
|
return RESPONSE.error(ERROR_CODES.SERVER_ERROR.code, err.message)
|
|
}
|
|
}
|
|
|
|
async function getSubscription(event) {
|
|
var user = auth.extractUser(event)
|
|
if (!user) return RESPONSE.error(ERROR_CODES.INVALID_TOKEN.code, ERROR_CODES.INVALID_TOKEN.message)
|
|
|
|
var subs = await db.query(
|
|
'SELECT id, type, plan, status, trial_used, started_at AS start_time, expired_at AS expire_time ' +
|
|
'FROM subscriptions ' +
|
|
'WHERE user_id = ? AND status = 1 AND expired_at > NOW() ' +
|
|
'ORDER BY expired_at DESC LIMIT 1',
|
|
[user.user_id]
|
|
)
|
|
|
|
if (subs.length === 0) {
|
|
return RESPONSE.success({
|
|
status: 0,
|
|
plan: null,
|
|
start_time: null,
|
|
expire_time: null,
|
|
remaining_days: 0
|
|
})
|
|
}
|
|
|
|
var sub = subs[0]
|
|
var remainingMs = new Date(sub.expire_time) - new Date()
|
|
var remainingDays = Math.ceil(remainingMs / 86400000)
|
|
|
|
return RESPONSE.success({
|
|
status: sub.type === 1 ? 1 : 2,
|
|
plan: sub.plan,
|
|
start_time: sub.start_time,
|
|
expire_time: sub.expire_time,
|
|
remaining_days: remainingDays
|
|
})
|
|
}
|
|
|
|
async function purchaseSubscription(event, body) {
|
|
var user = auth.extractUser(event)
|
|
if (!user) return RESPONSE.error(ERROR_CODES.INVALID_TOKEN.code, ERROR_CODES.INVALID_TOKEN.message)
|
|
|
|
if (!body.plan) {
|
|
return RESPONSE.error(ERROR_CODES.PARAM_ERROR.code, 'missing plan')
|
|
}
|
|
|
|
var planDays = { monthly: 30, quarterly: 90, yearly: 365 }
|
|
var days = planDays[body.plan] || 30
|
|
var orderId = 'ORD' + Date.now() + Math.random().toString(36).substring(2, 8)
|
|
|
|
return RESPONSE.success({
|
|
order_id: orderId,
|
|
payment_params: {
|
|
plan: body.plan,
|
|
days: days,
|
|
amount: 0,
|
|
channel: body.payment_method || 'wechat'
|
|
}
|
|
})
|
|
}
|
|
|
|
async function verifyPayment(event, body) {
|
|
var user = auth.extractUser(event)
|
|
if (!user) return RESPONSE.error(ERROR_CODES.INVALID_TOKEN.code, ERROR_CODES.INVALID_TOKEN.message)
|
|
|
|
if (!body.order_id) {
|
|
return RESPONSE.error(ERROR_CODES.PARAM_ERROR.code, 'missing order_id')
|
|
}
|
|
|
|
var planDays = { monthly: 30, quarterly: 90, yearly: 365 }
|
|
|
|
var currentSub = await db.query(
|
|
'SELECT id, expired_at FROM subscriptions WHERE user_id = ? AND status = 1 AND expired_at > NOW() ORDER BY expired_at DESC LIMIT 1',
|
|
[user.user_id]
|
|
)
|
|
|
|
var startDate = new Date()
|
|
if (currentSub.length > 0 && new Date(currentSub[0].expired_at) > startDate) {
|
|
startDate = new Date(currentSub[0].expired_at)
|
|
}
|
|
|
|
var plan = body.plan || 'monthly'
|
|
var days = planDays[plan] || 30
|
|
var expiredAt = new Date(startDate.getTime() + days * 86400000)
|
|
|
|
await db.insert(
|
|
'INSERT INTO subscriptions (user_id, type, plan, status, started_at, expired_at, source, source_id) VALUES (?, 2, ?, 1, ?, ?, ?, ?)',
|
|
[user.user_id, plan, startDate.toISOString().slice(0, 19).replace('T', ' '), expiredAt.toISOString().slice(0, 19).replace('T', ' '), 'purchase', body.order_id]
|
|
)
|
|
|
|
await log.writeLog({
|
|
operator_type: 2,
|
|
operator_id: user.user_id,
|
|
target_type: 'subscription',
|
|
target_id: body.order_id,
|
|
action: 'purchase',
|
|
remark: 'plan=' + plan + ',days=' + days
|
|
})
|
|
|
|
return RESPONSE.success({
|
|
status: 2,
|
|
plan: plan,
|
|
expire_time: expiredAt.toISOString().slice(0, 19).replace('T', ' ')
|
|
})
|
|
}
|
|
|
|
function parseBody(event) {
|
|
if (event.body) {
|
|
try { return JSON.parse(event.body) } catch (e) { return {} }
|
|
}
|
|
return event.queryStringParameters || {}
|
|
}
|