小程序二维码功能总结:
因为公司小程序通过二维码分享功能业务场景比较多,二维码功能开发过程中遇到的问题也比较多,
所以做个总结,有不妥之处希望大家指正。
微信提供生成的小程序二维码接口有三个分别是:
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("resultCode", BossResultCode.DATANOEXIST); map.put("resultDesc", RunnarBossConstant.resultCode.get(BossResultCode.GETTOKENCODEFAIL)); 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<>(); if(null==sceneStr) { sceneStr="a=runnar567"; } param.put("scene", sceneStr); //param.put("page", "pages/index/index");//跳转主页 param.put("page", "web/pages/wishListShare/wishListShare");//此路径必须是发布成功的 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 =RunnarBossConstant.userMiniCodeDir+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.ossUploadInputStreamWithoutDomain(is, filePath); map.put("miniCodeUrl", miniCodeUrl); map.put("resultCode", BossResultCode.SUCCESS); map.put("resultDesc", RunnarBossConstant.resultCode.get(BossResultCode.SUCCESS)); return map; } catch (Exception e) { e.printStackTrace(); LoggerUtil.DebugLogger.info("二维码上传oss失败:"+e.getMessage()); return null; } }