golang实现微信模板消息推送

    技术2023-12-19  94

    Golang实现发送微信模板消息(每日一句和天气预报)

    前言运行环境获取接口数据1、每日一句接口2、获取天气预报接口 二、微信公众平台接口测试帐号1、每日一句模板2、天气预报模板 三、发送微信模板消息的程序四、设置定时发送

    前言

    本文是基于https://www.cnblogs.com/connect/p/python-wechat-iciba.html 这篇博客写成的。该博客实现了用python将金山词霸的每日一句推送到微信公众测试号,我想既然python能实现,那么用Golang也可以。 特别提醒:另外是实际项目开发中,先在正式微信公众号平台找到合适的模板,获取到模板内容设置,然后在测试号中根据获取到的模板设置添加测试模板,获取到测试模板的模板id进行开发(遇到过的坑,因为不知道需要先去正式平台上获取模板内容设置,导致项目上线时找不到可用的模板) 。

    运行环境

    1、阿里云Linux服务器 2、Go开发环境 完整的项目代码:https://github.com/qq737310694/WechatTemplate

    获取接口数据

    1、每日一句接口

    参数必选参数必选date否string格式为:2013-05-06;如果date为空,则默认取当天type否string可选值为last和next;以date日期为准的,last返回前一天的,next返回后一天的

    返回类型:JSON JSON字段解释:

    属性名属性值类型说明sidstring每日一句IDttsstring音频地址contentstring英文内容notestring中文内容lovestring每日一句喜欢个数translationstring词霸小编picturestring图片地址picture2string大图片地址captionstring标题datelinestring时间s_pvstring浏览数sp_pvstring语音评测浏览数tagsarray相关标签fenxiang_imgstring合成图片,建议分享微博用的

    返回示例:

    { "sid": "3369", "tts": "http://news.iciba.com/admin/tts/2019-04-23-day.mp3", "content": "There is no such thing as a great talent without great will.", "note": "没有伟大的意志力,便没有雄才大略。", "love": "197", "translation": "小编的话:正如爱迪生所说一般,强者容易坚强。只有坚强的意志力才能给我们克服各种困难的勇气和决心。", "picture": "http://cdn.iciba.com/news/word/20190423.jpg", "picture2": "http://cdn.iciba.com/news/word/big_20190423b.jpg", "caption": "词霸每日一句", "dateline": "2019-04-23", "s_pv": "0", "sp_pv": "0", "tags": [ { "id": null, "name": null } ], "fenxiang_img": "http://cdn.iciba.com/web/news/longweibo/imag/2019-04-23.jpg" }

    请求示例:

    type sentence struct { Content string `json:"content"` Note string `json:"note"` Translation string `json:"translation"` } func getsen() (sentence, string) { resp, err := http.Get("http://open.iciba.com/dsapi/?date") sent := sentence{} if err != nil { fmt.Println("获取每日一句失败", err) return sent, "" } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("读取内容失败", err) return sent, "" } err = json.Unmarshal(body, &sent) if err != nil { fmt.Println("每日一句解析json失败") return sent, "" } fenxiangurl := gjson.Get(string(body), "fenxiang_img").String() fmt.Println(sent) return sent, fenxiangurl }

    这里使用了golang自带的http包发起了一次get请求,然后将返回的json数据解析出来,另外使用了gjon这个包,该包可以直接从json字符串中解析出需要的字段,十分方便。(其实这段代码我偷了个懒,如果内部有错误应该将错误return出去,大家不要学我啊 ~~o(>_<)o ~~)

    2、获取天气预报接口

    调用地址: https://www.tianqiapi.com/api 请求方式:GET 请求参数:

    参数必选类型说明version是stringv1(版本标识)cityid以下参数3选1string101120201(城市编号,不要带CN, 以下参数3选1)city3选1string青岛(城市名称,不要带市和区)ip3选1string27.193.XX.XXX(IP地址)callbackstringjsonp方式

    返回类型:JSON 返回示例:

    { "cityid": "101120201", "update_time": "2019-04-24 18:00:00", "city": "青岛", "cityEn": "qingdao", "country": "中国", "countryEn": "China", "data": [ { "day": "24日(今天)", "date": "2019-04-24", "week": "星期三", "wea": "阵雨", "wea_img": "lei", "air": 45, "humidity": 96, "air_level": "优", "air_tips": "空气很好,可以外出活动,呼吸新鲜空气,拥抱大自然!", "alarm": { "alarm_type": "大雾", "alarm_level": "橙色", "alarm_content": "青岛市气象台2019年04月24日02时15分继续发布大雾橙色预警信号:目前我市沿海地区和近海海域已出现能见度小于200米局部小于100米的大雾,预计今天凌晨到白天,我市沿海地区和近海海域仍将有能见度小于200米的大雾天气,局部小于100米,请注意防范。(预警信息来源:国家预警信息发布中心)" }, "tem1": "16℃", "tem2": "10℃", "tem": "13℃", "win": [ "南风" ], "win_speed": "3-4级", "hours": [ { "day": "24日20时", "wea": "晴", "tem": "13℃", "win": "南风", "win_speed": "<3级" }, { "day": "24日23时", "wea": "多云", "tem": "15℃", "win": "南风", "win_speed": "<3级" }, { "day": "25日02时", "wea": "多云", "tem": "15℃", "win": "南风", "win_speed": "<3级" }, { "day": "25日05时", "wea": "多云", "tem": "15℃", "win": "南风", "win_speed": "<3级" } ], "index": [ { "title": "紫外线指数", "level": "最弱", "desc": "辐射弱,涂擦SPF8-12防晒护肤品。" }, { "title": "减肥指数", "level": null, "desc": "天气较舒适,减肥正当时。" }, { "title": "健臻·血糖指数", "level": "较易波动", "desc": "血糖较易波动,注意监测。" }, { "title": "穿衣指数", "level": "较冷", "desc": "建议着厚外套加毛衣等服装。" }, { "title": "洗车指数", "level": "不宜", "desc": "有雨,雨水和泥水会弄脏爱车。" }, { "title": "空气污染扩散指数", "level": "中", "desc": "易感人群应适当减少室外活动。" } ] } ] }

    该接口会返回往后一周的天气预报,因为返回的参数过多,我只截取了当天的数据。如果需要其它数据可以自己请求一下。

    请求示例代码:

    func getweather(city string) (string, string, string, string) { url := fmt.Sprintf("https://www.tianqiapi.com/api?version=%s&city=%s", WeatherVersion, city) resp, err := http.Get(url) if err != nil { fmt.Println("获取天气失败", err) return "", "", "", "" } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("读取内容失败", err) return "", "", "", "" } data := gjson.Get(string(body), "data").Array() thisday := data[0].String() day := gjson.Get(thisday, "day").Str //日期 wea := gjson.Get(thisday, "wea").Str //天气 tem := gjson.Get(thisday, "tem").Str //平均气温 air_tips := gjson.Get(thisday, "air_tips").Str //提示 return day, wea, tem, air_tips }

    get请求获得天气数据,gjson包将当天的天气信息解析出来后返回。同样地,偷懒错误没return出去 ?。

    二、微信公众平台接口测试帐号

    通过上一步我们已经成功的获取到了数据,接下来申请一个微信公众平台测试帐号,其实正式帐号的操作也是一样的,但方便起见,我们直接用测试号。

    1、每日一句模板

    1、扫码登录公众平台测试号 申请测试号的地址 https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login 2、手机上确认登录 3、找到 新增测试模板 ,添加模板消息 填写模板标题 《每日一句》,填写如下模板内容

    {{content.DATA}} {{note.DATA}} {{translation.DATA}}

    注意:后面的.DATA必须保留,前面是你定义的字段。 提交保存之后,记住该模板ID,一会儿会用到 4、找到测试号信息,记住 appid 和 appsecret,一会儿会用到 5、找到测试号二维码。手机扫描此二维码,关注之后,你的昵称会出现在右侧列表里,记住该微信号,一会儿会用到(注:此微信号非你真实的微信号,而是你的微信在关注了该测试号后分配的在该号下的唯一ID)

    2、天气预报模板

    和每日一句的添加方法一样,区别在于第3步中新增测试模板使用的模板不同:

    {{city.DATA}} {{day.DATA}} {{wea.DATA}} {{tem1.DATA}} {{air_tips.DATA}}

    三、发送微信模板消息的程序

    //发送每日一句,将json字符串拼接好后调用templatepost函数发送模板 func everydaysen() { req, fxurl := getsen() if req.Content == "" { return } access_token := getaccesstoken() if access_token == "" { return } flist := getflist(access_token) //获取公众号关注人列表 if flist == nil { return } reqdata := "{\"content\":{\"value\":\"" + req.Content + "\", \"color\":\"#0000CD\"}, \"note\":{\"value\":\"" + req.Note + "\"}, \"translation\":{\"value\":\"" + req.Translation + "\"}}" for _, v := range flist { templatepost(access_token, reqdata, fxurl, SentTemplateID, v.Str) } } //发送天气预报 func weather() { access_token := getaccesstoken() if access_token == "" { return } flist := getflist(access_token) if flist == nil { return } var city string for _, v := range flist { switch v.Str { case "oeZ6P5kyGsLKn3sIGRVfpb8oT4mg": city = "青岛" go sendweather(access_token, city, v.Str) case "oeZ6P5jvFNh2y_h_2UcaoTXBaC2o": city = "西安" go sendweather(access_token, city, v.Str) default: } } fmt.Println("weather is ok") } //获取微信accesstoken func getaccesstoken() string { url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%v&secret=%v", APPID, APPSECRET) resp, err := http.Get(url) if err != nil { fmt.Println("获取微信token失败", err) return "" } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("微信token读取失败", err) return "" } token := token{} err = json.Unmarshal(body, &token) if err != nil { fmt.Println("微信token解析json失败", err) return "" } return token.AccessToken } //获取关注人列表 func getflist(access_token string) []gjson.Result { url := "https://api.weixin.qq.com/cgi-bin/user/get?access_token=" + access_token + "&next_openid=" resp, err := http.Get(url) if err != nil { fmt.Println("获取关注列表失败", err) return nil } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("读取内容失败", err) return nil } flist := gjson.Get(string(body), "data.openid").Array() return flist } //发送模板消息代码 func templatepost(access_token string, reqdata string, fxurl string, templateid string, openid string) { url := "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + access_token reqbody := "{\"touser\":\"" + openid + "\", \"template_id\":\"" + templateid + "\", \"url\":\"" + fxurl + "\", \"data\": " + reqdata + "}" resp, err := http.Post(url, "application/x-www-form-urlencoded", strings.NewReader(string(reqbody))) if err != nil { fmt.Println(err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println(err) return } fmt.Println(string(body)) } //拼接json字符串,调用templatepost函数发送天气模板 func sendweather(access_token, city, openid string) { day, wea, tem, air_tips := getweather(city) if day == "" || wea == "" || tem == ""|| air_tips == "" { return } reqdata := "{\"city\":{\"value\":\"城市:" + city + "\", \"color\":\"#0000CD\"}, \"day\":{\"value\":\"" + day + "\"}, \"wea\":{\"value\":\"天气:" + wea + "\"}, \"tem1\":{\"value\":\"平均温度:" + tem + "\"}, \"air_tips\":{\"value\":\"tips:" + air_tips + "\"}}" //fmt.Println(reqdata) templatepost(access_token, reqdata, "", WeatTemplateID, openid) }

    在发送模板消息之前要先获取微信 accesstoken 和 关注人列表 ,再遍历所有关注人,给每位关注人发模板消息,或者给某位特定的人发送。

    四、设置定时发送

    func main() { spec := "0 0 12 * * *" // 每天12:00 spec1 := "0 0 7 * * *" // 每天早晨7:00 c := cron.New() c.AddFunc(spec, everydaysen) c.AddFunc(spec1, weather) c.Start() fmt.Println("开启定时任务") select {} //weather() //everydaysen() }

    使用了 github.com/robfig/cron 包的定时任务,使每天早晨7点和中午12点发送天气预报和每日一句。

    spec := “0 0 12 * * *” 这里对应的分别是 “ 秒 分 时 日 月 周 ” 和linux里的crontab定时任务差不多。

    在阿里云Linux服务器上后台启动该程序既可。

    程序运行结果截图: 完整的项目代码:https://github.com/qq737310694/WechatTemplate ———————————————— 版权声明:本文为博主「我是要成为大神的男人」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/u012140251/article/details/89529540

    Processed: 0.024, SQL: 9