霸王茶姬微信小程序自动化签到系统完整实现解析

news2025/5/10 17:23:50

霸王茶姬微信小程序自动化签到系统完整实现解析

技术栈:Node.js + 微信小程序API + MD5动态签名

一、脚本全景架构

在这里插入图片描述

功能模块图

主入口
多账号轮询
Token验证
用户信息获取
新版签到
积分查询
结果推送

代码目录

  1. 核心配置
  2. 主流程控制
  3. 登录验证模块
  4. 签到功能实现
  5. 积分管理系统
  6. 安全签名机制

二、完整代码实现

核心配置

/**
 * 霸王茶姬自动化任务脚本
 * 环境变量格式: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. 签名安全机制

原始参数
字母序排序
拼接查询字符串
添加动态盐值
MD5加密
最终签名

3. 智能签到流程

  1. 先查询签到状态(避免重复签到)
  2. 未签到时生成动态签名
  3. 提交签名请求
  4. 失败自动重试(代码已内置)

四、使用指南

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过期

五、声明

  1. 本代码仅用于学习微信小程序API调用规范
  2. 禁止用于任何商业用途
  3. Token等敏感信息需自行保管
  4. 频繁请求可能导致账号风控

技术要点总结:动态签名生成 | 多账号隔离 | 微信小程序接口逆向

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2372480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

p2p虚拟服务器

ZeroTier Central ✅ 推荐工具&#xff1a;ZeroTier&#xff08;免费、稳定、跨平台&#xff09; ZeroTier 可以帮你把多台设备&#xff08;无论是否跨网&#xff09;加入一个虚拟局域网&#xff0c;彼此间可以像在同一个 LAN 中通信&#xff0c;UDP 视频、文件传输、SSH 等都…

python实现点餐系统

使用python实现点餐系统的增加菜品及价格&#xff0c;删除菜品&#xff0c;查询菜单&#xff0c;点菜以及会员折扣价等功能。 代码&#xff1a; 下面展示一些 内联代码片。 # coding utf-8menu {拍黄瓜: 6, 小炒肉: 28, 西红柿炒蛋: 18, 烤鱼: 30, 红烧肉: 38, 手撕鸡: 45,…

(三)毛子整洁架构(Infrastructure层/DapperHelper/乐观锁)

文章目录 项目地址一、Infrastructure Layer1.1 创建Application层需要的服务1. Clock服务2. Email 服务3. 注册服务 1.2 数据库服务1. 表配置Configurations2. Respository实现3. 数据库链接Factory实现4. Dapper的DataOnly服务实现5. 所有数据库服务注册 1.3 基于RowVersion的…

探索Stream流:高效数据处理的秘密武器

不可变集合 stream流 Stream流的使用步骤&#xff1a; 先得到一条Stream流&#xff08;流水线&#xff09;&#xff0c;并把数据放上去 使用中间方法对流水线上的数据进行操作 使用终结方法对流水线上的数据进行操作 Stream流的中间方法 注意1&#xff1a;中间方法&#xff0…

虚拟机ubantu20.04系统桥接模式下无法ping通外网,但可以ping通本机的解决方案

1.出现的问题&#xff1a; 虚拟机ubantu20.04系统桥接模式下无法ping通外网,但可以ping通本机。 2.解决方案&#xff1a; 如果 DHCP 未分配 IP 地址&#xff0c;可以手动配置静态 IP&#xff1a; 1.编辑网络配置文件&#xff1a; sudo nano /etc/netplan/01-netcfg.yaml 2…

日常知识点之随手问题整理(思考单播,组播,广播哪个更省带宽)

新入职的公司在某些场景下无脑使用组播技术&#xff0c;自己突然就意识到一个问题&#xff1a;单播&#xff0c;组播&#xff0c;广播&#xff0c;哪个更省带宽&#xff1f; 有所收获&#xff0c;做点笔记&#xff0c;仅仅是个人理解~ 1&#xff1a;简单理解 单播&#xff1…

qtcreater配置opencv

我配置opencv不管是按照网上的教程还是deep seek发现都有些问题&#xff0c;下面是我的配置方法以及实践成功的心得 电脑环境 windows平台qt6 下载 我这里直接提供官网下载地址&#xff1a;https://opencv.org/releases/ 我下载的是最新版&#xff0c;下载后是一个.exe文件…

机器学习-数据集划分和特征工程

一.数据集划分 API函数&#xff1a; sklearn.model_selection.train_test_split(*arrays&#xff0c;**options) 参数&#xff1a; - arrays&#xff1a;多个数组&#xff0c;可以是列表&#xff0c;numpy数组&#xff0c;也可以是dataframe数据框等 - options&#xff1a;&…

MySQL C API高效编程:C语言实现数据库操作的深入解析

知识点【MySQL C API】 1、头文件及MYSQL * 句柄 //头文件 #include <mysql/mysql.h>1、MYSQL MYSQL是一个结构体&#xff0c;封装了与数据库连接相关的所有状态&#xff0c;配置和数据。 2、MYSQL *的本质 类似于 FILE*&#xff0c;代表一个与数据库连接的通道&…

MySQL初阶:数据库约束和表的设计

数据库约束 数据库约束是针对数据库中的表中的数据进行施加规则和条件&#xff0c;用于确保数据的准确性和可靠性。 数据库约束类型 1&#xff09;not null 非空类型 &#xff1a;指定非空类型的列不能存储null&#xff0c;如果插入的数据是null便会报错。 2&#xff09;de…

LeetCode 解题思路 47(最长回文子串、最长公共子序列)

解题思路&#xff1a; dp 数组的含义&#xff1a; dp[i][j] 是否为回文子串。递推公式&#xff1a; dp[i][j] s.charAt(i) s.charAt(j) && dp[i 1][j - 1]。dp 数组初始化&#xff1a; 单字符 dp[i][i] true&#xff0c;双字符 dp[i][i 1] s.charAt(i) s.charA…

嵌入式培训之C语言学习完(十七)结构体、共用体、枚举、typedef关键字与位运算

目录 一、结构体&#xff08;struct关键字&#xff09; &#xff08;一&#xff09;声明一个结构体数据类型 &#xff08;二&#xff09;结构体的成员初始化与赋值 a、结构体变量赋值 b、结构体成员初始化 c、结构体的定义形式 &#xff08;三&#xff09;考点&#xff…

《软件项目经济性论证报告模板:全面解析与策略建议》

《软件项目经济性论证报告模板:全面解析与策略建议》 一、引言 1.1 项目背景阐述 在数字化浪潮席卷全球的当下,各行业对软件的依赖程度日益加深。[行业名称] 行业也不例外,随着业务规模的不断扩张、业务复杂度的持续提升以及市场竞争的愈发激烈,对高效、智能、定制化软件…

关税冲击下,FBA国际物流企业如何靠智能拓客跑出增长“加速度”?

国际物流行业正迎来前所未有的增长机遇。据中研普华最新报告&#xff0c;2025年全球物流市场规模已突破6.27万亿美元&#xff0c;其中中国跨境物流市场预计达2.71万亿元。在全球化与数字化双轮驱动下&#xff0c;国际物流从“规模扩张”迈向“价值重构”。可以说&#xff0c;国…

vue源代码采用的设计模式分解

No.大剑师精品GIS教程推荐0地图渲染基础- 【WebGL 教程】 - 【Canvas 教程】 - 【SVG 教程】 1Openlayers 【入门教程】 - 【源代码示例 300】 2Leaflet 【入门教程】 - 【源代码图文示例 150】 3MapboxGL【入门教程】 - 【源代码图文示例150】 4Cesium 【入门教程】…

使用 JavaScript 实现数据导出为 Excel 和 CSV 文件

在 Web 开发中&#xff0c;经常会遇到需要将数据导出为文件的需求&#xff0c;例如将数据导出为 Excel 或 CSV 文件。今天&#xff0c;我们就来探讨如何使用 JavaScript 实现这一功能。 一、实现思路 我们通过 HTML 创建一个按钮&#xff0c;点击按钮时&#xff0c;触发 Java…

eNSP中路由器RIP协议配置完整实验实验和命令解释

一、实验拓扑 二、配置命令 R1配置并先测试一下连通性 R1、R2和R3接口配置完后再测试连通性&#xff0c;直连路由可通 启动RIP进程&#xff0c;宣告直连网络 查看路由表&#xff0c;测试连通性 环回接口配置 三、命令解释及注意事项 配置命令逐行解释 system-view: 从用户视…

密码学--AES

一、实验目的 1、完成AES算法中1轮加密和解密操作 2、掌握AES的4个基本处理步骤 3、理解对称加密算法的“对称”思想 二、实验内容 1、题目内容描述 &#xff08;1&#xff09;利用C语言实现字节代换和逆向字节代换&#xff0c;字节查S盒代换 &#xff08;2&#xff09;利…

Vue项目中实现自定义连线图

需求描述 在vue项目中实现由自定义块元素组成的连线图。效果图 实现思路 Leader-Line 是一个用于 Web 的轻量级 JavaScript 库&#xff0c;专为创建从一个元素指向另一个元素的引导线而设计。它提供了高度自定义的能力&#xff0c;使得开发者能够轻松地在网页上实现各种指引用…

C++编程语言:标准库:标准库概观(Bjarne Stroustrup)

第30章 标准库概观(Standard-Library Overview) 目录 30.1 引言 30.1.1 标准库设施 30.1.2 设计约束 30.1.3 描述风格 30.2 头文件 30.3 语言支持 30.3.1 对initializer_list的支持 30.3.2 对范围for的支持 30.4 异常处理 30.4.1 异常 30.4.1…