2019-05-08 20:00:54 guobinhui 阅读数 684
  • 微信公众号开发5-自定义菜单-微信开发php

    微信公众平台开发之自定义菜单管理是子恒老师《微信公众平台开发》视频教程的第5部。详细讲解了用php开发微信,对微信公众平台中的自定义管理开发。内容包含微信添加菜单,获取自定义菜单配置,删除菜单等等。欢迎反馈,微信/QQ:68183131

    5686 人正在学习 去看看 秦子恒

10万+IT人都在关注,史上最全面的微信开发实战教程:包含公众号,小程序,微信支付等开发案例

欢迎关注笔者个人博客:http://blogs.chenyunkeji.com/

首先,直接上图,看效果,如下,有三个根菜单,每个菜单上有不同类型的子菜单,点击子菜单可以实现用户和公众号实时交互

http://blogs.chenyunkeji.com

本案例技术栈:springboot,mysql,logback,mybatis

菜单创建请求接口:https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

首先是菜单项(按钮)的基类,所有一级菜单、二级菜单都有一个相同的属性,那就是name。菜单项基类的封装代码如下:

public class Button {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

接着是子菜单项的封装。这里对子菜单是这样定义的:底部根菜单的二级菜单。这类子菜单项一定会包含三个属性:type、name和key,封装的代码如下

public class CommandButton extends Button{

    private String type;
    private String key;
    
    public String getType() {
	  return type;
    }
    public void setType(String type) {
	  this.type = type;
    }
    public String getKey() {
	  return key;
    }
    public void setKey(String key) {
	  this.key = key;
    }
}

 接着封装父菜单项。对父菜单项的定义:包含有二级菜单项的一级菜单。这类菜单项包含有二个属性:name和sub_button,而sub_button是一个子菜单项数组。父菜单项的封装代码如下:

public class ComplexButton extends Button{

    private Button[] sub_button;

    public Button[] getSub_button() {
        return sub_button;
    }

    public void setSub_button(Button[] sub_button) {
        this.sub_button = sub_button;
    }
}

最后是整个菜单对象的封装,菜单对象包含多个根菜单项(最多只能有3个),这些菜单项即可以是子菜单项(不含二级菜单的一级菜单),也可以是父菜单项(包含二级菜单的菜单项),如果能明白上面所讲的,再来看封装后的代码就很容易理解了:

public class Menu {
    private Button[] button;
    public Button[] getButton() {
        return button;
    }

    public void setButton(Button[] button) {
        this.button = button;
    }
}

 最后再封装一个链接类型的菜单,根据此处的名字也很好理解,不再赘述

public class ViewButton extends Button{

    private String type;
    private String url;
    
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
}

关于菜单实体类以及菜单对象的封装就介绍完了,下面根据微信接口创建自定义菜单。

一、封装菜单创建工具类

public class WeiXinMenuUtil {

    private static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";        private static Logger log = LoggerFactory.getLogger(WeiXinMenuUtil.class);
    public static int createMenu(Menu menu, String accessToken) {
        int result = 0;
        // 拼接创建菜单的url
        String url = menu_create_url .replace("ACCESS_TOKEN", accessToken);
        // 将菜单对象转换成json字符串
        String jsonMenu = JSON.toJSONString(menu);
        // 调用接口创建菜单
        JSONObject jsonObject = WeiXinUtil.httpPost(url, "POST", jsonMenu);
        if (null != jsonObject) {
            if (0 != (Integer)jsonObject.get("errcode")) {
                result = (Integer)jsonObject.get("errcode");
                log.error("创建菜单失败 errcode:{} errmsg:{}", jsonObject.get("errcode"), jsonObject.getString("errmsg"));
            }
        }
        return result;
    }
    
    public static Menu initMenu(){
        //1.创建菜单
        Menu menu = new Menu();
        // 主菜单1
        ComplexButton cb1 = new ComplexButton();
        cb1.setName("技术干货");
        
        // 主菜单2
        ComplexButton cb2 = new ComplexButton();
        cb2.setName("交流合作");
        
        // 主菜单3
        ComplexButton cb3 = new ComplexButton();
        cb3.setName("演示功能");
        
        // 主菜单1下面的子菜单1
        ViewButton cb01 = new ViewButton();
        cb01.setName("微服务教程连载");
        cb01.setType("view");
        cb01.setUrl("https://blog.csdn.net/guobinhui/article/category/8739270");
        
        // 主菜单1下面的子菜单2
        ViewButton cb02 = new ViewButton();
        cb02.setName("公众号开发教程");
        cb02.setType("view");
        cb02.setUrl("https://blog.csdn.net/guobinhui/article/category/8534361");
        
        ViewButton cb03 = new ViewButton();
        cb03.setName("小程序开发教程");
        cb03.setType("view");
        cb03.setUrl("https://blog.csdn.net/guobinhui/article/category/7763266");
        
        ViewButton cb04 = new ViewButton();
        cb04.setName("JavaEE基础");
        cb04.setType("view");
        cb04.setUrl("https://blog.csdn.net/guobinhui");
        
        ViewButton cb05 = new ViewButton();
        cb05.setName("笔者博客");
        cb05.setType("view");
        cb05.setUrl("http://blogs.chenyunkeji.com/");
        cb1.setSub_button(new ViewButton[]{cb01,cb02,cb03,cb04,cb05});
        
        // 主菜单2下面的子菜单1
        CommandButton cb11 = new CommandButton();
        cb11.setType("click");
        cb11.setKey("联系我");
        cb11.setName("联系笔者");
        
        CommandButton cb12 = new CommandButton();
        cb12.setName("技术交流");
        cb12.setType("click");
        cb12.setKey("18629374628");
        cb2.setSub_button(new CommandButton[]{cb11,cb12});
        
        CommandButton cb21 = new CommandButton();
        cb21.setType("scancode_waitmsg");
        cb21.setKey("rselfmenu_0_0");
        cb21.setName("扫码带提示");
        
        CommandButton cb22 = new CommandButton();
        cb22.setType("pic_sysphoto");
        cb22.setKey("rselfmenu_1_0");
        cb22.setName("系统拍照发图");
        
        CommandButton cb23 = new CommandButton();
        cb23.setType("pic_photo_or_album");
        cb23.setKey("rselfmenu_1_1");
        cb23.setName("拍照或者相册发图");
        
        CommandButton cb24 = new CommandButton();
        cb24.setType("pic_weixin");
        cb24.setKey("rselfmenu_1_2");
        cb24.setName("微信相册发图");
        
        CommandButton cb25 = new CommandButton();
        cb25.setType("location_select");
        cb25.setKey("rselfmenu_2_0");
        cb25.setName("发送地理位置");
        cb3.setSub_button(new CommandButton[]{cb21, cb22,cb23, cb24,cb25});
        menu.setButton(new Button[] { cb1,cb2, cb3});
        return menu;        
    }
}

二、微信接口凭证access_token的获取以及缓存实现

access_token可以用各种缓存插件或者线程,定时任务,写入数据库等多种方式对access_token进行缓存7200秒,开发者可以依据自己的喜好选择其一,本案例策略采用IO流定时写入文件的方法缓存。首先获取access_token:

public static JSONObject getToken()throws IOException{

 private String GET_ACCESS_TOKEN= "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
 String url = GET_ACCESS_TOKEN.replace("APPID",WeixinConstant.APPID).replace("APPSECRET",WeixinConstant.APPSECRET);
   JSONObject tokenObj = HttpGet(url);
   return tokenObj;
}

接着缓存access_token,也就是每隔7200秒生成一次access_token,生成的缓存7200秒,这样其余用到access_token的从文件中读取的就是最新的,不会过期。

public static  Map <String,Object> cacheToken() throws IOException {
      Gson gson = new Gson();
      Map <String,Object> map = new HashMap <String,Object> ();
      String token = null;
      JSONObject tokenObj = null; //需要获取的access_token对象;
      String filePath = System.getProperty("user.dir")+"/src/main/resources/static/token.txt";
      File file = new File(filePath);//Access_token保存的位置
      if (!file.exists())
        file.createNewFile();
      // 如果文件大小等于0,说明第一次使用,存入Access_token
      if (file.length() == 0) {
        tokenObj = WeiXinUtil.getToken();
        token = (String)tokenObj.get("access_token");
        FileOutputStream fos = new FileOutputStream(filePath, false);// 不允许追加
        tokenObj.put("expires_in",System.currentTimeMillis()/1000+"");
        String json = gson.toJson(tokenObj);
        fos.write(json.getBytes());
        fos.close();
      }else {
        //读取文件内容
        @SuppressWarnings("resource")
        FileInputStream fis = new FileInputStream(file);
        byte[] b = new byte[2048];
        int len = fis.read(b);
        String jsonAccess_token = new String(b, 0, len);// 读取到的文件内容
        JSONObject access_token = gson.fromJson(jsonAccess_token,JSONObject.class);
        if (access_token.get("expires_in") != null) {
          String lastSaveTime = (String)access_token.get("expires_in");
          long nowTime = System.currentTimeMillis()/1000;
          long remianTime = nowTime - Long.valueOf(lastSaveTime);
          if (remianTime < WeixinConstant.EXPIRESIN_TIME) {
              JSONObject access = gson.fromJson(jsonAccess_token,JSONObject.class);
              token = (String)access.get("access_token");
          } else {
              tokenObj = WeiXinUtil.getToken();
              FileOutputStream fos = new FileOutputStream(file, false);// 不允许追加
              tokenObj.put("expires_in",System.currentTimeMillis()/1000+"");
              String json = gson.toJson(tokenObj);
              fos.write((json).getBytes());
              fos.close();
          }
      }
      }
      map.put("access_token",token);
      return map;
    }

最后在项目的启动入口文件的main方法调用菜单创建方法进行初始化,那么项目在启动的时候,公众号的菜单就进行了初始化,用户就能看到公众号的菜单。

@SpringBootApplication
@MapperScan(basePackages = "com.chenyun.cloud.dao")
public class HelloServiceApplication {
    private final static Logger logger= LoggerFactory.getLogger(HelloServiceApplication.class);
    
    public static void main(String[] args) {
         SpringApplication.run(HelloServiceApplication.class, args);
         Map<String, Object> map;
        try {
            map = WeiXinUtil.cacheToken();
             String accessToken = (String)map.get("access_token");
             logger.info("accessToken:"+accessToken);
             Menu menu = WeiXinMenuUtil.initMenu();
             System.out.println(JSON.toJSONString(menu));
             int result  = WeiXinMenuUtil.createMenu(menu,accessToken);
             if (0 == result){
                  logger.info("菜单创建成功!");
              }else{
                  logger.info("菜单创建失败,错误码:" + result);
              }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }    
}

启动项目后,打印的JSON格式的日志打就显示了创建的菜单结构。

下节内容为大家分享公众号菜单栏的各种点击事件开发案例,更多JavaEE资料请关注下面公众号,欢迎广大开发者朋友一起交流。更多微信公众号功能演示请扫码体验,笔者电话(微信):18629374628

2019-02-23 11:17:13 weixin_43545329 阅读数 142
  • 微信公众号开发5-自定义菜单-微信开发php

    微信公众平台开发之自定义菜单管理是子恒老师《微信公众平台开发》视频教程的第5部。详细讲解了用php开发微信,对微信公众平台中的自定义管理开发。内容包含微信添加菜单,获取自定义菜单配置,删除菜单等等。欢迎反馈,微信/QQ:68183131

    5686 人正在学习 去看看 秦子恒

具体思路:菜单编辑实现的主要功能就是对菜单的增删改,以及同步到手机客户端上。
微信前端页面:

前端代码

<%@ Page Language="C#" AutoEventWireup="true" Inherits="WX_MenuAdm, DHERP.Web" EnableEventValidation="false" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head id="Head1" runat="server">
    <title></title>
    <link rel="Stylesheet" type="text/css" href="http://oa.datahelp.cn:808/erp/Public/Style/sub.css" />
    <link rel="Stylesheet" type="text/css" href="../../Public/css/ace.css" />
    <link rel="Stylesheet" type="text/css" href="../../Public/css/bootstrap.min.css" />
</head>

<body>
    <form id="form1" runat="server">
        <div class="col-xs-3" style="padding-left: 6px; padding-right: 0px;">
            <div class="widget-box widget-color-blue2">
                <div class="widget-header" style="background-image: -webkit-linear-gradient(bottom,#5090c1 0,#d7dcf2 100%)!important">
                    <h4 class="widget-title lighter smaller">选择</h4>
                </div>
                <div class="widget-body" id="tree">
                    <div class="widget-main padding-8">
                        <div id="tree-style" style="padding-right: 10px; overflow-y: auto; padding-left: 10px; scrollbar-face-color: #ffffff; font-size: 10pt; padding-bottom: 0px; scrollbar-shadow-color: #919192; color: blue; scrollbar-3dlight-color: #ffffff; line-height: 100%; scrollbar-arrow-color: #919192; padding-top: 0px; scrollbar-track-color: #ffffff; scrollbar-darkshadow-color: #ffffff; letter-spacing: 1pt; text-align: left; background-repeat: no-repeat;">
                            <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
                            <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="conditional" ChildrenAsTriggers="false">
                                <ContentTemplate>
                                    <asp:TreeView ID="TreeView1" runat="server" ShowLines="True" OnSelectedNodeChanged="TreeView1_SelectedNodeChanged">
                                        <SelectedNodeStyle BackColor="#7d8abe" BorderColor="White" />
                                    </asp:TreeView>
                                </ContentTemplate>
                                <Triggers>
                                    <asp:AsyncPostBackTrigger ControlID="btnAdds" EventName="Click" />
                                    <asp:AsyncPostBackTrigger ControlID="btnAdd" EventName="Click" />
                                    <asp:AsyncPostBackTrigger ControlID="btnMod" EventName="Click" />
                                    <asp:AsyncPostBackTrigger ControlID="btnDel" EventName="Click" />
                                    <asp:AsyncPostBackTrigger ControlID="btnSch" EventName="Click" />
                                     <asp:AsyncPostBackTrigger ControlID="btnUpdateWx" EventName="Click" />
                                    <asp:AsyncPostBackTrigger ControlID="TreeView1" EventName="SelectedNodeChanged" />
                                </Triggers>
                            </asp:UpdatePanel>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="col-xs-9">
            <div class="widget-box widget-color-blue2" id="max-box">
                <div class="widget-header" style="background-image: -webkit-linear-gradient(bottom,#5090c1 0,#d7dcf2 100%)!important">
                    <h4 class="widget-title lighter smaller">菜单编辑</h4>
                </div>
                <div class="widget-body-table" id="widget-body-table" style="width: 100%; height: 100%; overflow: scroll;">
                    <asp:UpdatePanel ID="UpdatePanel2" runat="server" ChildrenAsTriggers="false" UpdateMode="Conditional">
                        <ContentTemplate>
                            <fieldset class="layui-elem-field">
                                <legend>编辑信息</legend>
                                <div class="layui-form-item">
                                    <div class="layui-inline">
                                        <lable class="layui-form-label">菜单URL:</lable>
                                        <div class="layui-input-inline  layui-input-long">
                                            <asp:TextBox ID="tbUrl" runat="server" CssClass="layui-input-inline layui-input-long"></asp:TextBox>
                                        </div>
                                    </div>
                                </div>

                                <div class="layui-form-item">
                                    <div class="layui-inline">
                                        <lable class="layui-form-label">菜单类型:</lable>
                                        <div class="layui-input-inline">
                                            <asp:DropDownList ID="ddlWxMenuType" runat="server" CssClass="select">
                                                <asp:ListItem Value="click">click</asp:ListItem>
                                                <asp:ListItem Value="view">view</asp:ListItem>
                                            </asp:DropDownList>

                                        </div>
                                    </div>
                                    <div class="layui-inline">
                                        <lable class="layui-form-label">菜单名称:</lable>
                                        <div class="layui-input-inline">
                                            <asp:TextBox ID="tbBarText" runat="server" CssClass="layui-input"></asp:TextBox>
                                        </div>
                                    </div>
                                    <div class="layui-inline">
                                        <lable class="layui-form-label">菜单key:</lable>
                                        <div class="layui-input-inline">
                                            <asp:TextBox ID="tbWxMenuKey" runat="server" CssClass="layui-input"></asp:TextBox>
                                        </div>
                                    </div>

                                </div>

                            </fieldset>
                            <span style="display: none">
                                <asp:Button ID="btnSch" runat="server" ToolTip="刷新" Text="刷新" CssClass="btn btn-minier btn-purple" OnClick="btnSch_Click" UseSubmitBehavior="false" />
                                <asp:HiddenField ID="hfDepth" runat="server" Value="0" />
                                <asp:HiddenField ID="hfValuePath" runat="server" />
                                <asp:HiddenField ID="hfTemp" runat="server" />
                                <asp:HiddenField ID="hfRecID" runat="server" Value="-1" />
                                <asp:HiddenField ID="hfparentID" runat="server" Value="-1" />
                            </span>
                            <fieldset>
                                <legend>&nbsp;</legend>
                                <div style="text-align: center;">
                                    <asp:Button ID="btnAdds" runat="server" ToolTip="新建分类" Text="新建分类" CssClass="btn btn-minier btn-purple" OnClientClick="if(ChkAdds()==false)return false;" UseSubmitBehavior="false" OnClick="btnAdds_Click" />
                                    <asp:Button ID="btnAdd" runat="server" ToolTip="新建子类" Text="新建子类" CssClass="btn btn-minier btn-purple" OnClientClick="if(ChkAdd()==false)return false;" UseSubmitBehavior="false" OnClick="btnAdd_Click" />
                                    <asp:Button ID="btnMod" runat="server" ToolTip="修改" Text="修改" CssClass="btn btn-minier btn-purple" OnClientClick="if(ChkMod()==false)return false;" UseSubmitBehavior="false" OnClick="btnMod_Click" />
                                    <asp:Button ID="btnDel" runat="server" ToolTip="删除" Text="删除" CssClass="btn btn-minier btn-purple" OnClientClick="if(confirmAct('确定要删除吗?')==false)return false;" OnClick="btnDel_Click" UseSubmitBehavior="false" />
                                    <input id="btnMove" type="button" value="移动" class="btn btn-minier btn-purple" onclick="parent.layer_show(parent.layer.getFrameIndex(window.name), '移动菜单项目', '../Crm/Weixin/WeinxinMenuMove.aspx?id=' + document.getElementById('hfRecID').value, '800', '600');" />
                                    <asp:Button ID="btnUpdateWx" runat="server" ToolTip="同步微信" Text="同步微信" CssClass="btn btn-minier btn-purple" OnClick="btnUpdateWx_Click" />

                                    <input id="btnCls" type="button" value="关闭" class="btn btn-minier btn-purple" onclick="alert($('hfParent').value); CloseWindowClr('1');" />
                            </fieldset>

                        </ContentTemplate>
                        <Triggers>
                            <asp:AsyncPostBackTrigger ControlID="TreeView1" EventName="SelectedNodeChanged" />
                            <asp:AsyncPostBackTrigger ControlID="btnAdds" EventName="Click" />
                            <asp:AsyncPostBackTrigger ControlID="btnAdd" EventName="Click" />
                            <asp:AsyncPostBackTrigger ControlID="btnMod" EventName="Click" />
                            <asp:AsyncPostBackTrigger ControlID="btnDel" EventName="Click" />
                            <asp:AsyncPostBackTrigger ControlID="btnUpdateWx" EventName="Click" />
                        </Triggers>
                    </asp:UpdatePanel>
                    <span style="display: none">
                        <input name="hfparent" type="text" id="hfparent" />
                        <asp:HiddenField ID="hfActiveTab" runat="server" />
                    </span>
                </div>
            </div>
        </div>
    </form>
</body>

</html>
<script type="text/javascript" src="../../Public/js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="../../Public/js/erpcommon.js"></script>
<script type="text/javascript" src="../../Public/h-ui.admin/js/H-ui.admin.js"></script>
<script type="text/javascript">
    function ChkAdds() {
        if (document.getElementById("btnAdds").value == "保存") {
            if (ChkSave() == false) return false;
        }
    }

    function ChkAdd() {
        if (document.getElementById("hfRecID").value == "-1") {
            alert("请选择一条分类后操作!");
            return false;
        }
        if (document.getElementById("btnAdd").value == "保存") {
            if (ChkSave() == false) return false;
        }
    }

    function ChkMod() {
        if (document.getElementById("hfRecID").value == "-1") {
            alert("请选择一条分类后操作!");
            return false;
        }
        if (document.getElementById("btnMod").value == "保存") {
            if (ChkSave() == false) return false;
        }
    }
    function ChkSave() {
        if (isNull(document.getElementById("tbBarText").value)) {
            window.alert("操作失败!分类名不能为空");
            document.getElementById("tbBarText").focus();
            return false
        }
        if (!isNull(document.getElementById("tbWxMenuKey").value)) {
            if (!CheckNum(document.getElementById("tbWxMenuKey").value)) {
                window.alert("排序必须为数字.");
                document.getElementById("tbWxMenuKey").select();
                return false
            }
        }
    }

    function ChkFocus() {
        document.getElementById("tbBarText").select();
    }</script>
<script type="text/javascript">autodivheight();
    function autodivheight() { //函数:获取尺寸
        //获取浏览器窗口高度
        var winHeight = 0;
        if (window.innerHeight) winHeight = window.innerHeight;
        else if ((document.body) && (document.body.clientHeight)) winHeight = document.body.clientHeight;
        //通过深入Document内部对body进行检测,获取浏览器窗口高度
        if (document.documentElement && document.documentElement.clientHeight) winHeight = document.documentElement.clientHeight;
        //DIV高度为浏览器窗口的高度
        document.getElementById("widget-body-table").style.height = winHeight - 55 + "px";
        document.getElementById("tree").style.height = winHeight - 55 + "px";
        var treeheight = winHeight - 65 + "px";
        document.getElementById("tree-style").style.height = treeheight;
    }
    window.onresize = autodivheight; //浏览器窗口发生变化时同时变化DIV高度
</script>

选中左侧分类点击新建分类按钮,不可编辑区域变为可编辑区域,新建分类按钮变为保存按钮
在这里插入图片描述
页面后台代码

using System;
using System.Data;
using System.Web;
using System.Web.Profile;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using DHERP.DAL;
using DHERP.Library;
using DHERP.Model;
using DHERP.BLL;
using System.IO;
using System.Text;
using System.Net;
public class WX_MenuAdm : Page, IRequiresSessionState
{
	protected HtmlHead Head1;
	protected ScriptManager ScriptManager1;
	protected TreeView TreeView1;
	protected UpdatePanel UpdatePanel1;
	protected TextBox tbBarText;
    protected TextBox tbIcoPci;
    protected TextBox tbWxMenuKey;
    protected TextBox tbUrl;
    protected TextBox tbRemark;
    protected DropDownList ddlWxMenuType;
	protected HiddenField hfValuePath;
	protected HiddenField hfTemp;
	protected HiddenField hfRecID;
	protected HiddenField hfparentID;
	protected Button btnAdds;
    protected Button btnUpdateWx;
	protected Button btnAdd;
	protected Button btnMod;
	protected Button btnDel;
	protected UpdatePanel UpdatePanel2;
	protected HtmlForm form1;
    private int id;
	protected DefaultProfile Profile
	{
		get
		{
			return (DefaultProfile)this.Context.Profile;
		}
	}
	protected HttpApplication ApplicationInstance
	{
		get
		{
			return this.Context.ApplicationInstance;
		}
	}
	protected void Page_Load(object sender, EventArgs e)
	{
        int.TryParse(base.Request["id"], out this.id);//
        if (this.id == 0)
        {
            base.Response.End();
        } 
        FunLibrary.ChkLogin();
		if (!base.IsPostBack)
		{
			int num = int.Parse((string)this.Session["Session_GrantID"]);
			if (num > 0)
			{
				DALGrant dALGrant = new DALGrant();
				if (!dALGrant.GetGrant(num, "bg_r38"))
				{
					this.btnAdds.Enabled = false;
					this.btnMod.Enabled = false;
					this.btnDel.Enabled = false;
					this.btnAdd.Enabled = false;
				}
			}            
			this.SetEnable();
			this.FillData();
		}
	}
	protected void FillData()
	{
		int num = 0;
        DataTable dt = DALCommon.GetList_HL(0, "WX_WxMenu", "name as BarText,* ", 0, 0, "", " ID asc", out num).Tables[0];
		this.TreeView1.Nodes.Clear();
		TreeNode treeNode = new TreeNode();
		treeNode.Text = "全部(" + num.ToString() + ")";
		treeNode.Value = "-1";
		this.TreeView1.Nodes.Add(treeNode);
        BindControl.BindTreeNodePl(treeNode, dt, treeNode.Value);
		this.TreeView1.ExpandAll();
	}
	protected void CleanText()
	{
		this.tbBarText.Text = string.Empty;
	}
	protected void SetEnable()
	{
		this.tbBarText.Enabled = false;
	}
	protected void SetDisEnable()
	{
		this.tbBarText.Enabled = true;		
	}
    protected void btnSch_Click(object sender, EventArgs e)
    {
        this.FillData();
    }
	protected void btnAdds_Click(object sender, EventArgs e)
	{
		if (this.btnAdds.Text == "新建分类")
		{
			this.btnDel.Enabled = false;
			this.btnMod.Enabled = false;
			this.btnAdd.Enabled = false;
			this.btnAdds.Text = "保存";
			this.CleanText();
			this.SetDisEnable();
			this.SysInfoSlt("ChkFocus();");
		}
		else
		{
            MenuDal _MenuDal = new MenuDal();
            WxMenuModel _WxMenuModel = new WxMenuModel();
            _WxMenuModel.Name = FunLibrary.ChkInput(this.tbBarText.Text);
            _WxMenuModel.Type = this.ddlWxMenuType.SelectedItem.Value;
            _WxMenuModel.MenuKey = FunLibrary.ChkInput(this.tbWxMenuKey.Text);
            _WxMenuModel.Url = FunLibrary.ChkInput(this.tbUrl.Text);
            _WxMenuModel.OrgID = "";
            _WxMenuModel.Parent = -1;

          
          
            string str;
            int num = _MenuDal.Add("WX_WxMenu", _WxMenuModel, out str);
            if (num == 0)
            {
                this.btnDel.Enabled = true;
                this.btnMod.Enabled = true;
                this.btnAdd.Enabled = true;
                this.btnAdds.Text = "新建分类";
                this.SysInfoSlt("document.getElementById('btnAdds').focus();");
                this.SetEnable();
                this.FillData();
                this.hfRecID.Value = "-1";
            }
            else
            {
                if (num == -1)
                {
                    this.SysInfo("window.alert('" + str + "');document.getElementById('tbBarText').select();");
                }
                else
                {
                    this.SysInfo("window.alert('" + num + "');");
                }
            }
		}
        this.FillData();
	}
	protected void btnMod_Click(object sender, EventArgs e)
	{
		if (this.btnMod.Text == "修改")
		{
			this.btnDel.Enabled = false;
			this.btnAdds.Enabled = false;
			this.btnAdd.Enabled = false;
			this.btnMod.Text = "保存";
			this.SetDisEnable();
		}
		else
		{
            int id = 0;
            int.TryParse(this.hfRecID.Value, out id);
            if (id > 0)
            {
                string menuId = this.hfRecID.Value;
                string name = this.tbBarText.Text;
                string type = this.ddlWxMenuType.SelectedItem.Value;
                string key = this.tbWxMenuKey.Text;
                string url = this.tbUrl.Text;
                int uprow = MenuDal.UpdateMenu(menuId, name, type, key, url);
                if (uprow == 1)
                {
                    this.SysInfo("window.alert('保存成功');");
                }
                else
                {
                    this.SysInfo("window.alert('保存失败');");
                }
            }
            else
            {
                this.SysInfo("window.alert('错误,请选择左侧菜单项目');");
            }
		}
        this.FillData();
	}
	protected void btnDel_Click(object sender, EventArgs e)
	{
		int iD = int.Parse(this.hfRecID.Value);
        DALSideBarMenu dALSideBarMenu = new DALSideBarMenu();
		string empty = string.Empty;
        int num = dALSideBarMenu.Delete("WX_WxMenu", iD, out empty);
		if (num == 0)
		{
			this.hfRecID.Value = "-1";
			this.FillData();
			this.hfRecID.Value = "-1";
			this.CleanText();
		}
		else
		{
			if (num == -1)
			{
				this.SysInfo("window.alert('" + empty + "');");
			}
			else
			{
				this.SysInfo("window.alert('系统错误!请查看错误日志');");
			}
		}
        this.FillData();
	}
	protected void btnAdd_Click(object sender, EventArgs e)
	{
		if (this.btnAdd.Text == "新建子类")
		{
			this.btnDel.Enabled = false;
			this.btnMod.Enabled = false;
			this.btnAdds.Enabled = false;
			this.btnAdd.Text = "保存";
			this.CleanText();
			this.SetDisEnable();
			this.SysInfoSlt("ChkFocus();");
		}
		else
		{
            MenuDal _MenuDal = new MenuDal();
            WxMenuModel _WxMenuModel = new WxMenuModel();
            _WxMenuModel.Name = FunLibrary.ChkInput(this.tbBarText.Text);
            _WxMenuModel.Type = this.ddlWxMenuType.SelectedItem.Value;
            _WxMenuModel.MenuKey = FunLibrary.ChkInput(this.tbWxMenuKey.Text);
            _WxMenuModel.Url = FunLibrary.ChkInput(this.tbUrl.Text);
             WeixinUserInfo user = AdminUtil.GetWxInfo(this.id);//获取用户信息
             _WxMenuModel.OrgID = user.OrgID;//获取OrgID
            int iparent = 0;
            int.TryParse(this.hfRecID.Value, out iparent);
            _WxMenuModel.Parent = iparent;
            string str;
            int num = _MenuDal.Add("WX_WxMenu", _WxMenuModel, out str);
            this.SysInfo("window.alert('" + num + "');document.getElementById('tbBarText').select();");
            if (num == 0)
            {
                this.btnDel.Enabled = true;
                this.btnMod.Enabled = true;
                this.btnAdd.Enabled = true;
                this.btnAdds.Text = "新建分类";
                this.SysInfoSlt("document.getElementById('btnAdds').focus();");
                this.SetEnable();
                this.FillData();
                this.hfRecID.Value = "-1";
            }
            else
            {
                if (num == -1)
                {
                    this.SysInfo("window.alert('" + str + "');document.getElementById('tbBarText').select();");
                }
                else
                {
                    this.SysInfo("window.alert('" + num + "');");
                }
            }
		}
        this.FillData();
	}
    protected void btnUpdateWx_Click(object sender, EventArgs e)
    {

        WeixinUserInfo user = AdminUtil.GetWxInfo(this.id);
        string tok = AdminUtil.GetAccessToken(this.id);
        string result = WXApi.CreateMenu(tok, user.OrgID);
        this.SysInfoSlt("window.alert('" + result + "');");
       
    }
    private string GetPage(string posturl, string postData)
    {
        Stream outstream = null;
        Stream instream = null;
        StreamReader sr = null;
        HttpWebResponse response = null;
        HttpWebRequest request = null;
        Encoding encoding = Encoding.UTF8;
        byte[] data = null;
        if (postData.Length > 0) //有值代表创建菜单
        {
            data = encoding.GetBytes(postData);
        }

        // 准备请求...
        try
        {
            // 设置参数
            request = WebRequest.Create(posturl) as HttpWebRequest;
            CookieContainer cookieContainer = new CookieContainer();
            request.CookieContainer = cookieContainer;
            request.AllowAutoRedirect = true;
            if (postData.Length > 0)
            {
                request.Method = "POST"; //创建菜单
            }
            else
            {
                request.Method = "GET"; //删除菜单
            }

            request.ContentType = "application/x-www-form-urlencoded";

            if (postData.Length > 0) //有值代表创建菜单
            {
                request.ContentLength = data.Length;
                outstream = request.GetRequestStream();
                outstream.Write(data, 0, data.Length);
                outstream.Close();
            }

            //发送请求并获取相应回应数据
            response = request.GetResponse() as HttpWebResponse;
            //直到request.GetResponse()程序才开始向目标网页发送Post请求
            instream = response.GetResponseStream();
            sr = new StreamReader(instream, encoding);
            //返回结果网页(html)代码
            string content = sr.ReadToEnd();
            string err = string.Empty;
            return content;
        }
        catch (Exception ex)
        {
            string err = ex.Message;
            Response.Write(err);
            Response.End();
            return string.Empty;
        }
    }
    protected void CreateMenu(object sender, EventArgs e)
    {
        FileStream fs = new FileStream(HttpContext.Current.Server.MapPath(".") + "\\menu.txt", FileMode.Open);
        StreamReader sr = new StreamReader(fs, Encoding.GetEncoding("GBK"));
        string menu = sr.ReadToEnd();
        sr.Close();
        fs.Close();
        sr.Dispose();
        fs.Dispose();

        string AccessToken = AdminUtil.GetAccessToken(this.id); //获取access_token
        this.SysInfoSlt("window.alert('" + AccessToken + "');");
        string i = GetPage("https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" + AccessToken, menu);
        Response.Write("创建菜单结果:" + i);
        Response.End();
    }

    protected void TreeView1_SelectedNodeChanged(object sender, EventArgs e)
	{
		this.tbBarText.Text = this.TreeView1.SelectedNode.Text;
        //this.tbArray.Text = this.TreeView1.SelectedNode.Text;
        //this.tbUrl.Text = this.TreeView1.SelectedNode.Text;
        //this.wxMenuType.Text = this.TreeView1.SelectedNode.Text;
		this.hfTemp.Value = this.TreeView1.SelectedNode.Text;
		this.hfRecID.Value = this.TreeView1.SelectedNode.Value;
		this.hfValuePath.Value = this.TreeView1.SelectedNode.ValuePath;
        DataTable dt = MenuDal.GetMenuListID(int.Parse(this.hfRecID.Value));
        if(dt.Rows.Count>0)
        {
            this.tbWxMenuKey.Text = dt.Rows[0]["MenuKey"].ToString();
            this.tbBarText.Text = dt.Rows[0]["Name"].ToString();
            this.tbUrl.Text = dt.Rows[0]["Url"].ToString();
            //this.wxMenuType.Text = dt.Rows[0]["Type"].ToString();
            this.ddlWxMenuType.ClearSelection();
            for (int i = 0; i < this.ddlWxMenuType.Items.Count; i++)
            {
                if (this.ddlWxMenuType.Items[i].Value == dt.Rows[0]["Type"].ToString())
                {
                    this.ddlWxMenuType.Items[i].Selected = true;
                    break;
                }
            }

        }

		if (this.TreeView1.FindNode(this.hfValuePath.Value).Parent != null)
		{
			this.hfparentID.Value = this.TreeView1.FindNode(this.hfValuePath.Value).Parent.Value;
		}
		else
		{
			this.tbBarText.Text = string.Empty;
			this.hfparentID.Value = "-1";
		}
	}   
   
	protected void SysInfo(string str)
	{
		ScriptManager.RegisterClientScriptBlock(this.UpdatePanel1, this.UpdatePanel1.GetType(), "SysInfo", str, true);
	}
	protected void SysInfoSlt(string str)//前台弹出消息方法
	{
		ScriptManager.RegisterClientScriptBlock(this.UpdatePanel2, this.UpdatePanel2.GetType(), "SysInfo", str, true);
	}
}

同步菜单方法

  protected void btnUpdateWx_Click(object sender, EventArgs e)
    {

        WeixinUserInfo user = AdminUtil.GetWxInfo(this.id);
        string tok = AdminUtil.GetAccessToken(this.id);
        string result = WXApi.CreateMenu(tok, user.OrgID);
        this.SysInfoSlt("window.alert('" + result + "');");
       
    }

获取数据库中用户信息

public static WeixinUserInfo GetWxInfo(int id)
        {
            if (id >0)
            {
                DataTable dt = DbHelperSQL.Query(string.Format("select * from WX_Config where ID='{0}'", id)).Tables[0];
                if (dt.Rows.Count > 0)
                {
                    int BranchID = 0;
                    int IsAdmin = 0;
                    int.TryParse(dt.Rows[0]["BranchID"].ToString(), out BranchID);
                    int.TryParse(dt.Rows[0]["IsAdmin"].ToString(), out IsAdmin);
                    WeixinUserInfo userInfo = new WeixinUserInfo();
                    userInfo.UserName = dt.Rows[0]["UserName"].ToString(); 
                    userInfo.BranchID = BranchID;
                    userInfo.OrgID = dt.Rows[0]["OrgID"].ToString();
                    userInfo.AppID = dt.Rows[0]["AppID"].ToString();
                    userInfo.Token = dt.Rows[0]["Token"].ToString();
                    userInfo.EncodingAESKey = dt.Rows[0]["EncodingAESKey"].ToString();
                    userInfo.access_token = dt.Rows[0]["access_token"].ToString();
                    userInfo.AppSecret = dt.Rows[0]["AppSecret"].ToString();
                    userInfo.IsAdmin = IsAdmin;
                    return userInfo;
                }
            }
            return null;
        }

获取微信的Access Token

 public static string GetAccessToken( int id)
        {
            string access_token = string.Empty;

            WeixinUserInfo user = GetWxInfo(id);
            if (user != null)
            {
                if (user.access_token == "0" || user.access_token == "" || user.access_token == string.Empty) //尚未保存过access_token
                {
                    access_token = WXApi.GetToken(user.AppID, user.AppSecret);
                    DbHelperSQL.ExecuteSql(string.Format("update WX_Config set access_token='{0}' where UserName='{1}'", access_token, user.UserName));
                }
                else
                {
                    if (WXApi.TokenExpired(user.access_token)) //access_token过期
                    {
                        access_token = WXApi.GetToken(user.AppID, user.AppSecret);
                        DbHelperSQL.ExecuteSql(string.Format("update WX_Config set access_token='{0}' where UserName='{1}'", access_token, user.UserName));
                    }
                    else
                    {
                        return user.access_token;
                    }
                }

            }

            return access_token;
        }

创建菜单返回菜单 json数组

  #region 创建菜单
        /// <summary>
        /// 创建菜单
        /// </summary>
        public static string CreateMenu(string access_token, string orgID)
        {
            string menuJsonStr = MenuDal.GetMenuJsonStr(orgID);
            
            return CreateMenu2(access_token, menuJsonStr);
        }
        protected void SysInfoSlt(string str)
        {
            ScriptManager.RegisterClientScriptBlock(this.UpdatePanel2, this.UpdatePanel2.GetType(), "SysInfo", str, true);
        }
        /// <summary>
        /// 创建菜单
        /// </summary>
        public static string CreateMenu2(string access_token, string menuJsonStr)
        {
          
            return HttpRequestUtil.PostUrl(string.Format("https://api.weixin.qq.com/cgi-bin/menu/create?access_token={0}", access_token), menuJsonStr);
            

        }

菜单json数组拼接
注意:菜单分级根据数据库的code 长度决定 2位长度是一级菜单,4位长度是2级菜单。子集菜单根据前两位对应父及菜单。
在这里插入图片描述

  #region 生成菜单Json
        /// <summary>
        /// 生成菜单Json
        /// </summary>
        public static string GetMenuJsonStr(string orgID)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("{ \"button\":[");
            DataTable dt = GetMenuListByOrgID(orgID);
            foreach (DataRow dr in dt.Rows)
            {
                string sCode = dr["Code"].ToString();
                if (sCode.Length == 2)
                {
                    sb.AppendFormat("{{\"type\":\"{0}\"", dr["Type"].ToString());
                    sb.AppendFormat(",\"name\":\"{0}\"", dr["Name"].ToString());
                    if (dr["Type"].ToString() == "click")
                    {
                        sb.AppendFormat(",\"key\":\"{0}\"", dr["MenuKey"].ToString());
                    }
                    if (dr["Type"].ToString() == "view")
                    {
                        sb.AppendFormat(",\"url\":\"{0}\"", dr["Url"].ToString());
                    }
                    if (dr["Type"].ToString() == "scancode_waitmsg")
                    {
                        sb.AppendFormat(",\"key\":\"rselfmenu_0_0\",\"sub_button\":[]", dr["MenuKey"].ToString());
                    }
                    if (dr["Type"].ToString() == "scancode_push")
                    {
                        sb.AppendFormat(",\"key\":\"rselfmenu_0_1\",\"sub_button\":[]", dr["MenuKey"].ToString());
                    }
                    if (dr["Type"].ToString() == "pic_sysphoto")
                    {
                        sb.AppendFormat(",\"key\":\"rselfmenu_1_0\",\"sub_button\":[]", dr["MenuKey"].ToString());
                    }
                    if (dr["Type"].ToString() == "pic_photo_or_album")
                    {
                        sb.AppendFormat(",\"key\":\"rselfmenu_1_1\",\"sub_button\":[]", dr["MenuKey"].ToString());
                    }
                    if (dr["Type"].ToString() == "pic_weixin")
                    {
                        sb.AppendFormat(",\"key\":\"rselfmenu_1_2\",\"sub_button\":[]", dr["MenuKey"].ToString());
                    }
                    if (dr["Type"].ToString() == "location_select")
                    {
                        sb.AppendFormat(",\"key\":\"rselfmenu_2_0\",\"sub_button\":[]", dr["MenuKey"].ToString());
                    }
                    bool subMenuExists = false;
                    bool first = true;
                    foreach (DataRow drSub in dt.Rows)
                    {
                        string sSubCode = drSub["Code"].ToString();
                        if (sSubCode.Length == 4 && sSubCode.IndexOf(sCode) == 0)
                        {
                            subMenuExists = true;
                            if (subMenuExists && first)
                            {
                                sb.Append(",\"sub_button\":[");
                            }
                            if (!first) sb.Append(",");
                            if (first) first = false;

                            sb.AppendFormat("{{\"type\":\"{0}\"", drSub["Type"].ToString());
                            sb.AppendFormat(",\"name\":\"{0}\"", drSub["Name"].ToString());
                            if (drSub["Type"].ToString() == "click")
                            {
                                sb.AppendFormat(",\"key\":\"{0}\"", drSub["MenuKey"].ToString());
                            }
                            if (drSub["Type"].ToString() == "view")
                            {
                                sb.AppendFormat(",\"url\":\"{0}\"", drSub["Url"].ToString());
                            }
                            if (drSub["Type"].ToString() == "scancode_waitmsg")
                            {
                                sb.AppendFormat(",\"key\":\"rselfmenu_0_0\",\"sub_button\":[]", drSub["MenuKey"].ToString());
                            }
                            if (drSub["Type"].ToString() == "scancode_push")
                            {
                                sb.AppendFormat(",\"key\":\"rselfmenu_0_1\",\"sub_button\":[]", drSub["MenuKey"].ToString());
                            }
                            if (drSub["Type"].ToString() == "pic_sysphoto")
                            {
                                sb.AppendFormat(",\"key\":\"rselfmenu_1_0\",\"sub_button\":[]", drSub["MenuKey"].ToString());
                            }
                            if (drSub["Type"].ToString() == "pic_photo_or_album")
                            {
                                sb.AppendFormat(",\"key\":\"rselfmenu_1_1\",\"sub_button\":[]", drSub["MenuKey"].ToString());
                            }
                            if (drSub["Type"].ToString() == "pic_weixin")
                            {
                                sb.AppendFormat(",\"key\":\"rselfmenu_1_2\",\"sub_button\":[]", drSub["MenuKey"].ToString());
                            }
                            if (drSub["Type"].ToString() == "location_select")
                            {
                                sb.AppendFormat(",\"key\":\"rselfmenu_2_0\",\"sub_button\":[]", drSub["MenuKey"].ToString());
                            }
                            sb.Append("}");
                        }
                    }
                    if (subMenuExists) sb.Append("]");
                    sb.Append("},");
                }
            }
            if (sb.Length > 1 && sb.ToString(sb.Length - 2, 2) == "},")
            {
                sb.Remove(sb.Length - 1, 1);
            }
            sb.Append("]}");
            return sb.ToString();
        }
        #endregion

创建新菜单对应的code生成是通过数据库过程实现的,通过拼接自身id与父层id实现。
生成的菜单
在这里插入图片描述

2017-11-14 09:11:09 towtotow 阅读数 294
  • 微信公众号开发5-自定义菜单-微信开发php

    微信公众平台开发之自定义菜单管理是子恒老师《微信公众平台开发》视频教程的第5部。详细讲解了用php开发微信,对微信公众平台中的自定义管理开发。内容包含微信添加菜单,获取自定义菜单配置,删除菜单等等。欢迎反馈,微信/QQ:68183131

    5686 人正在学习 去看看 秦子恒

我们在使用微信公众号时,

会看到公众号底部有三栏菜单,

用户点击菜单后,

可以跳转到网页或者调用其它的功能,

这就是微信菜单的效果。


微信自定义菜单开发案例


微信公众号的菜单,

最多可以有三个一级,

每个一级菜单最多可以有5个二级菜单。


我们后面实现的微信三级分销海报,

就需要用到微信菜单,

在微信开发第5部分,

子恒老师跟你分享微信菜单开发…

微信自定义菜单开发案例视频教程在线观看

http://edu.csdn.net/course/detail/2953/48649

2019-11-05 09:24:52 Lance_One 阅读数 19
  • 微信公众号开发5-自定义菜单-微信开发php

    微信公众平台开发之自定义菜单管理是子恒老师《微信公众平台开发》视频教程的第5部。详细讲解了用php开发微信,对微信公众平台中的自定义管理开发。内容包含微信添加菜单,获取自定义菜单配置,删除菜单等等。欢迎反馈,微信/QQ:68183131

    5686 人正在学习 去看看 秦子恒

第一步,通过APPID和APPSecret获得access_token

我把自定义菜单的json内容写在了一个单独的文件里,放在项目的根目录,取名WeChatMenu

自定义菜单的设置规则和字数限制,在微信开发文档里都说的很清楚,url要写清楚能访问的asp.net项目网址,随便写的话会报错,遇到报错可以在这里查询报错代码:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Global_Return_Code.html

下面是json内容

{
    "button": [
        {
            "name": "doyoxia",
            "sub_button": [
                {
                    "type": "view",
                    "name": "doyoxia官网",
                    "url": "#"
                },
                {
                    "type": "view",
                    "name": "doyoxia小程序",
                    "url": "#"
                }
            ]
        },
        {
            "name": "APP下载",
            "sub_button": [
                {
                    "type": "view",
                    "name": "安卓",
                    "url": "#"
                },
                {
                    "type": "view",
                    "name": "IOS",
                    "url": "#"
                }
            ]
        },
        {
            "name": "关于我们",
            "sub_button": [
                {
                    "type": "view",
                    "name": "商业合作",
                    "url": "#"
                },
                {
                    "type": "view",
                    "name": "联系客服",
                    "url": "#"
                },
                {
                    "type": "view",
                    "name": "关于我们",
                    "url": "#"
                }
                    ]
                }
            ]
}

然后通过代码读取文件中的内容,读取内容后获得access_token,然后通过acces_token和自己写的自定义菜单的json内容访问接口,微信就会返回设置是否成功的代码,如果全部正确只需要访问一次,新的菜单就好了,可以取关再重新关注自己的公众号来查看新的菜单。

上代码

        [HttpPost]
        public IHttpActionResult WechatMenu(dynamic data)
        {

            string path = System.Web.Hosting.HostingEnvironment.MapPath(@"~/WechatMenu.json");


            //get access_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<WechatModels>(wm);

            //create menu  
            string turl = string.Format("https://api.weixin.qq.com/cgi-bin/menu/create?access_token={0}", info.access_token);
            using (StreamReader r = new StreamReader(path))
            {
                string json = r.ReadToEnd();
                HttpContent httpContent = new StringContent(json);
                httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
                var menu = new System.Net.Http.HttpClient().PostAsync(turl, httpContent).Result.Content.ReadAsStringAsync().Result;
                return Json(menu);
            }
        }

几个关键点,首先是WebApi里面如何获取json文件读取json内容

string path = System.Web.Hosting.HostingEnvironment.MapPath(@"~/WechatMenu.json");

尝试了几次,发现用这种方式获取文档地址最稳妥也不会出错,先通过相对路径查询文件位置,再通过物理路径读取文件

这是我的笨方法,可能不是最优解

 

WechatModels info = JsonConvert.DeserializeObject<WechatModels>(wm);

这句代码是把获取到的access_token返回代码转为实体类

    public class WechatModels
    {
        public string access_token { get; set; }
        public string expires_in { get; set; }
    }

基本上就是这些,所有这些都需要在配置好的服务器上面运行访问,才能返回想要的结果。

希望这篇文档有一定的帮助!

2016-02-19 18:09:04 echocdzh 阅读数 440
  • 微信公众号开发5-自定义菜单-微信开发php

    微信公众平台开发之自定义菜单管理是子恒老师《微信公众平台开发》视频教程的第5部。详细讲解了用php开发微信,对微信公众平台中的自定义管理开发。内容包含微信添加菜单,获取自定义菜单配置,删除菜单等等。欢迎反馈,微信/QQ:68183131

    5686 人正在学习 去看看 秦子恒
<?php
header('Content-type: text/html; charset=utf-8');#设置头信息
require_once('zhphpWeixinApi.class.php');#加载微信接口类文件
$zhwx=new zhphpWeixinApi();//实例化
$configArr=array(
				'token'=>'weixintest',
				'appid'=>'wx7b4b6ad5c7bfaae1',
				'appSecret'=>'faaa6a1e840fa40527934a293fabfbd1',
				'myweixinId'=>'gh_746ed5c6a58b'
				);
$zhwx->setConfig($configArr);//配置文件
if($zhwx->weixinBaseApiMessage()){
	              //准备菜单数据,
	           $menuListData=array(
					'button'=>array(
						//创建两个一级菜单  type 点击类型  name 菜单名称  key 菜单说明
						array('type'=>'view','name'=>'投票活动','url'=>'http://d005151912.0502.dodi.cn/toupiao.php'),
						array('type'=>'view','name'=>'查看结果','url'=>'http://d005151912.0502.dodi.cn/chakan.php'),
						//创建一个二级菜单
						array(
							'name'=>'我要赚钱',
							'sub_button'=>array(
								array('type'=>'view','name'=>'赚钱介绍','url'=>'http://d005151912.0502.dodi.cn/zhuanqian.php'),
								array('type'=>'click','name'=>'我要推广','key'=>'wytg')
							)
						)
					 )
               );
					//得到并检查 accessToken  高级接口
					if($zhwx->CheckAccessToken()){
                        $menuListInfo=$zhwx->queryMenu();
                        if(isset($menuListInfo['errcode']) &&  $menuListInfo['errcode'] == 46003){
                          //表示没有菜单数据,创建菜单
						      $info=$zhwx->createMenu($menuListData);
                            if($info == true){
                                echo '菜单创建成功';
                            }else{
								 echo '<pre>';
								   print_r($info);
								 echo '</pre>';
							}
                        }else{
                            //为了调试方便我们这里删除掉
                            $zhwx->deleteMenu();
                        }
                     }
        }else{
		    echo '配置文件失败';
	  }

没有更多推荐了,返回首页