go 集成个推需严格实现鉴权与 token 管理:签名用 sha256(appsecret+nonce+timestamp) 小写十六进制,nonce 为 10 位随机数,timestamp 用秒级 unix 时间;先调 /auth/token 获取 access_token 并缓存复用,推送时换 authorization: bearer;单设备推送需正确构造 audience.cid 数组、message.msg_type 等字段;token 失效时自动刷新重试一次。

Go 语言集成个推(Getui)推送服务,官方没有提供 Go SDK,必须自己封装 HTTP API 调用。直接硬编码拼 URL + json.Marshal 发请求,上线后大概率失败——不是签名错,就是时间戳/nonce 校验不通过,或者 token 过期没刷新。
个推鉴权:签名生成必须严格按文档算,别手写 base64 或 sha256
个推所有接口都要求 Authorization 请求头,格式为 GT<appkey>:<sign></sign></appkey>,其中 sign 是 sha256(appSecret + nonce + timestamp) 的十六进制小写字符串(不是 base64)。常见错误:
- 用
base64.StdEncoding.EncodeToString()替代fmt.Sprintf("%x", hash.Sum(nil)),导致 sign 错误 -
nonce用了固定字符串或 UUID,个推要求是 10 位随机数字(如rand.Intn(900000000) + 100000000) -
timestamp用time.Now().Unix(),但个推服务端校验窗口只有 ±300 秒,且要求秒级(不是毫秒),务必截断:time.Now().Unix() - 拼接前没确保
appSecret是原始密钥(控制台「应用配置」里那个 32 位 hex 字符串),不是 base64 编码后的
推送接口调用:别直接 POST /push/single/device,先走 /auth/token 拿 access_token
个推 v2 API 所有推送操作都依赖短期有效的 access_token(有效期 2 小时),必须先调用 /auth/token 获取。关键点:
- 该接口本身也需鉴权,同样走
Authorization: GT<appkey>:<sign></sign></appkey> - 返回的
access_token必须缓存并复用,不能每次推送都重新取;建议用sync.Map存,key 为appKey,value 带过期时间戳 - 若返回
{"result":"error","reason":"invalid appkey or secret"},90% 是appKey或appSecret填错了,注意控制台区分「应用标识」和「应用密钥」 - 推送时请求头要换掉:
Authorization: Bearer <access_token></access_token>,不是 GT 开头
单设备推送:/push/single/device 的 payload 结构容易少字段
向单个 CID(个推设备唯一标识)发消息,必须 POST 到 /push/single/device,body 是 JSON,但字段名和嵌套层级很具体:
- 外层必须有
request_id(建议用xid.New().String()生成,保证唯一可追溯) -
audience里必须是{"cid": ["xxx"]},不是{"cid": "xxx"}(即使只推一个也要包数组) -
message里msg_type必须是"notify"(通知)或"cmd"(透传),不能漏 -
notification是可选的,但如果要显示通知栏,必须包含title和content;iOS 还得额外加ios对象,含sound、badge等 - HTTP 客户端别用默认 timeout,个推响应慢(尤其高峰时段),设
http.Client{Timeout: 15 * time.Second}
token 过期与重试:access_token 失效时别 panic,要自动刷新再重放
调用推送接口返回 401 Unauthorized 或 {"result":"error","reason":"invalid access_token"},说明 token 已过期或被回收。此时不能直接返回 error,而应:
- 加锁(比如
sync.Mutex)防止多个 goroutine 同时刷新 token - 调用
/auth/token重新获取,并更新缓存 - 把原请求 body 重放一次(注意:body 是
io.Reader,已读完需重新构造,建议提前用bytes.Buffer缓存) - 最多重试 1 次,避免死循环;重试后还失败,才记录日志并返回 error
真正难的不是第一次调通,而是 token 自动续期、CID 绑定生命周期管理、以及 Android/iOS 推送效果差异带来的埋点验证——这些没法靠一次 HTTP 请求解决,得结合客户端上报和个推后台数据交叉比对。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











