Javaで微信公衆番号を構築する(一)基礎要求フレームワークを構築する


最近、友达に微信の公衆番号を作ってもらい、微信の公衆番号の開発者マニュアルを見ることで基本的な機能を実現しました.基本的に通用するコードを貼ってください.
微信公衆番号は2つのモードを提供しています.1つは直接編集モードで、ページを操作することで基本的な機能を構築することができます.例えば、カスタマイズメニュー機能が使いやすいです.1つは開発者モデルで,HTTPインタフェース(RESTスタイルに完全に合致しない)に基づいてコードを書く必要がある.面倒なのは2つのモードが2つの選択の関係で、開発者のモードを使って、いくつかの直接編集の便利さを捨てなければなりません.
開発者モードを使用する最初のステップは、サーバの構成です.URLを構成すると、Tokenの後、微信サーバはHTTP GET要求をURLに送信し、signature、timestamp、nonce、echostrといういくつかのパラメータを添付します.echostrをそのまま返すと、微信サーバは構成に成功したと考えられます.自分のサーバは次のルールで構成に成功したかどうかを判断します.
1.timestamp,nonce,tokenの3つのパラメータを並べ替え、文字列につづる
2.SHA 1を使用してこの文字列を暗号化する
3.暗号化された文字列がsignatureに等しい場合、自分のサーバは構成に成功したと考えられます.
構成されたURLに対応するコントローラは、マイクロ通信サーバから転送されたリクエストを処理するフロントエンドコントローラに相当します.ここで注意tokenの役割は,自分のコードが微信のHTTPインタフェースにアクセスする場合,HTTPリクエストにaccess_を加える必要がある.token.WeChatサーバから転送されたリクエストであればaccess_とtokenは関係なく、直接処理できます.微信サーバーから転送されたリクエストは2種類あり、1つはGETで、一般的にサーバーを構成するときだけあります.もう1つは、POST XMLの要求であり、例えば、ユーザが微信公衆のメニューをクリックしたり、ユーザが微信公衆番号で送信したりする要求などである.
基本的な処理では,微信サーバから転送されたリクエストコードフレームワークは以下の通りである.

import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.springframework.web.servlet.ModelAndView;
import org.w3c.dom.Document;


public class WeixinAPIController extends AbstractBackController {
	private static final String token = "1234567890";

	@Override
	public ModelAndView handleBackRequest(HttpServletRequest request,
			HttpServletResponse response, Map model) throws Exception {
		
		boolean isGet = request.getMethod().toLowerCase().equals("get");
		if (isGet) {
			String echostr = request.getParameter("echostr");
			StringBuilder weixinContent = new StringBuilder();
			if (checkSignature(request)) {
				weixinContent.append(echostr);
			} else {
				weixinContent.append("Invalid request");
			}
			response.getWriter().print(weixinContent.toString());
		} else {
			ServletInputStream in = request.getInputStream();
			acceptXML(in, response);
		}
		response.getWriter().flush();
		response.getWriter().close();

		return null;

	}
	
	private void acceptXML(InputStream in, HttpServletResponse response) throws Exception{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		try {
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document doc = builder.parse(in);
			String toUserName = doc.getElementsByTagName("ToUserName").item(0).getFirstChild().getNodeValue();
			String fromUserName = doc.getElementsByTagName("FromUserName").item(0).getFirstChild().getNodeValue();
			String msgType = doc.getElementsByTagName("MsgType").item(0).getFirstChild().getNodeValue();
			if("text".equals(msgType)){
				String content = doc.getElementsByTagName("Content").item(0).getFirstChild().getNodeValue();
				
				if(content != null && content.length() > 0){
			             //         POST       		
				     // Do something
					
				}
			}else if("event".equals(msgType)){
				String event = doc.getElementsByTagName("Event").item(0).getFirstChild().getNodeValue();
				if("CLICK".equals(event)){
					String commandStr = doc.getElementsByTagName("EventKey").item(0).getFirstChild().getNodeValue();
					
					//         POST                 
                                        // Do something
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	

	private boolean checkSignature(HttpServletRequest request) {
		boolean valid = false;
		String signature = request.getParameter("signature");
		String timestamp = request.getParameter("timestamp");
		String nonce = request.getParameter("nonce");
		if (signature == null || timestamp == null || nonce == null) {
			return false;
		}

		List<String> array = new ArrayList<String>();
		array.add(token);
		array.add(timestamp);
		array.add(nonce);
		Collections.sort(array);
		String tempString = array.get(0) + array.get(1) + array.get(2);

		MessageDigest sha1;
		try {
			sha1 = MessageDigest.getInstance("SHA1");
			sha1.update(tempString.getBytes());
			byte[] bytes = sha1.digest();
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < bytes.length; i++) {
				String shaHex = Integer.toHexString(bytes[i] & 0xFF);
				if (shaHex.length() < 2) {
					sb.append(0);
				}
				sb.append(shaHex);
			}
			String encodedToken = sb.toString();
			if (encodedToken.equals(signature)) {
				valid = true;
			}
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}

		return valid;
	}

}

サーバ構成を開始すると、有効になるまで数分待たなければなりません.有効になると、微信サーバから転送されたメッセージを受信できます.