小工具      在线工具  汉语词典  css  js  c++  java

Java生成微信小程序二维码,5种实现方式,每一种都比上一种简单

java,微信小程序,小程序,微信,二维码,http 额外说明

收录于:40天前


前言

先介绍一下项目场景,主要是通过微信小程序二维码裂变分享,每个账号有专属邀请二维码,分享出去,有新人扫码入驻,就可以得到现金奖励或红包奖励。当然,产品设计会更丰富,不止有裂变模式,还有渠道推广模式,还有各种奖励规则,但核心实现都是生成二维码。对于如何生成微信小程序二维码,本文一共列举了5种实现方式,其中1 型和 2 型是网上常见的方式,类型 3、4 和 5封装的更为优雅,文章结束可打包下载全套源代码开箱即用,我更期待老铁的文末 投票 :哪种方式你更喜欢?
请添加图片描述


先看官网

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

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

在这里插入图片描述


一、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自带的功能都可以实现,但是代码似乎跟不上时代的发展!


二、Apache的HttpClient方式

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;
}

Maven 依赖项:

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

三、okhttp3方式

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;
}

Maven 依赖项:

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

四、Unirest方式

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();
}

Maven 依赖项:

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

五、RestTemplate方式

我之前写过一篇博文对RestTemplate.exchange合并案例进行了详细的介绍:RestTemplate.exchange的各种用法(包括泛型等——全部),推荐阅读!

这也是我们项目实际使用情况的方式,使用Spring框架开发,还是强烈推荐使用Spring的RestTemplate,它是对于其它方式的先进封装,内部可以配置客户端HttpRequestFactory来指定底层请求方式:

  • 指定为SimpleClientHttpRequestFactory,则内部使用JDK自带的HttpURL连接方式
  • 指定为HttpComponentsClientHttpRequestFactory,则内部使用Apache HttpClient方式
  • 指定为OkHttp3ClientHttpRequestFactory,则内部使用好的http3方式

核心代码也是一行:

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,建议保存到redis,2小时过期后获取。

构建参数map

身体 就是参数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://download.csdn.net/download/scm_2008/87398320

❤️ 博客主页:https://blog.csdn.net/scm_2008
❤️ 欢迎喜欢- 收集信息✏️ 如有错误敬请指正!
❤️ 本文由 天罡格 原创,首发于 CSDN博客-
❤️ 停下休息的时候不要忘了别人还在奔跑,希望大家抓紧时间学习,全力奔赴更美好的生活


. . .

相关推荐

额外说明

如何在微服务框架中创建新的子模块?

本章教程,主要介绍如何利用若依微服务框架新建一个子模块。   目录 1、在ruoyi-modules下新建业务模块目录  2、新建目录和添加依赖文件

额外说明

junit学习(三)——junit测试失败的两种情况

junit测试失败的两种情况:一个是Failure,一个是Error。 先上测试代码: package com.wjl.junit; import static org.junit.Assert.*; import org.junit.Test; /

额外说明

强化学习基础篇【1】:基础知识点、马尔科夫决策过程、蒙特卡洛策略梯度定理、REINFORCE 算法

【强化学习原理+项目专栏】必看系列:单智能体、多智能体算法原理+项目实战、相关技巧(调参、画图等、趣味项目实现、学术应用项目实现 专栏详细介绍:【强化学习原理+项目专栏】必看系列:单智能体、多智能体算法原理+项目实战、相关技巧(调参、画图等、趣味项目实现

额外说明

我的创作纪念日-四周年

机缘         我是老寇,我接触CSDN是在大一的时候,因为一些个人原因,我缺了几个月的课,但是这丝毫不影响到我,因此,我开启了自学模式,疯狂学习Java知识,其中,大部分知识是在CSDN上面查找的,在这里说一声:感谢CSDN! 收获 1.认识很多

额外说明

智能机器人与AI助手:未来办公场景的变革者

文章目录 智能机器人与AI助手:概念与区别 智能机器人 AI助手 智能机器人的应用领域 制造业 医疗保健 农业 服务业 智能机器人的未来趋势 自主决策能力的提升 协作与互操作性 个性化定制 环境感知与适应性 结论 -欢迎来到AIGC人工智能专栏~智能机器

额外说明

[爱分享]Linux命令——cd

cd命令 cd 命令可以说是Linux中最基本的命令语句,其他的命令语句要进行操作,都是建立在使用 cd 命令上的。所以一定要学好这个命令。 1.命令格式: cd[目录名] 2.命令功能:切换当前目录至dirName 3.常用范例: 3.1 例一:进入系

额外说明

2_2 c++ 链表节点的定义,创建, 以及删除;

#include <stdio.h> #include <stdlib.h> //#include <cstdio> //#include <vector> #include<iostream> #include<cstdlib> using names

额外说明

Apache Beam构建批处理任务

在之前的博客中我介绍了如何用Beam来构建一个实时处理Kafka消息的流处理任务,Apache Beam构建流处理任务_gzroy的博客-CSDN博客,这次我将介绍一下如何构建批处理的任务。对于不同的业务场景来说,我们需要选择一个合适的方案,并不是说只有

额外说明

golang 快速为项目添加插件功能

golang 快速为项目添加插件功能 首先,了解下go自带的plugin包,其中open方法会返回plugin.Plugin的指针,和error pluginer, err := plugin.Open("your plugin file path")

额外说明

【Python篇】Python基础--Python基本操作

【Python篇】Python基础–Python基本操作 前言  啦啦啦,现在开始,打算做一期Python基础教程,欢迎大家来看哦! 导读  这期文章真的是Python基础中的基础,相信有一定编程基础的小伙伴们都一定能看懂的…  本文共分为以下几个部分:

ads via 小工具