1. 程式人生 > >wechat-0050,微信公眾號,帶引數的二維碼獲取與掃碼事件推送

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資料,具體資料上述截圖中已列出,針對不同的事件做出不同的相應。