微信公众号生成带参数二维码跳转关注与未关注以及事件推送

首先说下业务场景
需要从某个页面生成二维码,用户扫描二维码,如果已关注公众号,跳到公众号页面,推送小程序链接
如果还未关注公众号,跳转到关注页面,关注公众号后推送小程序链接。
当然从公众号跳转到小程序,多多少少是需要带一点业务相关参数的。
本篇主要将二维码生成,以及事件推送

一、二维码生成

根据官方文档介绍,目前公众号二维码主要有永久和临时两种,但是永久二维码是有数量限制的,临时二维码携带参数又有限制。
所以我们一般都使用临时二维码
官方介绍
生成二维码的动作主要有两步,第一步根据参数拿到二维码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对应的小程序必须与公众号有绑定关系。

下一篇详细介绍怎么回消息以及代码~

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