调用微信wxacode.getUnlimited API获取小程序菊花码,有处理返回的错误信息

最近项目需要一个获取微信小程序菊花码的接口,查看了官方文档,发现有两个获取菊花码的api:wxacode.getwxacode.getUnlimited

这两个的区别的主要是wxacode.get用的path, path最大长度 128 字节,有数量限制

wxacode.getUnlimited用scene且最大32个可见字符,只支持数字,大小写英文以及部分特殊字符,path不支持带参数,数量暂无限制

共同点就是生成的菊花码永久有效,这里我根据我的业务需求选择的是wxacode.getUnlimited

但是官方文档描述的不是那么容易明白,只能从网上去找下别人做的示例,但是我发现其他人写的都没有把返回的错误信息给转换出来,例如,小程序没有发布或者page页面找不到的话,他返回的是json格式的错误信息的。如果不小心把这串信息给转换成图片,图片是肯定打不开的。

下面是我项目中用到的基本没啥问题的逻辑,供大家参考。

1.首先需要获取微信的access_token

注意的是这个token的时效是两个小时,而且一旦获取就会被刷新,所以我这里做的操作是把生成的access_token放到Redis,然后用appid来做主键,然后设置过期时间7150s

/**
     * 获取微信accesstoken
     *
     * @param wxappid
     * @param wxappkey
     * @return
     */
    @Override
    public ResultMsg getWxAcesstoken(String wxappid, String wxappkey) {
        ResultMsg msg=new ResultMsg();
        logger.info("活跃accesstoken:appid="+wxappid);
        String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+wxappid+"&secret="+wxappkey;
        if (redisUtil.isExists("wxaccesstoken_"+wxappid)){
            msg.setData(redisUtil.getString("wxaccesstoken_"+wxappid));
            msg.setResult(true);
            return msg;
        }
        try {
            String jsonstr = httpClient.request(tokenUrl);
            JSONObject jsonObject =JSON.parseObject(jsonstr);
            if (jsonObject.containsKey("access_token")){
                String accesstoken=jsonObject.getString("access_token");
                redisUtil.save("wxaccesstoken_"+wxappid,accesstoken,7150);
                msg.setData(accesstoken);
                msg.setResult(true);
                return msg;
            }else{
                msg.setErrorMsg("未获取到token");
                msg.setResult(false);
                return msg;
            }

        }catch (Exception e){
            getLogger().error("获取token异常:",e);
            msg.setResult(false);
            msg.setErrorMsg(e.getLocalizedMessage());
            return msg;
        }
    }
注:这里的ResultMsg是我们项目中统一的数据返回格式。

2.第二步就是http请求

我根据需求又重写了一个方法,返回的格式是ByteArrayInputStream,它是一个访问数组的字节输入流

public static ByteArrayInputStream sendPost(String URL, String json) {
        InputStream inputStream = null;
        ByteArrayInputStream byteArrayInputStream = null;
        // 创建默认的httpClient实例.
        CloseableHttpClient httpclient = HttpClients.createDefault();
        // 创建httppost
        HttpPost httppost = new HttpPost(URL);
        httppost.addHeader("Content-type", "application/json; charset=utf-8");
        httppost.setHeader("Accept", "application/json");
        try {
            StringEntity s = new StringEntity(json, Charset.forName("UTF-8"));
            s.setContentEncoding("UTF-8");
            httppost.setEntity(s);
            HttpResponse response = httpclient.execute(httppost);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                // 获取相应实体
                HttpEntity entity = response.getEntity();
                inputStream = entity.getContent();
                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                // 创建一个Buffer字符串
                byte[] buffer = new byte[1024];
                // 每次读取的字符串长度,如果为-1,代表全部读取完毕
                int len = 0;
                // 使用一个输入流从buffer里把数据读取出来
                while ((len = inputStream.read(buffer)) != -1) {
                    // 用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
                    outStream.write(buffer, 0, len);
                }
                // 关闭输入流
                inputStream.close();
                // 把outStream里的数据写入内存
                byteArrayInputStream = new ByteArrayInputStream(outStream.toByteArray());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭连接,释放资源
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return byteArrayInputStream;
    }

3.第三步就是用来生成菊花码的逻辑了

/**
     * 获取小程序菊花码
     * @Description //TODO
     * @Author zhaowx
     * @Date 2020/3/25 15:23
     **/
    @Override
    public ResultMsg getWXCode() {
        ResultMsg msg = new ResultMsg();
        try {
            //这里调用的是上面的获取access_token方法
            ResultMsg wxAcesstoken = userService.getWxAcesstoken(appid,secret);
            if (!wxAcesstoken.getResult() || StringUtils.isBlank(wxAcesstoken.getData().toString()) || wxAcesstoken.getData() == null){
                return wxAcesstoken;
            }
            String access_token = (String) wxAcesstoken.getData();
            String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+access_token;
            String scene = "p="+phone;
            Map<String, String> param = new HashMap<>();
            param.put("scene",scene);
            //这里的page如果没有的话可以不写,默认是跳主页,如果写了没有的页面的话,会返回错误信息
            param.put("page","pages/webview/index");
            String json = JSON.toJSONString(param);
            ByteArrayInputStream inputStream = httpClient.sendPost(url, json);
            //这里判断的是返回的图片还是错误信息,一般错误信息不会大于200
            if (inputStream.available() <= 200){
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                int i;
                byte[] buffer = new byte[200];
                while ((i = inputStream.read(buffer)) != -1){
                    byteArrayOutputStream.write(buffer,0,i);
                }
                String str = new String(byteArrayOutputStream.toByteArray());
                //错误信息的格式在官方文档里有
                JSONObject jsonObject = JSONObject.parseObject(str);
                if ("41030".equals(jsonObject.getString("errcode"))){
                    msg.setResult(false);
                    msg.setMsg("所传page页面不存在,或者小程序没有发布");
                }else if ("45009".equals(jsonObject.getString("errcode"))){
                    msg.setResult(false);
                    msg.setMsg("调用分钟频率受限");
                }
                byteArrayOutputStream.close();
                return msg;
            }
            //这里我选择是上传到了oss,你也可以选择输出到本地
            String fileName = "noilCode_userNo"+".jpeg";
            String path = "wxcode/noilCode";
            String imgUrl = ossClientUtil.UploadImgAndReturnImgUrlInputStream(inputStream, fileName, path);
            //输出到本地的代码
             FileOutputStream fileOutputStream = new FileOutputStream("D:/123.png");
            int i;
            byte[] buffer = new byte[200];
            while ((i = inputStream.read(buffer)) != -1){
                fileOutputStream.write(buffer,0,i);
            }
            fileOutputStream.flush();
            fileOutputStream.close();
            
            inputStream.close();
            msg.setMsg("菊花码生成成功");
            msg.setResult(true);
        }catch (Exception e){
            msg.setMsg("获取菊花码异常");
            msg.setResult(false);
        }
        return msg;
    }

到这里基本就完成了,生成的小程序图片我就不贴出来了。

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值