前言
在微信自动化业务中,发送长文本消息是高频场景:批量客户通知、订单回执、营销文案、知识问答等。然而不少开发者都踩过同一个坑——接口调用返回成功,接收方收到的却是被截断的半截内容,甚至完全丢失。这个问题表现隐蔽,日志看不出来,用户反馈才知道。本文系统梳理微信长文本发送被截断的所有常见原因和排查方法,帮助你快速定位并彻底解决。
微信长文本截断的常见表现与分类
在正式排查前,先把"截断"这个问题分清楚,否则排查方向会走偏。截断大致分三类:
类型一:消息在接收端显示不完整 接口返回 ret:200,发送方日志一切正常,但接收方只看到文本的前半段,后面的内容不翼而飞。这是最典型的截断。
类型二:消息被拆成多条 发送时是一整段文字,到了接收端变成了两条甚至三条消息,顺序可能还乱了。这属于"分片发送失控"。
类型三:消息根本没有到达 既不是截断,也不是分片,接收方压根没收到任何内容。这通常是超长文本触发了微信的风控机制,被静默丢弃。
区分这三类,决定了排查的起点不同。
原因一:字符数超出微信客户端渲染上限
微信对单条文本消息的字符数有隐性上限限制。这个限制在官方文档里从未明确标注,但根据大量实测,规律如下:
| 场景 | 安全字数上限(中文字符) | 超出后行为 |
|---|---|---|
| 个人微信单聊 | 约 4000 字 | 接收端截断显示 |
| 个人微信群聊 | 约 2000 字 | 触发风控或截断 |
| 包含大量 URL 的文本 | 约 1500 字 | 更容易被截断 |
| 纯英文/数字 | 约 8000 字节 | 视编码方式而定 |
注意这里说的是"字符数"而非"字节数"。中文字符在 UTF-8 编码下占 3 字节,一条 4000 中文字的消息实际传输体积接近 12 KB。超出上限后,微信客户端或服务端会在某个位置硬截断,截断点并不固定,跟网络状态和客户端版本都有关系。
排查方法: 先用二分法缩小问题范围。把要发送的文本减半,测试是否还截断。如果减半后正常,再把三分之二的原文发送,以此类推,找到截断的临界字符数。一旦确认是字数问题,解决思路只有两种:压缩内容,或者拆分发送。
使用 WechatApi 的个人微信API 时,可以在业务层做分片处理,把超长文本按段落或句号切分成多条,依次调用发送接口,每条之间加适当延迟,避免频率触发风控。
原因二:请求体编码或序列化问题
这是开发层面最常见也最容易被忽视的坑。发送方日志看起来消息完整,实际上在 HTTP 请求打包阶段就已经被截断或转义错误。
常见的编码陷阱:
1. Content-Type 设置错误
如果你把 Content-Type 设置为 application/x-www-form-urlencoded 而不是 application/json,那么消息中的换行符、特殊字符、中文字符都可能在 URL 编码过程中被截断或乱码。
pythonimport requests
import json
url = "https://api.example.com/message/send" # 示意性接口地址
headers = {
"Content-Type": "application/json", # 必须是 JSON
"VideosApi-token": "your_token_here" # 鉴权 token
}
payload = {
"appId": "your_device_id", # 设备ID,非微信ID
"toUser": "target_wxid",
"content": "这里是超长文本内容……"
}
response = requests.post(url, headers=headers, data=json.dumps(payload, ensure_ascii=False))
# 注意:用 json= 参数时 requests 会自动设置 Content-Type,但 ensure_ascii=False 要手动处理
print(response.json())
2. json.dumps 默认 ensure_ascii=True 问题
Python 的 json.dumps 默认把非 ASCII 字符(包括中文)转义成 \uXXXX 形式。一条 200 字的中文消息被转义后体积会膨胀 6 倍,达到 1200 字节,超出某些中间件的默认请求体大小限制就会被截断。务必加上 ensure_ascii=False。
3. 网关或代理层的 body 大小限制
如果你的业务服务通过 Nginx 反向代理再转发到 WechatApi,Nginx 默认的 client_max_body_size 是 1MB,一般够用,但 proxy_buffer_size 和 proxy_buffers 的默认值很小(通常 4KB/8KB),超出部分会被写到临时文件,处理不当就可能截断。
排查方法:在发送前把序列化后的 JSON 字符串长度打印出来,和实际接口收到的请求体大小对比。如果两端数字不一致,问题就在传输链路上。
原因三:微信iPad协议层的分片机制与乱序
WechatApi 基于微信iPad协议实现,这一点决定了它的消息发送行为和网页微信、PC微信有本质区别。
iPad 协议在传输层对超长文本有自己的分片逻辑:当单条消息超过协议层的分片阈值,底层会自动把消息拆成多个 segment 发送,每个 segment 携带序号,接收端按序号重组。这个机制本身没问题,但在以下情况下会出现重组失败导致截断:
- 网络抖动:某个 segment 丢失,接收端等待超时后放弃重组,只显示已收到的部分
- 发送频率过高:短时间内发送多条消息,分片序号发生混乱,不同消息的 segment 互相干扰
- 设备重连:发送过程中设备断线重连,正在传输的 segment 丢失
针对这类问题,排查方式是检查 WechatApi 返回的响应体。标准响应格式如下:
json{
"ret": 200,
"msg": "success",
"data": {
"msgId": "1234567890",
"createTime": 1718000000,
"toUser": "target_wxid",
"status": "sent"
}
}
如果 ret 是 200 但消息被截断,问题大概率在协议层的分片重组;如果 ret 不是 200,先查错误码。
实用建议: 超长文本(超过 1000 中文字)不要依赖协议层自动分片,而是在业务代码里主动分割,每段控制在 800 字以内,每段之间等待 1-2 秒再发下一段,可以显著降低重组失败率。
原因四:风控触发导致消息静默截断或丢弃
微信对消息内容有实时风控检测,某些特征会触发截断或丢弃,但接口层面可能仍然返回成功。常见的风控触发特征:
- 高密度外链:消息中包含大量 URL,尤其是短链或非微信域名链接
- 重复内容:短时间内多次发送相同或高度相似的文本
- 敏感词:文本中包含违禁关键词,微信服务端会在投递前截断或替换
- 格式化符号过密:大量连续的换行、空格、星号等格式符号
排查方法:
bash# 用 curl 直接调试,排除业务代码的干扰
curl -X POST "https://api.example.com/message/send" \
-H "Content-Type: application/json" \
-H "VideosApi-token: your_token_here" \
-d '{
"appId": "your_device_id",
"toUser": "target_wxid",
"content": "把可疑文本粘贴到这里进行测试"
}'
用最小化文本测试,逐步加入可疑内容,定位到触发风控的具体段落。WechatApi 的微信二次开发接入文档中也有关于内容策略的说明,建议结合参考。
如果确认是敏感词问题,可以把文本先经过敏感词过滤库处理,或者改变文本结构(比如把外链放在末尾、减少链接密度)。
原因五:调用参数配置不当
除了内容本身,调用参数的配置错误也会导致截断。以下是几个容易踩的参数坑:
| 参数 | 错误配置 | 正确配置 | 影响 |
|---|---|---|---|
appId | 传了微信号而非设备ID | 传设备控制台分配的 appId | 消息发出但不计入指定设备,可能截断 |
content 编码 | 未做 Unicode 规范化 | 使用 NFC 规范化的 UTF-8 | 特殊字符截断 |
| 请求超时 | 客户端超时设置过短(如 3s) | 设置 10s 以上 | 长文本序列化耗时导致超时截断 |
| 重试逻辑 | 超时后立即重试同一请求 | 检查消息状态再决定是否重试 | 可能导致重复发送或发送不完整 |
appId 是设备层面的唯一标识,由 WechatApi 控制台分配,不是你的微信号,这一点新接入的开发者经常混淆。
长文本发送的最佳实践
综合以上排查经验,整理出一套稳定的长文本发送实践方案:
1. 文本预处理 发送前做字符数统计,超过 800 中文字的内容自动按句号/段落切分。切分时保持语义完整,不要在词语中间断开。
2. 分批发送 每批一条,批次之间等待 1500ms 以上。如果是群发场景,不同接收人之间也要有间隔,避免高并发触发风控。
3. 发送结果核验 不能只看接口返回的 ret:200 就认为发送成功。对于重要消息,建议在发送后通过消息查询接口验证实际投递状态。
4. 错误重试 ret 非 200 时才重试,且重试前检查消息是否已经发出(防止重复)。重试间隔指数级增加,最多重试 3 次。
5. 日志记录 把发送的完整文本、字符数、请求体大小、接口返回全部记录下来,出问题时有据可查。
这套方案在基于 WechatApi 构建的微信机器人开发场景中已经过大量验证,无论是客服自动回复、营销推送还是知识库问答,都能稳定运行。
小结
微信发送长文本被截断是一个多因素叠加的问题,单一排查视角容易走弯路。核心排查路径是:先确认截断类型 → 用二分法定位临界字数 → 检查编码和请求体 → 验证协议层分片 → 排查风控触发 → 核对调用参数。
大多数情况下,主动在业务层做文本分片、控制单条消息长度在 800 字以内、每批次发送加适当延迟,就能解决 90% 的截断问题。如果你在接入过程中遇到复杂的截断场景,可以查阅 WechatApi 开发文档(https://post.wechatapi.net)或在控制台(https://newmanager.wechatapi.net/dashboard/)提交技术支持请求,官方会协助排查协议层的具体问题。
