Asp.net core(c#)实现在微信公众号定时推送模板消息(包括获取access_token、openid与unionid)

一、登录微信公众号平台,进行模板消息设置

(1)URL:https://mp.weixin.qq.com/ , 扫描登录

在这里插入图片描述
扫码进入之后,如下图所示:
在这里插入图片描述

(2)进行模板消息的设置

点击左边的 新的功能,如下所示:
在这里插入图片描述
在这里可以使用订阅通知模板,也可以使用模板消息,我这里使用模板消息如下所示:
在这里插入图片描述
再点击查看功能,就可以看见你添加的历史模板:
在这里插入图片描述
如果你需要添加模板,点击 类目模板和从类目模板中添加,如下图所示:
在这里插入图片描述
我这里就只添加了服务类目中的商业服务->软件/建站/技术开发,里面有各种模板,你可以自由选择合适自己的模板,如下所示:
在这里插入图片描述
在这里你还可以添加类目,如下所示:
在这里插入图片描述
至此,在微信公众号上进行模板添加的步骤已经完成,大家可以参考,详细添加可以看看官方介绍。

二、通过微信公众号的AppID与AppSecret 获取AccessToken、openid及unionid,因为在后面构建请求的url与temp中会使用到

参考微信官方给出的请求方法(非常重要与详细,建议大家好好看一下):https://developers.weixin.qq.com/doc/channels/API/basics/getaccesstoken.html

//Requests为一个通用的get或post请求方法,RequestUrl为请求的地址,RequestMethod请求的get或post
 public static string Requests(string RequestUrl, string RequestMethod)
 {
     string RequestUrls = RequestUrl;
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(RequestUrls);
     request.Method = RequestMethod;
     request.ContentType = "textml;charset=UTF-8";
     HttpWebResponse response = (HttpWebResponse)request.GetResponse();
     Stream myResponseStream = response.GetResponseStream();
     StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
     string jsonData = myStreamReader.ReadToEnd();
     myStreamReader.Close();
     myResponseStream.Close();
     string jsonString = jsonData;
     return jsonString;
 }
 private static void Get(object source, ElapsedEventArgs e)
 {
     //通过AppID与AppSecret 获取AccessToken
     string AppID = "XXXXXXX";
     string AppSecret = "XXXXXXX";
     string AccessTokenUrl = String.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", AppID, AppSecret); //接口地址构建
     string AccessToken = Requests(AccessTokenUrl, "get");//请求方法为get
     JObject json1 = JObject.Parse(AccessToken);
     //Console.WriteLine(json1["access_token"]); //打印获取的access_token

     //通过AccessToken 获取openid
     string OpenidUrl = String.Format("https://api.weixin.qq.com/cgi-bin/user/get?access_token={0}", json1["access_token"]);//接口地址构建
     string OpenidList = Requests(OpenidUrl, "get");//请求方法为get
     JObject json2 = JObject.Parse(OpenidList);
     //Console.WriteLine(json2["data"]["openid"]); //打印获取的openid

     //通过AccessToken与openid 获取unionid(由于获取的openid很多,是一个list形式,因此遍历循环请求每一个openid获取它相应的unionid)
     for (int i = 0; i < json2["data"]["openid"].Count(); i++)
     {
         string UserInfoUrl = String.Format(" https://api.weixin.qq.com/cgi-bin/user/info?access_token={0}&openid={1}&lang=zh_CN", json1["access_token"], json2["data"]["openid"][i]);//接口地址构建
         string UserInfo = Requests(UserInfoUrl, "get");//请求方法为get
         JObject json3 = JObject.Parse(UserInfo);
         Console.WriteLine(json3["unionid"] + "+" + json2["data"]["openid"][i]);
     }
 }

三、推送代码的构建

推送的相关参数构造和接口详情,参考官方:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Template_Message_Interface.html#6

定时到每天上午的9点30分进行代码的执行

        private static void SendTemplateMessage(object source, ElapsedEventArgs e)
        {
            if (DateTime.Now.Hour == 9 && DateTime.Now.Minute == 30)
            {
                DataTable dt1 = new DataTable();
                string sql1 = " select XXXX from XXXX"; //数据库中获取数据,进行判断是否符合推送要求
                string str1 = GlobalFunction.selectDB(sql1, ref dt1);
                for (int i = 0; i < dt1.Rows.Count; i++)
                {
                    DateTime start = Convert.ToDateTime(DateTime.Now);
                    DateTime end = Convert.ToDateTime(dt1.Rows[i]["XXXX"]);
                    TimeSpan sp = end.Subtract(start);
                    if (sp.Days == 30) //判断两个时间是否相差30天,如果正好等于30天就进行推送
                    {
                        string strReturn = "";
                        try
                        {
                            //获取 access_token
                            string AppID = "XXXXXXXX";
                            string AppSecret = "XXXXXXXX";
                            string AccessTokenUrl = String.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", AppID, AppSecret);//构建请求的url,获取access_token
                            string AccessToken = Requests(AccessTokenUrl, "get");
                            JObject json1 = JObject.Parse(AccessToken);
                            var accessToken = json1["access_token"];
                            //获取推送者的 openid
                            DataTable dt2 = new DataTable();
                            string sql2 = " select XXXX from XXXX U1 inner join XXXX U2 on U1.WxUnionId=U2.UnionId"
                                   + " where XXXX";
                            string str2 = GlobalFunction.selectDB(sql2, ref dt2);
                            for (int j = 0; j < dt2.Rows.Count; j++)
                            {
                                string openId = dt2.Rows[j]["WxOpenId"].ToString();
                                string templateId = "XXXXXX"; //设置的模板ID
                                string url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;
                                //设置推送的模板,包括推送的openid、模板ID-templateId 、推送的信息:dt1.Rows[i]["XXX"]等
                                string temp = "{\"touser\": \"" + openId + "\"," +

                                              "\"template_id\": \"" + templateId + "\", " +

                                              "\"topcolor\": \"#FF0000\", " +
                                              
                                              "\"data\": " +

                                              "{\"thing3\": {\"value\": \""+ dt1.Rows[i]["XXX"] +"\"}," +

                                              "\"thing11\": { \"value\": \""+ dt1.Rows[i]["XXX"] + "\"}," +

                                              "\"thing4\": { \"value\": \""+ dt1.Rows[i]["XXX"] + "\"}," +

                                              "\"time20\": {\"value\": \"" + Convert.ToDateTime(dt1.Rows[i]["XXX"]) + "\" }}}";
                                //核心:进行推送请求,并返回相应的反馈信息,如:{"errcode":0,"errmsg":"ok","msgid":XXXXX}
                                string results = GetResponseData(temp, url);
                                strReturn = dt1.Rows[i]["UserName"]+"——"+ openId + "——" + "推送成功";
                                Console.WriteLine(strReturn);
                            }
                        }
                        catch (Exception ex)
                        {
                            strReturn = ex.Message;
                            Console.WriteLine(strReturn);
                        }
                    }
                    else
                    {
                        Console.WriteLine(String.Format("目前距离推送时间还有{0}天,当前时间是--{1}",sp.Days, DateTime.Now));
                    }
                }
            }
            else
            {
                Console.WriteLine(String.Format("未到数据推送时间,当前时间是--{0}", DateTime.Now));
            }
        }

        //获取请求的数据并返回相应的提示信息
        public static string GetResponseData(string JSONData, string Url)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(JSONData);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
            request.Method = "POST";
            request.ContentLength = bytes.Length;
            request.ContentType = "json";
            Stream reqstream = request.GetRequestStream();
            reqstream.Write(bytes, 0, bytes.Length);
            //声明一个HttpWebRequest请求
            request.Timeout = 90000;
            //设置连接超时时间
            request.Headers.Set("Pragma", "no-cache");
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream streamReceive = response.GetResponseStream();
            Encoding encoding = Encoding.UTF8;
            StreamReader streamReader = new StreamReader(streamReceive, encoding);
            string strResult = streamReader.ReadToEnd();
            streamReceive.Dispose();
            streamReader.Dispose();
            return strResult;
        }

四、定时推送代码的构建

//设置时间间隔为1分钟执行代码

static void Main(string[] args)
{
    System.Timers.Timer timer = new System.Timers.Timer();
    timer.Enabled = true;
    timer.Interval = 60000;//执行间隔时间,单位为毫秒;此时时间间隔为1分钟
    timer.Start();
    timer.Elapsed += new System.Timers.ElapsedEventHandler(SendTemplateMessage);
    Console.ReadKey();
}

这是我实现的一个结果:在这里插入图片描述

五、补充

(1)补充1
如果需要点击推送消息跳转到一个网址,只需要在模板里面添加url跳转链接即可。

 string temp = "{\"touser\": \"" + openId + "\"," +

                   "\"template_id\": \"" + templateId + "\", " +

                   "\"topcolor\": \"#FF0000\", " +

                   "\"url\": \"https://blog.csdn.net/nfkjdx?spm=1000.2115.3001.5343\", " +

                   "\"data\": " +

                   "{\"thing4\": {\"value\": \"XXXXX\"}," +

                   "\"thing23\": { \"value\": \"XXXXX\"}," +

                   "\"thing27\": { \"value\": \"XXXXX\"}," +

                   "\"time32\": {\"value\": \"" + Convert.ToDateTime(DateTime.Now) + "\" }}}";
 string results = GetResponseData(temp, url);

(2)补充2
如果需要点击推送消息跳转到一个小程序,需要先去登录推送消息的公众号平台,去里面的小程序管理添加关联的小程序,再去修改推送模板。
在这里插入图片描述

 var accessToken = "XXXXXXXXX";
 string openId = "XXXXXXXXX";
 string templateId = "XXXXXXXXX";

 string miniprogramAppId = "XXXXXXXXX";//小程序的appid
 string microProgramPath = "XXXXXXXXX";//跳转页面的相对路径

 string url = "XXXXXXXXX=" + accessToken;
 string temp = "{\"touser\": \"" + openId + "\"," +

                   "\"template_id\": \"" + templateId + "\", " +

                   "\"topcolor\": \"#FF0000\", " +

                   "\"miniprogram\":{\"appid\":\"" + miniprogramAppId + "\",\"pagepath\":\"" + microProgramPath.Trim() + "\"},"+

                   "\"data\": " +

                   "{\"thing4\": {\"value\": \"XXXXXXXXX\"}," +

                   "\"thing23\": { \"value\": \"XXXXXXXXX\"}," +

                   "\"thing27\": { \"value\": \"XXXXXXXXX \"}," +

                   "\"time32\": {\"value\": \"" + Convert.ToDateTime(DateTime.Now) + "\" }}}";
 string results = GetResponseData(temp, url);

在这里插入图片描述

参数类别	参数说明	参数值限制	说明
thing.DATA	事物	20个以内字符	可汉字、数字、字母或符号组合
number.DATA	数字	32位以内数字	只能数字,可带小数
letter.DATA	字母	32位以内字母	只能字母
symbol.DATA	符号	5位以内符号	只能符号
character_string.DATA	字符串	32位以内数字、字母或符号	可数字、字母或符号组合
time.DATA	时间	24小时制时间格式(支持+年月日),支持填时间段,两个时间点之间用“~”符号连接	例如:15:01,或:201910115:01
date.DATA	日期	年月日格式(支持+24小时制时间),支持填时间段,两个时间点之间用“~”符号连接	例如:2019101日,或:201910115:01
amount.DATA	金额	1个币种符号+10位以内纯数字,可带小数,结尾可带“元”	可带小数
phone_number.DATA	电话	17位以内,数字、符号	电话号码,例:+86-0766-66888866
car_number.DATA	车牌	8位以内,第一位与最后一位可为汉字,其余为字母或数字	车牌号码:粤A8Z888挂
name.DATA	姓名	10个以内纯汉字或20个以内纯字母或符号	中文名10个汉字内;纯英文名20个字母内;中文和字母混合按中文名算,10个字内
phrase.DATA	汉字	5个以内汉字	5个以内纯汉字,例如:配送中

到这里全部介绍完毕,大家可以参考一下!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值