Hermes 技能包:北京交警进京证官方接口 + 抓包授权 + 配置抽取 + 六环外自动续期。接口清单:apis.json;人类可读摘要:node scripts/api-catalog.js md。
vId、身份证 sfzmhm、车牌 hphm
Authorization
敏感信息只存 Hermes Secret Store,禁止写入仓库或对话明文。
| 能力 | 状态 | 脚本/接口 |
| --- | --- | --- |
| 抓包获取 Authorization | 已实现 | capture-auth-bridge.js + mitm/jinjing_capture.py |
| 查询状态 + 车辆列表 + 身份证 | 已实现 | POST .../stateList → official-query-tool.js |
| 抽取 vId / hphm / sfzmhm | 已实现 | extract-permit-profile.js |
| 提交办理(六环外) | 已实现 | POST .../insertApplyRecord → official-submit-tool.js |
| 自动续期 + 幂等 + 通知 | 已实现 | renewal-runner.js |
| 接口发现(补全未知 API) | 已实现 | api-discovery-monitor.js + mitm/jinjing_discover.py |
| 驾驶人姓名 jsrxm | 已发现 | cardInfo / applyDetail 响应(有证时) |
| 进京证图片下载 | 已实现 | cardInfo → tphtml / qrCode + download-permit-image.js |
| 用户车辆详情 | 已发现 | vehicleController/getUserIdInfo |
| 交互式抓包(你操作我监控) | 已实现 | capture-session.js + mitm 三插件 |
基础域名:https://jjz.jtgl.beijing.gov.cn:2443
公共请求头:Authorization、Host、Content-Type: application/json、X-Requested-With: com.zcbl.bjjj_driving、Origin
| ID | 方法 | 路径 | 作用 | 关键字段 |
| --- | --- | --- | --- | --- |
| stateList | POST | /pro//applyRecordController/stateList | 状态查询 + 车辆/身份 | 请求 {};响应 data.sfzmhm、data.bzclxx[].vId、data.bzclxx[].hphm、bzxx/ecbzxx |
| insertApplyRecord | POST | /pro//applyRecordController/insertApplyRecord | 提交办理 | 请求 vId,hphm,sfzmhm,jsrxm,... |
| cardInfo | POST | /pro//applyRecordController/cardInfo | 进京证图片 | data.tphtml、data.qrCode、data.jsrxm |
| historyCardInfo | POST | /pro//applyRecordController/historyCardInfo | 历史证图片 | 建议带 vId/hphm |
| getUserIdInfo | POST | /pro//vehicleController/getUserIdInfo | 身份+车辆列表 | data[].sfzmhm、vId、hphm |
| applyDetail | POST | /pro//applyRecordController/applyDetail | 办理详情 | jsrxm、jszh |
| auth_capture | 本地 | mitmweb + 插件 | Authorization | 18767 / 18768 / 18769 |
配置字段来源(推荐顺序):
JINJING_AUTH:stateList 请求头 Authorization(mitmweb 抓包)
JINJING_CARD:stateList → data.sfzmhm
JINJING_VID / JINJING_HPHM:stateList → data.bzclxx[] 按车牌匹配
JINJING_JSRXM:对话询问,或办理页抓包发现后写入
# 查看完整 API 清单
node scripts/api-catalog.js
node scripts/api-catalog.js md
# 用已有 Authorization 抽取车辆与身份证
$env:JINJING_AUTH = "<Authorization>"
node scripts/extract-permit-profile.js
cd beijing-entry-permit
npm install
# 终端 A:等待 Authorization
$env:JINJING_AUTH_MODE = "capture"
node scripts/capture-auth-bridge.js
# 终端 B:mitmweb(含抓包 + 接口发现)
$env:JINJING_CAPTURE_HOOK_URL = "http://127.0.0.1:18767/v1/capture"
$env:JINJING_DISCOVERY_HOOK_URL = "http://127.0.0.1:18768/v1/discover"
npm run auth:mitmweb
# 手机代理 -> 本机IP:8080,App 打开进京证刷新后:
$env:JINJING_QUERY_COMMAND = "node scripts/official-query-tool.js"
$env:JINJING_TOOL_PAYLOAD = '{"auth":"<Authorization>"}'
node scripts/official-query-tool.js
授权子技能(可选独立安装):../beijing-entry-auth-token → get-auth-token.js。
# 查看完整会话说明(含要在 App 里点的页面)
npm run capture:session
# 开四个终端(或合并 mitm + 三个监听):
npm run auth:capture # 18767 Authorization
npm run api:discover # 18768 接口发现 -> .jinjing-api-discovery.jsonl
npm run media:capture # 18769 图片自动落盘 -> downloads/captured-media
npm run auth:mitmweb # 8080 代理 + http://127.0.0.1:8081
# 你操作完 App 后,拉取进京证图片:
$env:JINJING_AUTH = "<Authorization>"
$env:JINJING_VID = "<vId>"
$env:JINJING_HPHM = "<车牌>"
npm run image:download
App 内建议操作顺序: 进京证首页 → 电子证件/办证记录 → 车辆管理 → 有「查看图片」则点开。
运行前需要准备以下变量:
| 变量 | 含义 | 必填 |
| --- | --- | --- |
| JINJING_AUTH | 进京证服务授权密钥 | 是 |
| JINJING_CARD | 申请人身份证号码 | 是 |
| JINJING_HPHM | 车牌号码 | 办理时必填 |
| JINJING_VID | 车辆唯一 ID | 办理时必填 |
| JINJING_JSRXM | 驾驶人姓名 | 办理时必填 |
| WEWORK_WEBHOOK | 企业微信机器人地址 | 通知时必填 |
| NOTIFY | 是否通知,1 通知,0 不通知 | 否,默认 1 |
| JINJING_PERMIT_TYPE | 进京证类型 | 否,默认 outside_sixth_ring |
| JINJING_RENEW_BEFORE_DAYS | 剩余多少天内触发续期 | 否,默认 1 |
| JINJING_SCHEDULE | Hermes 宿主定时表达式 | 否,由宿主解释 |
| JINJING_NOTIFY_CHANNEL | 通知渠道 | 否,默认 wework |
| JINJING_LOGIN_URL | 远程授权登录入口 | 否,默认进京证业务统一认证 URL |
| JINJING_LOGIN_PHONE | 登录手机号(可选,仅提示用) | 否 |
| JINJING_AUTH_MODE | capture(默认)/ paste / simple / sms | 否 |
| JINJING_CAPTURE_PORT | mitm 插件推送 Authorization 的端口 | 否,默认 18767 |
| JINJING_MITM_PORT | mitmproxy 监听端口 | 否,默认 8080 |
| JINJING_AUTH_PASTE | 已从 mitmweb 复制的 Authorization(paste 模式) | 否 |
| JINJING_AUTH_SIMPLE_PORT | 浏览器简易模式粘贴端口 | 否,默认 18766 |
| FEISHU_WEBHOOK | 飞书/企微机器人 Webhook(发文字说明) | 否 |
| JINJING_AUTH_TIMEOUT_MS | 等待 token 超时 | 否,默认 15 分钟 |
| JINJING_AUTH_DEBUG | 1 时向 stderr 输出调试信息 | 否 |
| JINJING_AUTH_URL_PATTERN | 匹配请求 URL 以捕获 Authorization(高级) | 否 |
| JINJING_AUTH_COMMAND | 自动刷新授权的外部命令 | 否,有则优先调用 |
| JINJING_STATE_PATH | 本地 runner 状态文件路径 | 否,仅脚本模式使用 |
| JINJING_QUERY_ENDPOINT / JINJING_QUERY_COMMAND | 查询工具入口 | 宿主未直接提供 tool 时必填其一 |
| JINJING_SUBMIT_ENDPOINT / JINJING_SUBMIT_COMMAND | 办理工具入口 | 宿主未直接提供 tool 时必填其一 |
如果用户只要求“查询状态”,可以只要求 JINJING_AUTH 和 JINJING_CARD。如果用户要求“办理”,还必须确认 JINJING_HPHM、JINJING_VID、JINJING_JSRXM。
本技能包含 package.json 和 package-lock.json。默认授权方式为 mitmproxy 抓包,无需 Chromium。 仅在使用 JINJING_AUTH_MODE=simple|sms 时需要 Playwright:
npm install
npx playwright install chromium
常用脚本:
npm run api:catalog
npm run profile:extract
npm run auth:capture:setup
npm run auth:mitmweb
npm run api:discover
npm run renew
npm test
当用户要求“开启六环外进京证自动续期”且配置缺失时,Hermes 应逐项询问缺失字段,并将结果写入 Hermes 安全配置或 Secret Store。不要把授权资料写入仓库、计划文件或 Skill 文件。
建议授权顺序:
JINJING_AUTH:进京证服务授权密钥。
JINJING_CARD:申请人身份证号码。
JINJING_HPHM:车牌号码。
JINJING_VID:车辆唯一 ID。
JINJING_JSRXM:驾驶人姓名。
WEWORK_WEBHOOK:企业微信群机器人 Webhook,可跳过。
辅助脚本 scripts/auth-config.js 提供了缺失字段识别、授权问题生成和脱敏展示函数。Hermes 宿主可以调用这些函数来驱动对话式授权,保存时应使用宿主自己的 Secret Store。
进京证业务的北京市统一身份认证入口为:
https://bjt.beijing.gov.cn/renzheng/open/m/login/goUserLogin?client_id=100100001423&redirect_uri=https%3A%2F%2Fssp.jtgl.beijing.gov.cn%2Fsso%2Fcallback%2Fuserauth&response_type=code&scope=user_info&state=100009
Hermes 可以通过 scripts/remote-login-url.js 展示该 URL,引导用户在已配置 mitmproxy 的手机或 WebView 中完成登录。用户登录后进入北京交警进京证页面,Hermes/运维工具从 stateList 请求中提取 Authorization header,并保存为 JINJING_AUTH。
如果宿主有独立的授权刷新脚本,可设置 JINJING_AUTH_COMMAND。scripts/renewal-runner.js 每次执行前会先调用该命令,命令可以输出纯 token,或输出 JSON:
{"auth":"authorization-value"}
刷新失败时不得继续提交办理,应提示用户重新远程授权。
node ..\beijing-entry-auth-token\scripts\get-auth-token.js(默认 capture 模式)
npm run auth:mitmweb(推荐 mitmweb,含接口发现插件)
jinjing_capture.py 将 stateList 的 Authorization POST 到 http://127.0.0.1:18767/v1/capture
说明 JSON:npm run auth:capture:setup
不要用 SSO 登录页 URL 的 ?token= 作为 JINJING_AUTH(查询会 401)。
其他模式:paste(手动粘贴 Authorization)、simple(本地浏览器)、sms(遗留)。
$env:JINJING_AUTH_COMMAND = "node `"..\beijing-entry-auth-token\scripts\get-auth-token.js`""
敏感信息不落盘到仓库;JINJING_AUTH 应写入宿主 Secret Store。
自动续期默认办理 outside_sixth_ring 类型。Hermes 定时器触发后应执行 scripts/renewal-runner.js 或调用其中的 runRenewal():
scripts/parse-status.js 解析状态并判断动作。
remainDays > JINJING_RENEW_BEFORE_DAYS 时不提交。
审核中 或 审核通过(待生效) 的二次证件时不重复提交。
Hermes 宿主推荐每天固定时间触发一次,例如早上 08:30。具体 JINJING_SCHEDULE 语法由 Hermes 宿主解释;本技能只要求定时触发同一个 runner 或同一套工具契约。
原流程包含以下主要节点:
进京证办理状态-插件:用 auth、card 查询当前进京证状态,返回 bzxxResut、ecbzxxResult 和 code。
进京证办理状态-数据提取:解析当前证件、二次证件、剩余天数、下一步状态和失败原因。
判断器-是否该办理进京证:根据查询结果决定是展示状态、等待复查、还是办理新证。
进京证办理-插件:用 auth、card、hphm、vId、jsrxm 提交办理申请。
判断进京证办理执行结果:根据办理接口 code 判断提交成功、失败或待后续处理。
企业微信 webhook:将最终消息发送到企业微信群。
流程等待:等待 5 分钟后再次查询状态。
查询状态返回两个对象:
bzxxResut:当前进京证信息
ecbzxxResult:二次进京证信息或待生效/审核中信息
解析逻辑:
function parsePermitStatus({ data1, data2 }) {
const result = {
result1: undefined,
result2: undefined,
rdata1: undefined,
rdata2: undefined,
remainDays: undefined,
nextNode1: undefined,
nextNode2: undefined,
failedMsg: undefined
};
if (data1) {
result.rdata1 = data1.data;
result.result1 = data1.result;
result.remainDays = data1.remainDays;
result.failedMsg = result.rdata1 && result.rdata1.shsbyyms;
if (result.rdata1 && result.rdata1.blztmc === "审核通过(待生效)") {
result.nextNode1 = 2;
} else if (result.rdata1 && result.rdata1.blztmc === "审核中") {
result.nextNode1 = 1;
} else if (result.rdata1 && result.rdata1.blztmc === "失败(审核不通过)") {
result.nextNode1 = 4;
} else {
result.nextNode1 = null;
}
}
if (data2) {
result.rdata2 = data2.data;
result.result2 = data2.result;
result.failedMsg = data2.shsbyyms || result.failedMsg;
if (result.rdata2 && result.rdata2.blztmc === "审核通过(待生效)") {
result.nextNode2 = 2;
} else if (result.rdata2 && result.rdata2.blztmc === "审核中") {
result.nextNode2 = 1;
} else if (result.rdata2 && result.rdata2.blztmc === "失败(审核不通过)") {
result.nextNode2 = 4;
} else {
result.nextNode2 = null;
}
}
return result;
}
注意:原 FastGPT 代码中处理 data2 的失败分支时误用了 rdata1.blztmc 并写入 nextNode1。这里已修正为判断 rdata2.blztmc 并写入 nextNode2。
查询完成后按以下规则判断下一步:
code === 0 且 remainDays > JINJING_RENEW_BEFORE_DAYS:
```text
【当前进京证信息】
{result1}
```
nextNode2 === 2:
```text
【当前进京证信息】
{result1}
【待生效进京证信息】
{result2}
```
nextNode2 === 1:
```text
【当前进京证信息】
{result1}
【审核中进京证信息】
{result2}
```
nextNode2 === 4:
```text
【当前进京证信息】
{result1}
【失败进京证信息】
{failedMsg}
```
当需要办理时,调用“进京证办理”能力,传入:
auth: JINJING_AUTH
card: JINJING_CARD
hphm: JINJING_HPHM
vId: JINJING_VID
jsrxm: JINJING_JSRXM
permitType: JINJING_PERMIT_TYPE,默认 outside_sixth_ring
办理接口返回 code 和 result 后:
code === 0:
```text
【到达进京证办理日期,自动办理】
进京证已提交申请,请耐心等待,1-10分钟后会收到办理结果通知!
```
code === 3 或其他非成功状态:
```text
【办理进京证回执】
{result}
```
如果 NOTIFY 未设置或值为 1,且 WEWORK_WEBHOOK 存在,则向企业微信机器人发送最终消息。
企业微信消息体建议使用:
{
"msgtype": "text",
"text": {
"content": "{message}"
}
}
如果没有 WEWORK_WEBHOOK,不要阻塞主流程,只需把消息返回给用户,并提示“未配置企业微信 webhook,已跳过通知”。
bzxxResut 和 ecbzxxResult。
NOTIFY=1,调用企业微信 webhook 发送消息。
本技能支持由 Hermes 宿主提供工具,也提供从 FastGPT HTTP 节点提取出的官方命令适配器。接入 Hermes 时应提供以下任一形式的工具:
query_beijing_entry_permit_status(auth, card, requestCount)
submit_beijing_entry_permit(auth, card, hphm, vId, jsrxm, permitType)
如果只有 HTTP API,请将其包装为脚本或工具,并保持返回字段兼容:
状态查询返回:
{
"code": 0,
"bzxxResut": {},
"ecbzxxResult": {}
}
办理申请返回:
{
"code": 0,
"result": "提交成功或失败原因"
}
本目录提供了以下脚本作为宿主接入参考:
scripts/permit-tools.js:支持 JINJING_QUERY_ENDPOINT、JINJING_SUBMIT_ENDPOINT、JINJING_QUERY_COMMAND、JINJING_SUBMIT_COMMAND,并把真实接口包装为兼容返回。
scripts/official-query-tool.js:根据北京交警 App 抓包形态封装官方状态查询接口 https://jjz.jtgl.beijing.gov.cn:2443/pro//applyRecordController/stateList,默认使用空 JSON 请求体 {},返回 code、bzxxResut 和 ecbzxxResult;如需旧 FastGPT 请求体,可设置 JINJING_QUERY_BODY_MODE=fastgpt。
scripts/official-submit-tool.js:根据 FastGPT HTTP 节点封装官方办理提交接口 https://jjz.jtgl.beijing.gov.cn:2443/pro//applyRecordController/insertApplyRecord,默认地区/道路参数来自原工作流,可用环境变量覆盖。
scripts/renewal-runner.js:面向 Hermes 定时器的自动续期入口,支持查询、提交、复查、通知和幂等审计。
scripts/renewal-state.js:每车每续期窗口的状态记录,状态中只保存哈希和脱敏审计信息。
官方命令适配器配置示例:
$env:JINJING_QUERY_COMMAND = "node `"scripts/official-query-tool.js`""
$env:JINJING_SUBMIT_COMMAND = "node `"scripts/official-submit-tool.js`""
审核中:不要重复提交办理申请,应等待后再查。
审核通过(待生效):不要重复提交办理申请,只返回待生效信息。
失败(审核不通过):返回失败原因,并要求用户确认是否修正材料后重新办理。
401 且提示“令牌为空,请重新登录”:说明 JINJING_AUTH 不是当前官方接口可用的完整 authorization,需要重新登录获取;此时返回 query_failed,不得提交办理。
完成技能迁移后,应能验证以下事项:
/beijing-entry-permit 或自然语言请求加载本技能。
permitType=outside_sixth_ring 传给提交工具。
共 1 个版本