Asp.net MVC实现微信扫码后推送消息

首先说下需求:

我有一个网站,网站上有很多作者分享自己的作品,如果其他用户浏览作品后想联系这位作者,就需要扫码关注我们的平台,我们会推送对方的联系方式。

第一步,生成带参数的二维码

步骤:

1.用微信appid和appsecret获取access_token

2.用access_token获取二维码的ticket,这其中要用json格式传入固定格式的值才能获取到ticket,传值的时候你可以在scene_id中带上自己的参数,方便用户扫码后回调的时候处理

3.用ticket直接得到二维码图片(注意:用这个方式,微信服务器返回的是图片的数据流。如果你需要处理二维码的图片,你不需要考虑如何操作这个数据流,只需要把整个访问微信的字符串带上ticket当成一个图片的地址放在src中就可以了,你可以操作图片本身)

下面是代码,省略了一些处理返回值的model类

        /// 
        /// 生成二维码
        /// 
        /// 
        [HttpPost]
        public IHttpActionResult CreateImg(dynamic data)
        {
            //用户ID
            int uid = Convert.ToInt32(data.userid);

            //get token
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=**********&secret=****************");
            var wm = new System.Net.Http.HttpClient().GetAsync(url).Result.Content.ReadAsStringAsync().Result;
            WechatModels info = JsonConvert.DeserializeObject(wm);

            //get ticket  
            string turl = string.Format("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={0}", info.access_token);
            var jsonInfo = "{\"action_name\": \"QR_LIMIT_SCENE\", \"action_info\": {\"scene\": {\"scene_id\": " + uid + "}}}";
            HttpContent httpContent = new StringContent(jsonInfo);
            httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
            var tickets = new System.Net.Http.HttpClient().PostAsync(turl, httpContent).Result.Content.ReadAsStringAsync().Result;
            TicketInfo tinfo = JsonConvert.DeserializeObject(tickets);

            //get imgUrl
            string imgUrl = string.Format("https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket={0}", System.Web.HttpUtility.UrlEncode(tinfo.ticket));
            //var res = new System.Net.Http.HttpClient().GetAsync(imgUrl).Result.Content.ReadAsStringAsync().Result;

            return Json(imgUrl);
        }

第二步,用户扫码后的处理

处理的前提是你已经在公众号中配置完成

如图,服务器地址中的方法,就是扫码后的回调地址,也是之前一开始你配置服务器时处理token的回调地址

 

Asp.net MVC实现微信扫码后推送消息_第1张图片

 

 下面插入回调处理的代码

 

        /// 
        /// 接收微信推送
        /// 
        public void Valid()
        {
            Stream requestStream = System.Web.HttpContext.Current.Request.InputStream;
            string result = "";
            string postString = string.Empty;
            //处理扫码后的回调,参考微信公众平台开发文档中给出的回调数据
            if (System.Web.HttpContext.Current.Request.HttpMethod.ToUpper() == "POST")
            {
                using (Stream stream = System.Web.HttpContext.Current.Request.InputStream)
                {
                    Byte[] postBytes = new Byte[stream.Length];
                    stream.Read(postBytes, 0, (Int32)stream.Length);
                    postString = Encoding.UTF8.GetString(postBytes);
                    if (!string.IsNullOrEmpty(postString))
                    {

                        string SendToWx = string.Empty;
                        //这里写方法解析Xml
                        XmlDocument xml = new XmlDocument();//
                        xml.LoadXml(postString);
                        XmlElement xmlElement = xml.DocumentElement;
                        //这里进行判断MsgType
                        switch (xmlElement.SelectSingleNode("MsgType").InnerText)
                        {
                            case "voice":
                                break;
                            case "video":
                                break;
                            case "shortvideo":
                                break;
                            case "location":
                                break;
                            case "link":
                                break;
                            case "event":
//扫码后的MsgType是event,在这里解析微信服务器的推送数据,我们再按照要求的格式推送给用户
                                string FromUserName = xmlElement.SelectSingleNode("FromUserName").InnerText == null ? "" : xmlElement.SelectSingleNode("FromUserName").InnerText;
                                string ToUserName = xmlElement.SelectSingleNode("ToUserName").InnerText == null ? "" : xmlElement.SelectSingleNode("ToUserName").InnerText;
                                string CreateTime = xmlElement.SelectSingleNode("CreateTime").InnerText == null ? "" : xmlElement.SelectSingleNode("CreateTime").InnerText;
                                string eventKey = xmlElement.SelectSingleNode("EventKey").InnerText == null ? "" : xmlElement.SelectSingleNode("EventKey").InnerText;

//这里需要注意,扫码后的eventKey就是你之前的场景值,但是如果用户没有关注,用户先选择了关注,那这里的eventKey就会多一个“qrscene_”的前缀,这在文档中有说明,但容易忽略,所以这里做一下处理
                                if (eventKey.Contains("_")) { eventKey = eventKey.Split('_')[1]; }
//我在这里通过场景值来查询用户信息,再把用户需要的信息发送出去
                                var user = Helper.Comm.HttpPost2(ip + "/api/Index/QueryWorks", new Dictionary()
                                        {
                                            { "uid", eventKey }
                                        });
                                TalentPool contents = JsonConvert.DeserializeObject(user);
//把联系方式发送给对方
                                string tips = "感谢关注!" + contents.Name + "的微信号是:" + contents.WX + " ";
//拼接xml或json格式的数据,才能正确发送给用户
                                string jsoninfo = "" + CreateTime + "";

//把数据转化为json格式
                                HttpContent httpContent = new StringContent(jsoninfo);
                                httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");

                                switch (xmlElement.SelectSingleNode("Event").InnerText)
                                {
                                    case "subscribe":
                                        System.Web.HttpContext.Current.Response.Write(jsoninfo);//关注事件 通过C#自带的Response.Write方法,就能把需要的信息发给扫码的人
                                        System.Web.HttpContext.Current.Response.End();
                                        break;
                                    case "unsubscribe":
                                        System.Web.HttpContext.Current.Response.Write(jsoninfo);
                                        System.Web.HttpContext.Current.Response.End();
                                        break;
                                    case "SCAN":
                                        System.Web.HttpContext.Current.Response.Write(jsoninfo);//扫码事件
                                        System.Web.HttpContext.Current.Response.End();
                                        break;
                                    case "LOCATION":
                                        break;
                                    case "CLICK":
                                        break;
                                    case "VIEW":
                                        break;
                                    default:
                                        break;
                                }
                                break;
                            default:
                                result = "没有识别的类型消息:" + xmlElement.SelectSingleNode("MsgType").InnerText;
                                WriteLog(result);
                                break;
                        }
                        if (!string.IsNullOrEmpty(SendToWx))
                        {
                            System.Web.HttpContext.Current.Response.Write(SendToWx);
                            System.Web.HttpContext.Current.Response.End();
                        }
                        else
                        {
                            result = "回传数据为空";
                            WriteLog(result);
                        }
                    }
                    else
                    {
                        result = "微信推送的数据为:" + postString;
                        WriteLog(result);
                    }
                }
            }
            else if (Request.HttpMethod.ToUpper() == "GET")
            {
//这里是之前你配置微信服务的时候验证token令牌的方法处理,可以删掉但没必要
                string token = ConfigurationManager.AppSettings["WXToken"];//从配置文件获取Token
                if (string.IsNullOrEmpty(token))
                {
                    result = string.Format("微信Token配置项没有配置!");
                    WriteLog(result);
                }
                string echoString = System.Web.HttpContext.Current.Request.QueryString["echoStr"];
                string signature = System.Web.HttpContext.Current.Request.QueryString["signature"];
                string timestamp = System.Web.HttpContext.Current.Request.QueryString["timestamp"];
                string nonce = System.Web.HttpContext.Current.Request.QueryString["nonce"];
                if (CheckSignature(token, signature, timestamp, nonce))
                {
                    if (!string.IsNullOrEmpty(echoString))
                    {
                        System.Web.HttpContext.Current.Response.Write(echoString);
                        System.Web.HttpContext.Current.Response.End();
                        result = string.Format("微信Token配置成功,你已成为开发者!");
                        WriteLog(result);
                    }
                }
            }
        }

        //token验证
        public bool CheckSignature(string token, string signature, string timestamp, string nonce)
        {
            string[] ArrTmp = { token, timestamp, nonce };
            Array.Sort(ArrTmp);
            string tmpStr = string.Join("", ArrTmp);
            tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
            tmpStr = tmpStr.ToLower();
            if (tmpStr == signature)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        //写入日志
        private void WriteLog(string str)
        {
            try
            {
                using (System.IO.FileStream fs = new System.IO.FileStream(Server.MapPath("Upload/log.txt"), System.IO.FileMode.Append))
                {
                    using (System.IO.StreamWriter sw = new System.IO.StreamWriter(fs))
                    {
                        string strlog = "----" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":" + str + "-----";
                        sw.WriteLine(strlog);
                        sw.Close();
                    }
                }
            }
            catch
            { }
        }

至此你就完成了用户扫码后获得自定义消息的流程,代码中省略了一些前端的处理,以及一些实体类的代码,但不影响阅读

微信公众平台中,提供了日志查看的功能,微信开发调试起来并不那么方便,可以通过日志来查看

Asp.net MVC实现微信扫码后推送消息_第2张图片

 

 总体来讲,微信开发文档基本很简洁,没有什么案例,网上的资料很多也是无效的资料,对于新手来讲,微信开发确实是比较头痛,在此记录一下,希望这篇案例对大家有帮助。

你可能感兴趣的:(微信开发)