news 2026/9/21 23:47:36

如何制作微信推送源码解析:3步搞定跑不通的代码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何制作微信推送源码解析:3步搞定跑不通的代码

如何制作微信推送源码解析:3步搞定跑不通的代码

复制来的代码跑不通,是不是让你抓狂?报错信息像天书,调试半天没头绪。别急,今天咱们直接扒开【如何制作微信推送】的底层逻辑,用源码解析帮你理清思路。

一句话原理:回调机制与签名校验

微信推送的本质,不是你去“发”消息,而是微信服务器“推”给你,或者你“推”给微信。对于公众号主动推送,核心是HTTP POST请求;对于模板消息,核心是接口调用。所有交互都建立在HTTPS安全通道Token签名校验之上。

这就好比你去银行柜台办事。你不能直接跑进金库拿钱(直接访问数据库),必须出示身份证(Token)、填写单据(XML/JSON数据),银行核验无误后,才给你办理业务。如果身份证不对(签名错误),或者单据格式乱(数据解析失败),业务直接拒绝。很多初学者失败,不是因为代码逻辑错,而是“身份证”没带对,或者“单据”写错了。

类比解释:微信推送像什么?

把微信开放平台想象成一个高速收费站

  1. Token是通行证:你在微信后台设置的那个随机字符串,就是收费站发给你这辆车的专用通行证。
  2. Timestamp是时间戳:每辆车过站时,记录一个精确到秒的时间。
  3. Nonce是随机数:防止你拿同一个凭证反复刷站,每次过站都换一个随机编号。
  4. Signature是签名:把通行证、时间、随机数按特定顺序排序,拼起来,用MD5加密,生成的那串字符就是签名。

当微信服务器向你发请求时,它会带上这四个参数。你的服务器必须立刻做三件事:

  1. 拿到微信发来的Token(你自己在后台设的)。
  2. 拿到微信发来的Timestamp、Nonce、Signature。
  3. 用你手里的Token,加上微信发来的Timestamp、Nonce,按字典序排序,拼接,MD5加密,算出一个新签名。
  4. 比对:如果你算出来的签名,和微信发来的Signature一模一样,说明请求来自微信,是合法的。否则,直接丢弃,返回403错误。

这个过程,就是所谓的签名校验。90%的“跑不通”,都卡在这一步。

源码/伪代码片段:Python实现签名校验

很多人用Java或Node.js,但Python代码最简洁,逻辑最清晰。下面这段代码,是微信官方文档逻辑的Python实现。你可以直接复制到本地运行,输入测试参数,看它是否能通过校验。

import hashlib
import urllib.parsedef check_wechat_signature(token, timestamp, nonce, signature):"""验证微信服务器发来的请求签名是否合法:param token: 你在微信后台设置的Token:param timestamp: 微信发来的时间戳:param nonce: 微信发来的随机数:param signature: 微信发来的签名:return: True 如果合法,False 如果非法"""# 1. 将 token、timestamp、nonce 三个参数进行字典序排序# 注意:是字典序(ASCII码顺序),不是时间顺序list_params = [token, timestamp, nonce]list_params.sort()# 2. 将三个参数字符串拼接成一个字符串进行sha1加密# 微信早期用MD5,现在主流用SHA1,务必确认你使用的算法# 很多旧教程还在用MD5,这是个大坑!string_to_sign = ''.join(list_params)# 使用SHA1哈希hash_object = hashlib.sha1(string_to_sign.encode('utf-8'))hex_digest = hash_object.hexdigest()# 3. 判断是否相等return hex_digest == signature# 测试案例
if __name__ == '__main__':# 假设你在微信后台设置的Token是 "my_secret_token_123"token = "my_secret_token_123"# 模拟微信发来的参数(这些是示例,实际运行需从请求头获取)timestamp = "1409659813"nonce = "265438"signature = "e76278513048d3f8869f3c1e88f27f0f6026f18e"is_valid = check_wechat_signature(token, timestamp, nonce, signature)print(f"签名校验结果: {is_valid}")# 如果返回False,说明你的Token、时间戳、随机数组合算出来的值不等于微信发来的Signature# 此时,你应该返回403,并记录日志,方便排查

逐行讲解关键坑点:

  1. list_params.sort():这是最容易出错的地方。排序必须是字典序(ASCII码)。比如 "1", "2", "a",排序后是 "1", "2", "a"。如果你用了Python的sorted(),默认就是字典序,没问题。但如果你手动拼接,顺序错了,结果必错。
  2. hashlib.sha1:微信在2015年左右将签名算法从MD5升级为SHA1。很多网上流传的旧代码还在用md5,导致签名永远对不上。务必检查你使用的算法
  3. 编码问题.encode('utf-8')。字符串必须转成字节串才能哈希。如果编码不一致(比如用了GBK),结果必错。微信要求UTF-8。

流程描述:从请求到响应的完整链路

理解了签名校验,我们来看整个推送流程。以公众号被动回复消息为例,这是最基础的场景。

流程图(文字版):

  1. 用户操作:用户在微信里给公众号发一条文本消息“你好”。
  2. 微信服务器:微信服务器收到消息,封装成XML格式,加上ToUserNameFromUserNameCreateTimeMsgTypeContent等字段。
  3. HTTP POST:微信服务器向你的服务器发送一个HTTPS POST请求,URL是你配置的服务器地址。
    • Query Parameterssignature, timestamp, nonce, echostr(如果是验证URL则带echostr,正常消息则不带)。
    • Body:XML格式的消息数据。
  4. 你的服务器接收
    • Step 1: 解析URL参数:从请求URL中提取signature, timestamp, nonce
    • Step 2: 签名校验:调用上面的check_wechat_signature函数。
      • 如果校验失败:返回HTTP 403,记录日志,流程结束。
      • 如果校验成功:继续下一步。
    • Step 3: 解析Body:读取POST请求的Body,解析XML,提取Content(用户发的消息)、FromUserName(用户ID)等。
    • Step 4: 业务逻辑:根据你的业务规则,决定回复什么。比如,如果内容是“你好”,就回复“您好,有什么可以帮您?”。
    • Step 5: 构造回复XML:将回复内容封装成XML格式。
    • Step 6: 返回响应:将构造好的XML字符串作为HTTP Response Body返回,Content-Type设置为text/xml
  5. 微信服务器:收到你的XML响应,解析后推送给用户。
  6. 用户看到:用户在微信对话框里看到你回复的“您好,有什么可以帮您?”。

关键细节:

  • 响应时间:微信要求你的服务器必须在5秒内返回响应。如果超时,微信会认为你的服务挂了,不再推送,且用户会看到“消息已发出,但被对方拒收”。所以,如果你的业务逻辑很复杂(比如查数据库、调第三方API),必须使用异步处理
  • 异步处理方案
    1. 收到请求,校验签名。
    2. 立即返回一个空的XML或简单的“正在处理”提示。
    3. 将用户消息放入消息队列(如RabbitMQ、Kafka)。
    4. 后台Worker从队列取消息,处理业务逻辑。
    5. 处理完成后,调用客服消息接口模板消息接口主动推送给用户。

实战验证:如何调试“跑不通”的代码?

现在,你有了原理和代码,怎么验证你的环境是通的?

方法一:本地调试(推荐)

  1. 安装微信开发者工具:这是微信官方提供的调试工具,可以在本地模拟微信服务器的请求。
  2. 配置本地服务器
    • 确保你的服务器监听80或443端口(微信要求HTTPS,本地调试需配置SSL证书,或使用微信提供的调试工具绕过)。
    • 在微信后台填写你的服务器URL、Token、EncodingAESKey(如果用消息加解密)。
  3. 使用Postman模拟请求
    • 在Postman中创建POST请求。
    • URL: http://your-local-ip/wechat/callback?signature=xxx&timestamp=xxx&nonce=xxx
    • Body: 选择raw,类型XML,填入模拟的XML数据。
    • 发送请求,查看你的服务器是否返回200,以及返回的Body是否正确。
  4. 日志记录
    • 在签名校验前后,打印token, timestamp, nonce, signature
    • 在解析XML前后,打印原始Body和解析后的字典。
    • 这是调试的核心。没有日志,你就是在盲猜。

方法二:GitHub开源仓库参考

如果你不想从零写,可以参考GitHub上的开源项目。比如搜索wechat-official-account,找到Star数高的仓库。

  • 推荐仓库wechatpy/wechatpy(Python库,封装了微信接口,处理了签名、加解密等细节)。
  • 为什么推荐
    • 它封装了check_signature方法,你只需传入参数即可。
    • 它提供了wechat对象,可以方便地发送消息、获取用户信息。
    • 它的文档详细,社区活跃,遇到问题容易找到解决方案。

避坑指南:

  1. Token不一致:微信后台设置的Token,和你代码里写死的Token,必须完全一致。包括大小写、空格。
  2. 端口不通:确保你的服务器80/443端口对外开放,防火墙没拦截。
  3. HTTPS证书:微信要求必须使用HTTPS。如果你用自签名证书,微信服务器会拒绝。请使用Let's Encrypt等免费证书,或购买商业证书。
  4. IP白名单:如果你配置了IP白名单,确保微信服务器的IP(203.205.244.0/24等)在白名单内。

进阶技巧:消息加解密与安全性

上面讲的是明文模式。现在,微信强烈建议使用安全模式(明文模式已被逐步淘汰)。

安全模式引入了AES加解密。这意味着:

  1. 请求Body是加密的:微信发来的XML是Base64编码的密文。
  2. 响应Body也要加密:你返回的XML必须加密后Base64编码。
  3. 需要EncodingAESKey:你在微信后台生成的那个43位字符串,是AES解密密钥。

加解密流程:

  1. 解密请求
    • 从URL获取msg_signature, timestamp, nonce
    • 从Body获取Encrypt字段。
    • EncodingAESKeytimestampnonceEncrypt计算msg_signature,校验合法性。
    • 校验通过后,用EncodingAESKeyEncrypt进行AES解密,得到明文XML。
  2. 加密响应
    • 构造明文XML。
    • EncodingAESKey、当前时间戳、随机数,对明文XML进行AES加密。
    • 对加密结果进行Base64编码。
    • EncodingAESKey、时间戳、随机数、Encrypt计算msg_signature
    • 返回包含Encryptmsg_signature的XML响应。

代码佐证(Python,使用wechatpy库):

from wechatpy.crypto import WeChatCrypto# 初始化加密器
# 注意:encoding_aes_key 是43位字符串,从微信后台获取
# app_id 是你的公众号AppID
# token 是你设置的Token
crypto = WeChatCrypto(token='my_secret_token_123',encoding_aes_key='your_43_char_aes_key_here',app_id='wx1234567890abcdef'
)# 解密微信发来的密文
# encrypted_msg: 微信发来的Base64编码的密文
# timestamp: URL中的timestamp
# nonce: URL中的nonce
# msg_signature: URL中的msg_signature
try:plaintext = crypto.decrypt_msg(encrypted_msg, timestamp, nonce, msg_signature)print("解密成功:", plaintext)
except Exception as e:print("解密失败:", e)# 加密你的回复
# reply_xml: 你要回复的明文XML
encrypted_reply = crypto.encrypt_msg(reply_xml)
print("加密后的回复:", encrypted_reply)

避坑:

  • AESKey长度:必须是43位。如果少了或多了,解密必失败。
  • 时间戳:解密时的时间戳必须和URL中的完全一致。
  • Padding:AES加密需要填充。wechatpy库已经处理了,但如果你自己写,务必注意PKCS7填充。

结尾互动引导

微信推送的底层原理,核心就是签名校验加解密。掌握了这两点,你就能搞定90%的问题。剩下的10%,是业务逻辑和异步处理。

你公司项目里是怎么处理微信推送的?是用的明文模式还是安全模式?有没有遇到过签名校验失败但日志显示参数正确的情况?欢迎在评论区分享你的踩坑经验,一起避坑。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/21 23:47:25

袁雪拆解3个核心考点,攻克高频面试题不再难

袁雪拆解3个核心考点,攻克高频面试题不再难 官方文档动辄几百页,读起来头晕眼花,真正到了面试现场,那些关键细节却怎么也想不起来。这种“看懂了但没记住”的尴尬,在技术求职中太常见了。尤其是面对那些被反复咀嚼的 高频面试题…

作者头像 李华
网站建设 2026/9/21 23:47:23

libeccio速查手册:5个致命性能坑,实测提升3倍

libeccio速查手册:5个致命性能坑,实测提升3倍 刚接手一个遗留的 C++ 项目,打开日志一看,满屏的 std::exception 和晦涩难懂的 StackTrace,头大得想砸键盘。想查文档,GitHub 上的 README 只有几行字,Issue…

作者头像 李华
网站建设 2026/9/21 23:47:23

3招搞定win7关闭系统更新,面试高频考点避坑指南

3招搞定win7关闭系统更新,面试高频考点避坑指南 版本升级后 API 全变了,很多老项目直接崩盘,这正是 高频面试题 里最扎心的痛点。别急着骂系统,Win7 停服后强制更新是运维噩梦。今天直接上代码,用 Python 写个自动化脚本,彻底解决 win7关闭系统更新 的顽疾。 项目目标与场景痛点…

作者头像 李华
网站建设 2026/9/21 23:47:10

2026最新虚拟机多少钱实测:3步搞定性能瓶颈与成本优化

2026最新虚拟机多少钱实测:3步搞定性能瓶颈与成本优化 很多开发者盯着语法书啃完,代码能跑,但一上手真实项目就卡壳。不知道环境怎么搭,不知道资源怎么配,更不知道 虚拟机多少钱 才能既省钱又高性能。2026年的云资源价格体系变了,单纯看单价已经不够,得看“性价比”和“性能利用率”。…

作者头像 李华
网站建设 2026/9/21 23:47:04

长沙有哪些旅游景点:一文搞懂底层逻辑与避坑全解

长沙有哪些旅游景点:一文搞懂底层逻辑与避坑全解 看了一堆旅游攻略还是踩坑?别急,这跟咱们写代码没跑通一个道理。今天用程序员思维, 一文搞懂 【长沙有哪些旅游景点】背后的规划原理。 一句话原理:旅游即路由匹配 旅游本质是 资源-需求…

作者头像 李华
网站建设 2026/9/21 23:46:34

3个核心优化让光盘播放器手写实现性能翻倍

3个核心优化让光盘播放器手写实现性能翻倍 面试被问原理答不上来,往往不是不懂概念,而是没写过代码。很多开发者对 光盘播放器 的理解停留在“读取数据、解码、渲染”的抽象层面,一旦要求 手写实现 核心调度逻辑,立刻卡壳。这种脱节在性能优化场景中尤为致命:你无法优化一个自己没亲手构建过的系统。…

作者头像 李华