小程序二维码功能总结:
因为公司小程序通过二维码分享功能业务场景比较多,二维码功能开发过程中遇到的问题也比较多,
所以做个总结,有不妥之处希望大家指正。


微信提供生成的小程序二维码接口有三个分别是:
createWXAQRCode(普通的二维码-方形)
getWXACode (小程序二维码-圆形)
getWXACodeUnlimit(小程序二维码-圆形)

这三个接口,调用的逻辑其实是一样,区别应该在于传参不同,使用场景不同,具体详情可以看官方文档:
https://developers.weixin.qq.com/miniprogram/dev/api-backend/createWXAQRCode.html

其中需要注意的地方,容易犯错的地方:
a、 调用的时候url都需要先去获取小程序对应的token,token获取正确是第一步。
b、 二维码接口参数设置这个地方坑很多。
1、比如参数path,这个参数设置的路径必须是小程序发布过的路径,没有发布过的路径就会报错,测试可以使用主页pages/index/index
2、参数width,设置二维码宽度,设置时注意它是String类型,这样写width="430" 而不是width=430。
c、通过什么方式调用这三个接口是比较重要,因为方式不同,接口返回的数据形式就不同,比如,
一种方式通过文件IO流把二维码是生成图片到本地了,但是怎么传给页面就是问题。
我更倾向于使用生成字节流的方式,这种数据形式容易被ImageIO图片io流获取,传送到oss或者直接
字节流形式返给前台比较方便。两种方式,我都会列举。具体可以看代码。


获取token的java代码:

    /** 
     * access_token是公众号的全局唯一接口调用凭据
     * */
    public String getAccessToken(){
        String accessToken = "";
        String grantType = "client_credential";// 获取access_token填写client_credential
        String appId ="xxxxxxxxxxxxx";// 第三方用户唯一凭证
        String secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";// 第三方用户唯一凭证密钥,即appsecret
        // 这个url链接地址和参数皆不能变
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=" + grantType + "&appid=" + appId + "&secret="+ secret;
        try {
            URL urlGet = new URL(url);
            HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
            http.setRequestMethod("GET"); // 必须是get方式请求
            http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            http.setDoOutput(true);
            http.setDoInput(true);
            System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
            System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
            http.connect();
            InputStream is = http.getInputStream();
            int size = is.available();
            byte[] jsonBytes = new byte[size];
            is.read(jsonBytes);
            String message = new String(jsonBytes, "UTF-8");
//            System.out.println("获取access_token返回的message:"+message);
            JsonObject demoJson = JsonUtil.parseJson(message);
            String jsonElement = demoJson.get("access_token").toString();
//            System.out.println("获取access_token返回的json:"+demoJson);
            accessToken=jsonElement;
            accessToken = accessToken.replace("\"", "");            
//            System.out.println("新获取的access_token:"+accessToken);
            is.close();
            return accessToken;
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("获取access_token发生异常");
            return null;
        }

 


请求微信接口生成二维码的java代码:
拿getwxacodeunlimit举的例子,另外两个接口,套进去同样适用。

    /**
     * 获取小程序二维码
     * @param AppID
     * @param AppSecret
     * @return
     */
    public Map<String, Object> getMiniCode(String sceneStr) {
        Map<String, Object> map = new HashMap<>();
        
        try
        {
            //获取token
            String accessToken = getAccessToken();            
            if(null==accessToken && accessToken.isEmpty()) {
                map.put("resultDesc","获取token失败");
                return map;
            }
            RestTemplate rest = new RestTemplate();
            InputStream inputStream = null;
            String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+accessToken;
            Map<String,Object> param = new HashMap<>();
            param.put("scene", sceneStr);
            param.put("page", "pages/index/index");//此路径必须是小程序发布过的
            param.put("width", 430);
            param.put("auto_color", false);
            Map<String,Object> line_color = new HashMap<>();
            line_color.put("r", 0);
            line_color.put("g", 0);
            line_color.put("b", 0);
            param.put("line_color", line_color);
//            LoggerUtil.DebugLogger.info("调用生成微信URL接口传参:" + param);
            MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
            HttpEntity requestEntity = new HttpEntity(param, headers);
            ResponseEntity<byte[]> entity = rest.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
//            LoggerUtil.DebugLogger.info("调用小程序生成微信永久小程序码URL接口返回结果:" + entity.getBody());
            byte[] result = entity.getBody();
//            LoggerUtil.DebugLogger.info(Base64.encodeBase64String(result));
            inputStream = new ByteArrayInputStream(result);
            
              //开始获取数据-写本地
//            BufferedInputStream bis = new BufferedInputStream(inputStream);
//            OutputStream os = new FileOutputStream(new File("C:/Users/xuxiaomu/Desktop/abc.png"));//生成到本地路径
//            int len;
//            byte[] arr = new byte[1024];
//            while ((len = bis.read(arr)) != -1)
//            {
//                os.write(arr, 0, len);
//               os.flush();
//            }
//            os.close();
               
              // 根据时间产生路径
              long ymdhms = DateUtil.getYYYYMMDDHHmmssByLong(new Date());
              String ext = "png";
              String userCertificateJPGName = sceneStr + "_" + ymdhms + "."+ext; // 用户的证书存放目录+文件名   
              String filePath ="ossPath"+userCertificateJPGName;//根据工具类设置上传oss的路径
            
            BufferedImage bufferedImage = ImageIO.read(inputStream);
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, ext, os);
            InputStream is = new ByteArrayInputStream(os.toByteArray());
            
            //下面这个方法是我根据公司需要把图片二进制流写到oss服务上了,返回访问的路径。前端直接访问oss存的图片路径就可以看到二维码。
            //具体情况具体分析,拿到的是图片的字节类型输入流,大家可以自行处理,比如上传到项目的静态文件夹下。然后通过https://域名:端口号/项目名称/图片名称.png就可以访问了

            String miniCodeUrl = OssOperUtil.ossUploadInputStream(is, filePath);
            map.put("codeUrl", codeUrl);return map;            
        }
        catch (Exception e)
        {
            e.printStackTrace();return null;            
        }

    }