.NET开发微信公众号之创建自定义菜单
一、简介
微信公众平台服务号以及之前成功申请内测资格的订阅号都具有自定义菜单的功能。开发者可利用该功能为公众账号的会话界面底部增加自定义菜单,用户点击菜单中的选项,可以调出相应的回复信息或网页链接。自定义菜单接口将为公众账号的信息展示空间提供更多可能性。本文将针对自定义菜单做简单的开发应用,以供读者参考。
二、官方说明
开发者获取使用凭证后,可以使用该凭证对公众账号的自定义菜单进行创建、查询和删除等操作。 自定义菜单接口可实现以下类型按钮:
click(点击事件):
用户点击click类型按钮后,微信服务器会通过消息接口(event类型)推送点击事件给开发者,并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值进行消息回复。
view(访问网页):
用户点击view类型按钮后,会直接跳转到开发者指定的url中。
创建自定义菜单后,由于微信客户端缓存,需要24小时微信客户端才会展现出来。建议测试时可以尝试取消关注公众账号后,再次关注,则可以看到创建后的效果。
文档地址:http://mp.weixin.qq.com/wiki
三、获取使用凭证
3.1 获取appid 和appsecret
在 微信公众平台 > 高级功能 > 开发模式中找到appid 和appsecret。
3.2 使用appid 和appsecret 向微信凭证获取接口请求access_token
请求地址:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
请求参数说明:
grant_type:获取access_token填写client_credential
appid:第三方用户唯一凭证
secret:第三方用户唯一凭证密钥,既appsecret
返回说明:
正确的Json返回结果:
{"access_token":"ACCESS_TOKEN","expires_in":}
返回参数说明:
access_token:获取到的凭证
expires_in:凭证有效时间,单位:秒
3.3具体实现
//与微信平台那边填写的token一致
string Token = "tokenAccountName";
// 获取access_token的接口地址GET方式
public static string access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
public static string createurl = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
public static void CreateMenue(string appid, string appsecret)
{
//获取access_token值
string requestUrl = access_token_url.Replace("APPID", appid).Replace("APPSECRET", appsecret);
WebResponse result = null;
WebRequest req = WebRequest.Create(requestUrl);
result = req.GetResponse();
Stream s = result.GetResponseStream();
XmlDictionaryReader xmlReader = JsonReaderWriterFactory.CreateJsonReader(s, XmlDictionaryReaderQuotas.Max);
xmlReader.Read();
String XMLString = xmlReader.ReadOuterXml();
s.Close();
s.Dispose();
XmlDocument doc = new XmlDocument();
doc.LoadXml(XMLString);
XmlElement rootElement = doc.DocumentElement;
string access_token = rootElement.SelectSingleNode("access_token").InnerText;
//根据access_token值
createurl = createurl.Replace("ACCESS_TOKEN", access_token);
string responeJsonStr = "{" +
"\"button\":[" +
"{\"name\":\"中秋系列\"," +
"\"type\":\"click\"," +
"\"key\":\"V1001_ZhongQiu\"" +
"}" +
",{\"name\":\"摘星星\"," +
"\"type\":\"click\"," +
"\"key\":\"V1002_ZhaiXing\"" +
"}" +
"]" +
"}";
WebRequest req = WebRequest.Create(createurl);
byte[] bytes = Encoding.UTF8.GetBytes(responeJsonStr.ToString());
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = bytes.Length;
Stream reqStr = req.GetRequestStream();
reqStr.Write(bytes, 0, bytes.Length);
reqSrt.Close();
}
protected void Page_Load(object sender, EventArgs e)
{
CreateMenue("wxddsd8521111fdfs", "r85f5gf222222222sdsdd2dsdsdsddddd");
string postStr = "";
if (Request.HttpMethod.ToLower() == "POST")
{
Stream s = System.Web.HttpContext.Current.Request.InputStream;
byte[] b = new byte[s.Length];
s.Read(b, , (int)s.Length);
postStr = Encoding.UTF8.GetString(b);
if (!string.IsNullOrEmpty(postStr))
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(postStr);
XmlElement rootElement = doc.DocumentElement;
XmlNode MsgType = rootElement.SelectSingleNode("MsgType");
WeiXinRequest requestXML = new WeiXinRequest();
requestXML.ToUserName = rootElement.SelectSingleNode("ToUserName").InnerText;
requestXML.FromUserName = rootElement.SelectSingleNode("FromUserName").InnerText;
requestXML.CreateTime = rootElement.SelectSingleNode("CreateTime").InnerText;
requestXML.MsgType = MsgType.InnerText; if (requestXML.MsgType == "text")
{
requestXML.Content = rootElement.SelectSingleNode("Content").InnerText;
requestXML.MsgId = rootElement.SelectSingleNode("MsgId").InnerText;
}
else if (requestXML.MsgType == "location")
{
requestXML.Location_X = rootElement.SelectSingleNode("Location_X").InnerText;
requestXML.Location_Y = rootElement.SelectSingleNode("Location_Y").InnerText; }
else if (requestXML.MsgType == "event")
{
requestXML.Wxevent = rootElement.SelectSingleNode("Event").InnerText;
requestXML.EventKey = rootElement.SelectSingleNode("EventKey").InnerText;
}
WriteTxt("---消息,消息类型:" + requestXML.MsgType + "----:" + postStr);
//回复消息
ResponseMsg(requestXML);
}
}
else
{
CheckSource();
}
}
private void CheckSource()
{
string echoStr = Request.QueryString["echoStr"];
if (CheckSignature())
{
if (!string.IsNullOrEmpty(echoStr))
{
Response.Write(echoStr);
Response.End();
}
}
}
private bool CheckSignature()
{
string signature = Request.QueryString["signature"];
string timestamp = Request.QueryString["timestamp"];
string nonce = Request.QueryString["nonce"];
string[] ArrTmp = { Token, timestamp, nonce };
Array.Sort(ArrTmp);
string tmpStr = string.Join("", ArrTmp);
tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
tmpStr = tmpStr.ToLower();
if (tmpStr == signature)
{
return true;
}
else
{
return false;
}
}
private int ConvertDate(System.DateTime time)
{
System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
return (int)(time - startTime).TotalSeconds;
}
private void ResponseMsg(WeiXinRequest requestXML)
{
string resxml = "<xml><ToUserName><![CDATA[" + requestXML.FromUserName + "]]></ToUserName><FromUserName><![CDATA[" + requestXML.ToUserName + "]]></FromUserName><CreateTime>" + ConvertDate(DateTime.Now) + "</CreateTime>";
try
{
if (requestXML.MsgType == "text")
{
int count = ;
resxml += "<MsgType><![CDATA[text]]></MsgType><Content><![CDATA[好看信息]]></Content><FuncFlag>0</FuncFlag></xml>"; //}
}
else if (requestXML.MsgType == "location")
{
resxml += "<MsgType><![CDATA[text]]></MsgType><Content><![CDATA[坐标消息]]></Content><FuncFlag>0</FuncFlag></xml>";
}
else if (requestXML.MsgType == "event")
{
if (requestXML.Wxevent == "unsubscribe")
{
//取消关注
}
else if (requestXML.Wxevent == "subscribe")
{
//新增关注
resxml += "<MsgType><![CDATA[text]]></MsgType><Content><![CDATA[感谢关注!]]></Content><FuncFlag>0</FuncFlag></xml>";
}
else if (requestXML.Wxevent.ToUpper() == "CLICK")
{
if (requestXML.EventKey == "V1001_ZhongQiu") { string P_Code = ""; }
else if (requestXML.EventKey == "V1002_ZhaiXing") { resxml += "<MsgType><![CDATA[news]]></MsgType><ArticleCount>" + + "</ArticleCount><Articles>";
resxml += "<item><Title><![CDATA[摘颗星星给你]]></Title><Description><![CDATA[查看您的中秋惊喜]]></Description><Url><![CDATA[" + Request.Url.Authority + "/WeiXin/PurchaseLogin.aspx?weixinId=" + requestXML.FromUserName + "&gzhID=" + requestXML.ToUserName + "]]></Url></item>"; resxml += "</Articles><FuncFlag>0</FuncFlag></xml>"; } } } }
catch (Exception ex) { WriteTxt("异常:" + ex.Message); }
WriteTxt("返回给对方的消息:" + resxml);
Response.Write(resxml); Response.End(); }
public bool WriteTxt(string str)
{
try
{
FileStream fs = new FileStream(Server.MapPath("/Log.txt"), FileMode.Append);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine(str);
sw.Flush();
sw.Close();
fs.Close();
}
catch (Exception)
{
return false;
}
return true;
}
}
} public class WeiXinRequest
{
private string toUserName;
/// <summary>
/// 消息接收方微信号
/// </summary>
public string ToUserName
{
get { return toUserName; }
set { toUserName = value; }
} private string fromUserName;
/// <summary>
/// 消息发送方微信号
/// </summary>
public string FromUserName
{
get { return fromUserName; }
set { fromUserName = value; }
} private string createTime;
/// <summary>
/// 创建时间
/// </summary>
public string CreateTime
{
get { return createTime; }
set { createTime = value; }
}
private string msgType;
/// <summary>
/// 信息类型 文本消息:text,消息类型:image,音频:voice,视频:video,
/// </summary>
public string MsgType
{
get { return msgType; }
set { msgType = value; }
} private string content;
/// <summary>
/// 信息内容
/// </summary>
public string Content
{
get { return content; }
set { content = value; }
}
private string msgId;
/// <summary>
/// 消息ID(文本)
/// </summary>
public string MsgId
{
get { return msgId; }
set { msgId = value; }
} private string wxevent;
/// <summary>
/// 取消关注时的Event节点
/// </summary>
public string Wxevent
{
get { return wxevent; }
set { wxevent = value; }
} private string eventKey;
/// <summary>
/// 取消关注时的EventKey节点
/// </summary>
public string EventKey
{
get { return eventKey; }
set { eventKey = value; }
} private string location_X;
/// <summary>
/// 坐标维度
/// </summary>
public string Location_X
{
get { return location_X; }
set { location_X = value; }
} private string location_Y;
/// <summary>
/// 经度
/// </summary>
public string Location_Y
{
get { return location_Y; }
set { location_Y = value; }
} private string picUrl;
/// <summary>
/// 图片链接
/// </summary>
public string PicUrl
{
get { return picUrl; }
set { picUrl = value; }
}
}
.NET开发微信公众号之创建自定义菜单的更多相关文章
- tp6微信公众号开发者模式自定义菜单
1,参考上篇博客,获取access_token https://www.cnblogs.com/xiaoyantongxue/p/15803334.html 2:控制器写以下代码 /* * 获取普通a ...
- 微信公众号开发者模式自定义菜单 node
纯属分享 var config = require('./admin/wx/config/config'); var API = require('wechat-api'); var api = ne ...
- Java开发微信公众号(五)---微信开发中如何获取access_token以及缓存access_token
获取access_token是微信api最重要的一个部分,因为调用其他api很多都需要用到access_token.比如自定义菜单接口.客服接口.获取用户信息接口.用户分组接口.群发接口等在请求的时候 ...
- Java开发微信公众号(三)---微信服务器请求消息,响应消息,事件消息以及工具处理类的封装
在前面几篇文章我们讲了微信公众号环境的配置 和微信公众号服务的接入,接下来我们来说一下微信服务器请求消息,响应消息以及事件消息的相关内容,首先我们来分析一下消息类型和返回xml格式及实体类的封装. ( ...
- vue开发微信公众号--开发准备
由于工作项目的原因,需要使用vue开发微信公众号,但是这种微信公众号更多是将APP套了一个微信的壳子,除了前面的授权和微信有关系以外,其他的都和微信没多大的关系了,特此记录 开发流程 首先需要在电脑上 ...
- php开发微信公众号获取信息LBS
1.一般的公众号都可以在微信公众平台里面设置自定义菜单和自动回复消息,如果需要获取用户位置,则必须开启 服务器配置,当次功能开启后,微信公众平台的自定义菜单和自动回复则失效. 需要通过接口开发来实现微 ...
- Java开发微信公众号(四)---微信服务器post消息体的接收及消息的处理
在前几节文章中我们讲述了微信公众号环境的搭建.如何接入微信公众平台.以及微信服务器请求消息,响应消息,事件消息以及工具处理类的封装:接下来我们重点说一下-微信服务器post消息体的接收及消息的处理,这 ...
- Java开发微信公众号(二)---开启开发者模式,接入微信公众平台开发
接入微信公众平台开发,开发者需要按照如下步骤完成: 1.填写服务器配置 2.验证服务器地址的有效性 3.依据接口文档实现业务逻辑 资料准备: 1.一个可以访问的外网,即80的访问端口,因为微信公众号接 ...
- Java开发微信公众号(一)---初识微信公众号以及环境搭建
ps:1.开发语言使用Java springMvc+Mybaits+spring maven实现 2.使用微信接口测试账号进行本地测试 https://mp.weixin.qq.com/debug/c ...
随机推荐
- Java 处理 iphone拍照后 图片EXIF属性翻转90度的方法
http://blog.csdn.net/z69183787/article/details/50320821 Java获取照片EXIF信息 http://blog.csdn.net/ghsau/ar ...
- 《大型分布式网站架构》学习笔记--01SOA
"学无长幼,达者为先",作者陈康贤通过3年左右时间就能写出如此著作确实令人钦佩,加油,熊二,早日成为一个合格的后端程序员. 基础概念 SOA(Service-Oriented Ar ...
- 为什么要使用getter/setter
变量私有化的好处 1. 在setter中可以加入合法性检查,比如设置颜色的函数中,对于RGB颜色要判断其值在0~255之间. 2. 更新与被设置变量相关的其它变量的值,比如在一个潜水艇模拟系统中,改变 ...
- FTP 学习笔记
由于最近在跟LMS项目,前期的环境部署需要使用到FTP协议,所以在这里记录一下项目中学习到的知识,以作记录. FTP为基于TCP/IP网络传输协议的文件传输应用层协议. FTP协议在两台服务器中传输文 ...
- 安卓工作室 Android studio 或 Intellij IDEA 美化 修改 汉化 酷炫 装逼 Android studio or Intellij IDEA beautify modify Chinesization cool decoration
安卓工作室 Android studio 或 Intellij IDEA 美化 修改 汉化 酷炫 装逼 Android studio or Intellij IDEA beautify modify ...
- BZOJ.1875.[SDOI2009]HH去散步(DP 矩阵乘法)
题目链接 比较容易想到用f[i][j]表示走了i步后到达j点的方案数,但是题目要求不能走上一条走过的边 如果这样表示是不好转移的 可以考虑边,f[i][j]表示走了i步后到达第j条边的方案数,那么有 ...
- python 发送邮件脚本
一.该脚本适合在 linux 中做邮件发送测试用,只需要填写好 发送账号和密码以及发送人即可,然后使用 python ./filename.py (当前目录下)即可.如果发送出错,会将错误详情抛出来 ...
- Spark MLlib 之 大规模数据集的相似度计算原理探索
无论是ICF基于物品的协同过滤.UCF基于用户的协同过滤.基于内容的推荐,最基本的环节都是计算相似度.如果样本特征维度很高或者<user, item, score>的维度很大,都会导致无法 ...
- C#编程(八十)---------- 异常类
异常类 在C#里,异常处理就是C#为处理错误情况提供的一种机制.它为每种错误情况提供了定制的处理方式,并且把标志错误的代码预处理错误的代码分离开来. 对.net类来说,一般的异常类System.Exc ...
- centos npm 安装后 command not found
ok,