php 开发微信公众号杂记————自定义菜单(微信公众号自定义菜单接口)
1
在本文中,我们将给您介绍关于php开发微信公众号杂记————自定义菜单的详细内容,并且为您解答微信公众号自定义菜单接口的相关问题,此外,我们还将为您提供关于Android开发技巧之我的菜单我做主(自定
在本文中,我们将给您介绍关于php 开发微信公众号杂记————自定义菜单的详细内容,并且为您解答微信公众号自定义菜单接口的相关问题,此外,我们还将为您提供关于Android开发技巧之我的菜单我做主(自定义菜单)、asp.net开发微信公众平台(8)微信9大高级接口,自定义菜单、C# .net微信开发,开发认证,关注触发消息,自动应答,事件响应,自定义菜单、CI框架微信开发-自定义菜单的知识。
本文目录一览:
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 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大高级接口,自定义菜单
前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微信开发,开发认证,关注触发消息,自动应答,事件响应,自定义菜单
成为开发者
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框架下面实现了自定义菜单功能.写了一个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>-><span>dolist();
</span><span>return</span> <span>$this</span>-><span>setmenu();
}
</span><span>private</span> <span>function</span><span> dolist(){
</span><span>$CI</span> =&<span> get_instance();
</span><span>$CI</span> -> load ->model("Menu_model","menu"<span>);
</span><span>$plist</span> = <span>$CI</span>->menu -><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>->menu ->maketree(<span>$CI</span>->menu-><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"=><span>$btn</span>[''menutype''],
"name"=><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"=><span>$btn</span>[''menutype''],
"name"=><span>$btn</span>[''content''],
"key"=><span>$btn</span>[''clickkey''],
"url"=><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"=><span>$btn</span>[''menutype''],
"name"=><span>$btn</span>[''content''],
"key"=><span>$btn</span>[''clickkey''],
"url"=><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>->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>-><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>->load-><span>database();
</span><span>$this</span>->table_name = "data_menu"<span>;
}
</span><span>public</span> <span>function</span> query(<span>$sql</span><span>){
</span><span>return</span> <span>$this</span>->db->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>->table_name} where id = {<span>$id</span>}"<span>;
</span><span>return</span> <span>$this</span>->query(<span>$get_sql</span>)-><span>row();
}
</span><span>public</span> <span>function</span> addone(<span>$data</span><span>){
</span><span>if</span>((<span>$data</span>[''pid''] == 0)&&(<span>$this</span>->checksum()>=3<span>)){
</span><span>//</span><span>一级菜单不超过3个</span>
<span>return</span> "toomany1"<span>;
}</span><span>elseif</span>((<span>$data</span>[''pid'']!=0)&&(<span>$this</span>->checksum(<span>$data</span>[''pid'']))>=7<span>){
</span><span>//</span><span>二级菜单不超过7个</span>
<span>return</span> "toomany2"<span>;
}
</span><span>if</span>(<span>is_array</span>(<span>$data</span>)&&!<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>->table_name} (<span>$keys</span>) values (<span>$vals</span>)"<span>;
</span><span>return</span> <span>$this</span>->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>->getone(<span>$id</span><span>);
</span><span>$del_sql</span> = "delete from {<span>$this</span>->table_name} where id = {<span>$id</span>} and pid = {<span>$id</span>}"<span>;
</span><span>return</span> <span>$this</span>->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>->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>->table_name} where pid ={<span>$id</span>}"<span>;
}
</span><span>$r</span> = <span>$this</span>->db->query(<span>$get_sql</span>)-><span>row();
</span><span>return</span> <span>$r</span>-><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>->table_name} where pid=0 order by menuorder asc"<span>;
</span><span>return</span> <span>$this</span>->db->query(<span>$get_sql</span>)-><span>result_array();
}
</span><span>public</span> <span>function</span><span> isplist(){
</span><span>$get_sql</span> = "select pid from {<span>$this</span>->table_name} where pid 0 group by pid"<span>;
</span><span>return</span> <span>$this</span>->db->query(<span>$get_sql</span>)-><span>result_array();
}
</span><span>public</span> <span>function</span><span> getlist(){
</span><span>$get_sql</span> = "select * from {<span>$this</span>->table_name} where 1 order by pid asc, menuorder asc"<span>;
</span><span>return</span> <span>$this</span>->db->query(<span>$get_sql</span>)-><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>=><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>)&&!<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>=><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>->table_name} set {<span>$update_fs</span>} where id = {<span>$id</span>}"<span>;
</span><span>return</span> <span>$this</span>->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&appid=".APPID."&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框架微信开发-自定义菜单等相关知识的信息别忘了在本站进行查找喔。