Golangは、WeChat公式アカウントテンプレートメッセージ(毎日の文と天気予報)の送信を実現します

Golangは、WeChatテンプレートメッセージ(その日の文と天気予報)の送信を実装します

序文

この記事は、ブログhttps://www.cnblogs.com/connect/p/python-wechat-iciba.htmlに基づいてますこのブログでは、python使用してKingsoft PowerWordの毎日の文をWeChatパブリックテストアカウントにプッシュするように実装しています。pythonを実装できるので、Golangも使用できると思います

その後、毎朝自分とガールフレンドに天気予報のリマインダーを追加して、それを始めました、gogogo!

動作環境

  1. アリババクラウドLinuxサーバー
  2. 開発環境に行く

完全なプロジェクトコード:https//github.com/qq737310694/WechatTemplate

1つは、インターフェイスデータを取得する

1。1日あたり1文のインターフェース

呼び出し元アドレス:http//open.iciba.com/dsapi/
要求メソッド:GET
要求パラメーター:

パラメータ 必須 の種類 説明
日付 番号 ストリング 形式は次のとおりです。2013-05-06;日付が空の場合、デフォルトで当日が使用されます
タイプ 番号 ストリング オプションの値はlastとnextです。日付に基づいて、lastは前日を返し、nextは翌日を返します。

戻りタイプ:JSON
JSONフィールドの説明:

属性名 属性値タイプ 説明
sid ストリング 1日1つのID
tts ストリング 音声アドレス
コンテンツ ストリング 英語のコンテンツ
注意 ストリング 中国のコンテンツ
愛する ストリング 1日あたりのいいねの数
翻訳 ストリング PowerWordエディター
画像 ストリング 地図の住所
picture2 ストリング 全体像のアドレス
キャプション ストリング 題名
デートライン ストリング 時間
s_pv ストリング 視聴回数
sp_pv ストリング 音声評価ビュー
タグ アレイ 関連タグ
fenxiang_img ストリング 合成画像、Weiboを共有することをお勧めします

戻り例:

{
    "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データを解析し、json文字列から必要なフィールドを直接解析できるgjonパッケージを使用します。これは非常に便利です。(実際、私はこのコードを盗みました。内部エラーがある場合は、エラーを返す必要があります。私をフォローしないでください~~ o(> _ <)o ~~)

2.天気予報インターフェースを取得します

呼び出し元アドレス:https//www.tianqiapi.com/api
要求メソッド:GET
要求パラメーター:

パラメータ 必須 の種類 説明
バージョン はい ストリング v1(バージョン識別)
cityid 次のパラメータのいずれかを選択してください ストリング 101120201(都市番号、CNを持参しない、次のパラメーターの3つから1つを選択)
31を選択 ストリング Qingdao(市名、市や地区を持参しないでください)
ip 31を選択 ストリング 27.193.XX.XXX(IPアドレス)
折り返し電話 ストリング 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パッケージはその日の天気情報を解析して返します。同様に、怠惰なエラーは返されませんでしたか?

2.WeChatパブリックプラットフォームインターフェイステストアカウント

前の手順でデータを取得できました。次に、WeChatパブリックプラットフォームのテストアカウントを申請します。実際には、公式アカウントの操作は同じですが、便宜上、テストアカウントを直接使用します。

1.毎日の文のテンプレート

  1. コードをスキャンして、パブリックプラットフォームのテスト
    アカウントにログインします。テストアカウントに申請するアドレスhttps://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
  2. 電話でのログインを確認する
  3. 新しいテストテンプレートを見つけ、メッセージテンプレートここに写真の説明を挿入
    追加して、テンプレートのタイトル「Daily a」を入力し、次のテンプレートコンテンツを入力します

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

注:後ろの.DATAは保持する必要があり、前のフィールドは定義したフィールドです。ここに写真の説明を挿入
送信して保存した後、テンプレートIDを覚えておいてください。後で使用しますここに写真の説明を挿入

  1. テスト番号情報を見つけ、appidappsecretを覚えておいください。後で必要になりますここに写真の説明を挿入
  2. テスト番号のQRコードを見つけますこのQRコードを携帯電話でスキャンします。フォローすると、右側のリストにニックネームが表示されます。WeChatIDを覚えておくと、後で使用できます(注:このWeChat IDは、実際のWeChat IDではなく、WeChatIDです。テスト番号の下に割り当てられた一意のIDに注意してください)ここに写真の説明を挿入

2.天気予報テンプレート

これは、その日の文を追加する方法と同じですが、違いはステップ3で使用される新しいテストテンプレート異なることです。

{ {city.DATA}}
{ {day.DATA}}
{ {wea.DATA}}
{ {tem1.DATA}}
{ {air_tips.DATA}}
ここに写真の説明を挿入

3.WeChatテンプレートメッセージを送信するための手順

//发送每日一句,将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)
}

テンプレートのマイクロレターアクセストークン関係者リストを送信する前に、まずメッセージを取得します。次に、すべての関係者を通じて、各テンプレートへの人間の髪の毛を心配してメッセージを送信するか、特定の人に誰かを送信します。

4、送信するタイミングを設定します

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タイミングタスクに似ています。

AliyunLinuxサーバーのバックグラウンドでプログラムを開始できます。

プログラムの結果のスクリーンショット:
ここに写真の説明を挿入
完璧な解決策、わかりました、完璧ではありません。実際、コードにはまだ最適化の余地がたくさんあります。時間が厳しいため、最適化されません。わかりますか?O(∩_∩)O〜

完全なプロジェクトコード:https//github.com/qq737310694/WechatTemplate

おすすめ

転載: blog.csdn.net/u012140251/article/details/89529540