Golang微信消息推送服务开发

最近在用Golang开发微信消息推送服务时遇到几个问题:

  1. 如何正确接入微信公众平台的API接口?文档里提到的access_token获取和刷新机制不太明白具体实现方式
  2. 消息加解密这块比较困惑,官方提供的加密库在Golang中要怎么使用?
  3. 推送消息时经常出现40001错误码,排查了半天也没找到原因
  4. 有没有成熟的Golang开源框架推荐?自己从零开发感觉有些吃力
  5. 高并发场景下如何保证消息推送的稳定性?特别是在access_token过期需要刷新的情况下
2 回复

要开发一个Golang微信消息推送服务,可以基于企业微信或微信公众号的API实现。以下是核心步骤:

  1. 选择推送方式

    • 企业微信:适合内部通知,API稳定
    • 公众号:适合对外推送,需用户关注
  2. 核心实现

    // 1. 获取访问令牌
    func GetAccessToken(corpID, secret string) string
    
    // 2. 消息结构体
    type TextMessage struct {
      ToUser  string `json:"touser"`
      MsgType string `json:"msgtype"`
      Text    struct {
        Content string `json:"content"`
      } `json:"text"`
    }
    
    // 3. 发送消息
    func SendMessage(token string, msg TextMessage) error
    
  3. 关键点

    • 令牌需要缓存(有效期2小时)
    • 支持文本/图文等消息格式
    • 处理微信API频率限制
    • 添加重试机制
  4. 部署建议

    • 使用gin框架提供HTTP接口
    • 用redis缓存access_token
    • 通过cron定时推送

示例项目结构:

/wechat-push
  ├── main.go      # 服务入口
  ├── wechat/      # 微信SDK封装
  ├── config/      # 配置管理
  └── storage/     # 令牌存储

更多关于Golang微信消息推送服务开发的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang中开发微信消息推送服务,主要涉及微信公众号或企业微信的API调用。以下是核心实现步骤和示例代码:

1. 准备工作

  • 注册微信公众号/企业微信,获取AppID和AppSecret
  • 配置服务器URL和Token(用于消息接收)

2. 核心代码实现

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

// 获取访问令牌
func getAccessToken(appID, appSecret string) (string, error) {
    url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appID, appSecret)
    
    resp, err := http.Get(url)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()
    
    body, _ := ioutil.ReadAll(resp.Body)
    
    var result struct {
        AccessToken string `json:"access_token"`
        ExpiresIn   int    `json:"expires_in"`
    }
    
    json.Unmarshal(body, &result)
    return result.AccessToken, nil
}

// 发送模板消息
func sendTemplateMessage(accessToken, openID, templateID string, data map[string]interface{}) error {
    url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s", accessToken)
    
    message := map[string]interface{}{
        "touser":      openID,
        "template_id": templateID,
        "data":        data,
    }
    
    jsonData, _ := json.Marshal(message)
    resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
    if err != nil {
        return err
    }
    defer resp.Body.Close()
    
    // 处理响应
    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Printf("发送结果: %s\n", string(body))
    return nil
}

func main() {
    appID := "your_appid"
    appSecret := "your_secret"
    
    // 获取访问令牌
    token, err := getAccessToken(appID, appSecret)
    if err != nil {
        panic(err)
    }
    
    // 发送模板消息示例
    data := map[string]interface{}{
        "first":    {"value": "您好,有新消息"},
        "keyword1": {"value": "系统通知"},
        "keyword2": {"value": time.Now().Format("2006-01-02 15:04:05")},
        "remark":   {"value": "请及时处理"},
    }
    
    err = sendTemplateMessage(token, "user_openid", "template_id", data)
    if err != nil {
        fmt.Printf("发送失败: %v\n", err)
    }
}

3. 服务器配置验证(接收消息)

// 验证服务器配置
func verifyServer(w http.ResponseWriter, r *http.Request) {
    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, "your_token") {
        w.Write([]byte(echostr))
    } else {
        w.WriteHeader(403)
    }
}

4. 注意事项

  • 访问令牌需要缓存,避免频繁请求
  • 消息模板需要在公众号后台配置
  • 处理消息时需要验证签名确保安全
  • 建议使用结构体封装消息数据

5. 扩展建议

  • 使用Redis缓存access_token
  • 添加重试机制
  • 使用协程处理并发请求
  • 集成Prometheus监控

这个基础框架可以满足大部分推送需求,根据具体业务场景调整消息模板和发送逻辑即可。

回到顶部