微信公衆平臺接口開發-接入驗證測試token

今天打算開發一個微信公衆平臺的一個閱讀功能,使用開發者模式,第一個件就是要經過驗證,就是token的驗證. php

我寫的東西比較直接沒有過多的解釋性語言,若是有疑問能夠經過評論來討論一下. java

接口開發必定要先看好接口說明,這個是很重要的,你對接口文檔的理解直接影響到你的接口開發速度與質量. web

開發工具:eclipse 3.5 算法

使用技術:struts2 , spring 3.0 , hibernate 3.3 ,dom4j 等等 spring

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(您在使用的時候別忘了換成你本身的.) 微信

===========接===口===說===明============================= app


網址接入

公衆平臺用戶提交信息後,微信服務器將發送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了.

相關文章
相關標籤/搜索