欢迎使用优快云-markdown编辑器

asp.net 之微信自定义菜单创建

前段时间由于公司需要,申请了大批量的微信公众账号,并要求每个公众账号都需要创建自定义菜单,由于数量相当庞大,单个创建简直是个巨大的工作量,于是我开动脑筋,搞了一个自义定菜单管理后台,实现一键添加、删除自定义菜单:

  • 管理后台是基于asp.net+MVC+dwz来写,至于什么是dwz自己百度,很简单也很实用的国产开源框架
    -公众账号列表页面:
<div class="pageContent">
    <div class="panelBar">
        <ul class="toolBar">
            <li><a class="icon" href="#" onclick="GetID()"><span>创建菜单</span></a></li>
            <li><a class="delete" href="@Url.Content("~/WeiXin/DelMenu")" target="selectedTodo"  title="确定删除该账号的自定义菜单吗?">
                <span>删除菜单</span></a></li>
        </ul>
    </div>
    <table class="table" width="100%" layouth="135">
        <thead>
            <tr>
                <th width="2%">
                    <input type="checkbox" class="checkboxCtrl" group="ids" />
                </th>
                <th width="5%">
                    序号
                </th>
                <th width="auto">
                    区域名称
                </th>
                <th width="auto">
                    账号
                </th>
                <th width="10%">
                    密码
                </th>
                <th width="5%">
                    AppID
                </th>
                <th width="5%">
                    AppSecret
                </th>
                <th width="8%">
                    是否认证
                </th>
                <th width="10%">
                    是否创建菜单
                </th>
                <th width="8%">
                    查看菜单结构
                </th>
                <th width="10%">
                    开通时间
                </th>
            </tr>
        </thead>
        <tbody>
            @{
                if (dt != null)
                {
                    foreach (DataRow Dr in dt.Rows)
                    {
                <tr target="ID" rel="@Dr["ID"].ToString()">
                    <td>
                        @if (Convert.ToInt32(Dr["CerTification"]) == 1)
                        {
                            <input type="checkbox" name="ids" value="@Dr["ID"]"/>
                        }
                        else
                        {
                            <input type="checkbox" name="ids" disabled="disabled" value="-1" />
                        }
                    </td>
                    <td align="center">@Dr["RowNumber"]
                    </td>
                    <td align="center">@Dr["AccountName"]
                    </td>
                    <td align="center">@Dr["Account"]
                    </td>
                    <td align="center">@Dr["PassWord"]
                    </td>
                    <td align="center">@Dr["AppID"]
                    </td>
                    <td align="center">@Dr["AppSecret"]
                    </td>
                    <td align="center">
                        @if (Convert.ToInt32(Dr["CerTification"]) == 1)
                        {
                            <a class="btnSelect" title="已认证"></a>
                        }
                        else
                        {
                            <a class="btnDel" title="未认证"></a>
                        }
                    </td>
                    <td align="center">
                        @if (Convert.ToInt32(Dr["Status"]) == 2)
                        {
                            <a class="btnSelect" title="已创建"></a>
                        }
                        else
                        {
                            <a class="btnDel" title="未创建"></a>
                        }
                    </td>
                    <td>
                        <a class="btnLook" href="@Url.Content("~/WeiXin/FindMenu?ID=" + Dr["ID"])"  target="dialog" mask="true" width="800" height="600" title="查看菜单结构" >
                        </a>
                    </td>
                    <td align="center">@Dr["AddTime"]
                    </td>
                </tr>
                    }
                }
            }
        </tbody>
    </table>
    <div class="panelBar">
        <div class="pages">
            <span>每页显示: @ViewBag.fTable.NumPerPage 条, </span><span>共 @ViewBag.fTable.RecordCount
                条</span>
        </div>
        <div class="pagination" targetType="navTab" totalCount="@ViewBag.fTable.RecordCount" numPerPage="@ViewBag.fTable.NumPerPage" pageNumShown="10" currentPage="@ViewBag.fTable.PageNum">
        </div>
    </div>
</div>

-公众号列表为了展示所有需要创建自定义菜单的公众账号,每条数据都加了复选框,允许多个账号同时创建菜单
创建菜单按钮事件控制器:

public ActionResult CreateMenu(string s1 = "")
        {
            DWZJson djson = null;
            if (string.IsNullOrWhiteSpace(s1))
            {
                djson = new DWZJson() { message = "请选择要创建菜单的公众号", statusCode = "300" };
                return Content(djson.ToJsonString());
            }
            //string[] ids = s1.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            //获取选中的公众账号名称
            DataTable dt_accout = DALWeiXin.GetAccountList(s1);
            StringBuilder sb = new StringBuilder();
            if (dt_accout != null && dt_accout.Rows.Count > 0)
            {
                for (int i = 0; i < dt_accout.Rows.Count; i++)
                {
                    sb.AppendFormat("<li class='{0}' style=\"display: inline; margin-right: 10px;\"><strong>☑&nbsp;{1}</strong></li>", dt_accout.Rows[i]["ID"], HttpUtility.HtmlDecode(Convert.ToString(dt_accout.Rows[i]["AccountName"])));
                }
            }
            ViewData["AccountList"] = sb.ToString();
            //所有菜单列表
            DataTable dt = DALWeiXin.getMenuList();
            ViewBag.Table = dt;
            ViewBag.accountID = s1;//对应公众账号id
            return View();
        }

选择之后弹出菜单选择窗口,菜单以树形结构分两级展示,根据直观
弹窗页面:

@using System.Data;
@{
    ViewBag.Title = "CreateMenu";
    DataTable dt = ViewBag.Table;//菜单集合
}
<div class="pageContent">
    <form id="Menuform" method="post" action="@Url.Content("~/WeiXin/CreateMenuSubmit")" enctype="multipart/form-data" class="pageForm required-validate"
    onsubmit="return iframeCallback(this,dialogAjaxDone);">
    <input type="hidden" name="ids" id="ids" value="@ViewBag.accountID" />
    <div class="pageFormContent" layouth="56" style="overflow: auto;">
        <div style="width: 640px; border: 1px solid rgb(204, 204, 204); line-height: 21px;
            background: none repeat scroll 0% 0% rgb(255, 255, 255); height: auto;">
            <ul style="margin: 15px 15px 15px; list-style: circle;">
                @Html.Raw(Convert.ToString(ViewData["AccountList"]))
            </ul>
        </div>
        <div style="float: left; display: block; overflow: auto; width: 640px; border: 1px solid rgb(204, 204, 204);
            line-height: 21px; background: none repeat scroll 0% 0% rgb(255, 255, 255); height: auto;
            margin-top: 20px;">
            <ul class="tree treeFolder treeCheck expand">
                @if (dt != null && dt.Rows.Count > 0)
                {
                    for (var i = 0; i < dt.Rows.Count; i++)
                    {
                        DataRow[] foundRow = dt.Select("PID=" + dt.Rows[i]["MID"]);
                        if (Convert.ToInt32(dt.Rows[i]["PID"]) == -1 && foundRow.Length == 0)
                        {
                    <li><a tname="PMenu" tvalue="@dt.Rows[i]["MID"]">@dt.Rows[i]["MName"]@Html.Raw("(一级)")</a></li>
                        }
                        else if (Convert.ToInt32(dt.Rows[i]["PID"]) == -1 && foundRow.Length > 0)
                        {
                    <li><a tname="PMenu" tvalue="@dt.Rows[i]["MID"]">@dt.Rows[i]["MName"]@Html.Raw("(一级)")</a><ul>
                        @for (var j = 0; j < foundRow.Length; j++)
                        {
                            <li><a tname="CMenu" tvalue="@foundRow[j]["MID"]">@foundRow[j]["MName"]@Html.Raw("(二级)")</a>
                            </li>
                        }
                    </ul>
                    </li>
                        }
                    }
                }
            </ul>
        </div>
    </div>
    <div class="formBar">
        <ul>
            <li>
                <div class="buttonActive">
                    <div class="buttonContent">
                        <button type="submit">
                            提交</button></div>
                </div>
            </li>
            <li>
                <div class="button">
                    <div class="buttonContent">
                        <button type="button" class="close">
                            取消</button></div>
                </div>
            </li>
        </ul>
    </div>
    </form>
</div>

选择对应菜单之后提交事件控制器

 public ActionResult CreateMenuSubmit(FormCollection collection)
        {
            DWZJson djson = null;
            var pmid = collection["PMenu"] == null ? "" : collection["PMenu"];//父级菜单id
            var cmid = collection["CMenu"] == null ? "-1" : collection["CMenu"];//子级菜单id
            var account = collection["ids"];//创建菜单所属对象(公众号)
            if (string.IsNullOrWhiteSpace(pmid) &&  cmid == "-1")
            {
                djson = new DWZJson() { message = "请选择菜单", statusCode = "300" };
                return Content(djson.ToJsonString());
            }
            //根据菜单编号查询所有菜单
            DataTable dt = DALWeiXin.GetMenu(pmid, cmid);
            if (dt != null && dt.Rows.Count > 0)
            {
                try
                {
                    //构建拼接字符串
                    StringBuilder sb = new StringBuilder();
                    //begin create menu
                    sb.Append("{'button':[");
                    for (int i = 0; i < dt.Rows.Count; i++)
                    {
                        DataRow[] foundRow = dt.Select("PID=" + dt.Rows[i]["MID"], "Seq DESC");
                        //设置按钮类型,view: url 否则:key
                        var cont = Convert.ToString(dt.Rows[i]["MType"]) == "view" ? "url" : "key";
                        if (Convert.ToInt32(dt.Rows[i]["PID"]) == -1 && foundRow.Length == 0)
                        {
                            sb.Append("{");
                            sb.AppendFormat("'name':'{0}','type':'{1}','{3}':'{2}'", dt.Rows[i]["MName"], dt.Rows[i]["MType"], dt.Rows[i]["MContent"], cont);
                            sb.Append("},");
                        }
                        else if (Convert.ToInt32(dt.Rows[i]["PID"]) == -1 && foundRow.Length > 0)
                        {
                            sb.Append("{");
                            sb.AppendFormat("'name':'{0}','sub_button':[", dt.Rows[i]["MName"]);
                            for (int j = 0; j < foundRow.Length; j++)
                            {
                                cont = Convert.ToString(foundRow[j]["MType"]) == "view" ? "url" : "key";
                                sb.Append("{");
                                sb.AppendFormat("'name':'{0}','type':'{1}','{3}':'{2}'", foundRow[j]["MName"], foundRow[j]["MType"], foundRow[j]["MContent"], cont);
                                if (j == foundRow.Length - 1)
                                    sb.Append("}");
                                else
                                    sb.Append("},");
                            }
                            sb.Append("]},");
                        }
                    }
                    sb.Append("]}");
                    sb.Replace("'", "\"");
                    //获取appid  appsecret 集合
                    DataTable Tab = DALWeiXin.GetAccountList(account);
                    if (Tab != null && Tab.Rows.Count > 0)
                    {
                        //消息提示,记录创建菜单返回结果
                        var ShowMsg = "";
                        //记录创建成功的公众账号,修改状态
                        var successAccount = "";
                        for (int t = 0; t < Tab.Rows.Count; t++)
                        {
                            //创建菜单
                            string ResStr = CreateMemu(GetToken(Convert.ToString(Tab.Rows[t]["AppID"]), Convert.ToString(Tab.Rows[t]["AppSecret"])), sb.ToString());
                            //解析微信后台处理之后的json字符串,提取状态值
                            NameValueCollection msg = ParseJson(ResStr);
                            if (msg["errcode"] == "0,")
                            {
                                //拼接已经创建成功的公众账号id
                                successAccount += Tab.Rows[t]["ID"] + ",";
                            }
                            //拼接每个公众账号创建菜单的返回值
                            ShowMsg += "☑" + Tab.Rows[t]["AccountName"] + ":" + msg["errmsg"];
                        }
                        //更改菜单创建成功的公众账号状态,记录该账号已经创建菜单 状态置为2
                        bool result = DALWeiXin.UpdateAccountStatus(successAccount, 2);
                        djson = new DWZJson() { message = ShowMsg, statusCode = "200" };
                        return Content(djson.ToJsonString());
                    }
                    else
                    {
                        djson = new DWZJson() { message = "系统异常", statusCode = "300" };
                        return Content(djson.ToJsonString());
                    }
                }
                catch (Exception ex)
                {
                    djson = new DWZJson() { message = "系统异常" + ex.ToString(), statusCode = "300" };
                    return Content(djson.ToJsonString());
                }
            }
            return Content(djson.ToJsonString());
        }
  /// <summary>
        /// 创建自定义菜单
        /// </summary>
        /// <param name="weixin_token">token</param>
        /// <param name="Json">json结构的菜单</param>
        /// <returns></returns>
        public static string CreateMemu(string weixin_token, string Json)
        {
            string CreateMenuUrl = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token={0}";//创建自定义菜单链接

            string url = string.Format(CreateMenuUrl, weixin_token);
            return HttpPost(url, Json); //returnData 返回的是 {"errcode":0,"errmsg":"ok"} 此时,你取消服务号关注,在添加关注,菜单就生成了 

        }
 /// <summary>  
        /// HTTP POST方式请求数据  
        /// </summary>  
        /// <param name="url">URL.</param>  
        /// <param name="param">POST的数据</param>  
        /// <returns></returns>  
        public static string HttpPost(string url, string param)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.Accept = "*/*";
            request.Timeout = 15000;
            request.AllowAutoRedirect = false;

            StreamWriter requestStream = null;
            WebResponse response = null;
            string responseStr = null;

            try
            {
                requestStream = new StreamWriter(request.GetRequestStream());
                requestStream.Write(param);
                requestStream.Close();

                response = request.GetResponse();
                if (response != null)
                {
                    StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                    responseStr = reader.ReadToEnd();
                    //File.WriteAllText(Server.MapPath("~/") + @"\test.txt", responseStr);
                    reader.Close();
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                request = null;
                requestStream = null;
                response = null;
            }

            return responseStr;
        }
  /// <summary>
        /// 获取access_token
        /// </summary>
        /// <returns></returns>
        public static string GetToken(string AppID, string AppSecret)
        {
            string access_token = "";
            string url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + AppID + "&secret=" + AppSecret + "";//你成为开发者后会有一个appID和appSecret  

            string response = HttpGet(url);
            JavaScriptSerializer json = new JavaScriptSerializer();   //实例化一个能够序列化数据的类  
            ToJson list = json.Deserialize<ToJson>(response);    //将json数据转化为对象类型并赋值给list  
            access_token = list.access_token;      //获取JSON里access_token值  
            return access_token;
        }

-至于后台取数据的方法就不贴了,不同程序不同用法,以上有些代码可以删除,比喻修改状态云云,就不多说了。以上有不到位的欢迎指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值