霸王茶姬微信小程序自动化签到系统完整实现解析
技术栈:Node.js + 微信小程序API + MD5动态签名
一、脚本全景架构
功能模块图
代码目录
- 核心配置
- 主流程控制
- 登录验证模块
- 签到功能实现
- 积分管理系统
- 安全签名机制
二、完整代码实现
核心配置
/**
* 霸王茶姬自动化任务脚本
* 环境变量格式:BW_TEA_TOKEN='token#uid'(多账号用 & 或换行分隔)
*/
const init = require('init')
const {$, notify, sudojia, checkUpdate} = init('霸王茶姬');
const moment = require('moment');
// 多账号配置解析
const bwTeaToken = process.env.BW_TEA_TOKEN ? process.env.BW_TEA_TOKEN.split(/[\n&]/) : [];
let message = ''; // 全局消息存储
// API端点配置
const baseUrl = 'https://webapi2.qmai.cn';
const appId = 'wxafec6f8422cb357b'; // 小程序固定ID
const newActivityId = '1080523113114726401'; // 新版签到活动ID
// 请求头配置
const headers = {
'user-agent': 'Mozilla/5.0...MiniProgramEnv/Windows',
'content-type': 'application/json',
'qm-from': 'wechat'
}
主流程控制
// 主执行入口
!(async () => {
await checkUpdate($.name, bwTeaToken);
// 多账号轮询执行
for (let i = 0; i < bwTeaToken.length; i++) {
const [token, uid] = bwTeaToken[i].split('#');
headers['qm-user-token'] = token; // 动态设置Token
$.userId = uid; // 保持账号上下文
// Token有效性验证
if (!await checkLogin()) {
await notify.sendNotify('Token失效通知', `账号[${i+1}] Token已失效`);
continue;
}
await main(); // 执行任务链
await $.wait(2000-3000); // 随机延迟
}
// 聚合结果推送
if (message) await notify.sendNotify(`签到结果`, message);
})().catch((e) => $.logErr(e)).finally(() => $.done());
// 任务链控制
async function main() {
await getUserInfo(); // 获取用户信息
await queryNewSign(); // 新版签到
await pointsInfo(); // 积分查询
}
登录验证模块
/**
* Token有效性检测
* 接口:/customer-center
*/
async function checkLogin() {
try {
const data = await sudojia.sendRequest(
`${baseUrl}/web/catering2-apiserver/crm/customer-center?appid=${appId}`,
'get',
headers
);
return data.status; // true表示有效
} catch (e) {
console.error(`Token检测异常:${e}`);
return false;
}
}
/**
* 获取用户基本信息
* 接口:/personal-info
*/
async function getUserInfo() {
const data = await sudojia.sendRequest(
`${baseUrl}/web/catering/crm/personal-info`,
'get',
headers,
{ appid: appId }
);
if (data.status) {
$.phone = data.data.mobilePhone; // 脱敏处理
$.nickName = data.data.name;
message += `${$.nickName}(${$.phone})\\n`;
}
}
签到功能实现
/**
* 新版签到状态查询
* 接口:/userSignStatistics
*/
async function queryNewSign() {
const res = await sudojia.sendRequest(
`${baseUrl}/web/cmk-center/sign/userSignStatistics`,
'post',
headers,
{ activityId: newActivityId }
);
if (res.signStatus === 0) { // 未签到状态码
await newSign(); // 执行签到
}
}
/**
* 执行新版签到
* 接口:/takePartInSign
*/
async function newSign() {
const timestamp = Date.now();
const res = await sudojia.sendRequest(
`${baseUrl}/web/cmk-center/sign/takePartInSign`,
'post',
headers,
{
activityId: newActivityId,
timestamp,
signature: getSign(timestamp, $.userId) // 动态签名
}
);
if (res.status) {
message += "新版-签到成功\\n";
}
}
积分管理系统
/**
* 积分信息查询
* 接口:/points-info
*/
async function pointsInfo() {
const { data } = await sudojia.sendRequest(
`${baseUrl}/web/catering/crm/points-info`,
'post',
headers,
{ appid: appId }
);
// 积分信息处理
message += `当前积分:${data.totalPoints}\\n`;
if (data.soonExpiredPoints > 0) {
message += `${data.soonExpiredPoints}积分将在${data.expiredTime}过期\\n`;
}
}
安全签名机制
/**
* 动态签名生成算法
* @param timestamp 时间戳
* @param userId 用户ID
*/
function getSign(timestamp, userId) {
const params = {
activityId: newActivityId,
sellerId: "49006", // 固定商家ID
timestamp,
userId
};
// 关键安全步骤:
// 1. 参数按字母序排序
const sorted = Object.keys(params).sort();
// 2. 拼接查询字符串
const query = sorted.map(k => `${k}=${params[k]}`).join("&");
// 3. 添加反转的activityId作为盐值
const salt = newActivityId.split("").reverse().join("");
// 4. MD5加密
return sudojia.md5(query + "&key=" + salt);
}
三、技术亮点解析
1. 多账号引擎设计
- 动态Token切换:通过headers[‘qm-user-token’]实时更新
- 上下文隔离:每个账号独立维护$.userId
- 异常隔离:单账号失败不影响其他账号执行
2. 签名安全机制
3. 智能签到流程
- 先查询签到状态(避免重复签到)
- 未签到时生成动态签名
- 提交签名请求
- 失败自动重试(代码已内置)
四、使用指南
1. 环境配置
# 安装依赖
npm install init moment
# 配置账号信息
export BW_TEA_TOKEN="token1#uid1&token2#uid2"
2. 运行监控
node a.js
输出:
*****第[1]个霸王茶姬账号*****
用户昵称(138****1234)登录成功~
新版-签到成功!已连续签到7天
当前积分:1580
2积分将在2025-5-31过期
五、声明
- 本代码仅用于学习微信小程序API调用规范
- 禁止用于任何商业用途
- Token等敏感信息需自行保管
- 频繁请求可能导致账号风控
技术要点总结:动态签名生成 | 多账号隔离 | 微信小程序接口逆向