Java 微信机器人开发教程:从登录到收发消息怎么写
用 Java 做微信机器人,适合已经有 Spring 后台的团队。个人号没有官方 SDK,开发方式就是:HTTP 调登录和发送,再起一个接口收消息回调。 这篇按 Spring Boot 习惯写最小闭环,不绑具体厂商。
工程怎么拆
建议三个包,避免所有代码堆在一个 Controller:
-
channel:HTTP 客户端,负责登录、发文本、查在线 -
callback:对外回调接口,只做验签、去重、入队 -
bot:规则和会话,决定回什么、是否转人工
业务类不要出现 URL 拼接和 token。token 放配置,超时、重试放客户端。
配置项
wechat:
base-url: https://your-channel-host
token: ${WECHAT_TOKEN}
callback-token: ${WECHAT_CALLBACK_TOKEN}
send-timeout-ms: 8000
登录态 token 和回调校验 token 分开。一个过期不该让另一个一起失效。
回调接口:先 200,再处理
@PostMapping("/hooks/wechat/message")
public ResponseEntity<Void> onMessage(
@RequestHeader(value = "X-Token", required = false) String token,
@RequestBody String rawBody) {
if (!callbackAuth.matches(token)) {
return ResponseEntity.status(401).build();
}
MessageEvent event = parser.parse(rawBody);
if (event == null || store.seen(event.getAccountId(), event.getMsgId())) {
return ResponseEntity.ok().build();
}
store.saveRaw(event.getAccountId(), event.getMsgId(), rawBody);
queue.offer(event);
return ResponseEntity.ok().build();
}
要点:
-
解析失败也尽量 200 + 告警,避免对方疯狂重试把你打满(鉴权失败除外)
-
accountId + msgId做幂等 -
查订单、调大模型禁止写在这个方法里
消费者里再调 bot.handle(event)。
发送:带业务单号
public SendResult sendText(String accountId, String toWxid, String text, String requestId) {
if (!accountService.isOnline(accountId)) {
return SendResult.blocked("offline");
}
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(props.getToken());
Map<String, Object> body = new LinkedHashMap<>();
body.put("accountId", accountId);
body.put("to", toWxid);
body.put("content", text);
body.put("requestId", requestId);
ResponseEntity<String> resp = restTemplate.postForEntity(
props.getBaseUrl() + "/message/text",
new HttpEntity<>(body, headers),
String.class);
return SendResult.fromHttp(resp);
}
路径和字段名以你对接的通道文档为准,这里只演示形态。requestId 用消息表主键,方便超时后对账,避免客服点两次重发。
规则引擎先写死三条
public Optional<String> reply(MessageEvent e, Session session) {
if (session.isHumanTaken()) {
return Optional.empty();
}
if (!e.isPrivateChat()) {
return Optional.empty();
}
String t = e.getText();
if (t == null) {
return Optional.of("请发文字,或回复「人工」");
}
if ("人工".equals(t.trim())) {
session.takeHuman();
return Optional.of("已转接,请稍候");
}
if (t.contains("运费")) {
return Optional.of("满 99 包邮,偏远地区以客服确认为准");
}
return Optional.of("可以说「运费」或「人工」");
}
群默认不回。人工接管后必须 empty。这三条能跑,再把词库迁到数据库。
线程与重试
-
回调线程不做 IO 密集业务,用队列(内存队列只适合单机试,生产用 Redis / MQ)
-
只对网络超时重试,不对“不是好友”“参数错误”重试
-
同一好友出站加短间隔,不要在 Tomcat 线程里
Thread.sleep做全局频控,用队列延迟
本地联调顺序
-
通道侧扫码,Java 能查到 online
-
用 curl 打你的
/hooks/wechat/message,库里有 raw -
消费者发出文本,message 表有回执
-
连续推同一 msgId,只处理一次
通道字段以文档为准,Java 侧把 DTO 和枚举写清楚,后面加图片、群消息只扩 parser 和 bot。
小结
Java 微信机器人开发的核心是:回调快速落地、发送可对账、规则与通道分离。Spring 只是载体,真正要写对的是幂等、会话锁和错误分类。先跑通私聊文本闭环,再扩能力,返工会少很多。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)