首页 > PHP资讯 > 工具库 > 微信公众帐号开发教程第3篇-开发模式启用及接口配置

微信公众帐号开发教程第3篇-开发模式启用及接口配置

工具库

编辑模式与开发模式

微信公众帐号申请成功后,要想接收处理用户的请求,就必须要在“高级功能”里进行配置,点击“高级功能”,将看到如下界面:

从上图中可以看到,高级功能包含两种模式:编辑模式和开发模式,并且这两种模式是互斥关系,即两种模式不能同时开启。那两种模式有什么区别呢?作为开发人员到底要开启哪一种呢?

编辑模式:主要针对非编程人员及信息发布类公众帐号使用。开启该模式后,可以方便地通过界面配置“自定义菜单”和“自动回复的消息”。

开发模式:主要针对具备开发能力的人使用。开启该模式后,能够使用微信公众平台开放的接口,通过编程方式实现自定义菜单的创建、用户消息的接收/处理/响应。这种模式更加灵活,建议有开发能力的公司或个人都采用该模式。


启用开发模式(上)

微信公众帐号注册完成后,默认开启的是编辑模式。那么该如何开启开发模式呢?操作步骤如下:

1)点击进入编辑模式,将右上角的编辑模式开关由“开启”切换到“关闭”,如下图所示:

2)点击高级功能进入到开发模式,将右上角的开发模式开关由“关闭”切换到“开启”,但在切换时会遇到如下提示:

提示需要我们先成为开发者,才能开启开发模式。那就先点击下图所示的“成为开发者”按钮:

如果提示资料不全,那就先补齐资料再回来继续操作。需要补全的资料有公众帐号头像、描述和运营地区。

待资料补全后,再次点击“成为开发者”,这时将看到接口配置信息界面,如下图所示:

这里需要填写URL和Token两个值。URL指的是能够接收处理微信服务器发送的GET/POST请求的地址,并且是已经存在的,现在就能够在浏览器访问到的地址,这就要求我们先把公众帐号后台处理程序开发好(至少应该完成了对GET请求的处理)并部署在公网服务器上。Token后面会详细说明。

也就是说要完成接口配置,只需要先完成微信服务器的GET请求处理就可以?是的。 那这是为什么呢?因为这是微信公众平台接口中定义的。具体请参考API文档-消息接口-消息接口指南中的网址接入部分。点此进入。

上面写的很清楚,其实你只要能理解上面在说什么就OK了,至于怎么编写相关代码,我已经帮你完成了,请继续往下看。


创建公众帐号后台接口程序

创建一个Java Web工程,并新建一个能够处理请求的Servlet,命名任意,我在这里将其命名为org.liufeng.course.servlet.CoreServlet,代码如下:


[java] view plaincopyprint?
  1. package org.liufeng.course.servlet; 
  2.  
  3. import java.io.IOException; 
  4. import java.io.PrintWriter; 
  5.  
  6. import javax.servlet.ServletException; 
  7. import javax.servlet.http.HttpServlet; 
  8. import javax.servlet.http.HttpServletRequest; 
  9. import javax.servlet.http.HttpServletResponse; 
  10.  
  11. import org.liufeng.course.util.SignUtil; 
  12.  
  13. /**
  14. * 核心请求处理类
  15. *
  16. * @author liufeng
  17. * @date 2013-05-18
  18. */ 
  19. public class CoreServlet extends HttpServlet { 
  20.     private static final long serialVersionUID = 4440739483644821986L; 
  21.  
  22.     /**
  23.      * 确认请求来自微信服务器
  24.      */ 
  25.     public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
  26.         // 微信加密签名 
  27.         String signature = request.getParameter("signature"); 
  28.         // 时间戳 
  29.         String timestamp = request.getParameter("timestamp"); 
  30.         // 随机数 
  31.         String nonce = request.getParameter("nonce"); 
  32.         // 随机字符串 
  33.         String echostr = request.getParameter("echostr"); 
  34.  
  35.         PrintWriter out = response.getWriter(); 
  36.         // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败 
  37.         if (SignUtil.checkSignature(signature, timestamp, nonce)) { 
  38.             out.print(echostr); 
  39.         } 
  40.         out.close(); 
  41.         out = null; 
  42.     } 
  43.  
  44.     /**
  45.      * 处理微信服务器发来的消息
  46.      */ 
  47.     public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
  48.         // TODO 消息的接收、处理、响应 
  49.     } 
  50.  
package org.liufeng.course.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.liufeng.course.util.SignUtil;/** * 核心请求处理类 *  * @author liufeng * @date 2013-05-18 */public class CoreServlet extends HttpServlet {	private static final long serialVersionUID = 4440739483644821986L;	/**	 * 确认请求来自微信服务器	 */	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {		// 微信加密签名		String signature = request.getParameter("signature");		// 时间戳		String timestamp = request.getParameter("timestamp");		// 随机数		String nonce = request.getParameter("nonce");		// 随机字符串		String echostr = request.getParameter("echostr");		PrintWriter out = response.getWriter();		// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败		if (SignUtil.checkSignature(signature, timestamp, nonce)) {			out.print(echostr);		}		out.close();		out = null;	}	/**	 * 处理微信服务器发来的消息	 */	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {		// TODO 消息的接收、处理、响应	}}
可以看到,代码中只完成了doGet方法,它的作用正是确认请求是否来自于微信服务器;而doPost方法不是我们这次要讲的内容,并且完成接口配置也不需要管doPost方法,就先空在那里。


在doGet方法中调用了org.liufeng.course.util.SignUtil.checkSignature方法,SignUtil.java的实现如下:


[java] view plaincopyprint?
  1. package org.liufeng.course.util; 
  2.  
  3. import java.security.MessageDigest; 
  4. import java.security.NoSuchAlgorithmException; 
  5. import java.util.Arrays; 
  6.  
  7. /**
  8. * 请求校验工具类
  9. *
  10. * @author liufeng
  11. * @date 2013-05-18
  12. */ 
  13. public class SignUtil { 
  14.     // 与接口配置信息中的Token要一致 
  15.     private static String token = "weixinCourse"; 
  16.  
  17.     /**
  18.      * 验证签名
  19.      *
  20.      * @param signature
  21.      * @param timestamp
  22.      * @param nonce
  23.      * @return
  24.      */ 
  25.     public static boolean checkSignature(String signature, String timestamp, String nonce) { 
  26.         String[] arr = new String[] { token, timestamp, nonce }; 
  27.         // 将token、timestamp、nonce三个参数进行字典序排序 
  28.         Arrays.sort(arr); 
  29.         StringBuilder content = new StringBuilder(); 
  30.         for (int i = 0; i < arr.length; i++) { 
  31.             content.append(arr[i]); 
  32.         } 
  33.         MessageDigest md = null; 
  34.         String tmpStr = null; 
  35.  
  36.         try { 
  37.             md = MessageDigest.getInstance("SHA-1"); 
  38.             // 将三个参数字符串拼接成一个字符串进行sha1加密 
  39.             byte[] digest = md.digest(content.toString().getBytes()); 
  40.             tmpStr = byteToStr(digest); 
  41.         } catch (NoSuchAlgorithmException e) { 
  42.             e.printStackTrace(); 
  43.         } 
  44.  
  45.         content = null; 
  46.         // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信 
  47.         return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false; 
  48.     } 
  49.  
  50.     /**
  51.      * 将字节数组转换为十六进制字符串
  52.      *
  53.      * @param byteArray
  54.      * @return
  55.      */ 
  56.     private static String byteToStr(byte[] byteArray) { 
  57.         String strDigest = ""; 
  58.         for (int i = 0; i < byteArray.length; i++) { 
  59.             strDigest += byteToHexStr(byteArray[i]); 
  60.         } 
  61.         return strDigest; 
  62.     } 
  63.  
  64.     /**
  65.      * 将字节转换为十六进制字符串
  66.      *
  67.      * @param mByte
  68.      * @return
  69.      */ 
  70.     private static String byteToHexStr(byte mByte) { 
  71.         char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 
  72.         char[] tempArr = new char[2]; 
  73.         tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; 
  74.         tempArr[1] = Digit[mByte & 0X0F]; 
  75.  
  76.         String s = new String(tempArr); 
  77.         return s; 
  78.     } 
package org.liufeng.course.util;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.Arrays;/** * 请求校验工具类 *  * @author liufeng * @date 2013-05-18 */public class SignUtil {	// 与接口配置信息中的Token要一致	private static String token = "weixinCourse";	/**	 * 验证签名	 * 	 * @param signature	 * @param timestamp	 * @param nonce	 * @return	 */	public static boolean checkSignature(String signature, String timestamp, String nonce) {		String[] arr = new String[] { token, timestamp, nonce };		// 将token、timestamp、nonce三个参数进行字典序排序		Arrays.sort(arr);		StringBuilder content = new StringBuilder();		for (int i = 0; i < arr.length; i++) {			content.append(arr[i]);		}		MessageDigest md = null;		String tmpStr = null;		try {			md = MessageDigest.getInstance("SHA-1");			// 将三个参数字符串拼接成一个字符串进行sha1加密			byte[] digest = md.digest(content.toString().getBytes());			tmpStr = byteToStr(digest);		} catch (NoSuchAlgorithmException e) {			e.printStackTrace();		}		content = null;		// 将sha1加密后的字符串可与signature对比,标识该请求来源于微信		return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;	}	/**	 * 将字节数组转换为十六进制字符串	 * 	 * @param byteArray	 * @return	 */	private static String byteToStr(byte[] byteArray) {		String strDigest = "";		for (int i = 0; i < byteArray.length; i++) {			strDigest += byteToHexStr(byteArray[i]);		}		return strDigest;	}	/**	 * 将字节转换为十六进制字符串	 * 	 * @param mByte	 * @return	 */	private static String byteToHexStr(byte mByte) {		char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };		char[] tempArr = new char[2];		tempArr[0] = Digit[(mByte >>> 4) & 0X0F];		tempArr[1] = Digit[mByte & 0X0F];		String s = new String(tempArr);		return s;	}}
这里唯一需要注意的就是SignUtil类中的成员变量token,这里赋予什么值,在接口配置信息中的Token就要填写什么值,两边保持一致即可,没有其他要求,建议用项目名称、公司名称缩写等,我在这里用的是项目名称weixinCourse。


最后再来看一下web.xml中,CoreServlet是怎么配置的,web.xml中的配置代码如下:


[html] view plaincopyprint?
  1.  
  2.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  3.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  
  4.     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 
  5.      
  6.         coreServlet 
  7.          
  8.             org.liufeng.course.servlet.CoreServlet 
  9.          
  10.      
  11.  
  12.      
  13.      
  14.         coreServlet 
  15.         /coreServlet 
  16.      
  17.  
  18.      
  19.         index.jsp 
  20.      
  21.  
			coreServlet					org.liufeng.course.servlet.CoreServlet				
			coreServlet		/coreServlet				index.jsp	
到这里,所有编码都完成了,就是这么简单。接下来就是将工程发布到公网服务器上,如果没有公网服务器环境,可以去了解下BAE、SAE或阿里云。发布到服务器上后,我们在浏览器里访问CoreServlet,如果看到如下界面就表示我们的代码没有问题:




啊,代码都报空指针异常了还说证明没问题?那当然了,因为直接在地址栏访问coreServlet,就相当于提交的是GET请求,而我们什么参数都没有传,在验证的时候当然会报空指针异常。

接下来,把coreServlet的访问路径拷贝下来,再回到微信公众平台的接入配置信息界面,将coreServlet的访问路径粘贴到URL中,并将SignUtil类中指定的token值weixinCourse填入到Token中,填写后的结果如下图所示:

我在写这篇教程的时候是使用的BAE环境,如果想学习微信公众帐号开发又没有公网服务器环境的,建议可以试试,注册使用都很方便,如果有问题我们还可以交流。

接着点击“提交”,如果程序写的没问题,并且URL、Token都填写正确,可以在页面最上方看到“提交成功”的提示,并会再次跳转到开发模式设置界面,而且能够看到“你已成为开发者”的提示,如下图所示:


启用开发模式(下)

这个时候就已经成为开发者了,百般周折啊,哈哈,到这里还没有完哦,还有最后一步工作就是将开发模式开启。将右上角的开发模式开关由“关闭”切换到“开启”,如下图所示:

到这里,接口配置、开发模式的开启就都完成了,本章节的内容也就讲到这里。接下来要章节要讲的就是如何接收、处理、响应由微信服务器转发的用户发送给公众帐号的消息,也就是完成CoreServlet中doPost方法的编写。

工具库

本文由欣才IT学院整理发布,未经许可,禁止转载。
支持22不支持0