微信公众帐号开发-自定义菜单的创建及菜单事件响应的实例

微信开发公众平台自定义菜单需要花钱认证才能实现,不想花钱只能玩测试账号了,不过这并不影响开发。我的开发都是基于柳峰老师的微信公众平台应用开发做的。

只要我们使用公众平台测试账号就可以开发自定义菜单了,比较方便,测试账号开放了很多接口,很方便。

在开发自定义菜单的时候可以参考微信公众平台开发者文档的自定义菜单创建。

一、自定义菜单

1、自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。

2、一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。

3、创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,如果菜单有更新,就会刷新客户端的菜单。测试时可以尝试取消关注公众账号后再次关注,则

可以看到创建后的效果。

自定义菜单接口可实现多种类型按钮,如下:

1、click:点击推事件

用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互;

2、view:跳转URL

用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。

3、scancode_push:扫码推事件

用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者,开发者可以下发消息。

4、scancode_waitmsg:扫码推事件且弹出“消息接收中”提示框

用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具,然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。

5、pic_sysphoto:弹出系统拍照发图

用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机,随后可能会收到开发者下发的消息。

6、pic_photo_or_album:弹出拍照或者相册发图

用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。

7、pic_weixin:弹出微信相册发图器

用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册,随后可能会收到开发者下发的消息。

8、location_select:弹出地理位置选择器

用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具,随后可能会收到开发者下发的消息。

9、media_id:下发消息(除文本消息)

用户点击media_id类型按钮后,微信服务器会将开发者填写的永久素材id对应的素材下发给用户,永久素材类型可以是图片、音频、视频、图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id。

10、view_limited:跳转图文消息URL

用户点击view_limited类型按钮后,微信客户端将打开开发者在按钮中填写的永久素材id对应的图文消息URL,永久素材类型只支持图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id

二、访问自定义菜单接口

1:获取access_token

自定义菜单的创建、查询和删除需要调用公众平台开放的自定义菜单接口,而调用该接口需要先获取access_token(接口访问凭证),这些接口全都是基于https协议的,因此我们先要解决如何在Java程序中发送https请求的问题。

获取接口访问凭证access_token:

获取access_token是通过GET方式访问如下链接:
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

链接中有三个参数,分别是grant_type、appid和secret。根据图中的参数说明,grant_type传固定值client_credential,而appid和secret就是申请完自定义菜单后微信分配给我们的。
请求发送成功后,微信服务器会返回一个json串,包含access_token和expires_in两个元素。其中,access_token就是我们最终需要的凭证,而expires_in是凭证的有效期,单位是秒,7200秒也就是2个小时。这就意味着,不是每次访问特殊接口,都需要重新获取一次access_token,只要access_token还在有效期内,就一直可以使用。

2:菜单创建

创建菜单要调用菜单接口

接口调用请求说明

http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

其实就是向地址https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN以POST方式提交一个JSON格式的菜单字符串。

三、封装通用请求方法(自定义信任管理器)

创建菜单需要两个接口,一个是获取access_token接口,一个是自定义菜单接口,都是https请求。

1:创建证书信任管理器

对于https请求,我们需要一个证书信任管理器,这个管理器类需要自己定义,但需要实现X509TrustManager接口,代码如下:

package org.liufeng.weixin.util; 

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate; 

import javax.net.ssl.X509TrustManager; 

/**
 * 证书信任管理器(用于https请求)
 *
 * @author liufeng
 * @date 2013-08-08
 */
public class MyX509TrustManager implements X509TrustManager { 

 public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
 } 

 public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
 } 

 public X509Certificate[] getAcceptedIssuers() {
  return null;
 }
}

证书管理器的作用就是信任指定所有证书。

2:创建通用https请求

通用https请求应该

1)支持HTTPS请求;

2)支持GET、POST两种方式;

3)支持参数提交,也支持无参数的情况;

package org.liufeng.weixin.util; 

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL; 

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager; 

import net.sf.json.JSONObject; 

import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 

/**
 * 公众平台通用接口工具类
 *
 * @author liuyq
 * @date 2013-08-09
 */
public class WeixinUtil {
 private static Logger log = LoggerFactory.getLogger(WeixinUtil.class); 

 /**
  * 发起https请求并获取结果
  *
  * @param requestUrl 请求地址
  * @param requestMethod 请求方式(GET、POST)
  * @param outputStr 提交的数据
  * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
  */
 public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
  JSONObject jsonObject = null;
  StringBuffer buffer = new StringBuffer();
  try {
   // 创建SSLContext对象,并使用我们指定的信任管理器初始化
   TrustManager[] tm = { new MyX509TrustManager() };
   SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
   sslContext.init(null, tm, new java.security.SecureRandom());
   // 从上述SSLContext对象中得到SSLSocketFactory对象
   SSLSocketFactory ssf = sslContext.getSocketFactory(); 

   URL url = new URL(requestUrl);
   HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
   httpUrlConn.setSSLSocketFactory(ssf); 

   httpUrlConn.setDoOutput(true);
   httpUrlConn.setDoInput(true);
   httpUrlConn.setUseCaches(false);
   // 设置请求方式(GET/POST)
   httpUrlConn.setRequestMethod(requestMethod); 

   if ("GET".equalsIgnoreCase(requestMethod))
    httpUrlConn.connect(); 

   // 当有数据需要提交时
   if (null != outputStr) {
    OutputStream outputStream = httpUrlConn.getOutputStream();
    // 注意编码格式,防止中文乱码
    outputStream.write(outputStr.getBytes("UTF-8"));
    outputStream.close();
   } 

   // 将返回的输入流转换成字符串
   InputStream inputStream = httpUrlConn.getInputStream();
   InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
   BufferedReader bufferedReader = new BufferedReader(inputStreamReader); 

   String str = null;
   while ((str = bufferedReader.readLine()) != null) {
    buffer.append(str);
   }
   bufferedReader.close();
   inputStreamReader.close();
   // 释放资源
   inputStream.close();
   inputStream = null;
   httpUrlConn.disconnect();
   jsonObject = JSONObject.fromObject(buffer.toString());
  } catch (ConnectException ce) {
   log.error("Weixin server connection timed out.");
  } catch (Exception e) {
   log.error("https request error:{}", e);
  }
  return jsonObject;
 }
}

四、封装菜单实体类

1:按钮的分类

我们通常会把自定义菜单项看做是按钮,按钮的类型分成click(点击事件)和view(访问网页)。

click类型的按钮有type、name和key3个属性,而view类型的按钮有type、name和url3个属性

2:首先是调用获取凭证接口后,微信服务器会返回json格式的数据:{"access_token":"ACCESS_TOKEN","expires_in":7200},我们将其封装为一个AccessToken对象,对象有二个属性:token和expiresIn,代码如下:

package org.liufeng.weixin.pojo; 

/**
 * 微信通用接口凭证
 *
 * @author liufeng
 * @date 2013-08-08
 */
public class AccessToken {
 // 获取到的凭证
 private String token;
 // 凭证有效时间,单位:秒
 private int expiresIn; 

 public String getToken() {
  return token;
 } 

 public void setToken(String token) {
  this.token = token;
 } 

 public int getExpiresIn() {
  return expiresIn;
 } 

 public void setExpiresIn(int expiresIn) {
  this.expiresIn = expiresIn;
 }
}

接下来是对菜单结构的封装。因为我们是采用面向对象的编程方式,最终提交的json格式菜单数据就应该是由对象直接转换得到,而不是在程序代码中拼一大堆json数据。菜单结构封装的依据是公众平台API文档中给出的那一段json格式的菜单结构,如下所示:

click和view的请求示例

{
  "button":[
  {
   "type":"click",
   "name":"今日歌曲",
   "key":"V1001_TODAY_MUSIC"
  },
  {
   "name":"菜单",
   "sub_button":[
   {
    "type":"view",
    "name":"搜索",
    "url":"http://www.soso.com/"
   },
   {
    "type":"view",
    "name":"视频",
    "url":"http://v.qq.com/"
   },
   {
    "type":"click",
    "name":"赞一下我们",
    "key":"V1001_GOOD"
   }]
  }]
 }

3:封装菜单结构

每个按钮对象都要一个共同的name属性,因此需要定义一个按钮对象基类,所有的按钮对象都需要继承该类。基类的代码如下:

package org.liufeng.weixin.pojo; 

/**
 * 按钮的基类
 *
 * @author liufeng
 * @date 2013-08-08
 */
public class Button {
 private String name; 

 public String getName() {
  return name;
 } 

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

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

package org.liufeng.weixin.pojo; 

/**
 * 普通按钮(子按钮)
 *
 * @author liufeng
 * @date 2013-08-08
 */
public class CommonButton 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以是一个子菜单项数组。父菜单项的封装代码如下:

package org.liufeng.weixin.pojo; 

/**
 * 复杂按钮(父按钮)
 *
 * @author liufeng
 * @date 2013-08-08
 */
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个),这些菜单项即可以是子菜单项(不含二级菜单的一级菜单),也可以是父菜单项(包含二级菜单的菜单项)

package org.liufeng.weixin.pojo; 

/**
 * 菜单
 *
 * @author liufeng
 * @date 2013-08-08
 */
public class Menu {
 private Button[] button; 

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

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

这样我们就完成了菜单实体类的封装。

凭证access_token的获取方法

继续在先前通用请求方法的类WeixinUtil.java中加入以下代码,用于获取接口访问凭证:

// 获取access_token的接口地址(GET) 限200(次/天)
public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; 

/**
 * 获取access_token
 *
 * @param appid 凭证
 * @param appsecret 密钥
 * @return
 */
public static AccessToken getAccessToken(String appid, String appsecret) {
 AccessToken accessToken = null; 

 String requestUrl = access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
 JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
 // 如果请求成功
 if (null != jsonObject) {
  try {
   accessToken = new AccessToken();
   accessToken.setToken(jsonObject.getString("access_token"));
   accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
  } catch (JSONException e) {
   accessToken = null;
   // 获取token失败
   log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
  }
 }
 return accessToken;
}

自定义菜单的创建方法

继续在先前通用请求方法的类WeixinUtil.java中加入以下代码,用于创建自定义菜单:

// 菜单创建(POST) 限100(次/天)
public static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN"; 

/**
 * 创建菜单
 *
 * @param menu 菜单实例
 * @param accessToken 有效的access_token
 * @return 0表示成功,其他值表示失败
 */
public static int createMenu(Menu menu, String accessToken) {
 int result = 0; 

 // 拼装创建菜单的url
 String url = menu_create_url.replace("ACCESS_TOKEN", accessToken);
 // 将菜单对象转换成json字符串
 String jsonMenu = JSONObject.fromObject(menu).toString();
 // 调用接口创建菜单
 JSONObject jsonObject = httpRequest(url, "POST", jsonMenu); 

 if (null != jsonObject) {
  if (0 != jsonObject.getInt("errcode")) {
   result = jsonObject.getInt("errcode");
   log.error("创建菜单失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
  }
 } 

 return result;
}

调用封装的方法创建自定义菜单

package org.liufeng.weixin.main; 

import org.liufeng.weixin.pojo.AccessToken;
import org.liufeng.weixin.pojo.Button;
import org.liufeng.weixin.pojo.CommonButton;
import org.liufeng.weixin.pojo.ComplexButton;
import org.liufeng.weixin.pojo.Menu;
import org.liufeng.weixin.util.WeixinUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 

/**
 * 菜单管理器类
 *
 * @author liufeng
 * @date 2013-08-08
 */
public class MenuManager {
 private static Logger log = LoggerFactory.getLogger(MenuManager.class); 

 public static void main(String[] args) {
  // 第三方用户唯一凭证
  String appId = "000000000000000000";
  // 第三方用户唯一凭证密钥
  String appSecret = "00000000000000000000000000000000"; 

  // 调用接口获取access_token
  AccessToken at = WeixinUtil.getAccessToken(appId, appSecret); 

  if (null != at) {
   // 调用接口创建菜单
   int result = WeixinUtil.createMenu(getMenu(), at.getToken()); 

   // 判断菜单创建结果
   if (0 == result)
    log.info("菜单创建成功!");
   else
    log.info("菜单创建失败,错误码:" + result);
  }
 } 

 /**
  * 组装菜单数据
  *
  * @return
  */
 private static Menu getMenu() {
  CommonButton btn11 = new CommonButton();
  btn11.setName("天气预报");
  btn11.setType("click");
  btn11.setKey("11"); 

  CommonButton btn12 = new CommonButton();
  btn12.setName("公交查询");
  btn12.setType("click");
  btn12.setKey("12"); 

  CommonButton btn13 = new CommonButton();
  btn13.setName("周边搜索");
  btn13.setType("click");
  btn13.setKey("13"); 

  CommonButton btn14 = new CommonButton();
  btn14.setName("历史上的今天");
  btn14.setType("click");
  btn14.setKey("14"); 

  CommonButton btn21 = new CommonButton();
  btn21.setName("歌曲点播");
  btn21.setType("click");
  btn21.setKey("21"); 

  CommonButton btn22 = new CommonButton();
  btn22.setName("经典游戏");
  btn22.setType("click");
  btn22.setKey("22"); 

  CommonButton btn23 = new CommonButton();
  btn23.setName("美女电台");
  btn23.setType("click");
  btn23.setKey("23"); 

  CommonButton btn24 = new CommonButton();
  btn24.setName("人脸识别");
  btn24.setType("click");
  btn24.setKey("24"); 

  CommonButton btn25 = new CommonButton();
  btn25.setName("聊天唠嗑");
  btn25.setType("click");
  btn25.setKey("25"); 

  CommonButton btn31 = new CommonButton();
  btn31.setName("Q友圈");
  btn31.setType("click");
  btn31.setKey("31"); 

  CommonButton btn32 = new CommonButton();
  btn32.setName("电影排行榜");
  btn32.setType("click");
  btn32.setKey("32"); 

  CommonButton btn33 = new CommonButton();
  btn33.setName("幽默笑话");
  btn33.setType("click");
  btn33.setKey("33"); 

  ComplexButton mainBtn1 = new ComplexButton();
  mainBtn1.setName("生活助手");
  mainBtn1.setSub_button(new CommonButton[] { btn11, btn12, btn13, btn14 }); 

  ComplexButton mainBtn2 = new ComplexButton();
  mainBtn2.setName("休闲驿站");
  mainBtn2.setSub_button(new CommonButton[] { btn21, btn22, btn23, btn24, btn25 }); 

  ComplexButton mainBtn3 = new ComplexButton();
  mainBtn3.setName("更多体验");
  mainBtn3.setSub_button(new CommonButton[] { btn31, btn32, btn33 }); 

  /**
   * 这是公众号xiaoqrobot目前的菜单结构,每个一级菜单都有二级菜单项
   *
   * 在某个一级菜单下没有二级菜单的情况,menu该如何定义呢?
   * 比如,第三个一级菜单项不是“更多体验”,而直接是“幽默笑话”,那么menu应该这样定义:
   * menu.setButton(new Button[] { mainBtn1, mainBtn2, btn33 });
   */
  Menu menu = new Menu();
  menu.setButton(new Button[] { mainBtn1, mainBtn2, mainBtn3 }); 

  return menu;
 }
}

注意:在运行以上代码时,需要将appId和appSecret换成你自己公众号的。

响应菜单点击事件

package org.liufeng.course.service; 

import java.util.Date;
import java.util.Map; 

import javax.servlet.http.HttpServletRequest; 

import org.liufeng.course.message.resp.TextMessage;
import org.liufeng.course.util.MessageUtil; 

/**
 * 核心服务类
 *
 * @author liufeng
 * @date 2013-05-20
 */
public class CoreService {
 /**
  * 处理微信发来的请求
  *
  * @param request
  * @return
  */
 public static String processRequest(HttpServletRequest request) {
  String respMessage = null;
  try {
   // 默认返回的文本消息内容
   String respContent = "请求处理异常,请稍候尝试!"; 

   // xml请求解析
   Map<String, String> requestMap = MessageUtil.parseXml(request); 

   // 发送方帐号(open_id)
   String fromUserName = requestMap.get("FromUserName");
   // 公众帐号
   String toUserName = requestMap.get("ToUserName");
   // 消息类型
   String msgType = requestMap.get("MsgType"); 

   // 回复文本消息
   TextMessage textMessage = new TextMessage();
   textMessage.setToUserName(fromUserName);
   textMessage.setFromUserName(toUserName);
   textMessage.setCreateTime(new Date().getTime());
   textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
   textMessage.setFuncFlag(0); 

   // 文本消息
   if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
    respContent = "您发送的是文本消息!";
   }
   // 图片消息
   else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
    respContent = "您发送的是图片消息!";
   }
   // 地理位置消息
   else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
    respContent = "您发送的是地理位置消息!";
   }
   // 链接消息
   else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
    respContent = "您发送的是链接消息!";
   }
   // 音频消息
   else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
    respContent = "您发送的是音频消息!";
   }
   // 事件推送
   else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
    // 事件类型
    String eventType = requestMap.get("Event");
    // 订阅
    if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
     respContent = "谢谢您的关注!";
    }
    // 取消订阅
    else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
     // TODO 取消订阅后用户再收不到公众号发送的消息,因此不需要回复消息
    }
    // 自定义菜单点击事件
    else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
     // 事件KEY值,与创建自定义菜单时指定的KEY值对应
     String eventKey = requestMap.get("EventKey"); 

     if (eventKey.equals("11")) {
      respContent = "天气预报菜单项被点击!";
     } else if (eventKey.equals("12")) {
      respContent = "公交查询菜单项被点击!";
     } else if (eventKey.equals("13")) {
      respContent = "周边搜索菜单项被点击!";
     } else if (eventKey.equals("14")) {
      respContent = "历史上的今天菜单项被点击!";
     } else if (eventKey.equals("21")) {
      respContent = "歌曲点播菜单项被点击!";
     } else if (eventKey.equals("22")) {
      respContent = "经典游戏菜单项被点击!";
     } else if (eventKey.equals("23")) {
      respContent = "美女电台菜单项被点击!";
     } else if (eventKey.equals("24")) {
      respContent = "人脸识别菜单项被点击!";
     } else if (eventKey.equals("25")) {
      respContent = "聊天唠嗑菜单项被点击!";
     } else if (eventKey.equals("31")) {
      respContent = "Q友圈菜单项被点击!";
     } else if (eventKey.equals("32")) {
      respContent = "电影排行榜菜单项被点击!";
     } else if (eventKey.equals("33")) {
      respContent = "幽默笑话菜单项被点击!";
     }
    }
   } 

   textMessage.setContent(respContent);
   respMessage = MessageUtil.textMessageToXml(textMessage);
  } catch (Exception e) {
   e.printStackTrace();
  } 

  return respMessage;
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • .NET微信公众号开发之创建自定义菜单

    一.前言 开发之前,我们需要阅读官方的接口说明文档,不得不吐槽一下,微信的这个官方文档真的很烂,但是,为了开发我们需要的功能,我们也不得不去看这些文档. 接口文档地址:http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 看了这些个文档,基本意思明白了,就是我们把我们要创建的菜单创建好,post到微信的服务器上面,微信服务器然后给我们一些状态码,从而判断我们的菜单是否创建成功,只是在发送json数据以前我们要做

  • ASP.NET微信公众号添加菜单

    本文实例为大家分享了微信公众号添加菜单的具体代码,供大家参考,具体内容如下 testjs.aspx代码: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="testjs.aspx.cs" Inherits="MyTest.WebUI.Manager.Main.testjs" %> <!DOCTYPE html> <html xmln

  • 微信公众号开发 自定义菜单跳转页面并获取用户信息实例详解

    微信公众号开发 自定义菜单 请先读完本文再进行配置开发 请先前往微信平台开发者文档阅读"网页授权获取用户基本信息"的接口说明 在微信公众账号开发中,往往有定义一个菜单,然后用户点击该菜单就进入用户个人中心的功能,通常应用于各个公众账号中的会员服务. 如何在微信自定义菜单中将用户导航到个人中心页面呢? 首选需要通过用户点击获取用户openid,而通过用户的点击跳转获取用户openid就必须在菜单中动态绑定用户的openid,或者在菜单的跳转URL中填写微信提供的链接,官方给了两个链接类型

  • 微信公众号点击菜单即可打开并登录微站的实现方法

    本文实例讲述了微信公众号点击菜单即可打开并登录微站的实现方法.分享给大家供大家参考.具体分析如下: 总体来说,微信公众号点击菜单即可打开并登录微站实现步骤比较复杂,但很多微站在己用上了,本文对此进行整理归纳,相信可以给大家带来一定的参考借鉴价值. 现在大部分微站都通过用户的微信openid来实现自动登录.在我之前的开发中,用户通过点击一个菜单,公众号返回一个图文,用户点击这个图文才可以自动登录微站.但是如果你拥有高级接口,就可以实现点击菜单,打开网页就能获取这个openid,实现自动登录. 这里

  • .NET微信公众号开发之查询自定义菜单

    一.前言 前面我们已经创建好了我们的自定义菜单.那么我们现在要如何查询我们自定义的菜单. 原理都是一样的,而且都是相当简单,只是接口地址文档换掉了. 二.开始编码 同样我们首先创建好我的查询页面,在这里我们使用aspx页面 selectMenu.aspx 复制代码 代码如下: protected void Page_Load(object sender, EventArgs e)         {             var str = GetPage("https://api.weixi

  • 微信公众帐号开发-自定义菜单的创建及菜单事件响应的实例

    微信开发公众平台自定义菜单需要花钱认证才能实现,不想花钱只能玩测试账号了,不过这并不影响开发.我的开发都是基于柳峰老师的微信公众平台应用开发做的. 只要我们使用公众平台测试账号就可以开发自定义菜单了,比较方便,测试账号开放了很多接口,很方便. 在开发自定义菜单的时候可以参考微信公众平台开发者文档的自定义菜单创建. 一.自定义菜单 1.自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单. 2.一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以"..."代替. 3

  • 微信公众帐号开发教程之图文消息全攻略

    引言及内容概要 已经有几位读者抱怨"柳峰只用到文本消息作为示例,从来不提图文消息,都不知道图文消息该如何使用",好吧,我错了,原本以为把基础API封装完.框架搭建好,再给出一个文本消息的使用示例,大家就能够照猫画虎的,或许是因为我的绘画功底太差,画出的那只猫本来就不像猫吧-- 本篇主要介绍微信公众帐号开发中图文消息的使用,以及图文消息的几种表现形式.标题取名为"图文消息全攻略",这绝对不是标题党,是想借此机会把大家对图文消息相关的问题.疑虑.障碍全部清除掉. 图文消

  • asp.net实现微信公众账号接口开发教程

    说起微信公众帐号,大家都不会陌生,使用这个平台能给网站或系统增加一个新亮点,直接进入正题吧,在使用之前一定要仔细阅读官方API文档. 使用.net实现的方法: //微信接口地址 页面代码: weixin _wx = new weixin(); string postStr = ""; if (Request.HttpMethod.ToLower() == "post") { Stream s = System.Web.HttpContext.Current.Requ

  • .net实现微信公众账号接口开发实例代码

    说起微信公众帐号,大家都不会陌生,使用这个平台能给网站或系统增加一个新亮点,直接进入正题吧,在使用之前一定要仔细阅读官方API文档.API文档地址:http://mp.weixin.qq.com/wiki/index.php 使用.net实现的方法://微信接口地址 页面代码: 复制代码 代码如下: weixin _wx = new weixin();  string postStr = "";  if (Request.HttpMethod.ToLower() == "po

  • php版微信公众平台接口开发之智能回复开发教程

    本文实例讲述了php版微信公众平台接口开发之智能回复功能实现方法.分享给大家供大家参考,具体如下: 智能回复是根据用户输入的条件来反馈结果用用户了,这个小编以前有做过信整理了一些例子供各位参考,比较完整主要是介绍在开发端了. 微信自推出后,着实火了一把,而支付功能的推出,又把微信推到了一个无可比拟的高度,然后申请微信订阅号或者服务号的人也开始比肩接踵.下面我将给大家简单讲解下微信公众平台开发接口. 先去 微信公众平台 申请账号,然后按照提示一步步.在选择订阅号和服务号上,个人只能申请订阅号,而且

  • 微信公众平台接口开发入门示例

    本文实例讲述了微信公众平台接口开发入门示例.分享给大家供大家参考.具体如下: 微信公众平台的接口开发是一个现在比较常用的功能了,很多的人都会去了解一下微信公众平台一些简单开发应用,这里就来给大家介绍一个入门示例. 这段时间都在忙于微信公众号平台来发,现在已经接近尾声了,所以对于微信开发平台的接口如何使用,在这里也唠刀一两句. 微信平台的开发并不像你想像的那么难,无非就是数据的存取处理罢了,对于数据的存取,简单如留言板,存数据,我们通过表单向数据库提交数据以存入;取数据,通过查询语句从数据库取得,

  • PHP封装的微信公众平台接口开发操作类完整示例

    本文实例讲述了PHP封装的微信公众平台接口开发操作类.分享给大家供大家参考,具体如下: 示例调用 index.php <?php /** * Author: 惹妹子生气了 * Date: 2017-08-10 */ class MpWeixin { public $config; public $class_obj; public $is_check_signature = false; public function __construct() { //获取配置 $this->config

  • C#.net 微信公众账号接口开发

    微信越来越火,微信公众平台成为开发成新宠,本文用C#.net开发微信公众信号接口. 微信接口地址代码: weixin _wx = new weixin(); string postStr = ""; if (Request.HttpMethod.ToLower() == "post") { Stream s = System.Web.HttpContext.Current.Request.InputStream; byte[] b = new byte[s.Leng

  • 微信公众平台支付开发详解

    公众号支付就是在微信里面的H5页面唤起微信支付,不用扫码即可付款的功能.做这个功能首先要明确的就是,只有和商户号mch_id匹配的appid才能成功支付.商户号在注册成功的时候就会将相关信息发送到邮箱里面.而唤起支付的一个关键是靠openid拿到统一下单.而openid是和appid一一对应的.也就是说如果你登录使用的appid不是公众号的appid,得到的openid就无法唤起公众号内的支付(会出现appid和商户号不匹配的错误).曾经就在这个地方绕了个弯,因为微信的开放平台可以创建网站应用,

随机推荐