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。

验证签名的逻辑,说白了就是三步:

  1. 将 Token、timestamp、nonce 三个参数按字典序排序
  2. 拼接成一个字符串,做 SHA1 加密
  3. 对比加密结果和微信传来的 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 的流程是这样的:

  1. 微信 POST 一个加密的 XML 到你的 URL
  2. 你用 EncodingAESKey 解密,得到明文 XML
  3. 从 XML 中提取 InfoType 字段,如果是 component_verify_ticket,就提取 ComponentVerifyTicket 字段
  4. 把这个 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,那才是真正干活的开始。