以下是一个基于Go语言的微信公众号消息接收与回复实战案例,包含详细注释和配置说明:
package main
import (
"crypto/sha1"
"encoding/xml"
"fmt"
"io"
"log"
"net/http"
"sort"
"strings"
"time"
)
// 微信公众号配置信息(需替换为实际值)
const (
token = "your_wechat_token" // 公众号服务器配置Token
appID = "your_app_id" // 公众号AppID
appSecret = "your_app_secret" // 公众号AppSecret
serverPort = "8080" // 服务器监听端口
)
// TextMessage 接收的文本消息结构体
type TextMessage struct {
XMLName xml.Name `xml:"xml"`
ToUserName string `xml:"ToUserName"`
FromUserName string `xml:"FromUserName"`
CreateTime int64 `xml:"CreateTime"`
MsgType string `xml:"MsgType"`
Content string `xml:"Content"`
MsgId int64 `xml:"MsgId"`
}
// TextResponse 文本消息回复结构体
type TextResponse struct {
XMLName xml.Name `xml:"xml"`
ToUserName CDATA `xml:"ToUserName"`
FromUserName CDATA `xml:"FromUserName"`
CreateTime int64 `xml:"CreateTime"`
MsgType CDATA `xml:"MsgType"`
Content CDATA `xml:"Content"`
}
// CDATA 处理XML CDATA标签
type CDATA struct {
Value string `xml:",cdata"`
}
func main() {
// 设置路由处理函数
http.HandleFunc("/wechat", wechatHandler)
// 启动HTTP服务器
log.Printf("Starting server on :%s...", serverPort)
err := http.ListenAndServe(":"+serverPort, nil)
if err != nil {
log.Fatal("Server start failed: ", err)
}
}
// 微信消息处理入口
func wechatHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
// 验证服务器地址有效性
verifyServer(w, r)
case "POST":
// 处理用户消息
processMessage(w, r)
default:
w.WriteHeader(http.StatusMethodNotAllowed)
fmt.Fprintf(w, "Method not allowed")
}
}
// 验证微信服务器(首次配置使用)
func verifyServer(w http.ResponseWriter, r *http.Request) {
// 获取URL参数
query := r.URL.Query()
signature := query.Get("signature")
timestamp := query.Get("timestamp")
nonce := query.Get("nonce")
echostr := query.Get("echostr")
// 校验签名
if checkSignature(signature, timestamp, nonce) {
w.WriteHeader(http.StatusOK)
w.Write([]byte(echostr))
log.Println("Server verification successful")
} else {
w.WriteHeader(http.StatusForbidden)
log.Println("Invalid signature")
}
}
// 校验签名有效性
func checkSignature(signature, timestamp, nonce string) bool {
// 将token、timestamp、nonce按字典序排序
strs := sort.StringSlice{token, timestamp, nonce}
sort.Sort(strs)
combined := strings.Join(strs, "")
// SHA1加密
hasher := sha1.New()
hasher.Write([]byte(combined))
sha := fmt.Sprintf("%x", hasher.Sum(nil))
return sha == signature
}
// 处理用户消息
func processMessage(w http.ResponseWriter, r *http.Request) {
// 读取请求体
body, err := io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
log.Printf("Error reading body: %v", err)
return
}
defer r.Body.Close()
// 解析XML消息
var msg TextMessage
if err := xml.Unmarshal(body, &msg); err != nil {
w.WriteHeader(http.StatusBadRequest)
log.Printf("Error unmarshaling XML: %v", err)
return
}
// 构造回复消息
response := createTextResponse(msg.FromUserName, msg.ToUserName, "已收到您的消息: "+msg.Content)
// 序列化为XML
respXML, err := xml.Marshal(response)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Printf("Error marshaling response: %v", err)
return
}
// 返回响应
w.Header().Set("Content-Type", "application/xml")
w.Write(respXML)
}
// 创建文本回复消息
func createTextResponse(toUser, fromUser, content string) TextResponse {
return TextResponse{
ToUserName: CDATA{toUser},
FromUserName: CDATA{fromUser},
CreateTime: time.Now().Unix(),
MsgType: CDATA{"text"},
Content: CDATA{content},
}
}
🛠 前置条件
- 拥有微信公众平台账号(订阅号或服务号)
- 进入公众号后台 -> 开发 -> 基本配置:
- 启用服务器配置
- 设置服务器URL(示例:
http://your-domain.com/wechat
) - 设置Token(与代码中
token
常量一致)
- 服务器要求:
- 公网可访问(本地开发可使用ngrok等内网穿透工具)
- 支持HTTP 80/443端口(若用其他端口需在URL中明确)
📦 依赖项
- Go 1.16+ 开发环境
- 标准库:
net/http
:HTTP服务器encoding/xml
:XML处理crypto/sha1
:签名验证sort
:参数排序
🚨 注意事项
-
安全规范:
- 验证消息来源(必须校验签名)
- 敏感信息不要硬编码(建议使用环境变量)
- 生产环境必须使用HTTPS
-
消息处理:
- 微信服务器5秒超时限制
- 消息去重(通过MsgId)
- 支持消息加密模式(示例为明文模式)
-
服务器配置:
# 使用ngrok进行内网穿透示例 ngrok http 8080
-
运行方式:
# 设置环境变量(推荐) export WECHAT_TOKEN="your_token" export WECHAT_APPID="your_appid" # 编译运行 go build -o wechat-server ./wechat-server
🧰 功能扩展建议
- 添加消息加解密支持(使用
wechat-crypto
库) - 支持更多消息类型(图片、语音、事件等)
- 集成AccessToken管理
- 添加消息日志记录
- 实现自定义菜单管理
完整项目结构建议:
/wechat-demo
├── config
│ └── config.go # 配置管理
├── wechat
│ ├── crypto.go # 加解密处理
│ ├── message.go # 消息结构定义
│ └── service.go # 核心业务逻辑
├── go.mod
└── main.go # 入口文件
该代码实现了微信公众号基础的消息接收与回复功能,可通过扩展支持更多微信生态功能(菜单、支付、模板消息等)。生产环境使用时请务必添加错误处理、日志记录和监控机制。