首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >小程序利用golang beego实现订阅消息服务端

小程序利用golang beego实现订阅消息服务端

作者头像
hotqin888
发布2020-02-24 15:46:40
1.2K0
发布2020-02-24 15:46:40
举报
文章被收录于专栏:hotqin888的专栏hotqin888的专栏

微信由模板消息改为订阅消息,其实我压根也不知道模板消息是个啥子,就在前几天,心血来潮,想试试这个消息订阅,发现目前只能是订阅消息,模板消息已经停止了。

开始搞不清楚这个逻辑,比如,服务端是否要保存用户订阅的记录啊?开始还写了,用户订阅了消息,我将用户胡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发送订阅消息,提醒打卡。

以服务通知的形式发到微信中: 

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-02-20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档