票根网开发票
在票根网(txffp.com)为指定 ETC 车牌开具通行费电子发票。
站点是强会话、强验证码的老式 Java 系统,全流程必须由浏览器自动化完成:
登录 → 个人中心 → 我要开票 → 选卡 → 选月 → 加载全部 → 按条件勾选 → 填邮箱 → 去开票 → 提交。
> ⛔ 不要凭记忆回答,也不要手写脚本从零调试。 本技能附带一套已实测跑通的引擎与脚本,直接按下面的阶段执行即可。
> 站点结构、选择器、坑点已记录在 references/site-map.md,排障时再读。
使用说明(推荐:邮箱 + 定时任务,一次配置长期自动开票)
> 推荐把本技能接入智能体邮箱 + 定时任务:每月自动把发票发到你的邮箱,无需手动操作。以下三步按顺序配置即可。
第 1 步:启用你的邮箱,并复制邮箱地址
在左侧「更多」>「我的邮箱」中启用自己的邮箱,然后复制自己的邮箱地址,例如:abc123@agent.qq.com。
这个地址就是开票时填写的发票接收邮箱,第 2 步的提示词里要用到。
第 2 步:创建定时任务
新建一个长期有效的定时任务,让它每月固定时间执行一次。
- 执行时间:建议设在每月 9 号到 15 号之间。
- 8 号之前无法开票(上月数据尚未出齐);
- 太晚可能会被系统自动开具,导致无票可开。
- 重复方式:选「每月」,并不设结束日期(长期有效)。
提示词内容如下(把尖括号部分替换为你自己的信息):
请执行“txffp-invoice”技能,使用以下账户信息完成票根网开票:
- 用户名:<您在票根网的用户名>
- 密码:<您在票根网的密码>
- 车牌号:<您的车牌号>
- 出入站:<你希望开发票的出入站>
- 发票接收邮箱:<您刚刚复制过来的邮箱地址>
> 补充:提示词里不写月份时,默认开具「当前月的前一个月」的发票;「出入站」不填则默认 河南郑新黄河大桥站。若你的发票有固定出入站(如日常固定走某条高速),在「出入站」处填对应站点即可。
第 3 步:确认任务状态为「开启」
创建后回到定时任务列表,确认该任务状态为「开启」。只有处于开启状态,任务才会按期自动执行。
手动执行(可选)
若某次想自己手动跑一遍,直接发送与第 2 步相同的提示词即可;还可额外加上月份参数(格式示例:202609)指定开具哪个月份,例如:
请执行“txffp-invoice”技能,使用以下账户信息完成票根网开票:
- 用户名:<您在票根网的用户名>
- 密码:<您在票根网的密码>
- 车牌号:<您的车牌号>
- 月份:202609
- 出入站:<你希望开发票的出入站>
- 发票接收邮箱:<您刚刚复制过来的邮箱地址>
一、参数规则(强制,开工前逐条核对)
| 参数 | 必填 | 缺失 / 未指定时的行为 |
|---|---|---|
username 用户名 |
是 | 停下来提示用户提供用户名,不得猜测 |
password 密码 |
是 | 停下来提示用户提供密码;不得从本地凭据文件或浏览器密码库获取,也不得猜测或暴破 |
plate 车牌号 |
是 | 停下来提示用户提供车牌号(形如 豫AF59097) |
month 开票月份 |
否 | 默认 当前月份的前一个月,格式 YYYYMM(例:当前 2026-10 → 202609) |
station 出入口信息 |
否 | 默认 河南郑新黄河大桥站 |
email 发票接收邮箱 |
是 | 停下来提示用户提供发票接收邮箱 |
| 匹配到的待开票记录 | — | 为 0 条时 → 直接终止操作,并提示用户:「未找到需要开票的通行信息」 |
补充约定:
- 只勾选「出入口信息含
station」且「开票情况为『待开票』」的记录;其他站点(如焦作黄河大桥站、文化路站等)与「已开票」记录一律不选。 - 缺失必填参数时,一次把缺的参数一起问清楚(用户名 / 密码 / 车牌号 / 邮箱),不要反复追问。
- 开票口径为按月合并开具(选中的多条记录合成 1 张发票)。
二、环境准备
两个运行时路径(若不存在,改用本机实际路径;node_modules 缺失时在 Node 工作区 npm i playwright-core):
NODE_BIN="C:/Users/Sean/.workbuddy/binaries/node/versions/22.22.2-6/node.exe"
NODE_MODULES="C:/Users/Sean/.workbuddy/binaries/node/workspace/node_modules"
SKILL_DIR="C:/Users/Sean/.workbuddy/skills/txffp-invoice"
为本轮任务建一个独立工作目录(所有中间文件都放这里;运行过程中不做清理):
WORKDIR="C:/Users/Sean/WorkBuddy/$(date +%Y-%m-%d-%H-%M-%S)/txffp-run" # 或任意临时目录
mkdir -p "$WORKDIR"
2.1 写配置(密码由调用方直接提供)
把下面内容写成 $WORKDIR/config.json:
{ "username": "<用户名>", "password": "<密码>", "headless": false }
- 密码只来自调用方在指令中给出的明文,写入
config.json的password字段。 - 本引擎不读取任何本地文件或浏览器凭据库(技能内不含凭据提取脚本)。
- 若
password为空 → 引擎以 exit code 3 退出,并向result.json写入"needsPassword": true;此时应停下来提示用户提供密码,不得尝试从本地获取或猜测。
三、执行
3.1 启动常驻浏览器代理(后台)
cd "$WORKDIR" && NODE_PATH="$NODE_MODULES" "$NODE_BIN" "$SKILL_DIR/scripts/browser_agent.cjs"
- 用
run_in_background方式启动。 - 代理会自动完成登录(含阿里云验证码,内置最多 5 次重试),随后进入命令轮询:读
cmd.json、把日志写result.json。 - 登录耗时约 40 秒。等待后检查
$WORKDIR/result.json出现"ready": true即为就绪。 - 若进程以 exit code 3 退出 → 没有可用密码,回到 2.1 处理。
3.2 下发一键开票指令
把下面 JSON 写成 $WORKDIR/cmd.json(id 每次递增,dryRun:false 为正式开票):
{
"id": 1,
"steps": [
{
"cmd": "invoiceFlow",
"plate": "豫AU5R02",
"month": "202609",
"station": "河南郑新黄河大桥站",
"email": "1000@agent.qq.com",
"dryRun": false
}
]
}
month省略 → 用当前月的前一月;station省略 → 用河南郑新黄河大桥站。- 不确定记录数量时可先跑一遍
dryRun: true:流程会走到「填好邮箱」为止就停下,不点提交,并在flow里返回匹配条数与金额,便于核对。
等待约 1分钟后读取 $WORKDIR/result.json,看 flow.status(见下表)。
3.3 结束
向 cmd.json 写入 {"id": 99, "steps": [{"cmd":"quit"}]},等待代理退出即可。
> 运行过程中不执行任何本地文件删除操作,也不需要为此向用户确认;工作目录内的中间文件按原样保留。
四、结果处理(result.json → flow)
flow.status |
含义 | 你要做的事 |
|---|---|---|
SUBMITTED |
开票申请已成功提交 | 汇报车牌、月份、条数、金额、邮箱、申请时间;附 resultText / 结果页截图作为凭证 |
NO_RECORDS |
没有符合条件的待开票记录 | 严格照此提示用户:「未找到需要开票的通行信息」,并补充说明所选月份与出入口条件 |
DRY_RUN |
预演完成(未提交) | 汇报将开票的条数与金额,请用户确认后再以 dryRun:false 重跑 |
SELECTION_LOST |
勾选在跳转前失效 | 直接重跑 invoiceFlow(不要中途插入耗时操作) |
PLATE_NOT_FOUND |
用户名下没有该车牌 | 提示用户核对车牌号与账号是否匹配 |
MONTH_UNAVAILABLE |
该月份不在可选范围 | 站点只提供最近若干月(近期实测为 5 个月),提示用户改用可选月份 |
PICKER_MISSING / CONFIRM_PAGE_MISSING |
页面结构异常 | 重试一次;仍失败则读 references/site-map.md 排查 |
ERROR |
其他异常 | 把 flow.error 与日志尾部转述给用户 |
flow 关键字段:matched(匹配条数)、selected(已勾选条数)、amount(开票总金额)、monthApplied(实际生效月份)、resultText(结果页文字)。
五、注意事项
- 会话不跨进程持久:站点用 URL 级
jsessionid,浏览器进程一旦关闭即失效 —— 所以登录、筛选、提交必须在同一次运行内完成(本引擎已自动串起来)。 - 验证码偶发失败:阿里云验证码 2.0 只能点
#aliyunCaptcha-checkbox-icon(文字区域无事件)。引擎已内置重试;若日志出现captcha: FAILED,整体重跑即可。 - 页面会自动刷新:空闲较久后页面会重置(月份回到上次查询值、勾选被清空)。因此勾选后要立刻点「去开票」,不要在中间插入长耗时步骤 —— 这也是
invoiceFlow存在的意义。 - 提交后还有一个弹窗:点「提交」后会出现「关注票根公众号」的倒计时弹窗,需再点「继续提交」(
#closePg2)才真正落地。引擎已处理;手工排障时别漏掉这一步。 - 发票份数:按月合并开具,选中 N 条 = 1 张发票(含全部行程明细)。
- 凭据来源单一:密码只来自调用方在指令中给出的明文(写入
config.json);本技能不读取本地凭据文件或浏览器密码库。运行过程不做本地文件删除,也无需用户确认。
六、文件清单
| 文件 | 作用 |
|---|---|
scripts/browser_agent.cjs |
常驻浏览器代理引擎:自动登录(密码由 config.json 传入)+ 命令轮询 + 高层 invoiceFlow |
references/site-map.md |
站点结构、全部选择器、坑点与排障手册 |