GVKun编程网logo

php 开发微信公众号杂记————自定义菜单(微信公众号自定义菜单接口)

1

在本文中,我们将给您介绍关于php开发微信公众号杂记————自定义菜单的详细内容,并且为您解答微信公众号自定义菜单接口的相关问题,此外,我们还将为您提供关于Android开发技巧之我的菜单我做主(自定

在本文中,我们将给您介绍关于php 开发微信公众号杂记————自定义菜单的详细内容,并且为您解答微信公众号自定义菜单接口的相关问题,此外,我们还将为您提供关于Android开发技巧之我的菜单我做主(自定义菜单)、asp.net开发微信公众平台(8)微信9大高级接口,自定义菜单、C# .net微信开发,开发认证,关注触发消息,自动应答,事件响应,自定义菜单、CI框架微信开发-自定义菜单的知识。

本文目录一览:

php 开发微信公众号杂记————自定义菜单(微信公众号自定义菜单接口)

php 开发微信公众号杂记————自定义菜单(微信公众号自定义菜单接口)

在项目根目录(可能还可以放到一个可访问的文件夹【猜测,懒于验证】)新建wechat_menu.php

代码如下

$appid = "kjllkjlkj456564";         //自己公众号的APPID
$appsecret = "54ads4564adsf464f";        //自己公众号的 secret  ,需要自行设置
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret;

$output = https_request($url);
$access_token_Arr    = json_decode($output,true);
$access_token        =   $access_token_Arr[''access_token''];

$jsonmenu = ''{
    "button": [
        {
            "type": "view", 
            "name": "游戏签到", 
            "url": "http://wx.test.com/"
        },
        {
            "name": "游戏充值", 
            "sub_button": [
                {
                    "type": "view", 
                    "name": "购买游戏卡", 
                    "url": "http://wx.test.com/index.php/pay/index"
                }, 
                {
                    "type": "view", 
                    "name": "新版下载", 
                    "url": "http://wx.test.com/index.php/down/index"
                }
            ]
        }
    ]
}'';


$url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$access_token;
$result = https_request($url, $jsonmenu);
//var_dump($result);

function https_request($url,$data = null){
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
    if (!empty($data)){
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    }
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($curl);
    curl_close($curl);
    return $output;
}

确认该项目的域名解析到公网环境后,直接访问
http://wx.test.com/wechat_menu.php

成功后返回

{"errcode":0,"errmsg":"ok"}

其余都是错误,具体对照开发文档的错误代码

Android开发技巧之我的菜单我做主(自定义菜单)

Android开发技巧之我的菜单我做主(自定义菜单)

     Android SDK本身提供了一种默认创建菜单的机制。但通过这种机制创建的菜单虽然从功能上很完备,但在界面效果上实在是有点“土”。对于一个拥有绚丽界面的程序配上一个有点“土”的菜单,会使用户感觉很怪,甚至会使绚丽的界面大打折扣。实际上,对于如此灵活和强大的Android系统,修改菜单的样式只是小菜一碟。为程序加入漂亮菜单的方法很多。在本节先介绍一种比较常用的方法,就是通过onKeyDown事件方法和PopupWindow实现自定义的菜单。至于通过这种技术能否设计出绚丽的菜单效果,那就要看我们的设 计、美学、心理学功底了。

     通过6.1.1节介绍的选项菜单可以知道。通过按手机的“Menu”键(是手机上的硬按键,不同手机“Menu”键所在的位置会不同),可以弹出选项菜单,再按“Back”键,选项菜单会关闭。那么要想模拟选项菜单的弹出和关闭效果,只需要监听这两个键的按下事件即可。并且在“Menu”键按下时使用PopupWindow弹出一个窗口作为模拟的选项菜单。下面先来看看如图6.9所示的模拟选项菜单的效果。



从图6.9可以看出,在界面的下方显示了3个菜单项:“首页”、“我的”和“更多”。其中“我的”菜单项的文字和图像是左右水平排列,而另两个菜单项上的文字和图像是上下垂直排列。实际上,这种效果由一个普通的布局文件(menu_layout.xml)完成的,代码如下:

复制代码 代码如下:

<?xml version="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"android:layout_width="fill_parent"
android:layout_height="wrap_content"android:gravity="bottom">
<!-- 第一个菜单项:“首页” -->
<LinearLayout android:id="@+id/home"android:orientation="vertical"
android:layout_width="fill_parent"android:layout_height="wrap_content"
android:background="@drawable/button_normal_translucent"
android:layout_weight="1">
<ImageView android:layout_width="fill_parent"
android:layout_height="wrap_content"android:src="@drawable/home"
android:paddingTop="5dp" />
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"android:text="首页"
android:gravity="center" />
</LinearLayout>
<!-- 第二个菜单项:“我的” -->
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:background="@drawable/button_normal"android:layout_weight="1"
android:gravity="center">
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:src="@drawable/mine"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="我的" />
</LinearLayout>
<!-- 第三个菜单项
<LinearLayout android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content" android:background="@drawable/button_normal"
android:layout_weight="1">
<ImageView android:layout_width="fill_parent"
android:layout_height="wrap_content"android:src="@drawable/more"
android:paddingTop="18dp" />
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="更多"
android:gravity="center"android:paddingTop="5dp"/>
</LinearLayout>
</LinearLayout>


在编写上面代码之前,别忘了准备几个相关的图像,例如,本例使用了5个图像。其中button_normal_translucent.png用于“首页”菜单项的背景(半透明效果),button_normal.png用于“我的”和“更多”菜单项的背景。home.png、mine.png和more.png分别用于这三个菜单项的图像。

下面来编写监听“menu”和“back”键按下动作的代码。按下“back”键要处理的任务有如下两个。

如果选项菜单已经弹出,关闭选项菜单。如果选项菜单未弹出,或已经被关闭,直接关闭当前的Activity,也就是调用finish方法。

为了区分上面两个任务,在程序中设置了一个int类型状态变量(state),当state为1时表示选项菜单已弹出,state为2时表示选项菜单未弹出。下面我们看一下完整的实现代码。

复制代码 代码如下:

package mobile.android.ch06.custom.menu;
import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.PopupWindow;
import android.widget.Toast;
public class Main extends Activity
{
privatePopupWindow pop;
privateView layout;
private int state = 2; //状态变量,1:选项菜单已弹出,2:选项菜单未弹出
@Override
publicvoid onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
publicboolean onKeyDown(int keyCode,KeyEvent event)
{
switch (keyCode)
{
case KeyEvent.KEYCODE_MENU: // 按下“menu”键的动作
// 选项菜单已弹出,不再弹出新的窗口
if (state == 1)
return false;
// 装载选项菜单布局文件
layout =getLayoutInflater().inflate(R.layout.menu_layout,null);
// 创建PopupWindow对象,并在指定位置弹出用于显示菜单的窗口
pop = new PopupWindow(layout,getwindowManager()
.getDefaultdisplay().getWidth(),getwindowManager()
.getDefaultdisplay().getHeight());
// 设置弹出窗口的位置
pop.showAtLocation(layout,Gravity.BottOM,0);
View home = layout.findViewById(R.id.home);
// 为“首页”菜单项添加单击事件
home.setonClickListener(new OnClickListener()
{
@Override
public void onClick(View view)
{
Toast.makeText(Main.this,"单击定制菜单.",Toast.LENGTH_LONG).show();
// 单击“首页”菜单项后,关闭选项菜单
pop.dismiss();
// 重新设置状态变量
state = 2;
}
});
// 弹出选项菜单后,将状态变量设为1,表示选项菜单已弹出
state = 1;
return false;
case KeyEvent.KEYCODE_BACK: // 按下“back”键的动作
if (state == 1)
{
// 如果选项菜单已弹出,关闭它
pop.dismiss();
// 将状态变量设为选项菜单已关闭
state = 2;
}
else if (state == 2)
{
// 如果选项菜单还没有显示,或已经关闭,则直接关闭当前的Activity
finish();
}
return false;
}
// 除“menu”和“back”按下事件外,仍需调用Activity类的onKeyDown方法来响应其他键的按下事件
return super.onKeyDown(keyCode,event);
}
}

在编写上面代码时应注意如下几点。

对于选项菜单来说,一般单击某个菜单项后,会执行一些动作,并且选项菜单会自动关闭。为了模拟这一过程。为“首页”菜单项添加了一个单击事件。当单击“首页”菜单项时,会弹出一个Toast提示信息,并且选项菜单会关闭。 当执行完按下“menu”或“back”键的动作后,onKeyDown方法应返回一个常量(false或true都可以),不能再调用super.onKeyDown方法,否则在执行完定制的菜单项动作后,又会执行系统的默认动作。例如,当按下“back”键后,关闭弹出菜单后,连当前的Activity也一起关了。当然,如果是除了“menu”和“back”的其他键按下时还是需要调用Activity类的onKeyDown方法的(也就是super.onKeyDown方法),这样在程序中还可以响应其他的按键事件,否则程序除了“menu”和“back”键外,其他的键几乎都不好使了。showAtLocation方法用于控件弹出窗口的位置。该方法的第1个参数是一个View对象。实际上,showAtLocation方法内部只是需要调用View.getwindowToken方法来获得一个IBinder对象。showAtLocation方法的第2个参数表示弹出窗口的位置。本例中设置了弹出窗口在屏幕底部显示。最后两个参数分别表示水平和垂直偏移量。本例都设为0,表示不发生偏移。因此,弹出窗口会在屏幕的最底部显示,也就是显示选项菜单的位置。

您可能感兴趣的文章:

  • 安卓(Android)实现3DTouch效果
  • Android左右滑出菜单实例分析
  • android底部菜单栏实现原理与代码
  • android popwindow实现左侧弹出菜单层及PopupWindow主要方法介绍
  • 基于Android实现点击某个按钮让菜单选项从按钮周围指定位置弹出
  • Android ListView长按弹出菜单二种实现方式示例
  • Android界面设计(APP设计趋势 左侧隐藏菜单右边显示content)
  • Android仿QQ空间底部菜单示例代码
  • Android实现原生侧滑菜单的超简单方式
  • Android实现类似3D Touch菜单功能

asp.net开发微信公众平台(8)微信9大高级接口,自定义菜单

asp.net开发微信公众平台(8)微信9大高级接口,自定义菜单

前7篇把最基础的消息接收和回复全做完了, 也把高级接口的入口和分拆处理写好了空方法, 此篇接着介绍微信的9大高级接口, 并着重讲解其中的自定义菜单。

微信9大接口为:

1.语音识别接口

2.客服接口

3.OAuth2.0 网页授权接口

4.生成带参数的二维码接口

5.获取用户地理位置接口

6.获取用户基本信息接口

7.获取关注者列表接口

8.用户分组接口

9.上传下载多媒体文件接口

具体介绍:

1. 语音识别

功能描述:通过语音识别接口,用户发送的语音,将同时给出语音识别出的文本内容。

实用意义:第三方可以调用微信自主研发的语音识别技术。意味着微信向第三方开放语音识别技术,直接调用语音识别接口,对语音识别结果进行互动或根据识别的内容进行自动答复。

2. 客服接口

功能描述:通过客服接口,公众号可以在用户发送过消息的 12 小时内,向用户回复消息。

实用意义:以前公众帐号跟订户只能被动响应,比如用户触发了需求,如发送关键字给公众帐号,后者才可以与用户对话。如今,如果订户跟公众帐号对话过一次,公众帐号就可以在 12 个小时内持续给用户下发消息。这提高了公众帐号发送消息的能力。

3. OAuth 2.0 网页授权

功能描述:通过网页授权接口,公众号可以请求用户授权。

实用意义:这就像微博、QQ的帐号授权功能。这意味着微信帐号正式成为一个帐号系统。

4. 生成带参数二维码

功能描述:通过该接口,公众号可以获得一系列携带不同参数的二维码,在用户扫描关注公众号后,公众号可以根据参数分析各二维码的效果。

实用意义:举例来说,以前放一个二维码在网站或者线下的广告牌,效果都是一样的:获得关注用户。现在可以分析订户来自哪里。开发者可以在链接里设置特殊信息,做更多的数据分析。这一功能也可以用来做帐号绑定,

5. 获取用户地理位置

功能描述:通过该接口,公众号能够获得用户进入公众号会话时的地理位置。

实用意义:两种情况可以获得用户地理位置:一是与公众帐号“会话时”,二是在会话界面“每隔 5 秒”。在用户同意下,这就可以做微信导航或地理围栏方面的服务。

6. 获取用户基本信息

功能描述:通过该接口,公众号可以根据加密后的用户 OpenID,获取用户基础信息,包括头像、名称、性别、地区。

实用意义:以前这是一个非常高的权限。获得用户基本信息后,可以做 CRM 管理后台,方便商家管理用户。

7. 获取关注者列表

功能描述:通过该接口,用户可以获取所有关注者的 OpenID

实用意义:以前不能知道有多少人关注你,是谁在关注你。如今你可以知道谁在关注你。

8. 用户分组接口

功能描述:通过分组接口,公众号可以在后台为用户移动分组,或创建、修改分组。

实用意义:可以对用户进行分组,比如乐思享组织一场“听众交流会”,现场来了 1000 人,可以把它归为一组,后续的活动花絮照片只发给这 1000 人。这对于商家来说,就是一个 VIP 会员管理,是 CRM 管理平台。

9. 上传下载多媒体文件

功能描述:通过该接口公众号可以在需要时在微信服务器上传下载多媒体文件。

实用意义:可以下发图片、视频。比如搞笑视频,上传到微信公众账号后台,可以向听众推送出来,相当于视频网站的一个业务。

C# .net微信开发,开发认证,关注触发消息,自动应答,事件响应,自定义菜单

C# .net微信开发,开发认证,关注触发消息,自动应答,事件响应,自定义菜单

成为开发者


string[] ArrTmp = { "token", 
Request["timestamp"], 
Request["nonce"] };
Array.Sort(ArrTmp);     
//字典排序string tmpStr = string.Join("", ArrTmp);
tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
tmpStr = tmpStr.ToLower();if (tmpStr != Request["signature"].ToLower())
{
   Response.Write(Request["echostr"]);
}
登录后复制
关注帐号,触发消息,自动应答,事件响应

   

 

namespace ElegantWM.WebUI.Areas.WeiXin.Controllers
{
    /// <summary>
    /// 微信公共服务类
    /// </summary>
    public class RobotController : BaseController
    {
        /// <summary>
        /// 接收微信请求接口,认证的接口
        /// </summary>
        /// <returns></returns>
        public ContentResult Index()
        {
            string result = AnalyzeXmlFromWeiXin();
            return Content(result);
        }

        /// <summary>
        /// 分析微信POST到本服务器的XML数据
        /// </summary>
        /// <param name="xmlStream"></param>
        /// <returns></returns>
        private string AnalyzeXmlFromWeiXin()
        {
            StreamReader reader = new StreamReader(Request.InputStream);
            string xml = reader.ReadToEnd();
            //获取MsgType
            log.Info(xml);
            string msgType = XmlHelper.ReadXmlStr(xml, "/xml/MsgType", "");
            switch (msgType)
            {
                case "event"://如果是事件
                    return OnAttention(xml);
                case "text"://如果是文本消息
                    return OnReceiveTextMsg(xml);
                default:
                    return "不被支持的关键字!";
            }
        }

        /// <summary>
        /// 响应文本消息
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        private string OnReceiveTextMsg(string xml)
        {
            WxTextMsg msg = XmlEntityExchange<WxTextMsg>.ConvertXml2Entity(xml);
            //返回消息,互换收发用户
            string toUser = msg.FromUserName;
            msg.FromUserName = msg.ToUserName;
            msg.ToUserName = toUser;

            switch (msg.Content.Trim())
            {
                case "?":
                    msg.Content = HelpDocument();
                    break;
                case "?":
                    msg.Content = HelpDocument();
                    break;
                case "1":
                    msg.Content = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    break;
                case "2":
                    msg.Content = Tools.HttpCrossDomain.Get("http://www.weather.com.cn/data/sk/101210301.html");
                    break;
                case "3":
                    msg.Content = "来吧,想唠点什么呢? [偷笑]";
                    break;
                case "你是男的女的":
                    msg.Content = "姑娘一枚 [偷笑]";
                    break;
                default:
                    msg.Content = "抱歉哦,我不认识您输入的命令。/害羞 /:,@-D";
                    break;
            }
            return XmlEntityExchange<WxTextMsg>.ConvertEntity2Xml(msg);
        }
        /// <summary>
        /// 获取帮助菜单文档
        /// </summary>
        /// <returns></returns>
        private string HelpDocument()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("HI,请回复数字,选择服务").Append("\n\n");
            sb.Append("1. 当前时间").Append("\n");
            sb.Append("2. 天气信息").Append("\n");
            sb.Append("3. 聊天唠嗑").Append("\n");
            sb.Append("n. 更多服务开发中...").Append("\n");
            sb.Append("回复【?】显示此帮助菜单");
            return sb.ToString();
        }

        /// <summary>
        /// 当用户关注微信帐号的时候触发,事件响应
        /// </summary>
        /// <param name="xml"></param>
        private string OnAttention(string xml)
        {
            WxEvent wxevent = XmlEntityExchange<WxEvent>.ConvertXml2Entity(xml);
            WxTextMsg msg = new WxTextMsg();
            msg.ToUserName = wxevent.FromUserName;
            msg.FromUserName = wxevent.ToUserName;
            msg.CreateTime = DateTime.Now.Ticks;
            msg.MsgType = "text";
            //如果是关注,则发送欢迎消息
            switch (wxevent.Event)
            {
                case "subscribe":
                    msg.Content = System.Configuration.ConfigurationManager.AppSettings["DefaultWxMsg"];
                    break;
                case "CLICK":
                    msg.Content = "您单击的是:" + wxevent.EventKey;
                    break;
                default:
                    msg.Content = "暂未处理的事件:Event" + wxevent.Event + ";EventKey:" + wxevent.EventKey;
                    break;
            }
            string rst = XmlEntityExchange<WxTextMsg>.ConvertEntity2Xml(msg);
            log.Info(rst);
            return rst;
        }
    }
}
登录后复制

辅助类

//实体
public class WxEvent
    {
        /// <summary>
        /// 接收人
        /// </summary>
        public string ToUserName { get; set; }
        /// <summary>
        /// 发送人
        /// </summary>
        public string FromUserName { get; set; }
        /// <summary>
        /// 时间
        /// </summary>
        public string CreateTime { get; set; }
        /// <summary>
        /// 类型
        /// </summary>
        public string MsgType { get; set; }
        /// <summary>
        /// 事件
        /// </summary>
        public string Event { get; set; }

        public string EventKey { get; set; }
    }

public class WxTextMsg
    {
        /// <summary>
        /// 接收人
        /// </summary>
        public string ToUserName { get; set; }
        /// <summary>
        /// 发送人
        /// </summary>
        public string FromUserName { get; set; }
        /// <summary>
        /// 时间
        /// </summary>
        public long CreateTime { get; set; }
        /// <summary>
        /// 类型
        /// </summary>
        public string MsgType { get; set; }
        /// <summary>
        /// 内容
        /// </summary>
        public string Content { get; set; }
    }
登录后复制
//XML和实体对象间的相互转化
namespace ElegantWM.WebUI.Areas.WeiXin
{
    public class XmlEntityExchange<T> where T : new()
    {
        /// <summary>
        /// 将XML转换为对象
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        public static T ConvertXml2Entity(string xml)
        {
            XmlDocument doc = new XmlDocument();
            PropertyInfo[] propinfos = null;
            doc.LoadXml(xml);
            XmlNodeList nodelist = doc.SelectNodes("/xml");
            T entity = new T();
            foreach (XmlNode node in nodelist)
            {
                //初始化propertyinfo
                if (propinfos == null)
                {
                    Type objtype = entity.GetType();
                    propinfos = objtype.GetProperties();
                }
                //填充entity类的属性
                foreach (PropertyInfo pi in propinfos)
                {
                    XmlNode cnode = node.SelectSingleNode(pi.Name);
                    pi.SetValue(entity, Convert.ChangeType(cnode.InnerText, pi.PropertyType), null);
                }
            }
            return entity;
        }

        /// <summary>
        /// 构造微信消息
        /// </summary>
        /// <param name="t">对象实体</param>
        /// <returns>返回微信消息xml格式</returns>
        public static string ConvertEntity2Xml(T t)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("<xml>");
            Type objtype = t.GetType();
            //填充entity类的属性
            foreach (PropertyInfo pi in objtype.GetProperties())
            {
                object obj = pi.GetValue(t);
                string value = obj == null ? "" : obj.ToString();
                if (pi.PropertyType.Name.ToLower() == "int64")
                    builder.Append("<" + pi.Name + ">" + value + "</" + pi.Name + ">");
                else
                    builder.Append("<" + pi.Name + "><![CDATA[" + value + "]]></" + pi.Name + ">");
            }
            builder.Append("</xml>");
            return builder.ToString();
        }
    }
}
登录后复制

基础类:http请求

/* *
 * Copyright © 2013 CCT All Rights Reserved 
 * 作者:JackChain 
 * 时间:2013/8/23 18:21:23
 * 功能:跨域访问
 * 版本:V1.0
 *
 * 修改人:
 * 修改点:
 * */namespace ElegantWM.Tools
{    public class HttpCrossDomain
    {        /// <summary>
        /// 跨域访问        /// </summary>
        /// <param name="url"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public static string Post(string url, string param, int time = 60000)
        {
            Uri address = new Uri(url);
            HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
            request.Method = "POST";
            request.ContentType = "application/json;charset=utf-8"; //"application/x-www-form-urlencoded";
            request.Timeout = time;            byte[] byteData = UTF8Encoding.UTF8.GetBytes(param == null ? "" : param);
            request.ContentLength = byteData.Length;            using (Stream postStream = request.GetRequestStream())
            {
                postStream.Write(byteData, 0, byteData.Length);
            }            string result = "";            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                StreamReader reader = new StreamReader(response.GetResponseStream());
                result = reader.ReadToEnd();
            }            return (result);
        }        /// <summary>
        /// 跨域访问        /// </summary>
        /// <param name="url"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public static string Get(string url, int time = 60000)
        {
            Uri address = new Uri(url);
            HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
            request.Method = "GET";
            request.ContentType = "application/json;charset=utf-8"; //"application/x-www-form-urlencoded";
            request.Timeout = time;            string result = "";            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                StreamReader reader = new StreamReader(response.GetResponseStream());
                result = reader.ReadToEnd();
            }            return (result);
        }

    }
}
登录后复制

获取Token:


public class CommonController : Controller
    {
        /// <summary>
        /// 获取微信凭证
        /// </summary>
        /// <returns></returns>
        public JsonResult GetWxCredential()
        {
            string url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
            url = string.Format(url, ConfigurationManager.AppSettings["AppId"], ConfigurationManager.AppSettings["AppSecret"]);
            string rst = HttpCrossDomain.Get(url);
            if (rst.Contains("access_token"))
            {
                string tokenId=rst.Replace("{\"access_token\":\"", "").Replace("\",\"expires_in\":7200}", "");
                CacheHelper.CacheInsertAddMinutes("access_token",tokenId,120);
                return Json(tokenId, JsonRequestBehavior.AllowGet);
            }
            else
                return Json(rst, JsonRequestBehavior.AllowGet);
        }
    }
登录后复制

获取和更新菜单


/// <summary>
        /// 获取微信菜单
        /// </summary>
        /// <returns></returns>
        public JsonResult Get()
        {
            string url = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=";
            if (CacheHelper.CacheValue("access_token") != null)
            {
                url = url + CacheHelper.CacheValue("access_token").ToString();
            }
            string rst = HttpCrossDomain.Get(url);
            return Json(rst,JsonRequestBehavior.AllowGet);
        }
        /// <summary>
        /// 创建Menu
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult Create(string json)
        {
            string url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=";
            if (CacheHelper.CacheValue("access_token") != null)
            {
                url = url+CacheHelper.CacheValue("access_token").ToString();
            }
            string rst = HttpCrossDomain.Post(url, json);
            return Json(rst);
        }
登录后复制

更多C# .net微信开发,开发认证,关注触发消息,自动应答,事件响应,自定义菜单 相关文章请关注PHP中文网!

CI框架微信开发-自定义菜单

CI框架微信开发-自定义菜单

在ci框架下面实现了自定义菜单功能.写了一个model,一个类库.顺便附带access_token的实现方式

<span>php
</span><span>class</span><span> Makemenu{
    </span><span>public</span> <span>$menustr</span><span>;
    </span><span>public</span> <span>function</span><span> __construct(){
    }
    </span><span>public</span> <span>function</span><span> init(){
        </span><span>$this</span>-&gt;<span>dolist();
        </span><span>return</span>  <span>$this</span>-&gt;<span>setmenu();
    }
    </span><span>private</span> <span>function</span><span> dolist(){
        </span><span>$CI</span> =&amp;<span> get_instance();
        </span><span>$CI</span> -&gt; load -&gt;model("Menu_model","menu"<span>);
        </span><span>$plist</span> = <span>$CI</span>-&gt;menu -&gt;<span>isplist();
        </span><span>foreach</span>(<span>$plist</span> <span>as</span> <span>$pid</span><span>){
            </span><span>$pidarr</span>[] = <span>$pid</span>[''pid''<span>];
        }
        </span><span>$list</span> = <span>$CI</span>-&gt;menu -&gt;maketree(<span>$CI</span>-&gt;menu-&gt;<span>getlist());
        </span><span>foreach</span>(<span>$list</span> <span>as</span> <span>$btn</span><span>){
            </span><span>if</span>(<span>in_array</span>(<span>$btn</span>[''id''],<span>$pidarr</span><span>)){
                </span><span>//</span><span>生成不带key和url的链接作为父级菜单</span>
                <span>$btn_arr</span>[<span>$btn</span>[''id'']] = <span>array</span>("type"=&gt;<span>$btn</span>[''menutype''],
                                                        "name"=&gt;<span>$btn</span>[''content''<span>]);
            }</span><span>elseif</span>(<span>$btn</span>[''pid''] == 0<span>){
                </span><span>//</span><span>生成有操作的一级菜单</span>
                <span>$btn_arr</span>[<span>$btn</span>[''id'']] = <span>array</span>("type"=&gt;<span>$btn</span>[''menutype''],
                                                        "name"=&gt;<span>$btn</span>[''content''],
                                                        "key"=&gt;<span>$btn</span>[''clickkey''],
                                                        "url"=&gt;<span>$btn</span>[''url''<span>]);
            }</span><span>else</span><span>{
                </span><span>//</span><span>生成子菜单</span>
                <span>$btn_arr</span>[<span>$btn</span>[''pid'']][''sub_button''][] = <span>array</span>("type"=&gt;<span>$btn</span>[''menutype''],
                                                        "name"=&gt;<span>$btn</span>[''content''],
                                                        "key"=&gt;<span>$btn</span>[''clickkey''],
                                                        "url"=&gt;<span>$btn</span>[''url''<span>]);
            }
        }
        </span><span>$btnarr</span>[''button''] = <span>array_values</span>(<span>$btn_arr</span><span>);
        </span><span>$r</span> = <span>$this</span>-&gt;menustr = json_encode(<span>$btnarr</span>,<span>JSON_UNESCAPED_UNICODE);
        </span><span>return</span> <span>$r</span><span>;
    }
    </span><span>private</span> <span>function</span><span> setmenu(){
        </span><span>$accesstoken</span> =<span> get_access_token();
        </span><span>$url</span> = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token={<span>$accesstoken</span>}"<span>;
        </span><span>$ch</span> =<span> curl_init();
        curl_setopt(</span><span>$ch</span>, CURLOPT_URL, <span>$url</span><span>);
        curl_setopt(</span><span>$ch</span>, CURLOPT_CUSTOMREQUEST, "POST"<span>);
        curl_setopt(</span><span>$ch</span>, CURLOPT_SSL_VERIFYPEER, <span>FALSE</span><span>);
        curl_setopt(</span><span>$ch</span>, CURLOPT_SSL_VERIFYHOST, <span>FALSE</span><span>);
        curl_setopt(</span><span>$ch</span>, CURLOPT_USERAGENT, ''Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)''<span>);
        curl_setopt(</span><span>$ch</span>, CURLOPT_FOLLOWLOCATION, 1<span>);
        curl_setopt(</span><span>$ch</span>, CURLOPT_AUTOREFERER, 1<span>);
        curl_setopt(</span><span>$ch</span>, CURLOPT_POSTFIELDS, <span>$this</span>-&gt;<span>menustr);
        curl_setopt(</span><span>$ch</span>, CURLOPT_RETURNTRANSFER, <span>true</span><span>);
        </span><span>$info</span> = curl_exec(<span>$ch</span><span>);
        </span><span>if</span> (curl_errno(<span>$ch</span><span>)) {
            </span><span>return</span> curl_error(<span>$ch</span><span>);
        }
        curl_close(</span><span>$ch</span><span>);
        </span><span>return</span> <span>$info</span><span>;
    }
}</span>
登录后复制

上面是library里面的内容,主要是根据数据表生成菜单的json串

<span>php

</span><span>class</span> Menu_model <span>extends</span><span> CI_Model {
    </span><span>public</span> <span>$table_name</span><span>;
    </span><span>public</span> <span>function</span><span> __construct(){
        parent</span>::<span>__construct();
        </span><span>$this</span>-&gt;load-&gt;<span>database();
        </span><span>$this</span>-&gt;table_name = "data_menu"<span>;
    }
    </span><span>public</span> <span>function</span> query(<span>$sql</span><span>){
        </span><span>return</span> <span>$this</span>-&gt;db-&gt;query(<span>$sql</span><span>);
    }
    </span><span>public</span> <span>function</span> getone(<span>$id</span><span>){
        </span><span>$get_sql</span>  = "select * from {<span>$this</span>-&gt;table_name} where id = {<span>$id</span>}"<span>;
        </span><span>return</span> <span>$this</span>-&gt;query(<span>$get_sql</span>)-&gt;<span>row();
    }
    </span><span>public</span> <span>function</span> addone(<span>$data</span><span>){
        </span><span>if</span>((<span>$data</span>[''pid''] == 0)&amp;&amp;(<span>$this</span>-&gt;checksum()&gt;=3<span>)){
            </span><span>//</span><span>一级菜单不超过3个</span>
            <span>return</span> "toomany1"<span>;
        }</span><span>elseif</span>((<span>$data</span>[''pid'']!=0)&amp;&amp;(<span>$this</span>-&gt;checksum(<span>$data</span>[''pid'']))&gt;=7<span>){
            </span><span>//</span><span>二级菜单不超过7个</span>
            <span>return</span> "toomany2"<span>;
        }
        </span><span>if</span>(<span>is_array</span>(<span>$data</span>)&amp;&amp;!<span>empty</span>(<span>$data</span><span>)){
            </span><span>$keys</span> = "`".<span>implode</span>("`,`",<span>array_keys</span>(<span>$data</span>))."`"<span>;
            </span><span>$vals</span> = "''".<span>implode</span>("'',''",<span>array_values</span>(<span>$data</span>))."''"<span>;
            </span><span>$insert_sql</span> = "insert into {<span>$this</span>-&gt;table_name} (<span>$keys</span>) values (<span>$vals</span>)"<span>;
            </span><span>return</span> <span>$this</span>-&gt;query(<span>$insert_sql</span><span>);
        }</span><span>else</span><span>{
            </span><span>return</span> <span>false</span><span>;
        }
    }
    </span><span>public</span> <span>function</span> del(<span>$id</span><span>){
        </span><span>$infos</span> = <span>$this</span>-&gt;getone(<span>$id</span><span>);
        </span><span>$del_sql</span> = "delete from {<span>$this</span>-&gt;table_name} where id = {<span>$id</span>} and pid = {<span>$id</span>}"<span>;
        </span><span>return</span> <span>$this</span>-&gt;query(<span>$del_sql</span><span>);
    }
    </span><span>private</span> <span>function</span> checksum(<span>$id</span> = ''''<span>){
        </span><span>if</span>(<span>$id</span> == ''''<span>){
            </span><span>$get_sql</span> = "select count(1) as total from {<span>$this</span>-&gt;table_name} where pid =0"<span>;
        }</span><span>else</span><span>{
            </span><span>$id</span> = <span>intval</span>(<span>$id</span><span>);
            </span><span>$get_sql</span> = "select count(1) as total from {<span>$this</span>-&gt;table_name} where pid ={<span>$id</span>}"<span>;
        }
        </span><span>$r</span> = <span>$this</span>-&gt;db-&gt;query(<span>$get_sql</span>)-&gt;<span>row();
        </span><span>return</span> <span>$r</span>-&gt;<span>total;
    }
    </span><span>public</span> <span>function</span><span> getplist(){
        </span><span>//</span><span>获取一级菜单</span>
        <span>$get_sql</span> = "select * from {<span>$this</span>-&gt;table_name} where pid=0 order by menuorder asc"<span>;
        </span><span>return</span> <span>$this</span>-&gt;db-&gt;query(<span>$get_sql</span>)-&gt;<span>result_array();
    }
    </span><span>public</span> <span>function</span><span> isplist(){
        </span><span>$get_sql</span> = "select pid from {<span>$this</span>-&gt;table_name} where pid  0 group by pid"<span>;
        </span><span>return</span> <span>$this</span>-&gt;db-&gt;query(<span>$get_sql</span>)-&gt;<span>result_array();
    }
    </span><span>public</span> <span>function</span><span> getlist(){
        </span><span>$get_sql</span> = "select * from {<span>$this</span>-&gt;table_name} where 1 order by pid asc, menuorder asc"<span>;
        </span><span>return</span> <span>$this</span>-&gt;db-&gt;query(<span>$get_sql</span>)-&gt;<span>result_array();
    }
    </span><span>public</span> <span>function</span> maketree(<span>$data</span><span>){
        </span><span>$pids</span> = <span>array</span><span>();
        </span><span>foreach</span>(<span>$data</span> <span>as</span> <span>$k</span>=&gt;<span>$v</span><span>){
            </span><span>if</span>(<span>$v</span>[''pid''] == 0<span>){
                </span><span>$pids</span>[<span>$v</span>[''id'']][] = <span>$v</span><span>;
            }</span><span>else</span><span>{
                </span><span>$pids</span>[<span>$v</span>[''pid'']][] = <span>$v</span><span>;
            }
        }
        </span><span>list</span>(<span>$t1</span>,<span>$t2</span>,<span>$t3</span>) = <span>array_values</span>(<span>$pids</span><span>);
        </span><span>$r</span> = <span>array_merge_recursive</span>(<span>is_array</span>(<span>$t1</span>)?<span>$t1</span>:<span>array</span>(),<span>is_array</span>(<span>$t2</span>)?<span>$t2</span>:<span>array</span>(),<span>is_array</span>(<span>$t3</span>)?<span>$t3</span>:<span>array</span><span>());
        </span><span>return</span> <span>$r</span><span>;
    }
    </span><span>public</span> <span>function</span> update(<span>$data</span><span>){
        </span><span>if</span>(<span>is_array</span>(<span>$data</span>)&amp;&amp;!<span>empty</span>(<span>$data</span><span>)){
            </span><span>$id</span> = <span>$data</span>[''id''<span>];
            </span><span>unset</span>(<span>$data</span>[''id''<span>]);
            </span><span>foreach</span>(<span>$data</span> <span>as</span> <span>$k</span>=&gt;<span>$v</span><span>){
                </span><span>$update_arr</span>[] = "`".<span>$k</span>."` = ''".<span>$v</span>."''"<span>;
            }
            </span><span>$update_fs</span> = <span>implode</span>(",",<span>$update_arr</span><span>);
            </span><span>$update_sql</span> = "update {<span>$this</span>-&gt;table_name} set {<span>$update_fs</span>} where id = {<span>$id</span>}"<span>;
            </span><span>return</span> <span>$this</span>-&gt;query(<span>$update_sql</span><span>);
        }</span><span>else</span><span>{
            </span><span>return</span> <span>false</span><span>;
        }
    }

}</span>
登录后复制

上面是model里面的各种方法.

数据库的表结构如下,附创建表的语句.

<span>CREATE</span> <span>TABLE</span><span> `menu` (
  `id` </span><span>int</span>(<span>11</span>) <span>NOT</span> <span>NULL</span><span> AUTO_INCREMENT,
  `content` </span><span>varchar</span>(<span>20</span>) <span>DEFAULT</span> <span>NULL</span><span>,
  `pid` </span><span>int</span>(<span>11</span>) <span>DEFAULT</span> <span>''</span><span>0</span><span>''</span><span>,
  `menutype` enum(</span><span>''</span><span>click</span><span>''</span>,<span>''</span><span>view</span><span>''</span>,<span>''</span><span>scancode_push</span><span>''</span>,<span>''</span><span>scancode_waitmsg</span><span>''</span>,<span>''</span><span>pic_sysphoto</span><span>''</span>,<span>''</span><span>pic_photo_or_album</span><span>''</span>,<span>''</span><span>pic_weixin</span><span>''</span>,<span>''</span><span>location_select</span><span>''</span>) <span>DEFAULT</span> <span>''</span><span>view</span><span>''</span> COMMENT <span>''</span><span>消息类型</span><span>''</span><span>,
  `url` </span><span>varchar</span>(<span>200</span>) <span>DEFAULT</span> <span>NULL</span> COMMENT <span>''</span><span>链接地址</span><span>''</span><span>,
  `clickkey` </span><span>varchar</span>(<span>20</span>) <span>DEFAULT</span> <span>NULL</span> COMMENT <span>''</span><span>事件KEY</span><span>''</span><span>,
  `menuorder` </span><span>int</span>(<span>11</span>) <span>DEFAULT</span> <span>NULL</span> COMMENT <span>''</span><span>排序</span><span>''</span><span>,
  `submenu` </span><span>tinyint</span>(<span>2</span>) <span>DEFAULT</span> <span>''</span><span>0</span><span>''</span><span>,
  </span><span>PRIMARY</span> <span>KEY</span><span> (`id`)
) ENGINE</span><span>=</span>MyISAM AUTO_INCREMENT<span>=</span><span>0</span> <span>DEFAULT</span> CHARSET<span>=</span>utf8
登录后复制

  Field Type Comment
主键 id int(11) NOT NULL
  content varchar(20) NULL
  pid int(11) NULL
  menutype enum(''click'',''view'',''scancode_push'',''scancode_waitmsg'',''pic_sysphoto'',''pic_photo_or_album'',''pic_weixin'',''location_select'') NULL 消息类型
  url varchar(200) NULL 链接地址
  clickkey varchar(20) NULL 事件KEY
  menuorder int(11) NULL 排序
  submenu tinyint(2) NULL

下面是写在system/core/common.php下面的获取token的方法,其实要做一个加盐处理,要么会有恶心的人做恶心的事情.

<span>function</span><span> get_access_token(){
        </span><span>//</span><span>从微信服务器获取access_token  并保留一个小时</span>
        <span>$old_filename</span> = APPPATH."cache/".<span>md5</span>(<span>date</span>("YmdH",<span>time</span>()-3600)).".php"<span>;
        @</span><span>unlink</span>(<span>$old_filename</span><span>);
        </span><span>$filename</span> = APPPATH."cache/".<span>md5</span>(<span>date</span>("YmdH",<span>time</span>())).".php"<span>;
        </span><span>if</span>(<span>is_file</span>(<span>$filename</span><span>)){
            </span><span>$r</span> = <span>include</span>(<span>$filename</span><span>);
        }</span><span>else</span><span>{
            </span><span>$url</span> = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&amp;appid=".APPID."&amp;secret=".<span>APPSECRET;
            </span><span>$access_token</span> =  <span>file_get_contents</span>(<span>$url</span><span>);
            </span><span>$res</span> = "<?php return ".<span>var_export(json_decode(<span>$access_token</span>,1),1).";"<span>;
            </span><span>file_put_contents</span>(<span>$filename</span>,<span>$res</span><span>);
            </span><span>$r</span> =  <span>include</span>(<span>$filename</span><span>);
        }
        </span><span>return</span> (<span>$r</span>[''access_token''<span>]);
    }</span>
登录后复制

前面的菜单管理就不写了,就是管理那个表的数据,保证数据表里面的数据没问题即可.

在控制器里面只需要

$this->load->library("Makemenu");

然后调用  $this->makemenu->dolist();

就会推送到微信的服务器.   还需要注意在入口文件定义两个常量   APPID和APPSECRET    .

放出来给大家,希望有用,也给我自己备份个.

以上就介绍了CI框架微信开发-自定义菜单,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

关于php 开发微信公众号杂记————自定义菜单微信公众号自定义菜单接口的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Android开发技巧之我的菜单我做主(自定义菜单)、asp.net开发微信公众平台(8)微信9大高级接口,自定义菜单、C# .net微信开发,开发认证,关注触发消息,自动应答,事件响应,自定义菜单、CI框架微信开发-自定义菜单等相关知识的信息别忘了在本站进行查找喔。

本文标签:

上一篇30 个优化 MySQL 语句的技巧(如何优化mysql语句)

下一篇php 开发微信公众号杂记————非登录获取用户信息(php微信公众号授权登录)