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字段解释:

属性名 属性值类型 说明
sid string 每日一句ID
tts string 音频地址
content string 英文内容
note string 中文内容
love string 每日一句喜欢个数
translation string 词霸小编
picture string 图片地址
picture2 string 大图片地址
caption string 标题
dateline string 时间
s_pv string 浏览数
sp_pv string 语音评测浏览数
tags array 相关标签
fenxiang_img string 合成图片,建议分享微博用的

返回示例:

{"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 string v1(版本标识)
cityid 以下参数3选1 string 101120201(城市编号,不要带CN, 以下参数3选1)
city 3选1 string 青岛(城市名称,不要带市和区)
ip 3选1 string 27.193.XX.XXX(IP地址)
callback string jsonp方式

返回类型: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 stringfor _, 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_tokenreqbody := "{\"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:00spec1 := "0 0 7 * * *" // 每天早晨7:00c := 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
————————————————
版权声明:本文为CSDN博主「我是要成为大神的男人」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012140251/article/details/89529540

golang实现微信模板消息推送相关推荐

  1. php 异步请求微信模板消息_php实现微信模板消息推送

    本文实例为大家分享了php微信模板消息推送的具体代码,供大家参考,具体内容如下 1.微信公众号模板消息配置 2.PHP代码/*** 发送模板消息*/ public function send_noti ...

  2. springboot实现微信模板消息推送

    springboot实现微信模板消息推送 在上一篇文章我们已经知道了怎么获取openid 还不知道的可以查看我的上一篇文章springboot+微信小程序用codeid换取openid 这次我们不光要 ...

  3. java 微信模板_java开发微信模板消息推送

    概述 微信公众平台开始支持前端网页,大家可能看到很多网页上都有分享到朋友圈,关注微信等按钮,点击它们都会弹出一个窗口让你分享和关注,这个是怎么实现的呢?今天就给大家讲解下如何在微信公众平台前端网页上添 ...

  4. PHP之 微信模板消息推送 的相关代码

    温馨提示: 微信模板消息推送,得先去微信端,设置模板配置,会生成相应的消息模板id,这个是一串字符,需连同参数数据,传给微信端,切记!~ 第一部分:主体部分代码,负责业务模块,准备微信端所需参数 /* ...

  5. java开发微信模板消息推送

    完整demo下载 概述 微信公众平台开始支持前端网页,大家可能看到很多网页上都有分享到朋友圈,关注微信等按钮,点击它们都会弹出一个窗口让你分享和关注,这个是怎么实现的呢?今天就给大家讲解下如何在微信公 ...

  6. 微信模板消息推送(内附工具类代码)

    文章目录 前言 一.添加模板消息 1.进入微信公众号后台 2.模板消息 3.填写信息 4.审核通过后 二.开发步骤 1.依赖坐标 2.实体类 1)AccessToken 2.WxTemplate模板消 ...

  7. Java实现微信模板消息推送

    模板消息推送功能仅限于微信服务号才行. 1.准备:微信公众号 appId,app密钥(这俩没啥好说的,都知道在哪拿). 模板Id,添加之后就能看到,如果没有合适的模板可以自定义模板(需要审核7-15天 ...

  8. qhfl-9 微信模板消息推送

    开发中用的是测试号 微信公众号认证流程 用户登陆 <!DOCTYPE html> <html lang="en"> <head><meta ...

  9. 微信模板消息推送接口说明

    微信服务号可以给关注此号码的粉丝推送消息.消息分为三种: 1.群发消息:给所有关注此微信的人同时发送,但每个月的发送次数有限制. 2.向单个粉丝发送消息:此种功能发送次数没有限制,但是接受消息的粉丝必 ...

  10. 微信模板消息推送心得

    我使用amp的软件,上百度找到相关的代码,复制,保存到php文件上,然后,打开浏览器,查看效果.遇到下面的问题 1.网页打不开,提示连接已重置. 后来发现,原来在apache下的logs文件夹内的er ...

最新文章

  1. Verilog中的条件编译语句 `ifdef、`else、`endif 等
  2. Codeforces 1198 1199
  3. Apache Maven 入门篇
  4. php.ini-development和php.ini-production的区别
  5. JavaSE进阶学习笔记-目录汇总(待完成)
  6. spark-sql建表语句限制_SparkSQL
  7. easyui crud java_Easyui 创建 CRUD 应用_EasyUI 插件
  8. 1.12 深层循环神经网络
  9. 软考——软件工程——结构化分析与设计方法
  10. Java实现本地缓存、分布式缓存及多级缓存
  11. matlab opnet,opnet环境变量和matlab联调心得
  12. 为什么买入不了创业版_为什么说不能买创业板?
  13. Fiddler调式使用(一)深入研究[转载]
  14. C语言读取文件时txt中的汉字出现乱码的解决方案
  15. 数据管理执行指南 | 你需要知道什么?
  16. 计算机语言的魅力,四年级语文下册《语言的魅力》说课稿
  17. linux环境下questasim 10.7的安装步骤
  18. 【P2P overlay network】跨内外网络虚拟私有云
  19. 腾讯后台面经大全(整合版)
  20. Linux基础知识问题解答

热门文章

  1. vim打开bin文件
  2. 常见的显卡故障与原因
  3. 现场直击 | 复旦MBA科创青干营开营
  4. 什么叫运营---一个人,一张网,一艘船,独钓寒江雪!
  5. 电脑技巧 ADSL如何远程盗号
  6. c 和易语言如何传字节集,易语言字节集参数传递详解
  7. 计算机软件维护方法,计算机软件维护策略
  8. 网络安全浏览器工作原理
  9. python如何确定拐点_如何在嘈杂的曲线中找到拐点?
  10. python求曲线拐点_使用Python检测新冠肺炎疫情拐点