配置比特浏览器RPA Webhook通常分四步:准备接收端(公网或ngrok)、在RPA添加Webhook并填写URL/方法/Headers、配置签名与重试策略、测试并检查日志。务必启用HTTPS、签名校验与幂等处理,下面逐步展开示例与排查要点。示例含Node.js与curl测试。会讲去重。并发示例

先把概念讲清楚:Webhook在RPA里是什么
Webhook本质上就是服务器之间的“回调通知”。当比特浏览器RPA流程跑完某个动作(比如任务完成、验证码识别结果、登录状态变化),它会把事件信息主动POST到你给定的URL。你要做的,是准备好那个能接收并正确处理这些POST请求的接收端。
为什么要用Webhook,而不是轮询?
- 实时性更好:事件发生后立刻通知,延迟低。
- 节省带宽与资源:不需要频繁轮询RPA状态。
- 配合幂等设计可以保证重复通知不会破坏系统状态。
配置前的准备工作(必须做的四件事)
- 准备一个公网可访问的接收端(生产用域名+HTTPS)。开发阶段可以用ngrok或本地反向代理。
- 设计接收API接口:支持POST,Content-Type通常是application/json。
- 约定签名或密钥机制(HMAC-SHA256最常见),用于校验请求来源。
- 考虑幂等和去重策略(request_id、timestamp、nonce等)。
在比特浏览器RPA中添加Webhook:逐步操作(通用流程)
不同版本UI可能位置稍有差别,但字段基本一致。下面按最常见的字段说明如何填写与为什么要这样填。
常见字段说明
- Webhook URL:接收端完整地址,例如:https://api.example.com/bit-rpa/webhook
- HTTP 方法:通常为 POST;少见场景可能支持 GET(不推荐)
- Headers:比如 Content-Type: application/json;以及自定义签名头 X-Bit-Signature 或 Authorization
- Payload 模板:选择或自定义发送的数据结构(任务ID、状态、结果、时间戳等)
- 重试策略:发生4xx/5xx时的重试次数与间隔,防止短暂故障丢失消息
- 并发/队列设置:控制并发发送数量,避免接收端被冲垮
- 事件选择:只订阅你关心的事件(如 task.completed、task.failed 等)
示例:推荐的Payload结构与Header
这是一个通用推荐,既能表达信息,又利于校验与去重。
| 字段 | 示例/说明 |
| event | task.completed(事件类型) |
| task_id | abc123(RPA内部任务ID) |
| status | success / failed |
| result | 对象或字符串(例如识别文本、截图链接) |
| timestamp | 2026-03-30T12:34:56Z(UTC时间) |
| request_id | uuid,用于幂等和去重 |
推荐Headers
- Content-Type: application/json
- X-Bit-Timestamp: 请求发送时间(可选,用于防重放)
- X-Bit-Signature: HMAC-SHA256签名,签名算法请与RPA端约定
签名校验:如何防止伪造请求
签名是Webhook安全的核心。通用做法是双方共享一个密钥secret,RPA在发送时用secret对payload或特定字符串做HMAC签名,接收端用同样的secret计算并对比。
签名示例(伪代码说明)
签名步骤:
- 接收端与RPA共享secret。
- RPA对字符串(例如:timestamp + “.” + body)计算HMAC-SHA256。
- 把签名放在X-Bit-Signature头发送。
- 接收端用相同方式计算签名并对比,匹配才处理请求。
// Node.js 伪代码:验证签名
const crypto = require('crypto');
function verifySignature(secret, timestamp, body, signature) {
const payload = `${timestamp}.${body}`;
const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex');
// 用恒定时间比较防止时序攻击
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
接收端实现示例(可复制修改)
下面给出两个简洁的接收端样例:Node.js(Express)和Python(Flask)。这些示例包括签名验证、幂等处理与基础日志。
Node.js(Express)示例
const express = require('express');
const crypto = require('crypto');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json({ limit: '1mb' }));
const SECRET = process.env.WEBHOOK_SECRET || 'your_secret';
const processed = new Set(); // 简单去重,生产请用DB或缓存
function verify(timestamp, body, signature) {
const payload = `${timestamp}.${JSON.stringify(body)}`;
const expected = crypto.createHmac('sha256', SECRET).update(payload).digest('hex');
try {
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
} catch (e) {
return false;
}
}
app.post('/webhook', (req, res) => {
const sig = req.headers['x-bit-signature'] || '';
const ts = req.headers['x-bit-timestamp'] || '';
const body = req.body;
if (!verify(ts, body, sig)) {
return res.status(401).send('invalid signature');
}
const id = body.request_id || `${body.task_id}_${body.timestamp}`;
if (processed.has(id)) {
// 幂等:已经处理过
return res.status(200).send('ok');
}
processed.add(id);
// 异步处理真实业务,避免阻塞
// doBusiness(body).catch(console.error);
console.log('收到事件:', body.event, id);
res.status(200).send('received');
});
app.listen(3000);
Python(Flask)示例
from flask import Flask, request, jsonify
import hmac, hashlib, os
from time import time
app = Flask(__name__)
SECRET = os.getenv('WEBHOOK_SECRET', 'your_secret')
processed = set()
def verify(ts, body, signature):
payload = f"{ts}.{body}".encode('utf-8')
expected = hmac.new(SECRET.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
@app.route('/webhook', methods=['POST'])
def webhook():
sig = request.headers.get('X-Bit-Signature', '')
ts = request.headers.get('X-Bit-Timestamp', '')
body_text = request.get_data(as_text=True)
if not verify(ts, body_text, sig):
return jsonify({'error': 'invalid signature'}), 401
data = request.json
id = data.get('request_id') or f"{data.get('task_id')}_{data.get('timestamp')}"
if id in processed:
return jsonify({'status': 'ok'}), 200
processed.add(id)
print('处理事件', data.get('event'), id)
return jsonify({'status': 'received'}), 200
if __name__ == '__main__':
app.run(port=3000)
测试Webhook:从简单到复杂
测试过程分成三步:本地开发测试、外网连通测试、压力与异常测试。
本地测试
- 用curl模拟:curl -X POST -H “Content-Type: application/json” -d ‘{“event”:”task.completed”}’ https://your-url/webhook
- 若使用签名,curl时也要计算并加上X-Bit-Signature和X-Bit-Timestamp头。
外网连通:使用ngrok或部署到测试域名
ngrok能把本地端口暴露到公网,方便你把这个临时URL填到比特浏览器RPA设置里做联调。测试完成换成正式域名并启用HTTPS。
压力与异常场景测试
- 模拟并发发送(比如每秒N条)观察接收端吞吐与队列情况。
- 测试重复通知(相同request_id)确认幂等逻辑。
- 模拟签名错误、慢响应、500错误,观察RPA端重试策略是否按预期工作。
常见问题与排查步骤(实战经验)
- 没有收到请求:确认RPA里URL无误、接收端可达、检查防火墙和HTTPS证书是否正确。
- 签名验证失败:可能是secret不一致、签名计算字符串不同(是否包含timestamp)、JSON序列化差异导致。
- 重复处理:没有幂等策略;建议使用request_id+DB/Redis去重。
- 接收端超时/断开:增加异步处理,把接收处理做最小;返回ACK后再异步消费长任务。
- 高并发导致丢包:增加队列(如RabbitMQ、Kafka)缓冲,并发控制。
关于重试与保证投递:你应该怎样设置
理想的策略:
- 短重试间隔与指数退避:比如初次1s、再10s、再1分钟、再10分钟,总尝试次数可配置。
- 明确失败判定:4xx通常是客户端问题(不重试或少重试),5xx和网络错误应重试。
- 幂等:同一request_id重复到达应不会改变业务结果。
安全与合规要点(别忽视)
- 强制HTTPS:避免中间人窃听或篡改。
- 签名与时间窗口:拒绝超过合理时间窗口(如5分钟)的timestamp以防重放攻击。
- IP白名单:若RPA端固定IP可用,进一步限制来源IP。
- 日志保留与告警:异常失败、签名错误、重试达到上限应告警运维或开发。
运维建议与监控项
- 记录每次Webhook的状态码、耗时、request_id、event类型。
- 为失败率设置阈值告警(例如失败率超过2%触发告警)。
- 定期清理去重缓存,避免内存持续增长。
示例场景:把结果回写到业务系统
常见做法:RPA发来task.completed,你的接收端验证签名后,将结果写入数据库并触发后续工作流(如发通知、调用上游API)。关键点是幂等、超时处理、以及异常重试。
常见错误码与含义(供排查用)
| HTTP 200 | 收到并已接受处理 |
| HTTP 400 | 请求格式错误(检查JSON结构) |
| HTTP 401/403 | 签名或鉴权失败 |
| HTTP 429 | 接收端限流(需调节并发或扩容) |
| HTTP 500 | 接收端内部错误(应重试) |
写到这儿,顺手再提醒几点:配置Webhook除了技术实现,也要和团队流程配合好——谁负责密钥管理、谁负责日志审计、发生异常时谁来排查。实践中最容易出问题的是签名约定不一致和去重策略缺失,提前把这两点落实好,会省很多时间。接下来就是边测边改,先把最简单能工作的一套搭通,再逐步强化安全与可用性。