微信測試號接入以及選單、身份證識別、自動智慧功能指南
阿新 • • 發佈:2019-01-01
一、首先進入微信公眾號的官網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;
}
}
時間很忙,也很晚了,附著的程式碼比較粗略,僅供參考,轉載請附著轉載原創路徑。