Logo
活死人の行知路

微信公众号消息推送接入指南


📅 | 📝 357 字
#微信公众号开发

本指南介绍如何在本地开发环境中接入微信公众号的消息推送功能,包括密钥配置、接口验证和内网穿透测试。

前置条件

  • 已注册微信公众号或服务号
  • 拥有公众号管理权限
  • 本地开发环境(示例使用 Go + Gin)
  • Cpolar 或其他内网穿透工具

第一步:启用开发密钥

登录 微信开发者平台,在左上角「我的业务与服务」中选择公众号或服务号。

进入后在「开发密钥」模块中启用 AppSecret

注意:启用后请妥善保存 AppSecret,它用于后续 API 调用的身份验证。

第二步:开发验证接口

在配置消息推送前,需要先开发一个用于微信服务器验证的接口。

接入原理

微信服务器会向你的接口发送一个 GET 请求,包含以下参数:

参数说明
signature微信加密签名,结合了 token、timestamp、nonce 生成
timestamp时间戳
nonce随机数
echostr随机字符串

你需要验证 signature 是否正确,验证成功后原样返回 echostr,即表示接入成功。

官方文档消息与事件推送介绍

代码实现

1.路由注册与验证接口

func (h *OAHandler) RegisterRoutes(server *gin.Engine) {
	// 微信公众平台 (Official Account) 消息推送网关
	g := server.Group("/api/v1/oa")
	{
		// portal 门户:入口站点需对微信服务器免登录放行
		g.GET("/portal", h.VerifyEcho)
	}
}
func (h *OAHandler) VerifyEcho(ctx *gin.Context) {
	appId := h.getAppId(ctx)
	if appId == "" {
		h.l.Warn("微信公众平台验证请求缺失 appId 参数")
		response.Fail(ctx, ecode.InvalidParams.WithDetails("缺失 appId 参数"))
		return
	}

	// 定义微信验证请求参数
	type EchoReq struct {
		Signature string `form:"signature" binding:"required"`
		Timestamp string `form:"timestamp" binding:"required"`
		Nonce     string `form:"nonce" binding:"required"`
		Echostr   string `form:"echostr" binding:"required"`
	}

	var req EchoReq
	if valid, errs := validator.BindAndValid(ctx, &req); !valid {
		h.l.Warn("接收到非法微信公众平台验证请求,参数缺失或格式不符", zap.Any("errs", errs))
		response.Fail(ctx, ecode.InvalidParams.WithDetails(errs))
		return
	}

	// 验证签名
	if h.svc.CheckSignature(ctx, appId, req.Signature, req.Timestamp, req.Nonce) {
		h.l.Info("微信公众平台服务器验证成功", zap.String("echostr", req.Echostr), zap.String("appId", appId))
		// 验证成功,原样返回 echostr 字符串
		ctx.String(http.StatusOK, req.Echostr)
		return
	}

	h.l.Warn("微信公众平台服务器签名验证失败",
		zap.String("appId", appId),
		zap.String("signature", req.Signature),
		zap.String("timestamp", req.Timestamp),
		zap.String("nonce", req.Nonce))
	ctx.String(http.StatusForbidden, "Signature Verification Failed")
}

2.签名验证逻辑

func (s *oaService) CheckSignature(ctx context.Context, appId, signature, timestamp, nonce string) bool {
	// 获取公众号配置中的 Token
	oaConfig, err := s.oaConfigRepo.GetByAppId(ctx, appId)
	if err != nil || oaConfig == nil || oaConfig.Token == "" {
		s.l.Warn("OA Token 未配置或拉取失败", zap.String("appId", appId), zap.Error(err))
		return false
	}
	token := oaConfig.Token

	// 1. 将 token、timestamp、nonce 三个参数进行字典序排序
	params := []string{token, timestamp, nonce}
	sort.Strings(params)

	// 2. 将排序后的参数拼接成一个字符串
	var raw string
	for _, p := range params {
		raw += p
	}

	// 3. 对拼接后的字符串进行 SHA1 加密
	h := sha1.New()
	h.Write([]byte(raw))
	hashStr := hex.EncodeToString(h.Sum(nil))

	// 4. 将加密后的字符串与微信传来的 signature 对比
	return hashStr == signature
}

3.启动服务

启动本地服务,确保监听在指定端口(示例中为 8080)。

第三步:内网穿透配置

为了避免频繁部署代码进行调试,使用内网穿透工具在本地进行功能验证。本示例使用 Cpolar

启动 Cpolar 隧道

cpolar http 8080

启动后会显示隧道信息:

cpolar by @bestexpresser                              (Ctrl+C to quit)

Tunnel Status       online
Account             4343 (Plan: Free)
Version             3.18/3.18
Web Interface       127.0.0.1:4040
Forwarding          https://34c4e47f.r1.cpolar.top -> http://localhost:8080
Forwarding          http://34c4e47f.r1.cpolar.top -> http://localhost:8080
# Conn              0
Avg Conn Time       0.00ms

此时,公网可以通过 http://34c4e47f.r1.cpolar.tophttps://34c4e47f.r1.cpolar.top 访问你本地 8080 端口的服务。

提示:将 Cpolar 生成的 HTTPS 地址复制,下一步配置微信消息推送时会用到。

第四步:配置微信消息推送

启用消息推送功能

  1. 登录 微信开发者平台,在「我的业务与服务」中选择公众号或服务号
  2. 进入「域名与消息推送配置」模块,启用「消息推送」功能

配置推送参数

填写以下信息:

参数说明
URL你的服务器接收微信消息的接口地址,格式为 https://你的域名/api/v1/oa/portal
Token自己设置的字符串,用于签名验证(需要在代码中配置相同的值)
EncodingAESKey消息加密密钥(可选,建议填写以提高安全性)
消息加解密方式推荐选择「安全模式」

URL 详解

URL 本质上是你业务服务器上的一个消息接口。当用户在公众号发送消息时:

用户 → 微信服务器 → 你的服务器 URL

微信服务器会将用户消息转发到你配置的 URL,由你的服务器进行后续处理。

完成配置

点击「确定」按钮后:

  1. 如果配置正确,页面会显示「已启用」提示
  2. 消息推送配置栏会显示你的配置信息
  3. 你的本地服务会接收到一条来自微信服务器的验证请求

验证接入成功

看到本地服务接收到微信服务器的请求,即表示消息推送已成功接入。此时你可以在公众号中发送测试消息,验证消息推送功能是否正常工作。