Golang實現發送微信模板消息(每日一句和天氣預報)
前言
本文是基於https://www.cnblogs.com/connect/p/python-wechat-iciba.html 這篇博客寫成的。該博客實現了用python將金山詞霸的每日一句推送到微信公衆測試號,我想既然python能實現,那麼用Golang也可以。
運行環境
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 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
————————————————
版權聲明:本文爲CSDN博主「我是要成爲大神的男人」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u012140251/article/details/89529540