Qoder签到助手(每日自动签到 · 接口直签)
Qoder(含 QoderWork CN / 通义灵码系)的「领取积分」本质是一次带本机登录 Token 的 HTTP 接口请求,
不需要模拟点击桌面客户端右上角的浮窗(自动化代理也没有点击桌面 UI 的能力)。
机制:Qoder 的「专属活动权益 · 每天领 100 Credits」
是 Campaign 体系,每天 10:00(UTC+8)服务端生成一个新的活动实例(新 campaignId),当天可领一次,
领取后 30 天有效。因此:
- 必须先 GET 当日列表拿到当天的 campaignId,再 POST claim。用昨天的 id 重放永远是
replayed=true(幂等,不重复发放)。 - 请求必须带
Cosy-Machine*机器指纹头(由客户端自带的resources/umid/runtime-info.exe实时生成): - 不带指纹 → 服务端软性反爬,GET 列表返回空数组(看起来像"没有活动",极具误导性);
- 伪造指纹 → 新领取被风控拦截,
503 RISK_DEPENDENCY_UNAVAILABLE。 - 另有一套 Activity 体系(
/api/v2/activity/claim/eligibility+/api/v2/activity/claim),
对 CN1.0 会话(login_source=qodercn)被服务端禁用(返回 data:[])。脚本也会尝试,对可用账号生效。
本 Skill 会同时尝试两套体系,并以服务端真实返回为准:有可领就领,无则可领就如实报告。
本 Skill 自带两个脚本,依赖极少(Python 3.8+ 标准库 + cryptography,后者用于解密登录态,WorkBuddy 托管 Python 已内置):
scripts/qoder_checkin.py:核心签到脚本(定位 token → 生成机器指纹 → 查/领当日活动 → 通知)。scripts/discover_qoder.py:只读探测本机 Qoder 登录态、域名与runtime-info.exe位置,输出可用配置片段。
关键事实(需一次性确认,见「首次搭建」)
- 登录态位置(关键:新版/旧版两种来源,脚本都会试):Qoder 桌面端为 Electron 应用,同一个数据目录下可能存在两种登录态文件,都用同一把密钥加密(Chromium OSCrypt:v10 + AES-256-GCM;密钥在同目录
Local State的os_crypt.encrypted_key,Windows 走 DPAPI): - A. 旧客户端:
User/globalStorage/state.vscdb里的secret://aicoding.auth.userInfo; -
B. 新版客户端(当前主流):数据目录根下的
auth.v1.dat。解密后是明文 JSON:{"schemaVersion":1,"token":"dt-…","refreshToken":"drt-…","expiresAt":…,"refreshTokenExpiresAt":…,"user":{id,name,email,phone}}。新版客户端目录里没有
state.vscdb(只有Local State+main.sqlite+auth.v1.dat+auth.machine-id),登录态不在
main.sqlite里,也不在 Windows 凭据管理器里 —— 只在auth.v1.dat。本机可能同时存在多个目录,只有一个是活跃的(旧目录是死数据)。脚本会遍历所有候选目录、同时尝试上面两种来源,按来源文件修改时间取最新;候选顺序:
%APPDATA%\com.qodercn.app.stable(新版 CN 客户端主目录)、%APPDATA%\QoderCN、%APPDATA%\Qoder、QoderWork CN等。
- 域名按客户端目录自动选择(最关键,选错必然 401):
- CN 客户端(com.qodercn.app.stable/QoderCN,login_source=qodercn)→https://openapi.qoder.com.cn;
- 其余目录(国际/旧版)→https://openapi.qoder.sh。
- 用 CN 会话的 token 访问.sh域 → 401TOKEN_EXPIRE;访问.com.cn→ 200。两个域是两套独立部署、会话不互通。
- 机器指纹Cosy-Machine*(最关键,缺了它必然"看不到活动"):每个请求都要带
User-Agent: Qoder、Cosy-ClientType: 10、Cosy-Version: 0.3.3、Cosy-MachineOS,
以及 Cosy-MachineToken / Cosy-MachineCode / Cosy-MachineType / Cosy-MachineId。
指纹由 Qoder 安装目录自带的原生二进制生成(阿里 securityguard 设备指纹 SDK):
<Qoder安装目录>\resources\umid\runtime-info.exe,调用方式与客户端完全一致:
echo {"account":"<账号>"} | runtime-info.exe <environment> --account-stdin
# 或 Python: subprocess.run([exe, "x", "--account-stdin"],
# input=json.dumps({"account": acct}) + " ", capture_output=True, text=True)
# stdout 首行第一个空格前的 JSON = {machineToken, machineType, machineCode, vmInfo, accountOutcome}
脚本会自动定位该二进制:配置 umid_path → 环境变量 QODER_UMID_PATH → 运行中的 Qoder 进程目录 → 已知安装根(含 %LOCALAPPDATA%\Programs、Program Files)下探 2 层。
- 鉴权方式:请求头 Authorization: Bearer <token>(dt- 开头的设备令牌;drt- 为刷新令牌)。
- 两套可领积分接口(脚本都会尝试,以服务端为准):
- A. Campaign(每日主链路「每天领 100 Credits」):
`GET /sash/api/v1/me/campaigns` → `{uid, showCampaign, claimable, campaigns:[{campaignId, campaignKey, actionType, claimStatus, benefit}]}`;
`POST /sash/api/v1/me/campaigns/<campaignId>/claim` → `{status:"CLAIMED", replayed:bool, grantedAt, expiresAt, benefit:{kind:"CREDITS", amount:100, validity:{mode:"RELATIVE_DAYS", days:30}}}`。
- **可领判据:`actionType == "CLAIM_BENEFIT"` 且 `claimStatus == "CLAIMABLE"`**(不要用顶层 `claimable`,也不要用 `c.claimable`,这两个不可靠)。
- `replayed=false` = 本次新领取;`replayed=true` = 已领过(幂等,不重复发放)。
- 每天 10:00(UTC+8)刷新,**每天是新的 `campaignId`**,所以必须当天先 GET 再 claim。
-
B. Activity(另一套签到体系,CN1.0 会话不可用):
GET /api/v2/activity/claim/eligibility→{code:0, data:[{activityId, canClaim, ...}]};POST /api/v2/activity/claim?activityId=<id>→{success:bool, ...}。CN1.0 会话(login_source=qodercn)被服务端禁用:eligibility 返回data:[]、claimActivity报 "not available for CN 1.0"。
- 余额:GET /api/v2/quota/usage→ 签到 Credits 落在addOnQuota.remaining(资源包)。
- token 可自行刷新(无需打开客户端):POST <openapi_base>/api/v1/deviceToken/refresh,头Authorization: Bearer <旧 dt->,体{"refresh_token":"<drt->"},返回{device_token, refresh_token, expires_at, refresh_token_expires_at}(约 30 天)。脚本在 token 过期或 401 时自动刷新,新 token 缓存到~/.workbuddy/scripts/.qoder_token_cache.json(600 权限,按数据目录隔离),不修改 Qoder 自己的登录态文件。
- 幂等性:当天已领取时列表里该 campaign 为claimStatus=CLAIMED(不再CLAIMABLE),脚本据此判定already_claimed,绝不重复发放;对同一 id 重复 POST claim 也是幂等重放(replayed=true),安全。
- 注意不要在沙箱里跑:runtime-info.exe运行时会调用reg.exe/sc.exe采集机器信息,若被安全策略拦截会导致指纹不完整(可能触发风控 503)。计划任务/自动化直接以普通进程运行即可。
自带脚本:scripts/qoder_checkin.py
配置文件(首次搭建后新建,不要提交到任何仓库)
路径:C:\Users\<user>\.workbuddy\scripts\qoder_checkin_config.json
{
"openapi_base": "",
"umid_path": "",
"cache_path": "",
"token": { "source": "auto" },
"notify": {
"enabled": false,
"success_notify": false,
"wecom_webhook": "",
"pushplus_token": "",
"bark_url": ""
}
}
openapi_base/umid_path一般留空:脚本会按登录态所在数据目录自动选域名(CN 客户端 →https://openapi.qoder.com.cn,其余 →https://openapi.qoder.sh),并自动定位 Qoder 自带resources/umid/runtime-info.exe生成机器指纹。仅在自动判断不符时才手动指定覆盖。token.source:auto(推荐,自动解密本机 Qoder 登录态,并在过期/401 时自行刷新)。- 自动解密需
cryptography库;原理:读取活跃数据目录Local State的os_crypt.encrypted_key(Windows DPAPI)解出 AES 密钥,再解state.vscdb的secret://aicoding.auth.userInfo或同目录根下的auth.v1.dat(两者都是 v10 + AES-GCM)。仅当完全没有实时登录态时才回退到缓存 token。 - 刷新得到的新 token 缓存到
~/.workbuddy/scripts/.qoder_token_cache.json(600 权限,含store_dir/account/known_campaign_ids),不写回 Qoder 自己的登录态(保持只读)。
逻辑(标准库 + cryptography)
- 遍历所有候选数据目录,每个目录尝试两种登录态来源(
User/globalStorage/state.vscdb与根下auth.v1.dat),按来源文件修改时间取最新的活跃账号;同目录未过期的缓存 token 优先复用;完全没有实时登录态时才回退缓存 token。 - 生成机器指纹:定位并调用
runtime-info.exe,取得machineToken/machineType/machineCode,组装Cosy-*请求头(拿不到指纹会在结果里明确标注machine_identity: unavailable)。 - 按目录自动选域名(CN 客户端 →
openapi.qoder.com.cn,其余 →openapi.qoder.sh);token 过期或接口 401 → 调/api/v1/deviceToken/refresh自行刷新 + 重新生成指纹,重试一次。 GET /sash/api/v1/me/campaigns(带 Cosy 头)取当日列表,筛出actionType=CLAIM_BENEFIT && claimStatus=CLAIMABLE的 campaign。- 对每个可领 campaign
POST /sash/api/v1/me/campaigns/<id>/claim:status==="CLAIMED"且replayed=false记为新领取;replayed=true记为已领过(幂等)。列表无「可领」但存在当日CLAIM_BENEFIT/CLAIMED时,报already_claimed(明确告知今日已领,而非"无活动")。 GET /api/v2/activity/claim/eligibility取 Activity 列表,对canClaim=true的逐个POST /api/v2/activity/claim?activityId=<id>领取。CN1.0 会话会返回空data:[],本步为空操作。GET /api/v2/quota/usage取余额(addOnQuota.remaining=资源包、userQuota.remaining=套餐内)。- action 取值:
claimed(新领取成功)/already_claimed(今日已领)/skip_no_claimable(确实无可领活动)/skip_check_only(仅查询)/claim_failed(领取被拒,如风控 503)/auth_failed(401 且刷新失败)/network_error/status_failed。 - 输出 JSON,全程不打印真实 token(仅脱敏
dt-xxxx...xxxx);退出码成功 0 / 失败 1。 - 跨平台桌面通知:领取后弹出系统级 toast;微信提醒(可选):
status!=ok时按notify配置推送,success_notify=true时播报成功。
运行(Python 3.8+)
WorkBuddy 代理自带托管 Python(~/.workbuddy/binaries/python),无需额外安装。
独立运行需本机有 Python 3.8+。
# 完整签到(自动定位 token + 生成机器指纹 + 领取当日活动)
python "<技能安装目录>/scripts/qoder_checkin.py"
# 仅查询(只读,不领取):追加 --check-only
# 跳过推送(调试):追加 --no-notify
# 强制刷新 token:追加 --force-refresh
# 只读探测本机登录态/域名/umid 位置(不改任何文件):python scripts/discover_qoder.py
调用本 Skill 时的首次搭建流程(照做即可)
- 探测登录态与域名
- 用 Bash 运行python scripts/discover_qoder.py,它会只读列出本机 Qoder 相关目录、逐一说明每个目录的state.vscdb(旧客户端)与auth.v1.dat(新版客户端)是否存在、猜测 API 域名,并输出一段建议配置。
- 判定标准:只要任一目录里state.vscdb或auth.v1.dat存在,且该目录有Local State,即可正常自动解密,无需任何手工步骤。
- 若输出「未发现任何可用的登录态文件」:请先在本机安装并登录 Qoder 桌面端(打开客户端登录一次即可),再重跑。 -
验证跑通(通常 1 分钟,无需 DevTools 抓包)
- 脚本会自动解密登录态(state.vscdb或auth.v1.dat)、自行刷新 token(POST /api/v1/deviceToken/refresh)、并自动生成本机机器指纹,不需要打开客户端,也不需要手动复制 token。
- 跑python qoder_checkin.py --check-only:看token_source里是否带上真实来源,例如qoder-store:…\com.qodercn.app.stable[auth-file:auth.v1.dat](account=…);machine_identity为ok(...)且campaigns_http=200即链路完全打通。
- 若token_source报「未找到/解密失败」:说明该机器上确实没有可解密的登录态 → 打开一次 Qoder 客户端完成登录后重跑;不要去折腾 Windows 凭据管理器或手工"播种"(那是不必要的弯路,见排错)。
- 若machine_identity=unavailable:说明没找到/没能执行runtime-info.exe,此时大概率campaign_count=0(服务端返回空列表)——请在配置里用umid_path指定路径,或确认 Qoder 客户端已安装。
- 仅当返回auth_failed(401 且刷新也失败)时,才需要在 Qoder 客户端重新登录一次,让本机登录态恢复。
3. 确认脚本与配置路径
- 脚本随技能一起安装,位于<技能安装目录>/scripts/qoder_checkin.py,自动化直接引用该路径即可,无需复制。
- 新建C:\Users\<user>\.workbuddy\scripts\qoder_checkin_config.json:openapi_base/umid_path留空即自动判断,按需填写notify。
- 跑一次--check-only验证 token 有效、机器指纹可用、接口通(应返回campaigns_http、machine_identity与是否今日已签)。
4. 创建 WorkBuddy 自带自动化(不要用 crontab / launchd / 第三方定时器)
- 用automation_update(mode=create)创建 recurring 自动化:
- name:Qoder签到助手 · 每日自动签到
- rrule:FREQ=DAILY;BYHOUR=10;BYMINUTE=5(每日 10:05,避开 Qoder 每日 10:00 开放领取的整点;可调整)
- status:ACTIVE
- 自动化提示词(让代理用 Bash 跑脚本并脱敏汇报):
请使用 Bash 工具运行以下命令,完成 Qoder签到助手(每日自动签到,接口直签,无需点击 GUI): python "C:/Users/<user>/.workbuddy/skills/totorosir-qoder-checkin/scripts/qoder_checkin.py" 若 python 命令不可用,改用 WorkBuddy 自带托管 Python(按本机实际用户名替换 <user>): C:/Users/<user>/.workbuddy/binaries/python/versions/*/python 执行后,根据脚本输出的 JSON 结果,用一句话向用户汇报: - action=claimed:签到成功,新领取活动奖励(附 campaignKey;若含 balance 字段则附「余额:资源包 XXX」)。 - action=already_claimed:今日已领取过(附余额),不会重复发放,无需操作。 - action=skip_no_claimable:当前无可领取的签到活动(活动未到开放时间或今日已领完),属正常(附余额)。 - action=skip_check_only:仅查询完成,汇报可领活动数与余额。 - action=claim_failed:领取被拒(如风控 503),如实报告 msg,并检查 machine_identity 是否为 ok。 - action=auth_failed 或 status=error:如实报告 msg 中的失败原因,不得谎报成功。 注意:结果里若 machine_identity=unavailable,说明未取到本机机器指纹,服务端会返回空活动列表, 请如实说明并在汇报中提示用户检查 Qoder 安装是否完整(或配置 umid_path)。 约束: 1. 严禁在任意输出中打印 token / accessToken / refreshToken。 2. 不要无限重试;脚本内部最多重试 1 次即可。 3. 若 status=error,脚本会自动向微信推送失败提醒(前提是已配置 notify);你仍需在对话中如实报告失败原因,并提示检查 Qoder 是否已登录、电脑是否联网、是否在 10:05 前后保持开机。
- 把上面的<user>替换为本机实际用户名。 -
向用户汇报:自动化名称、执行时间、脚本与配置路径;并提醒"若当天已手动签到会自动跳过;首个真实自动领取通常在次日 10:05,请到 Qoder 用量面板核对 +100 Credits"。
微信提醒(可选)
推送密钥只存在于本地 qoder_checkin_config.json,永不进入脚本或技能目录,避免泄露。支持的通道与 WorkBuddy签到助手一致:
- 企业微信群机器人 Webhook(推荐):
notify.wecom_webhook。 - PushPlus(推送到个人微信):
notify.pushplus_token。 - Bark(iOS):
notify.bark_url。
行为约定:enabled=false 或配置文件不存在 → 不推送;失败推送仅在 status!=ok;成功播报仅当 success_notify=true;--check-only 纯查询不推送;--no-notify 跳过全部推送。
安全约束(务必遵守)
- 只读登录态文件,绝不修改、删除、外传
accessToken/refreshToken。 - 任何输出(终端、日志、汇报)都不得包含真实 token;脚本已脱敏,代理也不要回显凭据。
- 本 Skill 只用 WorkBuddy 自带自动化(recurring 自动化)完成每日签到;若需要系统级定时任务(脱离 WorkBuddy 也能跑),请单独封装一份「分享包」,与本 Skill 互不冲突。
- 不要伪造或猜测登录态;若文件不存在或 token 失效,如实告知用户"请先在 Qoder 客户端登录"。
排错
token_source报「未找到/解密失败」且status=error:脚本在两个地方都没找到可解密的登录态。排查顺序(照做,别跳步):
1. 跑discover_qoder.py,确认至少一个目录里state.vscdb或auth.v1.dat存在,且同目录有Local State;
2. 都没有 → 说明该机器没登录过,或客户端刚安装还没登录 → 打开 Qoder 客户端登录一次后重跑;
3. 若Local State在但两个登录态文件都不在 → 检查客户端是否被装在非标准目录(Qoder CN 新版目录名是com.qodercn.app.stable,旧版是QoderCN)。- ⛔ 不要走的两条弯路:
- Windows 凭据管理器:凭据里可能看到
vscodealibaba-cloud.tongyi-lingma/cosyAuthSecret之类的条目,那是通义灵码 VS Code 扩展的 keytar 条目(且可能是用另一套 DPAPI 主密钥保护、CryptUnprotectData返回ERROR_INVALID_DATA(13)解不开的死数据),与 Qoder CN 客户端的登录态无关。Qoder 的 token 始终在state.vscdb/auth.v1.dat里。 - 手工"播种"缓存 / 让用户手动跑一次:完全没有必要。
auth.v1.dat用的就是脚本已有的同一套解密逻辑(Local State密钥 + AES-256-GCM),在 WorkBuddy 沙箱里也能正常解密。 - 判据:同一进程若
Local State的 DPAPI 能解开(len=32),却"解不开凭据管理器里的 blob",那就不是权限问题,而是那些凭据本就不是你要的东西。 campaign_count: 0(列表为空)但客户端弹窗明明显示「领取」:九成是机器指纹问题。检查结果里的machine_identity是否为ok(...);若为unavailable,说明没找到或没能执行resources/umid/runtime-info.exe→ 用配置umid_path指定路径后重跑。claim_failed+ HTTP 503RISK_DEPENDENCY_UNAVAILABLE:风控拦截,指纹不合法。可能是伪造/过期指纹,或runtime-info.exe被安全策略限制了reg.exe/sc.exe采集。以普通进程(非受限沙箱)重跑;必要时在客户端里手动领一次确认账号正常。auth_failed(401 且刷新失败):先看输出里的openapi_base与登录态目录是否匹配(CN 客户端必须用https://openapi.qoder.com.cn,.sh域与.com.cn域会话不互通)。域名正确仍失败,说明存储的 token 已被客户端轮换作废——打开一次 Qoder 客户端(它会刷新登录态)后重跑。- 拿昨天的 campaignId 去重试,永远
replayed=true:正常。每天 10:00 会生成新的 campaignId,必须当天先 GET 列表再 claim,不要复用旧 id 判断"今天能不能领"。 - 客户端升级后活动"消失":客户端换数据目录会导致读错登录态。当前活跃目录是
%APPDATA%\com.qodercn.app.stable,脚本已内置;若仍不对,检查输出里的token_source指向哪个目录。 already_claimed/skip_no_claimable:今日已领取 / 当前无可领活动,属正常,非错误。HTTP 404:路径错了,确认用的是/sash/api/v1/me/campaigns(/<id>/claim)。- 自动化到点没跑:检查电脑是否开机、是否联网、是否在指定时间(每日 10:05)前后保持开机。
备注:Qoder CLI 无 claim 命令
Qoder.exe(~/.qoder/shared_client/bin/<ver>/x86_64_windows/)的子命令只有
status / version / start / start-remote-agent / machine-info / import-data / profiler / uninstall / completion,
没有 claim / auth 之类的签到或取 token 命令。因此自动化应直接调用本脚本,不要依赖 CLI。
关于作者
本技能由 TOTORO(totorosir)开发维护;相关更新、用法答疑与实战笔记发布于公众号 龙猫科技说。