Browse Source

✨ feat: 加入自助更新乐跑账号状态接口

Pchen. 1 month ago
parent
commit
e50b6ac467
1 changed files with 135 additions and 0 deletions
  1. 135 0
      apis/Lepao/Account/UpdateSelfAccount.js

+ 135 - 0
apis/Lepao/Account/UpdateSelfAccount.js

@@ -0,0 +1,135 @@
+const API = require("../../../lib/API.js")
+const db = require("../../../plugin/DataBase/db.js")
+const axios = require("axios")
+const AccessControl = require("../../../lib/AccessControl.js")
+const { BaseStdResponse } = require("../../../BaseStdResponse.js")
+const { dataEncrypt, dataDecrypt, dataSign } = require("../../../plugin/Lepao/Crypto")
+const { URLSearchParams } = require("url")
+
+class UpdateSelfAccount extends API {
+    constructor() {
+        super()
+
+        this.setPath('/Lepao/Account/UpdateSelfAccount')
+        this.setMethod('POST')
+    }
+
+    async onRequest(req, res) {
+        const { uuid, session, student_num } = req.body
+
+        if ([uuid, session, student_num].some(v => v === '' || v === null || v === undefined)) {
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER
+            })
+        }
+
+        if (!await AccessControl.checkSession(uuid, session)) {
+            return res.status(401).json({
+                ...BaseStdResponse.ACCESS_DENIED
+            })
+        }
+
+        try {
+            const rows = await db.query(
+                'SELECT uid, token, school_id, userAgent, state FROM lepao_account WHERE student_num = ? AND create_user = ?',
+                [student_num, uuid]
+            )
+            if (!rows || rows.length !== 1) {
+                return res.json({
+                    ...BaseStdResponse.ERR,
+                    msg: '未找到该乐跑账号或无权限操作'
+                })
+            }
+
+            const account = rows[0]
+            const raw = {
+                uid: account.uid,
+                token: account.token,
+                school_id: account.school_id,
+                term_id: 0,
+                course_id: 0,
+                class_id: 0,
+                student_num,
+                card_id: student_num,
+                timestamp: Number((Date.now() / 1000).toFixed(3)),
+                version: 1,
+                nonce: String(Math.floor(Math.random() * 900000 + 100000)),
+                ostype: 5
+            }
+            raw.sign = dataSign(raw)
+
+            const form = new URLSearchParams()
+            form.append('ostype', '5')
+            form.append('data', dataEncrypt(JSON.stringify(raw)))
+
+            const headers = {
+                'Content-Type': 'application/x-www-form-urlencoded',
+                'Accept': '*/*',
+                'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
+                'Accept-Encoding': 'gzip, deflate, br',
+                'Referer': 'https://servicewechat.com/wxf94c4ddb63d87ede/32/page-frame.html',
+                'User-Agent': account.userAgent || 'Mozilla/5.0 (Linux; Android 16; 2211133C Build/BP2A.250605.031.A3; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/138.0.7204.180 Mobile Safari/537.36 XWEB/1380347 MMWEBSDK/20250202 MMWEBID/1020 wxwork/5.0.6.66174 MicroMessenger/8.0.28.48(0x28001c30) MiniProgramEnv/android Luggage/3.0.2.95ef3f83 NetType/WIFI Language/zh_CN ABI/arm64'
+            }
+
+            const apiRes = await axios.post(
+                'https://lepao.ctbu.edu.cn/v3/api.php/Run2/beforeRunV260',
+                form,
+                { headers, proxy: false }
+            )
+
+            let result = apiRes.data
+            if (result?.data && result?.is_encrypt === 1) {
+                result.data = JSON.parse(dataDecrypt(result.data))
+            }
+
+            const info = result?.info || result?.msg || '系统繁忙,请稍后再试'
+            const updateTime = Date.now()
+
+            // 登录失效:更新 state=0
+            if (String(info).includes('重新登录') || Number(result?.status) === 101) {
+                await db.query('UPDATE lepao_account SET state = 0, update_time = ? WHERE student_num = ? AND create_user = ?', [updateTime, student_num, uuid])
+                return res.json({
+                    ...BaseStdResponse.ERR,
+                    msg: info
+                })
+            }
+
+            if (!result || Number(result.status) !== 1 || !result.data) {
+                return res.json({
+                    ...BaseStdResponse.ERR,
+                    msg: info
+                })
+            }
+
+            const term_num = Number(result.data.term_num ?? 0)
+            const total_num = Number(result.data.total_num ?? 30)
+
+            const updateRows = await db.query(
+                'UPDATE lepao_account SET term_num = ?, total_num = ?, state = 1, update_time = ? WHERE student_num = ? AND create_user = ?',
+                [term_num, total_num, updateTime, student_num, uuid]
+            )
+            if (!updateRows || updateRows.affectedRows !== 1) {
+                return res.json({
+                    ...BaseStdResponse.DATABASE_ERR
+                })
+            }
+
+            return res.json({
+                ...BaseStdResponse.OK,
+                data: {
+                    term_num,
+                    total_num,
+                    state: 1
+                }
+            })
+        } catch (error) {
+            this.logger.error(`用户自助同步乐跑账号失败: ${error.stack || error}`)
+            return res.json({
+                ...BaseStdResponse.ERR,
+                msg: '同步失败,请稍后再试'
+            })
+        }
+    }
+}
+
+module.exports.UpdateSelfAccount = UpdateSelfAccount