二.微信开发入门

上一篇《微信开发学习总结(一)——微信开发环境搭建》咱们已经完成了微信开发的准备工做,准备工做完成以后,就要开始步入正题了。html

1、微信公众平台的基本原理

  在开始作以前,先简单介绍了微信公众平台的基本原理。java

  微信服务器就至关于一个转发服务器,终端(手机、Pad等)发起请求至微信服务器,微信服务器而后将请求转发给咱们的应用服务器。应用服务器处理完毕后,将响应数据回发给微信服务器,微信服务器再将具体响应信息回复到微信App终端。android

  通讯协议为:HTTPweb

  数据传输格式为:XMLjson

  具体的流程以下图所示:api

  

  来一张更加直观的图吧:数组

  

  咱们须要作的事情,就是对微信服务器转发的HTTP请求作出响应。具体的请求内容,咱们按照特定的XML格式去解析,处理完毕后,也要按照特定的XML格式返回。安全

2、微信公众号接入

  在微信公众平台开发者文档上,关于公众号接入这一节内容在接入指南上写的比较详细的,文档中说接入公众号须要3个步骤,分别是:服务器

  一、填写服务器配置
  二、验证服务器地址的有效性
  三、依据接口文档实现业务逻辑微信

  其实,第3步已经不能算作公众号接入的步骤,而是接入以后,开发人员能够根据微信公众号提供的接口所能作的一些开发。

  第1步中服务器配置包含服务器地址(URL)、Token和EncodingAESKey。

  服务器地址即公众号后台提供业务逻辑的入口地址,目前只支持80端口,以后包括接入验证以及任何其它的操做的请求(例如消息的发送、菜单管理、素材管理等)都要从这个地址进入。接入验证和其它请求的区别就是,接入验证时是get请求,其它时候是post请求;

  Token可由开发者能够任意填写,用做生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性);

  EncodingAESKey由开发者手动填写或随机生成,将用做消息体加解密密钥。本例中所有以未加密的明文消息方式,不涉及此配置项。

  第2步,验证服务器地址的有效性,当点击“提交”按钮后,微信服务器将发送一个http的get请求到刚刚填写的服务器地址,而且携带四个参数:

  

  接到请求后,咱们须要作以下三步,若确认这次GET请求来自微信服务器,原样返回echostr参数内容,则接入生效,不然接入失败。

  1. 将token、timestamp、nonce三个参数进行字典序排序
  2. 将三个参数字符串拼接成一个字符串进行sha1加密
  3. 开发者得到加密后的字符串可与signature对比,标识该请求来源于微信

  下面咱们用Java代码来演示一下这个验证过程

  使用IDE(Eclipse或者IntelliJ IDEA)建立一个JavaWeb项目,这里我使用的是IntelliJ IDEA,项目目录结构以下图所示:

  

  编写一个servlevt,在其中的doGet方法中定义校验方法,具体代码以下:

复制代码
  1 package me.gacl.wx.web.servlet;  2  3 import javax.servlet.ServletException;  4 import javax.servlet.annotation.WebServlet;  5 import javax.servlet.http.HttpServlet;  6 import javax.servlet.http.HttpServletRequest;  7 import javax.servlet.http.HttpServletResponse;  8 import java.io.IOException;  9 import java.security.MessageDigest;  10 import java.security.NoSuchAlgorithmException;  11 import java.util.Arrays;  12  13 /**  14  * Created by xdp on 2016/1/25.  15  * 使用@WebServlet注解配置WxServlet,urlPatterns属性指明了WxServlet的访问路径  16 */  17 @WebServlet(urlPatterns="/WxServlet")  18 public class WxServlet extends HttpServlet {  19  20 /**  21  * Token可由开发者能够任意填写,用做生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)  22  * 好比这里我将Token设置为gacl  23 */  24 private final String TOKEN = "gacl";  25  26 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  27  28  }  29  30 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  31 System.out.println("开始校验签名");  32 /**  33  * 接收微信服务器发送请求时传递过来的4个参数  34 */  35 String signature = request.getParameter("signature");//微信加密签名signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。  36 String timestamp = request.getParameter("timestamp");//时间戳  37 String nonce = request.getParameter("nonce");//随机数  38 String echostr = request.getParameter("echostr");//随机字符串  39 //排序  40 String sortString = sort(TOKEN, timestamp, nonce);  41 //加密  42 String mySignature = sha1(sortString);  43 //校验签名  44 if (mySignature != null && mySignature != "" && mySignature.equals(signature)) {  45 System.out.println("签名校验经过。");  46 //若是检验成功输出echostr,微信服务器接收到此输出,才会确认检验完成。  47 //response.getWriter().println(echostr);  48  response.getWriter().write(echostr);  49 } else {  50 System.out.println("签名校验失败.");  51  }  52  53  }  54  55 /**  56  * 排序方法  57  *  58  * @param token  59  * @param timestamp  60  * @param nonce  61  * @return  62 */  63 public String sort(String token, String timestamp, String nonce) {  64 String[] strArray = {token, timestamp, nonce};  65  Arrays.sort(strArray);  66 StringBuilder sb = new StringBuilder();  67 for (String str : strArray) {  68  sb.append(str);  69  }  70  71 return sb.toString();  72  }  73  74 /**  75  * 将字符串进行sha1加密  76  *  77  * @param str 须要加密的字符串  78  * @return 加密后的内容  79 */  80 public String sha1(String str) { 81 try { 82 MessageDigest digest = MessageDigest.getInstance("SHA-1"); 83 digest.update(str.getBytes()); 84 byte messageDigest[] = digest.digest(); 85 // Create Hex String 86 StringBuffer hexString = new StringBuffer(); 87 // 字节数组转换为 十六进制 数 88 for (int i = 0; i < messageDigest.length; i++) { 89 String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); 90 if (shaHex.length() < 2) { 91 hexString.append(0); 92 } 93 hexString.append(shaHex); 94 } 95 return hexString.toString(); 96 97 } catch (NoSuchAlgorithmException e) { 98 e.printStackTrace(); 99 } 100 return ""; 101 } 102 }
复制代码

  我这里用的Servlet3.0,使用Servlet3.0的好处就是能够直接使用@WebServlet注解映射Servlet的访问路径,再也不须要在web.xml文件中进行配置.

  将WxStudy项目部署到Tomcat服务器中运行,直接启动项目,而后用ngrok将本地8080端口映射到外网(如何使用ngrok请参考博客《微信开发学习总结(一)——微信开发环境搭建》)。以下图所示:

  

  测试是否能够经过http://xdp.ngrok.natapp.cn地址正常访问,测试结果以下:

  

  能够看到,咱们的项目已经能够被外网正常访问到了。

  进入微信测试公众号管理界面,在接口配置信息中填入映射的外网地址和token,以下图所示:

 

  点击提交按钮,页面会提示配置成功,

  

 

---------------------补充------------------------补充-----------------------------补充-------------------------------补充------------------------------补充-----------------------------补充--------------------------、

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  IDE的控制台中输出了校验经过的信息,以下图所示:

  

  到此,咱们的公众号应用已经可以和微信服务器正常通讯了,也就是说咱们的公众号已经接入到微信公众平台了。

3、access_token管理

3.一、access_token介绍

  咱们的公众号和微信服务器对接成功以后,接下来要作的就是根据咱们的业务需求调用微信公众号提供的接口来实现相应的逻辑了。在使用微信公众号接口中都须要一个access_token。

  关于access_token,在微信公众平台开发者文档上的获取接口调用凭据有比较详细的介绍:access_token是公众号的全局惟一票据,公众号调用各接口时都需使用access_token,开发者须要妥善保存access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将致使上次获取的access_token失效。而且天天调用获取access_token接口的上限是2000次。

  总结以上说明,access_token须要作到如下两点:

  1.由于access_token有2个小时的时效性,要有一个机制保证最长2个小时从新获取一次。

  2.由于接口调用上限天天2000次,因此不能调用太频繁。

3.二、微信公众平台提供的获取access_token的接口

  关于access_token的获取方式,在微信公众平台开发者文档上有说明,公众号能够调用一个叫"获取access token"的接口来获取access_token。

  获取access token接口调用请求说明

    http请求方式: GET

    请求的URL地址:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
       

  咱们能够看到,调用过程当中须要传递appID和AppSecret,appID和AppSecret是在申请公众号的时候自动分配给公众号的,至关于公众号的身份标示,使用微信公众号的注册账号登陆到腾讯提供的微信公众号管理后台就能够看到本身申请的公众号的AppID和AppSecret,以下图所示:

  

  这是我申请公众号测试账号时分配到的AppID和AppSecret。

3.三、获取access_token方案以及具体实现

  这里采用的方案是这样的,定义一个默认启动的servlet,在init方法中启动一个Thread,这个进程中定义一个无限循环的方法,用来获取access_token,当获取成功后,此进程休眠7000秒(7000秒=1.944444444444444小时),不然休眠3秒钟继续获取。流程图以下:

  

  下面正式开始在工程中实现以上思路,由于返回的数据都是json格式,这里会用到阿里的fastjson库,为构造请求和处理请求后的数据序列化和反序列化提供支持。

  1.定义一个AccessToken实体类

复制代码
 1 package me.gacl.wx.entry;  2  3 /**  4  * AccessToken的数据模型  5  * Created by xdp on 2016/1/25.  6 */  7 public class AccessToken {  8  9 //获取到的凭证 10 private String accessToken; 11 //凭证有效时间,单位:秒 12 private int expiresin; 13 14 public String getAccessToken() { 15 return accessToken; 16  } 17 18 public void setAccessToken(String accessToken) { 19 this.accessToken = accessToken; 20  } 21 22 public int getExpiresin() { 23 return expiresin; 24  } 25 26 public void setExpiresin(int expiresin) { 27 this.expiresin = expiresin; 28  } 29 }
复制代码

 2.定义一个AccessTokenInfo类,用于存放获取到的AccessToken,代码以下:

复制代码
 1 package me.gacl.wx.Common;  2  3 import me.gacl.wx.entry.AccessToken;  4  5 /**  6  * Created by xdp on 2016/1/25.  7 */  8 public class AccessTokenInfo {  9 10 //注意是静态的 11 public static AccessToken accessToken = null; 12 }
复制代码

  3.编写一个用于发起https请求的工具类NetWorkHelper,代码以下:

复制代码
 1 package me.gacl.wx.util;  2  3 import javax.net.ssl.*;  4 import java.io.BufferedReader;  5 import java.io.InputStream;  6 import java.io.InputStreamReader;  7 import java.net.URL;  8 import java.security.cert.CertificateException;  9 import java.security.cert.X509Certificate; 10 11 /** 12  * 访问网络用到的工具类 13 */ 14 public class NetWorkHelper { 15 16 /** 17  * 发起Https请求 18  * @param reqUrl 请求的URL地址 19  * @param requestMethod 20  * @return 响应后的字符串 21 */ 22 public String getHttpsResponse(String reqUrl, String requestMethod) { 23  URL url; 24  InputStream is; 25 String resultData = ""; 26 try { 27 url = new URL(reqUrl); 28 HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); 29 TrustManager[] tm = {xtm}; 30 31 SSLContext ctx = SSLContext.getInstance("TLS"); 32 ctx.init(null, tm, null); 33 34  con.setSSLSocketFactory(ctx.getSocketFactory()); 35 con.setHostnameVerifier(new HostnameVerifier() { 36  @Override 37 public boolean verify(String arg0, SSLSession arg1) { 38 return true; 39  } 40  }); 41 42 43 con.setDoInput(true); //容许输入流,即容许下载 44 45 //在android中必须将此项设置为false 46 con.setDoOutput(false); //容许输出流,即容许上传 47 con.setUseCaches(false); //不使用缓冲 48 if (null != requestMethod && !requestMethod.equals("")) { 49 con.setRequestMethod(requestMethod); //使用指定的方式 50 } else { 51 con.setRequestMethod("GET"); //使用get请求 52  } 53 is = con.getInputStream(); //获取输入流,此时才真正创建连接 54 InputStreamReader isr = new InputStreamReader(is); 55 BufferedReader bufferReader = new BufferedReader(isr); 56  String inputLine; 57 while ((inputLine = bufferReader.readLine()) != null) { 58 resultData += inputLine + "\n"; 59  } 60  System.out.println(resultData); 61 62 } catch (Exception e) { 63  e.printStackTrace(); 64  } 65 return resultData; 66  } 67 68 X509TrustManager xtm = new X509TrustManager() { 69  @Override 70 public X509Certificate[] getAcceptedIssuers() { 71 return null; 72  } 73 74  @Override 75 public void checkServerTrusted(X509Certificate[] arg0, String arg1) 76 throws CertificateException { 77 78  } 79 80 @Override 81 public void checkClientTrusted(X509Certificate[] arg0, String arg1) 82 throws CertificateException { 83 84 } 85 }; 86 }
复制代码

  getHttpsResponse方法是请求一个https地址,参数requestMethod为字符串“GET”或者“POST”,传null或者“”默认为get方式。

  4.定义一个默认启动的servlet,在init方法中启动一个新的线程去获取accessToken

复制代码
 1 package me.gacl.wx.web.servlet;  2  3 import com.alibaba.fastjson.JSON;  4 import com.alibaba.fastjson.JSONObject;  5 import me.gacl.wx.Common.AccessTokenInfo;  6 import me.gacl.wx.entry.AccessToken;  7 import me.gacl.wx.util.NetWorkHelper;  8  9 import javax.servlet.ServletException; 10 import javax.servlet.annotation.WebInitParam; 11 import javax.servlet.annotation.WebServlet; 12 import javax.servlet.http.HttpServlet; 13 14 /** 15  * 用于获取accessToken的Servlet 16  * Created by xdp on 2016/1/25. 17 */ 18 @WebServlet( 19 name = "AccessTokenServlet", 20 urlPatterns = {"/AccessTokenServlet"}, 21 loadOnStartup = 1, 22 initParams = { 23 @WebInitParam(name = "appId", value = "wxbe4d433e857e8bb1"), 24 @WebInitParam(name = "appSecret", value = "ccbc82d560876711027b3d43a6f2ebda") 25  }) 26 public class AccessTokenServlet extends HttpServlet { 27 28  @Override 29 public void init() throws ServletException { 30 System.out.println("启动WebServlet"); 31 super.init(); 32 33 final String appId = getInitParameter("appId"); 34 final String appSecret = getInitParameter("appSecret"); 35 36 //开启一个新的线程 37 new Thread(new Runnable() { 38  @Override 39 public void run() { 40 while (true) { 41 try { 42 //获取accessToken 43 AccessTokenInfo.accessToken = getAccessToken(appId, appSecret); 44 //获取成功 45 if (AccessTokenInfo.accessToken != null) { 46 //获取到access_token 休眠7000秒,大约2个小时左右 47 Thread.sleep(7000 * 1000); 48 //Thread.sleep(10 * 1000);//10秒钟获取一次 49 } else { 50 //获取失败 51 Thread.sleep(1000 * 3); //获取的access_token为空 休眠3秒 52  } 53 } catch (Exception e) { 54 System.out.println("发生异常:" + e.getMessage()); 55  e.printStackTrace(); 56 try { 57 Thread.sleep(1000 * 10); //发生异常休眠1秒 58 } catch (Exception e1) { 59 60  } 61  } 62  } 63 64  } 65  }).start(); 66  } 67 68 /** 69  * 获取access_token 70  * 71  * @return AccessToken 72 */ 73 private AccessToken getAccessToken(String appId, String appSecret) { 74 NetWorkHelper netHelper = new NetWorkHelper(); 75 /** 76  * 接口地址为https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET,其中grant_type固定写为client_credential便可。 77 */ 78 String Url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appId, appSecret); 79 //此请求为https的get请求,返回的数据格式为{"access_token":"ACCESS_TOKEN","expires_in":7200} 80 String result = netHelper.getHttpsResponse(Url, ""); 81 System.out.println("获取到的access_token="+result); 82 //使用FastJson将Json字符串解析成Json对象 83 JSONObject json = JSON.parseObject(result); 84 AccessToken token = new AccessToken(); 85 token.setAccessToken(json.getString("access_token")); 86 token.setExpiresin(json.getInteger("expires_in")); 87 return token; 88 } 89 }
复制代码

  AccessTokenServlet采用注解的方式进行配置
  至此代码实现完毕,将项目部署,看到控制台输出以下:

  

  为了方便看效果,能够把休眠时间设置短一点,好比10秒获取一次,而后将access_token输出。

  下面作一个测试jsp页面,并把休眠时间设置为10秒,这样过10秒刷新页面,就能够看到变化

复制代码
 1 <%-- Created by IntelliJ IDEA. --%>  2 <%@ page contentType="text/html;charset=UTF-8" language="java" %>  3 <%@ page import="me.gacl.wx.Common.AccessTokenInfo"%>  4 <html>  5 <head>  6 <title></title>  7 </head>  8 <body>  9  微信学习 10 <hr/> 11 access_token为:<%=AccessTokenInfo.accessToken.getAccessToken()%> 12 </body> 13 </html>
复制代码

  

  10秒钟后刷新页面,access_token变了,以下图所示:

  

4、接收微信服务器发送的消息并作出响应

  通过上述的三步,咱们开发前的准备工做已经完成了,接下来要作的就是接收微信服务器发送的消息并作出响应

  从微信公众平台接口消息指南中能够了解到,当用户向公众账号发消息时,微信服务器会将消息经过POST方式提交给咱们在接口配置信息中填写的URL,而咱们就须要在URL所指向的请求处理类WxServlet的doPost方法中接收消息、处理消息和响应消息。

4.1.编写一个用于处理消息的工具类

  编写处理消息的工具栏,工具类代码以下:

复制代码
  1 package me.gacl.wx.util;  2  3 import org.dom4j.Document;  4 import org.dom4j.Element;  5 import org.dom4j.io.SAXReader;  6  7 import javax.servlet.http.HttpServletRequest;  8 import java.io.InputStream;  9 import java.text.DateFormat;  10 import java.text.SimpleDateFormat;  11 import java.util.Date;  12 import java.util.HashMap;  13 import java.util.List;  14 import java.util.Map;  15  16 /**  17  * 消息处理工具类  18  * Created by xdp on 2016/1/26.  19 */  20 public class MessageHandlerUtil {  21  22 /**  23  * 解析微信发来的请求(XML)  24  * @param request  25  * @return map  26  * @throws Exception  27 */  28 public static Map<String,String> parseXml(HttpServletRequest request) throws Exception {  29 // 将解析结果存储在HashMap中  30 Map<String,String> map = new HashMap();  31 // 从request中取得输入流  32 InputStream inputStream = request.getInputStream();  33 System.out.println("获取输入流");  34 // 读取输入流  35 SAXReader reader = new SAXReader();  36 Document document = reader.read(inputStream);  37 // 获得xml根元素  38 Element root = document.getRootElement();  39 // 获得根元素的全部子节点  40 List<Element> elementList = root.elements();  41  42 // 遍历全部子节点  43 for (Element e : elementList) {  44 System.out.println(e.getName() + "|" + e.getText());  45  map.put(e.getName(), e.getText());  46  }  47  48 // 释放资源  49  inputStream.close();  50 inputStream = null;  51 return map;  52  }  53  54 // 根据消息类型 构造返回消息  55 public static String buildXml(Map<String,String> map) {  56  String result;  57 String msgType = map.get("MsgType").toString();  58 System.out.println("MsgType:" + msgType);  59 if(msgType.toUpperCase().equals("TEXT")){  60 result = buildTextMessage(map, "孤傲苍狼在学习和总结微信开发了,构建一条文本消息:Hello World!");  61 }else{  62 String fromUserName = map.get("FromUserName");  63 // 开发者微信号  64 String toUserName = map.get("ToUserName");  65 result = String  66  .format(  67 "<xml>" +  68 "<ToUserName><![CDATA[%s]]></ToUserName>" +  69 "<FromUserName><![CDATA[%s]]></FromUserName>" +  70 "<CreateTime>%s</CreateTime>" +  71 "<MsgType><![CDATA[text]]></MsgType>" +  72 "<Content><![CDATA[%s]]></Content>" +  73 "</xml>",  74  fromUserName, toUserName, getUtcTime(),  75 "请回复以下关键词:\n文本\n图片\n语音\n视频\n音乐\n图文");  76  }  77  78 return result;  79  }  80  81 /**  82  * 构造文本消息  83  *  84  * @param map  85 * @param content 86 * @return 87 */ 88 private static String buildTextMessage(Map<String,String> map, String content) { 89 //发送方账号 90 String fromUserName = map.get("FromUserName"); 91 // 开发者微信号 92 String toUserName = map.get("ToUserName"); 93 /** 94 * 文本消息XML数据格式 95 * <xml> 96 <ToUserName><![CDATA[toUser]]></ToUserName> 97 <FromUserName><![CDATA[fromUser]]></FromUserName> 98 <CreateTime>1348831860</CreateTime> 99 <MsgType><![CDATA[text]]></MsgType> 100 <Content><![CDATA[this is a test]]></Content> 101 <MsgId>1234567890123456</MsgId> 102 </xml> 103 */ 104 return String.format( 105 "<xml>" + 106 "<ToUserName><![CDATA[%s]]></ToUserName>" + 107 "<FromUserName><![CDATA[%s]]></FromUserName>" + 108 "<CreateTime>%s</CreateTime>" + 109 "<MsgType><![CDATA[text]]></MsgType>" + 110 "<Content><![CDATA[%s]]></Content>" + "</xml>", 111 fromUserName, toUserName, getUtcTime(), content); 112 } 113 114 private static String getUtcTime() { 115 Date dt = new Date();// 若是不须要格式,可直接用dt,dt就是当前系统时间 116 DateFormat df = new SimpleDateFormat("yyyyMMddhhmm");// 设置显示格式 117 String nowTime = df.format(dt); 118 long dd = (long) 0; 119 try { 120 dd = df.parse(nowTime).getTime(); 121 } catch (Exception e) { 122 123 } 124 return String.valueOf(dd); 125 } 126 }
复制代码

  为了方便解析微信服务器发送给咱们的xml格式的数据,这里咱们借助于开源框架dom4j去解析xml(这里使用的是dom4j-2.0.0-RC1.jar)

  

4.2.在WxServlet的doPost方法中处理请求

  WxServlet的doPost方法的代码以下:

复制代码
 1  /**  2  * 处理微信服务器发来的消息  3 */  4 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  5 // TODO 接收、处理、响应由微信服务器转发的用户发送给公众账号的消息  6 // 将请求、响应的编码均设置为UTF-8(防止中文乱码)  7 request.setCharacterEncoding("UTF-8");  8 response.setCharacterEncoding("UTF-8");  9 System.out.println("请求进入"); 10 String result = ""; 11 try { 12 Map<String,String> map = MessageHandlerUtil.parseXml(request); 13 System.out.println("开始构造消息"); 14 result = MessageHandlerUtil.buildXml(map); 15  System.out.println(result); 16 if(result.equals("")){ 17 result = "未正确响应"; 18  } 19 } catch (Exception e) { 20  e.printStackTrace(); 21 System.out.println("发生异常:"+ e.getMessage()); 22  } 23  response.getWriter().println(result); 24 }
复制代码

  到此,咱们的WxServlet已经能够正常处理用户的请求并作出响应了.接下来咱们测试一下咱们开发好的公众号应用是否能够正常和微信用户交互

  将WxStudy部署到Tomcat服务器,启动服务器,记得使用ngrok将本地Tomcat服务器的8080端口映射到外网,保证接口配置信息的URL地址:http://xdp.ngrok.natapp.cn/WxServlet能够正常与微信服务器通讯

  登陆到咱们的测试公众号的管理后台,而后用微信扫描一下测试号的二维码,以下图所示:

  

 

  

  

  关注成功后,咱们开发好的公众号应用会先给用户发一条提示用户操做的文本消息,微信用户根据提示操做输入"文本",咱们的公众号应用接收到用户请求后就给用户回复了一条咱们本身构建好的文本消息,以下图所示:

  

  咱们的公众号应用响应给微信用户的文本消息的XML数据以下:

复制代码
1 <xml> 2 <ToUserName><![CDATA[ojADgs0eDaqh7XkTM9GvDmdYPoDw]]></ToUserName> 3 <FromUserName><![CDATA[gh_43df3882c452]]></FromUserName> 4 <CreateTime>1453755900000</CreateTime> 5 <MsgType><![CDATA[text]]></MsgType> 6 <Content><![CDATA[孤傲苍狼在学习和总结微信开发了,构建一条文本消息:Hello World!]]></Content> 7 </xml>
复制代码

  测试公众号的管理后台也能够看到关注测试号的用户列表,以下图所示:

  

  经过这个简单的入门程序,咱们揭开了微信开发的神秘面纱了.

  本篇的内容就这么多了。本文的内容和代码参考了用java开发微信公众号:公众号接入和access_token管理(二)这篇博客,在此对做者"风的姿态"表示感谢。

  下载测试项目部署运行时,因为项目中使用的是Servlet3.0,因此要求部署的Tomcat必须是7.x,之前也写过几篇关于Servlet3.0的博客,你们有兴趣的话能够去看看,本篇博文对应的测试项目代码下载

 

 

 

                              来源:http://www.cnblogs.com/xdp-gacl/p/5151857.html

相关文章
相关标签/搜索