wechat-0050,微信公眾號,帶引數的二維碼獲取與掃碼事件推送
獲取二維碼
1. 二維碼型別
臨時二維碼,是有過期時間的,最長可以設定為在二維碼生成後的30天(即2592000秒)後過期,但能夠生成較多數量。臨時二維碼主要用於帳號繫結等不要求二維碼永久儲存的業務場景
永久二維碼,是無過期時間的,但數量較少(目前為最多10萬個)。永久二維碼主要用於適用於帳號繫結、使用者來源統計等場景。
2. 獲取帶引數的二維碼的過程包括兩步,首先建立二維碼ticket,然後憑藉ticket到指定URL換取二維碼。
3.帶引數的二維碼用處之一:可用於第三方登入
具體步驟:
獲取ticket:
1.簡要步驟:獲取token,拼湊引數(json資料),呼叫微信介面獲取ticket
1.1 獲取token
public class AccessTokenUtil { private static String ACCESSTOKENURL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appId}&secret={appSecret}"; /** * 獲取access_Token * * @return */ public static String getAccessToken(String appId, String appSecret) { String url = ACCESSTOKENURL.replace("{appId}", appId).replace("{appSecret}", appSecret); String accessTokenJsonStr = Browser.httpGet(url); Gson gson = new Gson(); AccessToken accessToken = gson.fromJson(accessTokenJsonStr, AccessToken.class); if(accessToken.getErrcode() != 0) { return null; }else { return accessToken.getAccess_token(); } } }
將appid和appSectet替換成自己的。
1.2 json資料拼湊
臨時二維碼json資料
{"expire_seconds": 604800, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": 123}}}
或(兩者的區別在於場景值的表示方法不同,上面是數字,下面是字串)
{"expire_seconds": 604800, "action_name": "QR_STR_SCENE", "action_info": {"scene": {"scene_str": "test"}}}
永久二維碼json資料(和臨時的區別在於沒有時間限制)
{"action_name": "QR_LIMIT_SCENE", "action_info": {"scene": {"scene_id": 123}}}
或(同上)
{"action_name": "QR_LIMIT_STR_SCENE", "action_info": {"scene": {"scene_str": "test"}}}
注意格式一定要確保正確,獲取可能會造成可以獲取二維碼,但在掃碼事件中無法獲取場景值。
為了獲取上述json資料,這邊先進行實體類封裝,然後利用Gson序列化
二維碼實體類,最大的類
/**
* 二維碼實體類
*
* @author WRY
*
*/
public class QrCode {
// 二維碼型別
// 臨時整形
public static final String QRSCENE = "QR_SCENE";
// 臨時字串
public static final String QRSTRSCENE = "QR_STR_SCENE";
// 永久整形
public static final String QRLIMITSCENE = "QR_LIMIT_SCENE";
// 永久字串
public static final String QRLIMITSTRSCENE = "QR_LIMIT_STR_SCENE";
// expire_seconds 該二維碼有效時間,以秒為單位。 最大不超過2592000(即30天),此欄位如果不填,則預設有效期為30秒。
@SerializedName("expire_seconds")
private Long expireSeconds;
// action_name
// 二維碼型別,QR_SCENE為臨時的整型引數值,QR_STR_SCENE為臨時的字串引數值,QR_LIMIT_SCENE為永久的整型引數值,QR_LIMIT_STR_SCENE為永久的字串引數值
@SerializedName("action_name")
private String actionName;
// action_info 二維碼詳細資訊
@SerializedName("action_info")
private ActionInfo actionInfo;
public long getExpireSeconds() {
return expireSeconds;
}
public void setExpireSeconds(long expireSeconds) {
this.expireSeconds = expireSeconds;
}
public String getActionName() {
return actionName;
}
public void setActionName(String actionName) {
this.actionName = actionName;
}
public ActionInfo getActionInfo() {
return actionInfo;
}
public void setActionInfo(ActionInfo actionInfo) {
this.actionInfo = actionInfo;
}
}
二維碼詳情類
public class ActionInfo {
// 場景值資訊
private Scene scene;
public Scene getScene() {
return scene;
}
public void setScene(Scene scene) {
this.scene = scene;
}
}
場景類
/**
* 二維碼場景
* @author WRY
*
*/
public class Scene {
// scene_id 場景值ID,臨時二維碼時為32位非0整型,永久二維碼時最大值為100000(目前引數只支援1--100000)
@SerializedName("scene_id")
private Long sceneId;
// scene_str 場景值ID(字串形式的ID),字串型別,長度限制為1到64
@SerializedName("scene_str")
private String sceneStr;
public long getSceneId() {
return sceneId;
}
public void setSceneId(long sceneId) {
this.sceneId = sceneId;
}
public String getSceneStr() {
return sceneStr;
}
public void setSceneStr(String sceneStr) {
this.sceneStr = sceneStr;
}
}
有了上述封裝,後續就可以很簡單拼湊json資料
1.3 封裝一個可以傳送post請求的瀏覽器類,基於httpClient封裝,這邊附上主要程式碼,整個類比較大,如果有需要知道全部的封裝類,請給我留言
/**
* post請求
*
* @param url
* @param param
* json格式的請求資料
* @return
*/
public static String httpPost(String url, String param) {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(5000).setConnectTimeout(5000)
.setSocketTimeout(5000).build();
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(config);
// 設定請求資料
StringEntity entity = new StringEntity(param, Charset.forName("UTF-8"));
entity.setContentEncoding("UTF-8");
// 傳送Json格式的資料請求
entity.setContentType("application/json");
httpPost.setEntity(entity);
CloseableHttpResponse httpResponse = null;
String soundCode = "";
try {
httpResponse = httpClient.execute(httpPost);
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entitytemp = httpResponse.getEntity();
soundCode = EntityUtils.toString(entitytemp, "utf-8");
}
} catch (ClientProtocolException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} finally {
if (httpResponse != null) {
try {
httpResponse.close();
httpResponse = null;
} catch (IOException e) {
}
}
if (httpClient != null) {
try {
httpClient.close();
httpClient = null;
} catch (IOException e) {
}
}
}
return soundCode;
}
1.4 service類
/**
* 二維碼的業務類
* @author WRY
*
*/
public class QrCodeService {
// 獲取臨時ticket
private static String GETTEMPTICKETURL = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={accessToken}";
// 獲取永久ticket
private static String GETPERMANENTTICKETURL = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={accessToken}";
/**
* 獲取臨時ticket
* @return
*/
public String getTempTicket(String accessToken, String param) {
String url = GETTEMPTICKETURL.replace("{accessToken}", accessToken);
return Browser.httpPost(url, param);
}
/**
* 獲取永久ticket
* @param accessToken
* @param param
* @return
*/
public String getPermanentTicket(String accessToken, String param) {
String url = GETPERMANENTTICKETURL.replace("{accessToken}", accessToken);
return Browser.httpPost(url, param);
}
}
1.5 測試類
public class QrCodeServiceTest {
private static final String accessToken = "9_0Zo6BjMhLNF7RACUjJ1sWg9Tk0IpkH8TvgkPx_WlrvZ0a5Ow7ZGxg_dY2_ECnaJSUHR8Aaz3K9AT4keuq4GMqHLgwXMt5lsNrElRWvEQ9uMC7RV3KS9VPl9jvgkXGGbAEARAA";
/**
* 獲取臨時ticket
*/
@Test
public void testGetTempTicket() {
// 建立場景值
Scene scene = new Scene();
scene.setSceneId(0001);
// 二維碼詳細資訊
ActionInfo actionInfo = new ActionInfo();
actionInfo.setScene(scene);
// 構建獲取二維碼的資訊
QrCode qrCode = new QrCode();
qrCode.setActionName(QrCode.QRSCENE);
qrCode.setActionInfo(actionInfo);
// 序列化資料
Gson gson = new Gson();
String param = gson.toJson(qrCode);
System.out.println(param);
// 獲取二維碼
QrCodeService service = new QrCodeService();
String soundCode = service.getTempTicket(accessToken, param);
System.out.println(soundCode);
ReturnMessage returnMessage = gson.fromJson(soundCode, ReturnMessage.class);
System.out.println(returnMessage);
}
// {"ticket":"gQHx7zwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyTDNXY2h4SlJmM2sxVjAxTk5xMU0AAgQwc-FaAwQQDgAA","expire_seconds":3600,"url":"http:\/\/weixin.qq.com\/q\/02L3WchxJRf3k1V01NNq1M"}
// 換取二維碼
// https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQFE8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyUjV3LWdUSlJmM2sxU3ZuT05xMXYAAgSPSfJaAwQQDgAA
/**
* 獲取永久ticket
*/
@Test
public void testGetPermanentTicket() {
// 建立場景值
Scene scene = new Scene();
scene.setSceneId(10000);
// 二維碼詳細資訊
ActionInfo actionInfo = new ActionInfo();
actionInfo.setScene(scene);
// 構建獲取二維碼的資訊
QrCode qrCode = new QrCode();
qrCode.setActionName(QrCode.QRLIMITSCENE);
qrCode.setActionInfo(actionInfo);
// 序列化資料
Gson gson = new Gson();
String param = gson.toJson(qrCode);
System.out.println(param);
// 獲取二維碼
QrCodeService service = new QrCodeService();
String soundCode = service.getPermanentTicket(accessToken, param);
System.out.println(soundCode);
ReturnMessage returnMessage = gson.fromJson(soundCode, ReturnMessage.class);
System.out.println(returnMessage);
}
// {"ticket":"gQF38TwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyZzczZGdLSlJmM2sxMDAwMHcwMzEAAgSLWPJaAwQAAAAA","url":"http:\/\/weixin.qq.com\/q\/02g73dgKJRf3k10000w031"}
}
返回資訊
2 用ticket獲取二維碼
https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET
ticket替換成自己獲取的ticket(左為臨時,右為永久)
掃碼推送事件
1.首先確保你的微信公眾號或則測試號已經接入自己的專案中,具體流程參考
2、推送事件
3. 後臺事件獲取(部分程式碼)
String event = map.get("Event");
// 返回的xml
String result = "";
// 訂閱事件
if (null != event && event.equals("subscribe")) {
result = new MessageService().subscribeHandle(map);
// 取消訂閱事件
} else if (null != event && event.equals("unsubscribe")) {
result = "退訂";
// 掃碼事件
} else if(null != event && event.equals("SCAN")){
}else {
if (null != keyWord && keyWord.equals("圖片")) {
result = new MessageService().imageHandle(map);
} else if (null != keyWord && keyWord.equals("圖文")) {
result = new MessageService().ArticleHandle(map);
} else {
result = new MessageService().textHandle(map);
}
}
大體思路就是獲取微信伺服器向我們專案推送的xml資料,具體資料上述截圖中已列出,針對不同的事件做出不同的相應。