1. 程式人生 > >微信測試號接入以及選單、身份證識別、自動智慧功能指南

微信測試號接入以及選單、身份證識別、自動智慧功能指南

一、首先進入微信公眾號的官網https://mp.weixin.qq.com/點選訂閱號下面的開發文件

 

二、點選微信測試好申請系統,並進行申請進入測試號管理頁面

 

三、以下是我已經申請好的測試號,appID和appseret分別是測試號的賬戶和密碼,URL是要訪問的請求路徑(即是首先需要接收測試號通過URL傳指定攜帶的引數(signature,timestamp,nonce,echotr這裡我就不再多說了,開發文件裡面都有,自己去了解)

signature 微信加密簽名,signature結合了開發者填寫的token引數和請求中的timestamp引數、nonce引數。
timestamp 時間戳
nonce 隨機數
echostr 隨機字串

到指定的對映地址,對映地址就是你專案需要接收測試號的傳來的引數,然後進行引數校驗,通過校驗成功之後之後就會返回校驗成功的提示資訊)Token是使用者自己隨便填寫的,但是在公眾號這填寫的Token要同項目中的Token一致,這樣才能保證效驗成功的其中一部

 

四、要想使用URL能夠對映到你的專案訪問路徑,那就少不了內網穿透 https://natapp.cn/

這是我購買的隧道,我是用的是VIP_1隧道,當然你也可以使用免費的隧道,只不過免費的隧道會隨機更換域名和埠,很煩的,然後就是無腦的一頓配置,詳細操作自己去看吧

 

五、專案的開發接收測試號URL傳來的引數並校驗返回


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 com.kq.common.util.AccessToken;
import com.kq.common.util.SignUtil;
import com.kq.common.util.Util;

import net.sf.json.JSONObject;


public class WechatSerlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	private static final  String  TOKEN = "123";
	private static final  String GET_TOKEN_URL="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
	private static  final String APPID="wx86221fcb84dd84cc";
	private static final  String  APPSECRET="32ea75a4d0a7ed4c0da1d98308ed5e50";
   //用於儲存token
	private static AccessToken at;
	
	private  static void getToken() {
		String url=GET_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);
		String tokenStr=Util.get(url);
		JSONObject jsonObject=JSONObject.fromObject(tokenStr);
		String token=jsonObject.getString("access_token");
		String expireIn=jsonObject.getString("expires_in");
		//建立token物件,存起來
		at=new AccessToken(token, expireIn);
	}
	
	//當token過期時,自動獲取token
	public static String getAccessToken() {
		if (at==null||at.isExpired()) {
			getToken();
		}
		return at.getAccessToken();
	}

	public WechatSerlet() {
		super();
	}

	public void init() throws ServletException {

	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.out.println("開始簽名校驗");

		String signature = request.getParameter("signature");
		System.out.println("signature:" + signature);

		String timestamp = request.getParameter("timestamp");
		System.out.println("timestamp:" + timestamp);

		String nonce = request.getParameter("nonce");
		System.out.println("nonce:" + nonce);

		String echostr = request.getParameter("echostr");
		System.out.println("echostr:" + echostr);

		// 通過校驗signature對請求進行校驗,若校驗成功則原樣返回echostr,表示接入成功,否則接入失敗
		PrintWriter out = response.getWriter();
		if (SignUtil.checkSignature(signature, timestamp, nonce)) {
			
			out.print(echostr);
		}
		out.close();
		out = null;
	}

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import com.kq.common.wechat.WechatSerlet;

public class SignUtil {

	// 與微信配置中的的Token一致 wechat為微信中的token 需自己填寫!!!!!!!!!!!!!!!!!
	private static String token = "123";

	public static boolean checkSignature(String signature, String timestamp, String nonce) {
		String[] arra = new String[] { token, timestamp, nonce };
		// 將signature,timestamp,nonce組成陣列進行字典排序
		Arrays.sort(arra);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < arra.length; i++) {
			sb.append(arra[i]);
		}
		MessageDigest md = null;
		String stnStr = null;
		try {
			md = MessageDigest.getInstance("SHA-1");
			byte[] digest = md.digest(sb.toString().getBytes());
			stnStr = byteToStr(digest);
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 釋放記憶體
		sb = null;
		// 將sha1加密後的字串與signature對比,標識該請求來源於微信
		return stnStr != null ? stnStr.equals(signature.toUpperCase()) : false;
	}

	/**
	 * 將位元組陣列轉換成十六進位制字串
	 * 
	 * @param digestArra
	 * @return
	 */
	private static String byteToStr(byte[] digestArra) {
		// TODO Auto-generated method stub
		String digestStr = "";
		for (int i = 0; i < digestArra.length; i++) {
			digestStr += byteToHexStr(digestArra[i]);
		}
		return digestStr;
	}

	/**
	 * 將位元組轉換成為十六進位制字串
	 */
	private static String byteToHexStr(byte dByte) {
		// TODO Auto-generated method stub
		char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
		char[] tmpArr = new char[2];
		tmpArr[0] = Digit[(dByte >>> 4) & 0X0F];
		tmpArr[1] = Digit[dByte & 0X0F];
		String s = new String(tmpArr);
		return s;
	}
	

}

public class AccessToken {

	private String accessToken;
	private long expireTiem;
	public String getAccessToken() {
		return accessToken;
	}
	public void setAccessToken(String accessToken) {
		this.accessToken = accessToken;
	}
	public long getExpireTiem() {
		return expireTiem;
	}
	public void setExpireTiem(long expireTiem) {
		this.expireTiem = expireTiem;
	}
	
	public AccessToken(String accessToken, String expireIn) {
		super();
		this.accessToken = accessToken;
		//計算過期時間
		expireTiem=System.currentTimeMillis()+Integer.parseInt(expireIn)*1000;
	}
	
	public boolean isExpired() {
		return System.currentTimeMillis()>expireTiem;
	}
	
	
}

public class Menu {

	public static void main(String[] args) {

		//選單物件
		Button btn=new Button();
		//第一個一級選單
		btn.getButton().add(new ClickButton("一級點選", "2"));
		
		//第二個一級選單
		btn.getButton().add(new ViewButton("一級跳轉", "http://www.baidu.com"));
		
		//建立第三個一級選單
	 /* SubButton sb=new SubButton("三級選單");
	    sb.getSub_button().add(new PhotoOrAlbumButton("拍照","31"));
	    sb.getSub_button().add(new PhotoOrAlbumButton("點選","32"));
	    sb.getSub_button().add(new PhotoOrAlbumButton("搜狐新聞","https://news.163.com/"));
	    btn.getButton().add(sb);*/
	    JSONObject jsonObject=JSONObject.fromObject(btn);
	    String url="https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=ACCESS_TOKEN";
		url=url.replace("ACCESS_TOKEN", WechatSerlet.getAccessToken());
		//請求傳送
		String result=Util.post(url,jsonObject.toString());
		System.out.println(result);
		
	}
}
package com.kq.common.entity;

import java.util.ArrayList;
import java.util.List;

public class Button {

	private List<AbstractButon> button=new ArrayList<AbstractButon>();
	
	public  List<AbstractButon> getButton(){
		return button;
	}

	public void setButton(List<AbstractButon> button) {
		this.button = button;
	}
	
}

public abstract class AbstractButon {

	private String name ;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public AbstractButon(String name) {
		super();
		this.name = name;
	}
	
	
}

 


import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

public class Util {

	public static String post(String url, String data) {
		URL urlobj;
		try {
			urlobj = new URL(url);
			URLConnection connection = urlobj.openConnection();
			connection.setDoOutput(true);
			// 獲取輸出流
			OutputStream os = connection.getOutputStream();
			// 寫出資料
			os.write(data.getBytes());
			os.close();
			// 獲取輸入流
			InputStream is = connection.getInputStream();
			byte[] b = new byte[1024];
			int len;
			StringBuilder sb = new StringBuilder();
			while ((len = is.read(b)) != -1) {
				sb.append(new String(b, 0, len));
			}
			return sb.toString();

		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	

	public static String get(String url) {
		try {
			URL urlObj = new URL(url);
			URLConnection connection = urlObj.openConnection();
			InputStream is = connection.getInputStream();
			byte[] b = new byte[1024];
			int len;
			StringBuilder sb = new StringBuilder();
			while ((len = is.read(b)) != -1) {
				sb.append(new String(b, 0, len));
			}
			return sb.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}

六、測試微信公眾號的連線

 

返回控制檯檢視控制檯輸出結果

七、關注微信測試公眾號檢視選單點選事件

八、當然你也可以新增其他的功能拓展類,比如身份證介面識別、自動回覆功能(我是呼叫圖靈機器人),這裡我就不一一介紹了直接附上程式碼,讓各位大佬們自己去看吧,畢竟這種寫還是自己多研究的好。俗話說熟能生巧嘛。

 


import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.json.JSONObject;
import org.junit.Test;

import com.baidu.aip.util.Base64Util;
import com.kq.common.vo.IdCardToken;
import com.kq.sys.entity.IdCard;
import com.kq.sys.service.IdCardService;

import common.utils.FileUtil;
import common.utils.HttpUtil;

/**
 * 身份識別
 * 
 */
public class IdCardController {

	private static IdCardService idCardService;

	public static String CardService(String picurl) {
		IdCard idCard = new IdCard();
		idCard = idCardService.findAll(picurl);
		return null;
	}

	public static String IdCard(String picurl) {
		// 身份證識別url
		String idcardIdentificate = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard";
		// 本地圖片路徑
		String filePath = picurl;
		String StringCard = null;
		try {
			// byte[] imgUata=FileUtil.readFileAsString(filePath);
			byte[] imgData = FileUtil.getImageStream(filePath);
			String imgStr = Base64Util.encode(imgData);
			// 識別身份證正面id_card_side=front;識別身份證背面id_card_side=back;
			String params = "id_card_side=front&" + URLEncoder.encode("image", "UTF-8") + "="
					+ URLEncoder.encode(imgStr, "UTF-8");
			/**
			 * 線上環境access_token有過期時間, 客戶端可自行快取,過期後重新獲取。
			 */
			String accessToken = IdCardToken.getAuth();
			String result = HttpUtil.post(idcardIdentificate, accessToken, params);
			JSONObject json = new JSONObject(result);
			IdCard idCard = new IdCard();
			String name = json.getJSONObject("words_result").getJSONObject("姓名").getString("words");
			String gender = json.getJSONObject("words_result").getJSONObject("性別").getString("words");
			String birthdate = json.getJSONObject("words_result").getJSONObject("出生").getString("words");
			String address = json.getJSONObject("words_result").getJSONObject("住址").getString("words");
			String idNumber = json.getJSONObject("words_result").getJSONObject("公民身份號碼").getString("words");
			idCard.setName(name);
			idCard.setGender(gender);
			idCard.setBirthdate(new SimpleDateFormat("yyyyMMdd").parse(birthdate));
			idCard.setAddress(address);
			idCard.setIdNumber(idNumber);
			System.out.println(idCard.toString());
			StringCard = idCard.toString();

		} catch (Exception e) {
			e.printStackTrace();
		}
		return StringCard;
	}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;

import org.json.JSONObject;

public class IdCardToken {
	 /**
     * 獲取許可權token
     */
    public static String getAuth() {
        // 官網獲取的 API Key 更新為你註冊的
        String clientId = "vkqBwe9WHvWLjSCFab5mfLT9";
        // 官網獲取的 Secret Key 更新為你註冊的
        String clientSecret = "eSyj3y36E8NFSymaRGuWkKMA0BiKdn5i";
        return getAuth(clientId, clientSecret);
    }

    /**
     * 獲取API訪問token
     */
    public static String getAuth(String ak, String sk) {
        // 獲取token地址
        String authHost = "https://aip.baidubce.com/oauth/2.0/token?";
        String getAccessTokenUrl = authHost
                // 1. grant_type為固定引數
                + "grant_type=client_credentials"
                // 2. 官網獲取的 API Key
                + "&client_id=" + ak
                // 3. 官網獲取的 Secret Key
                + "&client_secret=" + sk;
        try {
            URL realUrl = new URL(getAccessTokenUrl);
            // 開啟和URL之間的連線
            HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            // 獲取所有響應頭欄位
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍歷所有的響應頭欄位
            for (String key : map.keySet()) {
                System.err.println(key + "--->" + map.get(key));
            }
            // 定義 BufferedReader輸入流來讀取URL的響應
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String result = "";
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            /**
             * 返回結果示例
             */
            System.err.println("result:" + result);
            JSONObject jsonObject = new JSONObject(result);
            String access_token = jsonObject.getString("access_token");
            return access_token;
        } catch (Exception e) {
            System.err.printf("獲取token失敗!");
            e.printStackTrace(System.err);
        }
        return null;
    }
}

 


import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.jar.JarException;
//{key:value,key,value,key:{key:value}}
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;


public class TulingApiProcess {

	/**
	 * 呼叫圖靈機器人api介面,獲取智慧回覆內容,解析獲取自己所需結果
	 * 
	 * @param content
	 * @return
	 */
	public String getTulingResult(String content) throws JarException {
		/** 此處為圖靈api介面,引數key需要自己去註冊申請, */
		String apiUrl = "http://www.tuling123.com/openapi/api?key=********************";
		String param = "";
		try {
			param = apiUrl + URLEncoder.encode(content, "utf-8");
		} catch (UnsupportedEncodingException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} // 將引數轉為url編碼
		/** 傳送httpget請求 */
		HttpGet request = new HttpGet(param);
		System.out.println("param:"+param);
		String result = "";
		
		try {
			HttpResponse response = HttpClients.createDefault().execute(request);
			if (response.getStatusLine().getStatusCode() == 200) {
				result = EntityUtils.toString(response.getEntity());
							}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		/** 請求失敗處理 */
		if (null == result) {
			return "對不起,你說的話真是太高深了……";
		}
	
		JSONObject json = new JSONObject(result);
		// 以code=100000為例,參考圖靈機器人api文件
		if (100000 == json.getInt("code")) {//{code:100000,text:"text"}
			result = json.getString("text");
		}
		//System.out.println(result);
		return result;
	}

}

時間很忙,也很晚了,附著的程式碼比較粗略,僅供參考,轉載請附著轉載原創路徑。