【java】Java生成微信小程序二维码

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

文章目录

前言

应用场景

先介绍一下项目场景主要是通过微信小程序二维码裂变分享每个账号有专属邀请二维码分享出去有新人扫码入驻就可以得到现金奖励或红包奖励。当然产品设计会更丰富不止有裂变模式还有渠道推广模式还有各种奖励规则但核心实现都是生成二维码。对于如何生成微信小程序二维码本文一共列举了5种实现方式其中第4、5种是网上常见的方式第1、2、3种封装的更为优雅。

微信小程序官网

项目主要用的是微信官方提供的服务端能力考虑到涉及secret和token等安全问题所以从架构上设计的调用链路为前端->后端API->微信API。裂变的场景决定要选择获取不限制的小程序码接口永久有效数量暂无限制接口英文名getUnlimitedQRCode。

官方地址https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/qr-code/getUnlimitedQRCode.html

在这里插入图片描述

1.RestTemplate方式

这也是我们项目实际使用的方式使用Spring框架开发还是强烈推荐使用Spring的RestTemplate它是对于其它方式的高级封装内部可以配置ClientHttpRequestFactory来指定底层请求方式

  • 指定为SimpleClientHttpRequestFactory则内部使用JDK自带的HttpURLConnection方式
  • 指定为HttpComponentsClientHttpRequestFactory则内部使用Apache HttpClient方式
  • 指定为OkHttp3ClientHttpRequestFactory则内部使用okhttp3方式

核心代码

public byte[] getWechatQrcodeByRestTemplate(String url, Map<String, Object> body) {
    return restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(body, null), byte[].class).getBody();
}

另外RestTemplate在构造函数中默认增加了ByteArrayHttpMessageConverter可以读取和写入字节数组的HttpMessageConverter的实现默认情况下此转换器支持所有媒体类型(media types)。
在这里插入图片描述

getAccessToken

这是接口调用凭证用restTemplate调用也是非常简洁核心代码如下

private String wechatQrcodeUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=";
private String appid = "替换成你的appid";
private String s = "替换成你的secret";

public String getAccessToken() {
    String url = String.format(wechatAccessTokenUrl, appid, s);
    Map<String, String> responseBody = restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<Map<String, String>>() {}).getBody();
    if (responseBody == null || responseBody.get("errcode") != null) {
        // 获取失败
        System.out.println("getAccessToken失败" + (responseBody == null ? "null" : responseBody.toString()));
        return null;
    }
    return responseBody.get("access_token");
}

对于access_token建议保存到redis2小时过期后再获取

2. Unirest方式

Maven依赖

<dependency>
    <groupId>com.konghq</groupId>
    <artifactId>unirest-java</artifactId>
    <version>3.11.11</version>
</dependency>

okhttp3方式其实不管是性能还是代码的链式调用都已经非常优秀。但作为底层基于Apache HttpClient方式的unirest-java提供了更为便捷、链式调用、功能强大的API用于http请求核心代码如下一行代码搞定屌爆了

核心代码

public byte[] getWechatQrcodeByUnirest(String url, Map<String, Object> body) {
    return Unirest.post(url).body(JSONObject.toJSONString(body)).asBytes().getBody();
}

3. okhttp3方式

Maven依赖

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.14.2</version>
</dependency>

okhttp3是Square公司开发用于替代 HttpUrlConnection和Apache HttpClient方式优雅的 API 设计且链式调用让你顺滑到底

核心代码

public byte[] getWechatQrcodeByOkhttp3(String url, Map<String, Object> body) {
    OkHttpClient client = new OkHttpClient().newBuilder().build();
    okhttp3.MediaType mediaType = okhttp3.MediaType.parse("application/json");
    RequestBody requestBody = RequestBody.create(mediaType, JSONObject.toJSONString(body));
    Request request = new Request.Builder().url(url).method("POST", requestBody).build();
    try {
        Response response = client.newCall(request).execute();
        if (response.isSuccessful()) {
            return response.body().bytes();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

4. Apache的HttpClient方式

Maven依赖

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.12</version>
</dependency>

HttpClient 相比于 JDK 自带的 URLConnection方式代码做了封装可读性和简洁度都显著提升核心代码如下

核心代码

public byte[] getWechatQrcodeByHttpClient(String url, Map<String, Object> body) {
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();
    HttpPost httpPost = new HttpPost(url);
    try {
        StringEntity entity = new StringEntity(JSONObject.toJSONString(body));
        entity.setContentType("image/png");
        httpPost.setEntity(entity);
        HttpResponse response = httpClient.execute(httpPost);
        try (InputStream inputStream = response.getEntity().getContent();
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int len = -1;
            while ((len = inputStream.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            return out.toByteArray();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

5. JDK自带的URLConnection方式

在网上常见的方式这是从 JDK1.1 开始就自带的Http请求方式核心代码如下

核心代码

public byte[] getWechatQrcodeByHttpURL(String url, Map<String, Object> body) {
    HttpURLConnection httpURLConnection = null;
    try {
        httpURLConnection = (HttpURLConnection) new URL(url).openConnection();
        httpURLConnection.setRequestMethod("POST");
        // 发送POST请求必须设置如下两行
        httpURLConnection.setDoOutput(true);
        httpURLConnection.setDoInput(true);
        // 获取URLConnection对象对应的输出流
        PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
        // 发送请求参数
        printWriter.write(JSONObject.toJSONString(body));
        // flush输出流的缓冲
        printWriter.flush();
        //开始获取数据
        try (InputStream inputStream = httpURLConnection.getInputStream();
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int len = -1;
            while ((len = inputStream.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            return out.toByteArray();
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (httpURLConnection != null) {
            httpURLConnection.disconnect();
        }
    }
    return null;
}

JDK自带的方式功能虽然可以实现但代码看上去确实跟不上时代发展了

其它细节

构建参数map

body 就是参数Map需要根据实际情况自行设定

Map<String,Object> body = new HashMap<>();
// 场景码与前端约定最终是需要前端解析
body.put("scene", scene);
// 正式版为 "release"体验版为 "trial"开发版为 "develop"。默认是正式版。
body.put("env_version", envVersion);
// 透明根据你的场景自行设置body参数
body.put("is_hyaline", true);

在这里插入图片描述

byte[]数组

为什么要先得到byte[]数组因为我们需要先判断返回结果是否包含errcode如果不包含才是图片Buffer!

如果不包含errorCode那么byte[]数组不管是保存本地还是转成Base64或者上传到OSS都非常湿滑了

  • 保存本地
private void saveQrCodeToLocal(byte[] bytes) {
    try {
        InputStream inputStream = new ByteArrayInputStream(bytes);
        FileOutputStream out = new FileOutputStream("d:\\test.png");
        byte[] buffer = new byte[8192];
        int bytesRead = 0;
        while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
            out.write(buffer, 0, bytesRead);
        }
        out.flush();
        inputStream.close();
        out.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
  • Base64
Base64.getEncoder().encodeToString(bytes);
  • 上传OSS
    这是我们项目使用的, 底层做了封装直接传byte[]即可非常方便

❤️ 博客主页https://blog.csdn.net/u011397981
❤️ 欢迎点赞👍 收藏 ⭐留言✏️ 如有错误敬请指正
❤️ 本文由 逆流°只是风景 原创首发于 CSDN博客🙉
❤️ 停下休息的时候不要忘了别人还在奔跑希望大家抓紧时间学习全力奔赴更美好的生活

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Java