3、第三方平台配置:服务器配置与消息加解密
好,咱们接着聊。这一节要讲的东西,是第三方平台接入微信的“第一道门”。说白了,就是你怎么让微信服务器认识你,怎么安全地跟它通信。
我个人习惯,每次搭建新项目时,都会先把这块配置吃透。因为一旦配错,后面所有流程都跑不通。嗯,咱们一步步来。
3.1 服务器配置:URL、Token、EncodingAESKey
打开微信开放平台,进入第三方平台详情页,你会看到三个输入框:URL、Token、EncodingAESKey。这三个东西,缺一不可。
| 配置项 | 说明 | 我的建议 |
|---|---|---|
| URL | 你的服务器接收微信消息的接口地址 | 必须是公网可访问的 HTTPS 地址 |
| Token | 用于验证请求来源的密钥字符串 | 建议用随机字符串,别用 abc123 这种 |
| EncodingAESKey | 消息加解密的密钥,43位字符 | 让平台自动生成,省心 |
这里有个坑,我刚开始做的时候踩过。URL 必须指向一个能正常返回数据的接口,而且响应时间不能超过 5 秒。微信服务器会发一个 GET 请求来验证你的接口是否可用。
核心流程:微信服务器会携带 signature、timestamp、nonce、echostr 四个参数,GET 请求你的 URL。你需要验证 signature,然后原样返回 echostr。
验证签名的逻辑,说白了就是三步:
- 将 Token、timestamp、nonce 三个参数按字典序排序
- 拼接成一个字符串,做 SHA1 加密
- 对比加密结果和微信传来的 signature
代码实现其实很简单,我贴一段 Node.js 的示例:
const crypto = require('crypto');
function verifySignature(token, timestamp, nonce, signature) {
// 1. 排序
const arr = [token, timestamp, nonce].sort();
// 2. 拼接 + SHA1
const str = arr.join('');
const sha1 = crypto.createHash('sha1').update(str).digest('hex');
// 3. 对比
return sha1 === signature;
}
嗯,这里要注意。Token 是你自己填的,但一旦保存,微信那边就记住了。如果你改了 Token,两边都得同步更新,不然验证会失败。我曾经在线上环境改过一次 Token,忘了重启服务,结果整整排查了半小时……
3.2 消息加解密方案
微信开放平台支持三种消息加解密模式。我个人建议,直接选「安全模式」。为什么?因为明文模式太危险,兼容模式又没必要。
| 模式 | 说明 | 推荐度 |
|---|---|---|
| 明文模式 | 消息不加密,直接传输 | 不推荐 |
| 兼容模式 | 明文和密文同时存在 | 仅用于调试 |
| 安全模式 | 消息完全加密传输 | 强烈推荐 |
安全模式下,微信推送的消息体是加密的 XML。你需要用 EncodingAESKey 来解密。解密流程是这样的:
- 从 XML 中提取 Encrypt 字段
- 用 AES-256-CBC 解密,密钥是 EncodingAESKey
- 解密后得到 XML 明文,包含 ToUserName、FromUserName、CreateTime、MsgType、Content 等字段
小技巧:解密后的数据前 16 位是随机字符串,紧接着是 4 字节的消息长度,再往后才是真正的 XML 内容。记得按这个格式解析,别直接当 XML 读。
加密过程则相反。你要把响应消息先拼成 XML,然后加上随机字符串和长度信息,最后用 AES 加密。嗯,这块逻辑有点绕,我建议直接用微信官方提供的加解密库,别自己手写。我在项目中见过有人自己实现 AES,结果密钥长度搞错了,解密出来全是乱码……
3.3 component_verify_ticket 的获取
这个 ticket 是第三方平台的“心跳”。微信服务器每隔 10 分钟会向你的 URL 推送一次 component_verify_ticket,你收到后必须保存下来。
为什么说它重要?因为后面获取 component_access_token 时,必须用到这个 ticket。没有它,你连第一步都走不出去。
警告:component_verify_ticket 的有效期只有 12 分钟。如果你没在 10 分钟内收到新的 ticket,说明你的 URL 可能挂了,或者网络有问题。我曾经因为服务器负载过高,丢了好几次 ticket,结果 component_access_token 死活拿不到。
接收 ticket 的流程是这样的:
- 微信 POST 一个加密的 XML 到你的 URL
- 你用 EncodingAESKey 解密,得到明文 XML
- 从 XML 中提取 InfoType 字段,如果是 component_verify_ticket,就提取 ComponentVerifyTicket 字段
- 把这个 ticket 存到数据库或 Redis 里
代码示例(解密后的 XML 结构):
<xml>
<ToUserName><![CDATA[第三方平台appid]]></ToUserName>
<FromUserName><![CDATA[微信系统]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[component_verify_ticket]]></Event>
<ComponentVerifyTicket><![CDATA[ticket内容]]></ComponentVerifyTicket>
</xml>
你想想看,如果 ticket 丢了,整个第三方平台的授权流程就断了。所以我建议,每次收到 ticket 后,除了存数据库,还要打个日志。万一出问题,可以回溯排查。
最佳实践:用 Redis 存储 ticket,设置过期时间为 15 分钟。每次收到新 ticket 就覆盖旧值。这样即使服务重启,也能从 Redis 里拿到最新的 ticket。
嗯,这一节的内容就这些。配置好 URL、Token、EncodingAESKey,选对加解密模式,再稳稳地接住 component_verify_ticket,你的第三方平台就算迈出了第一步。下一节咱们聊聊怎么用这个 ticket 去换 access_token,那才是真正干活的开始。