微信公衆號生成帶參數二維碼跳轉關注與未關注以及事件推送

首先說下業務場景
需要從某個頁面生成二維碼,用戶掃描二維碼,如果已關注公衆號,跳到公衆號頁面,推送小程序鏈接
如果還未關注公衆號,跳轉到關注頁面,關注公衆號後推送小程序鏈接。
當然從公衆號跳轉到小程序,多多少少是需要帶一點業務相關參數的。
本篇主要將二維碼生成,以及事件推送

一、二維碼生成

根據官方文檔介紹,目前公衆號二維碼主要有永久和臨時兩種,但是永久二維碼是有數量限制的,臨時二維碼攜帶參數又有限制。
所以我們一般都使用臨時二維碼
官方介紹
生成二維碼的動作主要有兩步,第一步根據參數拿到二維碼ticket,第二步根據ticket換取二維碼

首先看獲取二維碼的參數
二維碼參數
拼接結構如下:{“action_name”: “QR_LIMIT_SCENE”, “action_info”: {“scene”: {“scene_id”: 123}}}
注意scene是在action_info 裏面的
請求URL爲 :https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN 類型爲POST
返回數據是這樣的
{“ticket”:“gQH47joAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL2taZ2Z3TVRtNzJXV1Brb3ZhYmJJAAIEZ23sUwMEmm
3sUw==”,“expire_seconds”:60,“url”:“http://weixin.qq.com/q/kZgfwMTm72WWPkovabbI”}
下面上具體代碼

/**
     * 創建臨時帶參二維碼
     *
     * @param accessToken   接口訪問憑證
     * @param expireSeconds 二維碼有效時間,單位爲秒,最大不超過1800
     * @param sceneId       場景ID
     * @return WeixinQRCode
     */
    public WeixinQRCode createTemporaryQRCode(String accessToken, int expireSeconds, String sceneStr) {
        QRCodeParMapping byMappingValue = qrCodeParamMappingUtil.getQrcodeParMappingByMappingValue(sceneStr);
        Integer mappingID = null;
        if (byMappingValue == null) {
            byMappingValue = new QRCodeParMapping();
            byMappingValue.setMappingValue(sceneStr);
            qrCodeParamMappingUtil.save(byMappingValue);
        }
        mappingID = byMappingValue.getMappingID();
        sceneStr = mappingID.toString();
        System.out.println("二維碼攜帶參數爲" + sceneStr);
        WeixinQRCode weixinQRCode = null;
        // 拼接請求地址
        String requestUrl = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=ACCESS_TOKEN";
        requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken);
        // 需要提交的json數據
        String jsonMsg = "{\"expire_seconds\": %d, \"action_name\": \"QR_SCENE\", \"action_info\": {\"scene\": {\"scene_id\": %s}}}";
        // 創建臨時帶參二維碼
        JSONObject jsonObject = WechatUtil.httpsRequest(requestUrl, "POST",
                String.format(jsonMsg, expireSeconds, sceneStr));

        if (null != jsonObject) {
            try {
                weixinQRCode = new WeixinQRCode();
                weixinQRCode.setTicket(jsonObject.getString("ticket"));
                weixinQRCode.setExpireSeconds(jsonObject.getInt("expire_seconds"));
                logger.info("創建臨時帶參二維碼成功 ticket:{} expire_seconds:{}", weixinQRCode.getTicket(),
                        weixinQRCode.getExpireSeconds());
            } catch (Exception e) {
                weixinQRCode = null;
                int errorCode = jsonObject.getInt("errcode");
                String errorMsg = jsonObject.getString("errmsg");
                logger.error("創建臨時帶參二維碼失敗 errcode:{} errmsg:{}", errorCode, errorMsg);
            }
        }
        return weixinQRCode;
    }

	/**
     * 發起https請求並獲取結果
     *
     * @param requestUrl    請求地址
     * @param requestMethod 請求方式(GET、POST)
     * @param outputStr     提交的數據
     * @return JSONObject(通過JSONObject.get ( key)的方式獲取json對象的屬性值)
     */
    public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        StringBuffer buffer = new StringBuffer();
        try {
            // 創建SSLContext對象,並使用我們指定的信任管理器初始化
            TrustManager[] tm = {new MyX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 從上述SSLContext對象中得到SSLSocketFactory對象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
            httpUrlConn.setSSLSocketFactory(ssf);

            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);
            // 設置請求方式(GET/POST)
            httpUrlConn.setRequestMethod(requestMethod);

            if ("GET".equalsIgnoreCase(requestMethod))
                httpUrlConn.connect();

            // 當有數據需要提交時
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意編碼格式,防止中文亂碼
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 將返回的輸入流轉換成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 釋放資源
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();
            jsonObject = JSONObject.fromObject(buffer.toString());
        } catch (ConnectException ce) {
            log.error("Weixin server connection timed out.");
        } catch (Exception e) {
            log.error("https request error:{}", e);
        }
        return jsonObject;
    }
/**
 * 臨時二維碼信息
 * 
 * @author liufeng
 * @date 2013-11-10
 */
public class WeixinQRCode {
	// 獲取的二維碼ticket
	private String ticket;
	// 二維碼的有效時間,單位爲秒,最大不超過1800
	private int expireSeconds;

	public String getTicket() {
		return ticket;
	}

	public void setTicket(String ticket) {
		this.ticket = ticket;
	}

	public int getExpireSeconds() {
		return expireSeconds;
	}

	public void setExpireSeconds(int expireSeconds) {
		this.expireSeconds = expireSeconds;
	}
}

一共兩個方法  一個類
第一個方法是生成二維碼的步驟,三個參數:1、accessToken 請自備2、過期時間 3、二維碼攜帶參數
第二個方法是訪問微信的GET請求
第三個二維碼實體類

這裏要額外說一個事情,
第一個查詢映射的方法,是幹什麼的
首先上面參數有說過,二維碼可攜帶參數有scene_id 和scene_str  但是臨時二維碼 只能用ID(關乎於後面的事件推送) 並且是32位非零整型,長度有限制,所以個人做了個參數映射,生成二維碼碼的參數在數據庫關聯一個ID,每次ID自增,每次傳參要查詢是否有對應的ID,沒有就生成一個新的
這部分邏輯很簡單先不上代碼了,如不需要,可自行註釋代碼,有需要可能後面會補。

這樣我們就拿到了二維碼的ticket
獲取二維碼就很簡單了
通過訪問鏈接就可以直接拿到二維碼
官方是這麼寫的:
HTTP GET請求(請使用https協議)https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET
提醒:TICKET記得進行UrlEncode
ticket正確的情況下,狀態碼200,是一張圖片可以下載。錯誤的話可能是404

這裏額外再說一句,那個攜帶參數,即使是它不支持或者超出限制了,二維碼仍然會正常返回,但是參數不會正常攜帶到後面的事件裏面

二、事件接收以及消息推送

首先說事件接收,這個事件接收是一個很廣的概念,可以接收很多類型的事件,官方是這麼寫的
事件
事件推送的URL需要在公衆號後臺自行配置,是一個URL哦~不同的事件按照分類進行區別開發
二維碼的推送參數如下:
事件參數
這是我代碼中打印的 已關注用戶推送的
在這裏插入圖片描述
根據這個我們能拿到二維碼攜帶過來的參數 就是Eventkey。
未關注用戶推送的:
在這裏插入圖片描述
注意未關注用戶的參數前面帶一個qrscene_ 獲取時自行截取

事件到了 我們需要做處理
這裏返回的不是模版消息,是客服消息
看官方文檔
在這裏插入圖片描述
消息類型是這樣,我的需求是要跳轉到小程序 並沒有鏈接類型
所以就使用文本類型,裏面自己嵌入鏈接,官方給出了方法

發送文本消息時,支持插入跳小程序的文字鏈

文本內容<a href="http://www.qq.com" data-miniprogram-appid="appid" data-miniprogram-path="pages/index/index">點擊跳小程序</a>
說明: 1.data-miniprogram-appid 項,填寫小程序appid,則表示該鏈接跳小程序; 2.data-miniprogram-path項,填寫小程序路徑,路徑與app.json中保持一致,可帶參數; 3.對於不支持data-miniprogram-appid 項的客戶端版本,如果有herf項,則仍然保持跳href中的網頁鏈接; 4.data-miniprogram-appid對應的小程序必須與公衆號有綁定關係。

下一篇詳細介紹怎麼回消息以及代碼~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章