今天打算开发一个微信公众平台的一个阅读功能,使用开发者模式,第一个件就是要通过验证,就是token的验证.
我写的东西比较直接没有过多的解释性语言,如果有疑问可以通过评论来讨论一下.
接口开发一定要先看好接口说明,这个是很重要的,你对接口文档的理解直接影响到你的接口开发速度与质量.
开发工具:eclipse 3.5
使用技术:struts2 , spring 3.0 , hibernate 3.3 ,dom4j 等等
AIP网址:http://mp.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3%E6%8C%87%E5%8D%97#.E7.94.B3.E8.AF.B7.E6.B6.88.E6.81.AF.E6.8E.A5.E5.8F.A3
测试网址(伪): http://www.xyz.com/weixin_msg.action
测试token: token(您在使用的时候别忘了换成你自己的.)
===========接===口===说===明=============================
公众平台用户提交信息后,微信服务器将发送GET请求到填写的URL上,并且带上四个参数:
参数 | 描述 |
---|---|
signature | 微信加密签名 |
timestamp | 时间戳 |
nonce | 随机数 |
echostr | 随机字符串 |
开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,否则接入失败。
signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
加密/校验流程: 1. 将token、timestamp、nonce三个参数进行字典序排序 2. 将三个参数字符串拼接成一个字符串进行sha1加密 3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
=====================================================
action代码.我使用的是struts2所以是action.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.StringBufferInputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller; import com.xyz.bbs.weixin.utils.WeixinMessageDigestUtil; import com.xyz.framework.utils.MessageDigestUtil; import com.xyz.framework.web.BaseAction; @SuppressWarnings("serial") @Controller("WeixinActionId") @Scope("prototype") public class WeixinAction extends BaseAction { private static final String TOKEN = "token"; private static final String GET = "GET"; private String signature; private String timestamp; private String nonce; private String echostr; /** * 微信回调方法、包括doGet & doPost * @return */ public String msg(){ if (GET.equals(getRequest().getMethod())) { //get doget(); }else { //post } //为什么返回null? return null; } /** * get方式验证token */ public void doget(){ logger.debug("signature" + signature); logger.debug("timestamp" + timestamp); logger.debug("nonce" + nonce); logger.debug("echostr" + echostr); Arrays.sort(ArrTmp); StringBuffer sb = new StringBuffer(); for (int i = 0; i < ArrTmp.length; i++) { sb.append(ArrTmp[i]); } String pwd = WeixinMessageDigestUtil.getInstance().encipher(sb.toString()); if(pwd.equals(signature)){ if(!"".equals(echostr) && echostr != null){ try { System.out.println("response"); this.getResponse().getWriter().write(echostr); } catch (IOException e) { e.printStackTrace(); } } } } //一下代码不用看的. //getter && setter public String getSignature() { return signature; } public void setSignature(String signature) { this.signature = signature; } public String getTimestamp() { return timestamp; } public void setTimestamp(String timestamp) { this.timestamp = timestamp; } public String getNonce() { return nonce; } public void setNonce(String nonce) { this.nonce = nonce; } public String getEchostr() { return echostr; } public void setEchostr(String echostr) { this.echostr = echostr; } }
加密工具类
import java.security.*; import java.util.Arrays; /* * SHA1 水印算法工具类 * AJ 2013-04-12 */ public final class WeixinMessageDigestUtil { private static final WeixinMessageDigestUtil _instance = new WeixinMessageDigestUtil(); private MessageDigest alga; private WeixinMessageDigestUtil() { try { alga = MessageDigest.getInstance("SHA-1"); } catch(Exception e) { throw new InternalError("init MessageDigest error:" + e.getMessage()); } } public static WeixinMessageDigestUtil getInstance() { return _instance; } public static String byte2hex(byte[] b) { String des = ""; String tmp = null; for (int i = 0; i < b.length; i++) { tmp = (Integer.toHexString(b[i] & 0xFF)); if (tmp.length() == 1) { des += "0"; } des += tmp; } return des; } public String encipher(String strSrc) { String strDes = null; byte[] bt = strSrc.getBytes(); alga.update(bt); strDes = byte2hex(alga.digest()); //to HexString return strDes; } public static void main(String[] args) { String signature="b7982f21e7f18f640149be5784df8d377877ebf9"; String timestamp="1365760417"; String nonce="1365691777"; String[] ArrTmp = { "token", timestamp, nonce }; Arrays.sort(ArrTmp); StringBuffer sb = new StringBuffer(); for (int i = 0; i < ArrTmp.length; i++) { sb.append(ArrTmp[i]); } String pwd =WeixinMessageDigestUtil.getInstance().encipher(sb.toString()); if (signature.equals(pwd)) { System.out.println("token 验证成功~!"); }else { System.out.println("token 验证失败~!"); } } }
服务搭建完成之后就可以进行测试了,这个测试方法就不用我写了吧..
看到他说明你成功了.
最后简单说一下为什么action返回的是null而不是一个String.
大家都之后默认写struts2的时候需要指定返回路径,通常使用String来做.struts会根据你所返回的值去查找对应的页面.返回null就是因为微信接口协议,协议中说了echostr参数要远洋返回,如果是使用浏览器来看的话页面只有echostr的值,没有其他的字符.直接返回response,到页面就输出print了.