Java微信公众平台开发之生成带参二维码(Spring Boot 2.X)

时间:2024-03-02 16:15:30

微信官方提供的生成二维码接口得到的是当前公众号的二维码官方文档(一定要先看)
目前有2种类型的二维码:
临时二维码,是有过期时间的,最长可以设置为在二维码生成后的30天(即2592000秒)后过期,但能够生成较多数量,主要用于帐号绑定等不要求二维码永久保存的业务场景
永久二维码,是无过期时间的,但数量较少(目前为最多10万个),主要用于适用于帐号绑定、用户来源统计等场景
获取带参数的二维码有两种方法
先获取二维码ticket,然后凭借ticket通过接口换取二维码图片,但是得到ticket之前首先得获取微信全局唯一接口调用凭据
根据微信返回二维码中url参数自行生成二维码

一、获取微信全局接口调用凭证

调用接口时,请登录“微信公开发-基本配置”提前将服务器IP地址添加到IP白名单中,否则将无法调用成功!!!

二、获取二维码的Ticket

 /**
     * 创建临时带参数二维码
     *
     * @param accessToken
     * @param sceneId     场景Id
     * @return
     * @expireSeconds 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。
     */
    @Override
    public String createTempTicket(String accessToken, int sceneId, int expireSeconds) {
        TreeMap<String, String> params = new TreeMap<>();
        params.put("access_token", accessToken);
        // output data
        JsonObject data = new JsonObject();
        data.addProperty("action_name", QRCodeConstant.QR_SCENE);
        data.addProperty("expire_seconds", expireSeconds);
        JsonObject scene = new JsonObject();
        scene.addProperty("scene_id", sceneId);
        JsonObject actionInfo = new JsonObject();
        actionInfo.add("scene", scene);
        data.add("action_info", actionInfo);
        String result = HttpUtil.doPost(WechatQRCodeConfig.getCreateTicketUrl(), params, data.toString());
        WechatQRCode qrcode = JsonUtil.fromJson(result, WechatQRCode.class);
        return qrcode == null ? null : qrcode.getTicket();
    }
 
    /**
     * 创建临时带参数二维码(字符串)
     *
     * @param accessToken
     * @param sceneStr    场景Id
     * @return
     * @expireSeconds 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。
     */
    @Override
    public String createTempTicket(String accessToken, String sceneStr, int expireSeconds) {
        TreeMap<String, String> params = new TreeMap<>();
        params.put("access_token", accessToken);
        // output data
        JsonObject data = new JsonObject();
        data.addProperty("action_name", QRCodeConstant.QR_STR_SCENE);
        data.addProperty("expire_seconds", expireSeconds);
        JsonObject scene = new JsonObject();
        scene.addProperty("scene_str", sceneStr);
        JsonObject actionInfo = new JsonObject();
        actionInfo.add("scene", scene);
        data.add("action_info", actionInfo);
        String result = HttpUtil.doPost(WechatQRCodeConfig.getCreateTicketUrl(), params, data.toString());
        WechatQRCode qrcode = JsonUtil.fromJson(result, WechatQRCode.class);
        return qrcode == null ? null : qrcode.getTicket();
    }
 
    /**
     * 创建永久二维码(数字)
     *
     * @param accessToken
     * @param sceneId     场景Id
     * @return
     */
    @Override
    public String createForeverTicket(String accessToken, int sceneId) {
        TreeMap<String, String> params = new TreeMap<>();
        params.put("access_token", accessToken);
        // output data
        JsonObject data = new JsonObject();
        data.addProperty("action_name", QRCodeConstant.QR_LIMIT_SCENE);
        JsonObject scene = new JsonObject();
        scene.addProperty("scene_id", sceneId);
        JsonObject actionInfo = new JsonObject();
        actionInfo.add("scene", scene);
        data.add("action_info", actionInfo);
        String result = HttpUtil.doPost(WechatQRCodeConfig.getCreateTicketUrl(), params, data.toString());
        WechatQRCode qrcode = JsonUtil.fromJson(result, WechatQRCode.class);
        return qrcode == null ? null : qrcode.getTicket();
    }
 
    /**
     * 创建永久二维码(字符串)
     *
     * @param accessToken
     * @param sceneStr    场景str
     * @return
     */
    @Override
    public String createForeverTicket(String accessToken, String sceneStr) {
        TreeMap<String, String> params = new TreeMap<>();
        params.put("access_token", accessToken);
        // output data
        JsonObject data = new JsonObject();
        data.addProperty("action_name", "QR_LIMIT_STR_SCENE");
        JsonObject actionInfo = new JsonObject();
        JsonObject scene = new JsonObject();
        scene.addProperty("scene_str", sceneStr);
        actionInfo.add("scene", scene);
        data.add("action_info", actionInfo);
        String result = HttpUtil.doPost(WechatQRCodeConfig.getCreateTicketUrl(), params, data.toString());
        WechatQRCode qrcode = JsonUtil.fromJson(result, WechatQRCode.class);
        return qrcode == null ? null : qrcode.getTicket();
    }

三、二维码长链接转成短链接

微信返回正确的二维码的结果,参数有个url,即二维码图片解析后的地址,也可以根据此URL生成需要的二维码图片,而不需要通过ticket去换取图片了

  /**
     * 长链接转短链接
     *
     * @param accessToken
     * @param longUrl     长链接
     * @return
     */
    private String toShortQRCodeurl(String accessToken, String longUrl) {
        TreeMap<String, String> params = new TreeMap<>();
        params.put("access_token", accessToken);
        JsonObject data = new JsonObject();
        data.addProperty("action", QRCodeConstant.LONG_TO_SHORT);
        data.addProperty("long_url", longUrl);
        String result = HttpUtil.doPost(WechatQRCodeConfig.getShortQrcodeUrl(),
                params, data.toString());
        WechatQRCodeShortUrl wechatQRCodeShortUrl = JsonUtil.fromJson(result, WechatQRCodeShortUrl.class);
        return wechatQRCodeShortUrl == null ? null : wechatQRCodeShortUrl.getShortUrl();
    }

四、通过ticket凭证直接获取二维码

   /**
     * 获取二维码ticket后,通过ticket换取二维码图片展示
     *
     * @param accessToken
     * @param ticket
     * @param isShortUrl  是否需要展示
     * @return
     */
    @Override
    public String showQrCode(String accessToken, String ticket, boolean isShortUrl) {
        String url = String.format(WechatQRCodeConfig.getShowQrcodeUrl(), EncodeUtils.urlEncode(ticket));
        if (isShortUrl) {
            return toShortQRCodeurl(accessToken, url);
        }
        return url;
    }

五、扫描带参数二维码事件推送

推送的XML信息通过之前开发者中心处设置的服务器地址获得,故得先接入

已关注推送XML示例

<xml><ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
<EventKey><![CDATA[qrscene_123123]]></EventKey>
<Ticket><![CDATA[TICKET]]></Ticket>
</xml>

EventKey 事件KEY值,qrscene_为前缀,后面为二维码的参数值

未关注推送XML示例

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[SCAN]]></Event>
<EventKey><![CDATA[SCENE_VALUE]]></EventKey>
<Ticket><![CDATA[TICKET]]></Ticket>
</xml>

EventKey 事件KEY值,是一个32位无符号整数,即创建二维码时的二维码scene_id

具体源码:https://github.com/philjing/my_wechat