微信由模板消息改为订阅消息,其实我压根也不知道模板消息是个啥子,就在前几天,心血来潮,想试试这个消息订阅,发现目前只能是订阅消息,模板消息已经停止了。
开始搞不清楚这个逻辑,比如,服务端是否要保存用户订阅的记录啊?开始还写了,用户订阅了消息,我将用户胡openid和消息模板id存到数据库。
后来想想不对,用户取消订阅没有触发的事件呀,那我的数据库不就无法删除了嘛。
对的。咱们的服务端不需要存储哪些用户订阅了消息。你将所有用户都发一遍就对了。如果用户订阅了,微信的服务器自然就会发给他们消息,如果用户没有订阅,那么他们也收不到。
利用beego的定时任务功能,每天固定一个时间发送订阅消息。
所以,只要在小程序上,添加一个按钮,用户点击订阅即可,后端是不需要动作的。
服务端要想具备订阅消息的能力,需要配置2个接口,CheckSignature和sendmessage
// @Title get Signature
// @Description get Signature
// @Param signature query string true "The signature of wx"
// @Param timestamp query string true "The timestamp of wx"
// @Param nonce query string true "The nonce for wx"
// @Param echostr query string true "The echostr for wx"
// @Success 200 {object} models.GetProductsPage
// @Failure 400 Invalid page supplied
// @Failure 404 articls not found
// @router /checksignature [get]
// 检验signature v1/checkin/checksignature
func (c *CheckController) CheckSignature() {
token := "任意填"
signature := c.Input().Get("signature")
timestamp := c.Input().Get("timestamp")
nonce := c.Input().Get("nonce")
echostr := c.Input().Get("echostr")
tmps := []string{token, timestamp, nonce}
sort.Strings(tmps)
tmpStr := tmps[0] + tmps[1] + tmps[2]
tmp := str2sha1(tmpStr)
if tmp == signature {
c.Ctx.WriteString(echostr)
} else {
c.Data["json"] = map[string]interface{}{"tmp": tmp, "signature": signature}
c.ServeJSON()
}
}
另外一个就是给用户发送消息
func SendMessage() {
app_version := "4"
accessToken, err := utils.GetAccessToken(app_version)
if err != nil {
beego.Error(err)
}
template_id := "模板id"
//查出所有openid
openids, err := models.GetOpenIDs()
if err != nil {
beego.Error(err)
} else {
for _, i := range openids {
errcode, errmsg, err := utils.SendMessage(accessToken, i.OpenID, template_id)
if err != nil {
beego.Error(err)
} else if errcode == 40003 {
beego.Error("touser字段openid为空或者不正确" + errmsg)
} else if errcode == 40037 {
beego.Error("订阅模板id为空不正确" + errmsg)
} else if errcode == 43101 {
beego.Error("用户拒绝接受消息,如果用户之前曾经订阅过,则表示用户取消了订阅关系" + errmsg)
} else if errcode == 47003 {
beego.Error("模板参数不准确,可能为空或者不满足规则,errmsg会提示具体是哪个字段出错" + errmsg)
} else if errcode == 41030 {
beego.Error("page路径不正确,需要保证在现网版本小程序中存在,与app" + errmsg)
} else {
beego.Error("发送成功" + errmsg)
}
}
}
}
utils.SendMessage.go:
// 发送订阅消息
func SendMessage(access_token, openid, template_id string) (errcode float64, errmsg string, err error) {
requestUrl := "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + access_token
// 对于 POST 请求,部分参数需以 QueryString 的形式写在 URL 中(一般只有 access_token,如有额外参数会在文档里的 URL 中体现),其他参数如无特殊说明均以 JSON 字符串格式写在 POST 请求的 body 中。
// "content":content
// 打卡类型
// {{phrase1.DATA}}
// 打卡时间
// {{date2.DATA}}
// 打卡地点
// {{thing3.DATA}}
//***********这个也行
// b := `{
// "touser":"opl4B5YvCVXaatKF6VGUSbohMlWQ",
// "template_id":"c8Dped7TztDiMJ2bzHMu4G3nikn-mSOHmQEh_7aTlLo",
// "page":"index",
// "data":{
// "phrase1":{"value":"设代打卡"},
// "date2":{"value":"8:30"},
// "thing3":{"value":"顺德、南沙、东莞、深圳"}
// }
// }`
// resp, err := http.Post(requestUrl, "application/json;charset=utf-8", bytes.NewBuffer([]byte(b))) //注意,这里是post
var phrase11 phrase1
phrase11.Value = "设代打卡"
var date21 date2
date21.Value = "8:30"
var thing31 thing3
thing31.Value = "顺德、南沙、东莞、深圳"
var data1 data
data1.Phrase1 = phrase11
data1.Date2 = date21
data1.Thing3 = thing31
var message Message
message.Data = data1
message.Template_id = template_id
message.Page = "packageA/pages/search/search"
message.Touser = openid
wxmessage, err := json.Marshal(message)
if err != nil {
beego.Error(err)
return 0, "json转换错误", err
}
// jsons,_:=json.Marshal(teamworkinfo)
// result := string(wxmessage)
// jsoninfo := strings.NewReader(result)——这个不是以body形式传递
//估计下面的"application/json;charset=utf-8"不影响结果吧,没有试
resp, err := http.Post(requestUrl, "application/json;charset=utf-8", bytes.NewBuffer(wxmessage))
if err != nil {
beego.Error(err)
return 0, "post请求错误", err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
beego.Error(err)
return 0, "请求返回错误", err
}
var msgdata map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&msgdata)
if err != nil {
beego.Error(err)
return 0, "解析body错误", err
} else {
errcode := msgdata["errcode"].(float64)
errmsg := msgdata["errmsg"].(string)
return errcode, errmsg, nil
}
}
main.go里定时:
time1 := "* 30 8 * * 1-5"
//"* 30 8 * * 1-5"
tk1 := toolbox.NewTask("tk1", time1, func() error { controllers.SendMessage(); return nil }) //func() error { fmt.Println("tk1"); return nil }
toolbox.AddTask("tk1", tk1)
toolbox.StartTask()
defer toolbox.StopTask()
周一至周五,每天早上8.30发送订阅消息,提醒打卡。
以服务通知的形式发到微信中: