欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

公司PC端项目向微信推送提示消息功能实现,问题,总结(附相关代码)

程序员文章站 2024-03-15 14:28:29
...

 背景:周末接到领导要求,实现一个功能,在公司绩效考核系统中,增加一个功能,每当同事点击任务需求,提交领导审核后,推送一条微信提示信息,

周六加班摸索了大半天,获得访问接口关键性凭证access_token,

周一一天时间拿到code,和openid,可以发送消息,

周二今天,进行各种优化,总算完成功能实现有图有真相

公司PC端项目向微信推送提示消息功能实现,问题,总结(附相关代码)

 第一步:获取access_token,为能够成功获取关键是配置微信公众号里,开发者,基础配置信息,

 

 public string GetAccess_Token()
        {
            string appid = "";
            string appsecret = "";
            //获取tokenstr
            string token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + appsecret;
            string result = GetWebContent(token_url);
            //saveOpenID(result);
            TokenAccess jsonObj = JsonConvert.DeserializeObject<TokenAccess>(result);
            return jsonObj.access_token;
        }

//优化,这个token有效期为两个小时,如果需要频繁发送推送,建议优化获取如下,
//记录获取时间,存到session当中,两个小时快结束前,进行重新获取,否则用存的
  private string GetAccessToken()
       {                    
           double Now = GetTimeStamp(DateTime.Now);//获取一个Unix时间戳
           if (Session["last"] != null)
           {
               last = Convert.ToDouble(Session["last"].ToString()); 
           }           
           if (Now - last > 7000)
           {
               var result = new WXutil().GetAccess_Token();
               try
               {
                   token = result;
                   Session["last"] = Now;
                   Session["token"] = result;
                   return token;
               }
               catch (Exception)
               {
                   return "err";
                   throw;
               }
           }
           else
           {
               return Session["token"].ToString();
           }
       }

       public double GetTimeStamp(DateTime d)
       {
           TimeSpan ts = d.ToUniversalTime() - new DateTime(1970, 1, 1);
           return ts.TotalSeconds;     //精确到毫秒
       }

重点:白名单填写当前可允许访问的ip,(因为是跨域请求微信那边,相当于让对方设置你可以访问的) 

公司PC端项目向微信推送提示消息功能实现,问题,总结(附相关代码) 

点击IP白名单 后面设置,弹出如下弹窗 

公司PC端项目向微信推送提示消息功能实现,问题,总结(附相关代码)

做完这一步很容易拿到token_token,

 

第二步:调用发送方法,除了有openid,还有一个关键信息templateid

这里先看拿到openid,即被发送消息的那个人标识,这个需要先拿到对方的验证code,

难点重点,难点重点,难点重点

公司PC端项目向微信推送提示消息功能实现,问题,总结(附相关代码)

配置完成如下:

公司PC端项目向微信推送提示消息功能实现,问题,总结(附相关代码)

 获取code至关重要关键性一步:验证填写

公司PC端项目向微信推送提示消息功能实现,问题,总结(附相关代码)

这个页面是用来指定验证微信发过来凭证的,上面url里就写这个页面的路径

这个页面是用来指定验证微信发过来凭证的,上面url里就写这个页面的路径

这个页面是用来指定验证微信发过来凭证的,上面url里就写这个页面的路径

获取token,提交失败概率非常大,仔细检查,确认无误,多提交两次,

如果是后台发送请求方式,建议用文件记录相关信息,毕竟服务器端调试并不方便


        protected void Page_Load(object sender, EventArgs e)
        {
            //处理微信验证服务请求,

            //微信加密签名
            string signature = Request["signature"];
            //随机数
            string nonce = Request["nonce"];
            //时间戳
            string timestamp = Request["timestamp"];
            //凭据
            string token = "fbjr";
            string[] sort = { token, nonce, timestamp };
            sort.Reverse();
            string str = sort.ToString();
            //理论来说,将以上三个参数,按照字典排序,进行拼接后,进行sha加密,和signature进行签名,
            //这里为了省事,不做对比
            //输出内容
            string res = SHA1(str);
            if (res==signature)
            {
                
            }
            //echostr:6989564500401158062&signature:cf05c734fa61a6f806ed3082cd58b4318d34795e&nonce:17909316&timestamp:1560752300
            //echostr:7261461738163745518--signature:6cd95895a307b5bf8569de43d71e4d84e97c5316--nonce:992486027--timestamp:1560752806
            string echostr = Request["echostr"];
            //string test = "echostr:" + echostr + "--" + "signature:" + signature + "--" + "nonce:" + nonce + "--" + "timestamp:" + timestamp;    
           // string path = AppDomain.CurrentDomain.BaseDirectory + "weixin\\";
            //StreamWriter mySw = new StreamWriter(path+"\\weixin.txt");//将文件流给写入器   
            //mySw.Write(Environment.NewLine+test + Environment.NewLine);
            //mySw.Close();
            Response.Write(echostr);
            Response.End();
        }

https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxx&redirect_uri=http://www.xxx.com/weixin/redirectByWX.aspx&response_type=code&scope=snsapi_userinfo&state=1&connect_redirect=1#wechat_redirect

可以用二维码生成这个超链接,手机扫码进行授权,授权成功后这个页面,后面会跟一个code,进行获取openid

这个链接,是直接打开的,不能用ajax等其他方式,直接手机端访问,建议做成二维码超链接,

这个链接,是直接打开的,不能用ajax等其他方式,直接手机端访问,建议做成二维码超链接,

这个链接,是直接打开的,不能用ajax等其他方式,直接手机端访问,建议做成二维码超链接,

 protected void Page_Load(object sender, EventArgs e)
        {
            string code=Request["code"];
            string codeTest = wx.getCode();
            string openId=wx.getopendid(code);
            //openId = "ow5Qi5kaNCIrCXWBeDZr3ug5rLPY";//徐维
            //openId="ow5Qi5n4Z5IiHINcg-0D2HDy1cAI";//邵然
            //openId = "ow5Qi5rGdirLy88Qli7-W0HQPKTU";//张总       
            Response.Redirect("../Login.aspx?openid="+openId);
        }

配置好域名,写好一个验证微信发送凭证的请求

 public void SendMsgToWX(string openId){           
                //token = GetAccessToken();
                string token = wx.GetAccess_Token();
                string msg = "{\"touser\": \"" + openId + "\"," +
                   "\"template_id\": \"rztm1VcS2iXnJBN-A8V-WA4NiAa2SGnUBr8Z82nl3kc\", " +
                   "\"topcolor\": \"#FF0000\", " +
                   "\"data\": " +
                   "{\"first\": {\"value\": \"您好,您在绩效考核系统中,收到一条消息!\"}," +
                   "\"keyword1\": { \"value\": \"填写内容和模板相对应\"}," +
                   "\"keyword2\": { \"value\": \"" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\"}," +
                   "\"keyword3\": { \"value\": \"填写内容和模板相对应\"}," +
                   "\"remark\": {\"value\": \"请尽快查看处理!\" }}}";
                wx.saveOpenID("获取openid:" +openId);
                string sendResult = wx.ModelMessageSend(msg, token);
                //wx.saveOpenID(Environment.NewLine + "------------------" + DateTime.Now.ToLocalTime() + "---------------------");
                wx.saveOpenID("发送结果返回消息:"+sendResult);
        }

第三步:获取模板,在微信后台菜单 添加功能里,将这个功能拖动过来,

申请下来模板,填写模板号,接口号,即大工告成。

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using Newtonsoft.Json;

namespace WX
{
    public class TokenAccess
    {
        public string access_token { get; set; }
        public string expires_in { get; set; }
    }

    public class OpenID
    {
        public string access_token { get; set; }
        public string expires_in { get; set; }
        public string refresh_token { get; set; }
        public string openid { get; set; }
        public string scope { get; set; }
    }

   


   

    public class WXutil
    {
//         redirect_uri 回调地址
//scope=snsapi_base 
//snsapi_base 发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的
//scope=snsapi_userinfo
//以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息

        //获取code,用来获取openid
        //获取opendi
        public String getCode()
        {
            string appid = "";
            string secret = "";
            string redirect_uri = Uri.EscapeUriString("http://jx.fbjr.cn/weixin/index.aspx");
            String openid_url = "https://open.weixin.qq.com/connect/oauth2/authorize"
             + "?appid=APPID"
             + "&redirect_uri=REDIRECT_URI"
             + "&response_type=code"
             + "&scope=snsapi_base"
             + "&state=STATE"
             + "#wechat_redirect";
            openid_url = openid_url.Replace("APPID", appid)
                .Replace("AppSecret", secret).Replace("State", "1").Replace("REDIRECT_URI", redirect_uri);            
            string openid = GetWebContent(openid_url);
            return openid;
        }


        public void saveOpenID(string openId)
        {
            string path = AppDomain.CurrentDomain.BaseDirectory + "weixin\\";
            //StreamWriter sw = new StreamWriter(path + "\\weixin.txt");
            //sw.Write(Environment.NewLine + test + Environment.NewLine);
            //sw.Close();            
            FileStream fs = File.OpenWrite(path + "\\weixin.txt");
            fs.Position = fs.Length;
            Encoding encoder = Encoding.UTF8;
            byte[] bytes = encoder.GetBytes(Environment.NewLine + openId + Environment.NewLine);
            fs.Write(bytes, 0, bytes.Length);
            fs.Close();
        }

        //获取opendi
        public String getopendid(String code)
        {

            string appid = "";
            string secret = "";
            String openid_url ="https://api.weixin.qq.com/sns/oauth2/access_token"
                    + "?appid=AppId"
                    + "&secret=AppSecret"
                    + "&code=CODE"
                    + "&grant_type=authorization_code";
            openid_url = openid_url.Replace("AppId", appid)
                .Replace("AppSecret", secret)
                    .Replace("CODE", code);
            string result = GetWebContent(openid_url);           
            //saveOpenID(Environment.NewLine+"------------------"+DateTime.Now.ToLocalTime()+"---------------------");
            saveOpenID("授权同意获取结果:"+result);
            //saveOpenID(Environment.NewLine + "---------------------------------------" );
            OpenID jsonObj = JsonConvert.DeserializeObject<OpenID>(result);
            return jsonObj.openid;          
            //return openid;
        }
        //此获取基础token,即开发者公众号身份id
        public string GetAccess_Token()
        {
            string appid = "";
            string appsecret = "";
            //获取tokenstr
            string token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + appsecret;
            string result = GetWebContent(token_url);
            //saveOpenID(result);
            TokenAccess jsonObj = JsonConvert.DeserializeObject<TokenAccess>(result);
            return jsonObj.access_token;
        }

      
        public string ModelMessageSend(string data, string tc)
        {
            string url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + tc;
            string result = HttpPost(url, data);
            if (result.Contains("ok"))
            {
                return result;
            }
            else
            {
                return "消息推送失败,具体错误为:" + result;
            }
        }

        public string HttpPost(string url, string postData)
        {
            byte[] data = Encoding.UTF8.GetBytes(postData);
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "Post";
            request.ContentType = "application/json";
            request.ContentLength = data.Length;
            request.KeepAlive = true;

            Stream stream = request.GetRequestStream();
            stream.Write(data, 0, data.Length);

            HttpWebResponse response;
            try
            {
                response = (HttpWebResponse)request.GetResponse();
            }
            catch (WebException ex)
            {
                response = (HttpWebResponse)ex.Response;
            }

            StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
            string content = reader.ReadToEnd();

            request.Abort();
            response.Close();
            reader.Dispose();
            stream.Close();
            stream.Dispose();

            return content;
        }

        public static string GetHtmlSource(string url, string encodestr)
        {
            Uri uri = new Uri(url);
            System.GC.Collect();
            HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(uri);
            myReq.UserAgent = "User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705";
            myReq.Accept = "*/*";
            myReq.KeepAlive = true;
            myReq.Timeout = 5 * 60 * 1000;
            myReq.Headers.Add("Accept-Language", "zh-cn,en-us;q=0.5");
            System.Net.ServicePointManager.DefaultConnectionLimit = 50;
            HttpWebResponse result = null;
            string strHTML = "";
            try
            {
                result = (HttpWebResponse)myReq.GetResponse();
            }
            catch (Exception ex)
            {
                // DebugForWinform(ex.ToString());
                throw ex;
            }
            finally
            {
                Stream receviceStream = result.GetResponseStream();
                if (result.ContentEncoding.ToLower().Contains("gzip"))
                {
                    receviceStream = new GZipStream(receviceStream, CompressionMode.Decompress);
                }
                StreamReader readerOfStream = new StreamReader(receviceStream, System.Text.Encoding.GetEncoding(encodestr));
                strHTML = readerOfStream.ReadToEnd();
                readerOfStream.Close();
                receviceStream.Close();
                result.Close();
            }
            return strHTML;
        }

        public string GetWebContent(string uri)
        {
            string strResult = "";
            try
            {
                HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(uri);
                myReq.Timeout = 3000;
                myReq.Headers.Set("Pragma", "no-cache");
                HttpWebResponse result = (HttpWebResponse)myReq.GetResponse();
                Stream receviceStream = result.GetResponseStream();
                Encoding encoding = Encoding.GetEncoding("UTF-8");
                StreamReader sr = new StreamReader(receviceStream, encoding);
                strResult = sr.ReadToEnd();
                sr.Close();
                result.Close();
                receviceStream.Close();
            }
            catch (Exception)
            {
                //连接出错,请重试
                throw;
            }
            return strResult;
        }
    }
}

以上是本文章全部内容,时间仓促,已经快下班了,有什么不清楚地方,欢迎留言交流,水平有限之处,也多包涵