zoukankan      html  css  js  c++  java
  • MVC下c#对接微信公众平台开发者模式

    在ashx文件中进行HttpContext的处理:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Biz.WX;
    
    namespace weixinplat
    {
        /// <summary>
        /// WeiXin 的摘要说明
        /// </summary>
        public class WeiXin : IHttpHandler
        {
    
            public void ProcessRequest(HttpContext context)
            {
                try
                {
                    string postString = string.Empty;//初始化空字符串来转抓到的request请求的bit流
                    context.Response.ContentType = "text/plain";
                    if (context.Request.HttpMethod.ToLower() == "post")//如果从requset的httpmethod方法是post就进行图文等处理
                    {
    
                    }
                    else//否则就是get方式,进行校验认证
                    {
                        AccessToken.Auth();
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                
                
            }
    
            public bool IsReusable
            {
                get
                {
                    return false;
                }
            }
        }
    }

    在专门处理数据的类库Biz中校验:

    其中AccessToken类用来处理token:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Web;
    using System.Configuration;
    
    namespace Biz.WeiXin
    {
        public class AccessToken
        {
            /// <summary>
            /// 这个函数是初始化配置服务器地址
            /// </summary>
            public static void Auth()
            {
                string echoStr = HttpContext.Current.Request.QueryString["echoStr"];
                if (CheckSignature()) //校验签名是否正确
                {
                    if (!string.IsNullOrEmpty(echoStr))
                    {
                        HttpContext.Current.Response.Write(echoStr);
                        HttpContext.Current.Response.End();
    
                    }
                }
            }
            /// <summary>
            /// 校验微信公众平台签名函数
            /// </summary>
            /// <returns></returns>
            public static bool CheckSignature()
            {
                string signature = HttpContext.Current.Request.QueryString["signature"];
                string timestamp = HttpContext.Current.Request.QueryString["timestamp"];
                string nonce = HttpContext.Current.Request.QueryString["nonce"];
                string token = ConfigurationManager.AppSettings["weixin_token"];
    
                string[] tmpArr = { token , timestamp, nonce };
                Array.Sort(tmpArr);
                string tmpStr = string.Join("", tmpArr);
                tmpStr = WX.Sha1_Hash(tmpStr);
    
                if (tmpStr == signature)
                {
                   
                    return true;
                }
                else
                {
                    return
                        false;
                }
    
    
            }
        }
    }

    WX类用来处理哈希算法:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Cryptography;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Biz.WX
    {
        public class WX
        {
            public static string Sha1_Hash(string str_sha1_in)
            {
                SHA1 sha1 = new SHA1CryptoServiceProvider();
                byte[] bytes_sha1_in = UTF8Encoding.Default.GetBytes(str_sha1_in);
                byte[] bytes_sha1_out = sha1.ComputeHash(bytes_sha1_in);
                string str_sha1_out = BitConverter.ToString(bytes_sha1_out);
                str_sha1_out = str_sha1_out.Replace("-", "").ToLower();
                return str_sha1_out;
            }
        }
    }
    •  将菜单发布到微信公众平台

    在treegrid空间的toolbar工具栏按钮中通过ajax来连接到后台方法:

     {
                        id: 'btnRefresh',
                        text: '发布到微信公众平台',
                        iconCls: 'icon-redo',
                        handler: function () {
                            $.ajax({
                                url: "/WxMenu/MenuToWeiXin",
                                data: {},
                                dataType: "json",
                                type: "POST",
                                traditional: true,
                                beforeSend: function () {
                                    showProcess(true, "系统提示", "正发布到微信公众平台......");
                                },
                                error: function () {
                                },
                                success: function (result) {
                                    showMsg("系统提示", result.Message, false);
                                },
                                complete: function () {
                                    showProcess(false);
                                }
                            });
                        }
    View Code

    连接到后台的MenuToWeiXin方法返回json对象:

     public JsonResult MenuToWeiXin()
            {
                try
                {
                    MenuManager.CreateMenu();
                    return Json(new { Success = true, Message = "请求成功" });
                }
                catch (Exception ex)
                {
                    return Json(new { Success = false,Message = ex.Message });
                }
            }
    View Code

    其中 MenuManager.CreateMenu()方法就是去将微信菜单对接到微信API上面。如下:

    public static void CreateMenu()
            {
                NHibernateHelper nhlper = new NHibernateHelper();
                ISession session = nhlper.GetSession();
                IEnumerable<WeiXinMenu> kinds = session.Query<WeiXinMenu>();
                if (kinds.Count() <= 1)
                {
                    throw new Exception("请先配置菜单");
                }
                string menu = "";
                menu += "{"button":[";
                kinds.Where(c => c.ParentId == "10000").Foreach(c => {
                    menu += "{";
                    menu += ""name":"{0}",".FormartWith(c.MenuName);
                    menu += ""sub_button":[";
                    kinds.Where(m=>m.ParentId==c.MenuId).Foreach(m=> {
                        menu += "{";
                        menu += ""type":"{0}",".FormartWith(m.MenuType);
                        menu += ""name":"{0}",".FormartWith(m.MenuName);
                        if (m.MenuType == "click")
                        {
                            menu += ""key":"{0}"".FormartWith(m.MenuKey);
                        }
                        else
                        {
                            menu += ""url":"{0}"".FormartWith(m.MenuUrl);
                        }
                        menu += "},";
                    });
                    menu = menu.Remove(menu.Length - 1, 1);
                    menu += "]";
                    menu += "},";
                });
                menu = menu.Remove(menu.Length - 1, 1);
    
                menu += "]";
                menu += "}";
                string url = url_menu_create + AccessToken.Weixin_ACCESS_TOKEN;
                string responsestring = HttpUtils.GetHttprequest(url);
                JObject result = JsonConvert.DeserializeObject(responsestring) as JObject;
                string errcode = result["errcode"].ToString();
                string errmsg = result["errmsg"].ToString();
                if (errcode != "0")
                {
                    throw new Exception(Weixin_Errorcode.GetErrormsg(int.Parse(errcode)));
                }
            }
    View Code

    其中url_menu_create是微信给的API接口 private static string url_menu_create = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token="; 

     然后将查询到的菜单组装成微信后台需要的json格式。然后调用接口,用post方式的httprequest去访问。可以根据返回的错误代码来知道具体问题是在哪里。

    tips:调用微信的很多API接口都需要微信的access_token,所以可以单独写个类来获取:其中AccessToken.Weixin_ACCESS_TOKEN就是获取到微信的access_token:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Web;
    using System.Configuration;
    using System.Security.Cryptography;
    using Business.Extsion;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    
    namespace Business.weixin
    {
        public class AccessToken
        {
            public static string AppID = ConfigurationManager.AppSettings["weixin_AppID"];
            public static string AppSecret = ConfigurationManager.AppSettings["weixin_AppSecret"];
    
            public static string mAccessToken;
            public static DateTime GettokenTime;
            public static int Expires_Period = 7200;//token有效时间,默认2小时
    
            /// <summary>
            /// 正经对接微信公众平台函数。获取echoStr,来返回。
            /// </summary>
            public static void Auth()
            {
                string echoStr = HttpContext.Current.Request.QueryString["echoStr"];
                if (CheckSignature())
                {
                    if (!string.IsNullOrEmpty(echoStr))
                    {
                        HttpContext.Current.Response.Write("echoStr");
                        HttpContext.Current.Response.End();
                    }
                }
            }
    
            /// <summary>
            /// 校验函数,微信后台返回的signature和token+timestamp+nonce 对比
            /// </summary>
            /// <returns></returns>
            public static bool CheckSignature()
            {
                string signature = HttpContext.Current.Request.QueryString["signature"];
                string timestamp = HttpContext.Current.Request.QueryString["timestamp"];
                string nonce = HttpContext.Current.Request.QueryString["nonce"];
                string token = ConfigurationManager.AppSettings["weixintoken"];
    
                string[] tmpArr = { token, timestamp, nonce };
                Array.Sort(tmpArr);
                string tmpStr = string.Join("", tmpArr);
                tmpStr = Sha1_Hash(tmpStr);//通过hash算法得到一个字符串,跟signature对比
                if (tmpStr == signature)
                {
                    return true;
                }
                else
                {
                    return false;
                }
    
            }
    
            public static string Sha1_Hash(string intputstr)
            {
                SHA1 sha1 =new SHA1CryptoServiceProvider();
                byte[] byte_in = UTF8Encoding.Default.GetBytes(intputstr);
                byte[] byte_out = sha1.ComputeHash(byte_in);
                string outputstr = BitConverter.ToString(byte_out);
                outputstr = outputstr.Replace("-","").ToLower();
                return outputstr;
            }
    
            
            public static string Weixin_ACCESS_TOKEN
            {
                get{
                    //如果为空或者过期。则重新获取
                    if (string.IsNullOrEmpty(mAccessToken) || HasExpired())
                    {
                        //获取accesstoken函数
                        mAccessToken = GetAccessToken(AppID, AppSecret);
                    }
                    return mAccessToken;
                }
            }
            /// <summary>
            /// 判断是不是token过期
            /// </summary>
            /// <returns></returns>
            public static bool HasExpired()
            {
                if (GettokenTime != null)
                {
                    if (DateTime.Now > GettokenTime.AddSeconds(7200).AddSeconds(-60))
                    {
                        return true;
                    }
                }
                return false;
            }
    
            /// <summary>
            /// 获取accesstoken函数
            /// </summary>
            /// <param name="AppID"></param>
            /// <param name="AppSecret"></param>
            /// <returns></returns>
            public static string GetAccessToken(string AppID,string AppSecret)
            {
                string url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
                url = string.Format(url, AppID, AppSecret);
                string responsestring = HttpUtils.GetHttprequest(url);
                JObject result = JsonConvert.DeserializeObject(responsestring) as JObject;
                if (result["access_token"] != null)
                {
                    GettokenTime = DateTime.Now;
                    if (result["expires_in"] != null)
                    {
                        Expires_Period = int.Parse(result["expires_in"].ToString());
                    }
                    return result["access_token"].ToString();
                }
                else
                {
                    GettokenTime = DateTime.MinValue;
                }
                return null;
            }
        }
    }
    View Code

    在访问这种api接口的时候都需要主动去访问,所以可以把httprequest请求单独写在一个类HttpUtils中:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Business.Extsion
    {
       public class HttpUtils
        {
            /// <summary>
            /// 发起一个post类型的http请求
            /// </summary>
            /// <param name="url"></param>
            /// <param name="data"></param>
            /// <returns></returns>
            public static string SendHttprequest(string url,string data)
            {
                return SendPostHttprequest( url, "application/x-www-form-urlencoded",  data);
            }
            /// <summary>
            /// 发起一个get模式的http请求
            /// </summary>
            /// <returns></returns>
            public static string GetHttprequest(string url)
            {
                return SendGetHttprequest(url,"application/x-www-form-urlencoded");
            }
            public static string SendPostHttprequest(string url,string contentType, string requestData)
            {
                WebRequest request = (WebRequest)HttpWebRequest.Create(url);
                request.Method = "POST";
                request.ContentType = contentType;
                byte[] postbytes = Encoding.UTF8.GetBytes(requestData);
                request.ContentLength = postbytes.Length;
                using (Stream outstream = request.GetRequestStream())
                {
                    outstream.Write(postbytes, 0, postbytes.Length);
                }
                string result = string.Empty;
                using (WebResponse response = request.GetResponse())
                {
                    if (response !=null)
                    {
                        using (Stream getstream = response.GetResponseStream())
                        {
                            using (StreamReader reader = new StreamReader(getstream,Encoding.UTF8))
                            {
                                result = reader.ReadToEnd();
                            }
                        }
                    }
                }
                return result;
    
            }
    
            public static string SendGetHttprequest(string url ,string contenType)
            {
                WebRequest request = (WebRequest)HttpWebRequest.Create(url);
                request.Method = "GET";
                request.ContentType = contenType;
                string result = string.Empty;
                using (WebResponse response = request.GetResponse())
                {
                    if (response != null)
                    {
                        using (Stream resstream = response.GetResponseStream())
                        {
                            using (StreamReader reader = new StreamReader(resstream,Encoding.UTF8) )
                            {
                                result = reader.ReadToEnd();
                            }
                        }
                    }
                }
                return result;
            }
        }
    }
    View Code
    • 编辑新增菜单

    通过控制器返回视图:

    public ActionResult MenuEdit(int id)
            {
                NHibernateHelper nhlper = new NHibernateHelper();
                ISession session = nhlper.GetSession();
                WeiXinMenu model = session.Get<WeiXinMenu>(id);
    
                if (model == null)
                {
                    model = new WeiXinMenu();
                    model.IsEnable = "1";
                    model.CreateTime = DateTime.Now;
                }
    
                return View(model);
            }
    View Code

    控制器动作跟着返回查询到的model在视图上显示:

    @model Domain.OrmLib.Entity.WeiXinMenu
    @{
        ViewBag.Title = "MenuEdit";
        Layout = "~/Views/Shared/_Form.cshtml";
    }
    
    @section header {
    
    }
    
    @section body{
        @using (Html.BeginForm("MenuSaveOrUpdate", "WeiXin", FormMethod.Post, new { id = "dataForm" }))
        {
            <table class="datalistDaily" cellpadding="5" style="font-size:12px;margin-top:10px;margin-left:10px;">
                <tr>
                    <td style="text-align:right;">菜单编码:</td>
                    <td>
                        <input class="easyui-textbox" id="MenuId" name="MenuId"
                               style="300px;" data-options="required:true" value="@Model.MenuId" />
                    </td>
                </tr>
                <tr>
                    <td style="text-align:right;">菜单名字:</td>
                    <td>
                        <input class="easyui-textbox" id="MenuName" name="MenuName"
                               style="300px;" data-options="required:true" value="@Model.MenuName" />
                    </td>
                </tr>
                <tr>
                    <td style="text-align:right;">动作类型:</td>
                    <td>
                        <select id="MenuType" name="MenuType" class="easyui-combobox" style="300px;">
                            <option selected="selected" value="view">跳转URL</option>
                            <option value="click">点击推事件</option>
                            <option value="scancode_push">扫码推事件</option>
                            <option value="scancode_waitmsg">扫码推事件且弹出(消息接收中)提示框</option>
                            <option value="pic_sysphoto">弹出系统拍照发图</option>
                            <option value="pic_photo_or_album">弹出拍照或者相册发图</option>
                            <option value="pic_weixin">弹出微信相册发图器</option>
                            <option value="location_select">弹出地理位置选择器</option>
                            <option value="media_id">下发消息(除文本消息)</option>
                            <option value="view_limited">跳转图文消息URL</option>
                        </select>
                    </td>
                </tr>
                <tr>
                    <td style="text-align:right;">菜单Url:</td>
                    <td>
                        <input class="easyui-textbox" id="MenuUrl" name="MenuUrl"
                               style="300px;" value="@Model.MenuUrl" />
                    </td>
                </tr>
                <tr>
                    <td style="text-align:right;">菜单Key:</td>
                    <td>
                        <input class="easyui-textbox" id="MenuKey" name="MenuKey"
                               style="300px;" value="@Model.MenuKey" />
                    </td>
                </tr>
                <tr>
                    <td style="text-align:right;">菜单排序:</td>
                    <td>
                        <input class="easyui-textbox" id="OrderBy" name="OrderBy" data-options="required:true"
                               style="300px;" value="@Model.OrderBy" />
                    </td>
                </tr>
                <tr>
                    <td style="text-align:right;">菜单状态:</td>
                    <td>
                        <select id="IsEnable" name="IsEnable" class="easyui-combobox" style="300px;">
                            <option selected="selected" value="1">启用菜单</option>
                            <option value="0">禁用菜单</option>
                        </select>
                    </td>
                </tr>
                <tr>
                    <td style="text-align:right;">上级菜单:</td>
                    <td>
                        <input class="easyui-combotree" name="ParentId" id="ParentId" style="300px;" />
                    </td>
                </tr>
                <tr>
                    <td colspan="2" align="center"></td>
                </tr>
                <tr>
                    <td colspan="2" align="center">
                        @Html.HiddenFor(model => model.Id)
                        @Html.HiddenFor(model => model.UserNum)
                        @Html.HiddenFor(model => model.UserName)
                        @Html.HiddenFor(model => model.CreateTime)
                        <a icon="icon-ok" class="easyui-linkbutton" onclick="save()">存盘</a>
                    </td>
                </tr>
            </table>
        }
    
        }
    
    @section scripts {
    <script src="~/Content/oa/scripts/xlayout.js"></script>
    <script type="text/javascript">
        $(function () {
            $('#ParentId').combotree({
                url: "/WxMenu/MenuTree",
                required: true,
                multiple: false,
                lines: true,
                queryParams: { ids: '@Model.ParentId' },
                onLoadSuccess: function () {
                    $('#ParentId').combotree('setValue', '@Model.ParentId');
                }
            });
            $('#MenuType').combobox('setValue', '@Model.MenuType');
            $('#IsEnable').combobox('setValue', '@Model.IsEnable');
        })
        function save() {
            alert(2212);
            var dataForm = $("#dataForm").form('validate');
            if (!dataForm) return;
    
            showProcess(true, "系统提示", "正在存盘中......");
            $.ajax({
                url: "/WxMenu/MenuSaveOrUpdate",
                data: $("#dataForm").serialize(),
                dataType: "json",
                type: "POST",
                traditional: true,
                success: function (result) {
                    showProcess(false);
                    if (result.Success) {
                        var sys_main = $(self.top.document).find("#sys_main").get(0).contentWindow;
                        sys_main.radWindowCallBackFn();
                        var url = document.URL;
                        url = url.replace("http://" + window.location.host, "");
                        url = url.replace(///g, "_");
                        sys_main.CloseWindow(url);
                    } else {
                        showMsg("系统提示", result.Message, false);
                    }
                }
            });
            return false;
        }
    
        </script>
    
    }
    View Code

    通过ajax在后台进行saveorupdate

  • 相关阅读:
    [UWP]使用CompositionLinearGradientBrush实现渐变画笔并制作动画
    [WPF 自定义控件]模仿UWP的ProgressRing
    [UWP]占领标题栏
    [WPF 自定义控件]关于ScrollViewer和滚动轮劫持(scroll-wheel-hijack)
    [WPF 自定义控件]给WPF一个HyperlinkButton
    VisualStudio中的单元测试
    重温《单元测试的艺术》,总结常用知识点
    [WPF 自定义控件]自定义Expander
    nhibernate入门使用经验
    个人搜藏小技巧:eclipse 设定proxy,仍不能连网的问题
  • 原文地址:https://www.cnblogs.com/jackcheblog/p/6864309.html
Copyright © 2011-2022 走看看