Java获取小程序码示例(三种小程序码)

news2025/2/24 15:16:01

首先我们可以看到官方文档上是有三种码的 获取小程序码

在这里插入图片描述

这里特别要注意的是第一种和第三种是有数量限制的,所以大家生成的时候记得保存,也不要一直瞎生成

还有一点要注意的是第一种和第二种是太阳码

在这里插入图片描述

第三种是方形码

在这里插入图片描述

好了直接上代码
这里要注意,它请求成功返回的是一个 base64 的图片流,但是失败返回的是JSON字符串,我这里没有处理请求失败的问题

package com.sakura.user.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sakura.common.exception.BusinessException;
import com.sakura.common.redis.RedisUtil;
import com.sakura.common.tool.HttpsRequestUtil;
import com.sakura.common.tool.StringUtil;
import com.sakura.user.param.GetAppCodeParam;
import com.sakura.user.vo.wx.WxAccessTokenVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * @author Sakura
 * @date 2024/8/22 11:04
 * 微信小程序工具类
 */
@Component
@Slf4j
public class WxAppUtil {

    @Value("${wx.app.appid}")
    private String appid;

    @Value("${wx.app.secret}")
    private String secret;

    // 获取授权token
    private static final String GET_TOKEN = "https://api.weixin.qq.com/cgi-bin/token";

    private static final String WX_APP_ACCESS_TOKEN = "wx_app_access_token";

    // 获取小程序码URL
    private static final String GET_APP_CODE_URL = "https://api.weixin.qq.com/wxa/getwxacode";

    // 获取不受限制的小程序码
    private static final String GET_UNLIMITED_APP_CODE_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit";

    private static final String GET_APP_QR_CODE_URL = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode";

    @Autowired
    private RedisUtil redisUtil;

    // 获取授权凭证
    public String getAccessToken() {
        // 优先从Redis获取,没有再调接口
        // 如果Redis里面有则直接取Redis里面的
        if (redisUtil.hasKey(WX_APP_ACCESS_TOKEN)) {
            log.info(redisUtil.get(WX_APP_ACCESS_TOKEN).toString());
            return redisUtil.get(WX_APP_ACCESS_TOKEN).toString();
        }
        // 拼接请求参数
        StringBuilder strUrl = new StringBuilder();
        strUrl.append(GET_TOKEN)
                .append("?grant_type=client_credential")
                .append("&appid=").append(appid)
                .append("&secret=").append(secret);
        try {
            String resultStr = HttpsRequestUtil.sendGetRequest(strUrl.toString());
            log.info("【微信小程序获取授权凭证】:返回结果:" + resultStr);
            WxAccessTokenVo wxAccessTokenVo = JSON.parseObject(resultStr, WxAccessTokenVo.class);
            if (StringUtil.isBlank(wxAccessTokenVo.getAccess_token())) {
                throw new BusinessException("微信小程序获取授权凭证异常");
            }

            //官方 access_token expires_in 为 2个小时, 这里设置 100分钟
            redisUtil.set(WX_APP_ACCESS_TOKEN, wxAccessTokenVo.getAccess_token(), 100 * 60);

            return wxAccessTokenVo.getAccess_token();
        } catch (Exception e) {
            log.info("【微信小程序获取授权凭证】:获取异常:" + e.getMessage());
            e.printStackTrace();
            throw new BusinessException("微信小程序获取授权凭证异常");
        }
    }

    // 获取小程序码
    public byte[] getAppCode(GetAppCodeParam getAppCodeParam) {
        // 先要获取access_token
        String accessToken = getAccessToken();
        // 拼接请求参数
        StringBuilder strUrl = new StringBuilder();
        strUrl.append(GET_APP_CODE_URL)
                .append("?access_token=")
                .append(accessToken);

        // 封装请求参数到body
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("path", getAppCodeParam.getPath());
        if (StringUtil.isNotBlank(getAppCodeParam.getEnvVersion())) {
            jsonObject.put("env_version", getAppCodeParam.getEnvVersion());
        }
        if (getAppCodeParam.getWidth() != null) {
            jsonObject.put("width", getAppCodeParam.getWidth());
        }
        if (getAppCodeParam.getIsHyaline() != null) {
            jsonObject.put("is_hyaline", getAppCodeParam.getIsHyaline());
        }

        try {
            return HttpsRequestUtil.sendPostReturnByte(strUrl.toString(), jsonObject.toJSONString());
        } catch (Exception e) {
            log.info("【微信小程序获取小程序码】:获取小程序码异常:" + e.getMessage());
            e.printStackTrace();
            throw new BusinessException("微信小程序获取小程序码异常");
        }
    }

    // 获取无限制的小程序码
    public byte[] getUnlimitedAppCode(GetAppCodeParam getAppCodeParam) {
        // 先要获取access_token
        String accessToken = getAccessToken();
        // 拼接请求参数
        StringBuilder strUrl = new StringBuilder();
        strUrl.append(GET_UNLIMITED_APP_CODE_URL)
                .append("?access_token=")
                .append(accessToken);

        // 封装请求参数到body
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("scene", getAppCodeParam.getScene());
        if (StringUtil.isNotBlank(getAppCodeParam.getPage())) {
            jsonObject.put("page", getAppCodeParam.getPage());
        }
        if (StringUtil.isNotBlank(getAppCodeParam.getEnvVersion())) {
            jsonObject.put("env_version", getAppCodeParam.getEnvVersion());
        }
        if (getAppCodeParam.getWidth() != null) {
            jsonObject.put("width", getAppCodeParam.getWidth());
        }
        if (getAppCodeParam.getIsHyaline() != null) {
            jsonObject.put("is_hyaline", getAppCodeParam.getIsHyaline());
        }
        if (getAppCodeParam.getCheckPath() != null) {
            jsonObject.put("check_path", getAppCodeParam.getCheckPath());
        }

        try {
            return HttpsRequestUtil.sendPostReturnByte(strUrl.toString(), jsonObject.toJSONString());
        } catch (Exception e) {
            log.info("【微信小程序获取不限制小程序码】:获取不限制小程序码异常:" + e.getMessage());
            e.printStackTrace();
            throw new BusinessException("微信小程序获取不限制小程序码异常");
        }
    }

    // 获取小程序二维码
    public byte[] getAppQRCode(GetAppCodeParam getAppCodeParam) {
        // 先要获取access_token
        String accessToken = getAccessToken();
        // 拼接请求参数
        StringBuilder strUrl = new StringBuilder();
        strUrl.append(GET_APP_QR_CODE_URL)
                .append("?access_token=")
                .append(accessToken);

        // 封装请求参数到body
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("path", getAppCodeParam.getPath());
        if (getAppCodeParam.getWidth() != null) {
            jsonObject.put("width", getAppCodeParam.getWidth());
        }

        try {
            return HttpsRequestUtil.sendPostReturnByte(strUrl.toString(), jsonObject.toJSONString());
        } catch (Exception e) {
            log.info("【微信小程序获取小程序二维码】:获取小程序二维码异常:" + e.getMessage());
            e.printStackTrace();
            throw new BusinessException("微信小程序获取小程序二维码异常");
        }
    }
}

http 工具类

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * @author Sakura
 * @date 2024/6/24 17:07
 */
public class HttpsRequestUtil {

    public static String sendPostRequest(String urlString, String jsonInputString) throws IOException {
        URL url = new URL(urlString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        // 设置请求方法为POST
        connection.setRequestMethod("POST");

        // 设置请求头
        connection.setRequestProperty("Content-Type", "application/json");
        connection.setRequestProperty("Accept", "application/json");

        // 启用输出流,用于发送请求数据
        connection.setDoOutput(true);

        try (OutputStream os = connection.getOutputStream()) {
            byte[] input = jsonInputString.getBytes("utf-8");
            os.write(input, 0, input.length);
        }

        // 获取响应
        try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) {
            StringBuilder response = new StringBuilder();
            String responseLine;
            while ((responseLine = br.readLine()) != null) {
                response.append(responseLine.trim());
            }
            return response.toString();
        } finally {
            // 关闭连接
            connection.disconnect();
        }
    }

    public static String sendGetRequest(String urlString) throws IOException {
        URL url = new URL(urlString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        // 设置请求方法为GET
        connection.setRequestMethod("GET");

        // 设置请求头
        connection.setRequestProperty("Accept", "application/json");

        // 获取响应
        try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) {
            StringBuilder response = new StringBuilder();
            String responseLine;
            while ((responseLine = br.readLine()) != null) {
                response.append(responseLine.trim());
            }
            return response.toString();
        } finally {
            // 关闭连接
            connection.disconnect();
        }
    }

    public static byte[] sendPostReturnByte(String urlString, String jsonInputString) throws IOException {
        URL url = new URL(urlString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        // 设置请求方法为POST
        connection.setRequestMethod("POST");

        // 设置请求头
        connection.setRequestProperty("Content-Type", "application/json");
        connection.setRequestProperty("Accept", "application/json");

        // 启用输出流,用于发送请求数据
        connection.setDoOutput(true);

        try (OutputStream os = connection.getOutputStream()) {
            byte[] input = jsonInputString.getBytes("utf-8");
            os.write(input, 0, input.length);
        }

        // 获取响应
        try (InputStream is = connection.getInputStream()) {
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            int bytesRead;
            byte[] data = new byte[1024];
            while ((bytesRead = is.read(data, 0, data.length)) != -1) {
                buffer.write(data, 0, bytesRead);
            }
            return buffer.toByteArray();
        } finally {
            // 关闭连接
            connection.disconnect();
        }
    }

}

请求的参数

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;

import javax.validation.constraints.NotNull;
import java.io.Serializable;

/**
 * 获取小程序码参数
 *
 * @author Sakura
 * @since 2024-08-26
 */
@Data
@Accessors(chain = true)
@ApiModel(value = "获取小程序码参数")
public class GetAppCodeParam implements Serializable {
    private static final long serialVersionUID = 1L;

    @ApiModelProperty("类型:1小程序码 2不受限制小程序码 3小程序二维码")
    @NotNull(message = "小程序码类型不能为空")
    private Integer type;

    @ApiModelProperty("type为1.3时必传 扫码进入的小程序页面路径")
    private String path;

    @ApiModelProperty("type为1.2时可传 要打开的小程序版本。正式版为 \"release\",体验版为 \"trial\",开发版为 \"develop\"。默认是正式版。")
    private String envVersion;

    @ApiModelProperty("二维码宽度 默认430,二维码的宽度,单位 px,最小 280px,最大 1280px")
    private Integer width;

    @ApiModelProperty("type为2时必传 自定义参数最大32个可见字符 如 a=1")
    private String scene;

    @ApiModelProperty("type为2时可传 默认是true,检查page 是否存在,为 true 时 page 必须是已经发布的小程序存在的页面(否则报错);为 false 时允许小程序未发布或者 page 不存在, 但page 有数量上限(60000个)请勿滥用。")
    private Boolean checkPath;

    @ApiModelProperty("type为2时可传 默认是主页,页面 page,例如 pages/index/index,根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面。scancode_time为系统保留参数,不允许配置")
    private String page;

    @ApiModelProperty("type为1.2时可传 默认值false;是否需要透明底色,为 true 时,生成透明底色的小程序码")
    private Boolean isHyaline;

}

还有因为返回的是个流,所以我们还需要把它转成图片保存起来,这里大家可以上传到云存储也可就放在服务器上,我这里就是放在服务器上的,在本地项目或者服务器 jar 包目录下 “./resources/files/appcode”

	@Override
    public String getAppCode(GetAppCodeParam getAppCodeParam) throws Exception {
        // 根据类型获取不同二维码
        byte[] bytes = null;
        if (getAppCodeParam.getType() == 1) {
            bytes = wxAppUtil.getAppCode(getAppCodeParam);
        } else if (getAppCodeParam.getType() == 2) {
            bytes = wxAppUtil.getUnlimitedAppCode(getAppCodeParam);
        } else if (getAppCodeParam.getType() == 3) {
            bytes = wxAppUtil.getAppQRCode(getAppCodeParam);
        }
        if (bytes == null || bytes.length < 1) {
            throw new BusinessException("获取小程序码失败");
        }
        // 目标目录
        String outputDir = "./resources/files/appcode";

        // 创建目录(如果不存在)
        File directory = new File(outputDir);
        if (!directory.exists()) {
            directory.mkdirs();
        }

        // 生成图片文件的完整路径
        String outputFileName = RandomStringUtils.randomAlphanumeric(32);
        String outputFilePath = outputDir + "/" + outputFileName + ".png";

        // 将字节数组写入到图片文件中
        try (FileOutputStream fos = new FileOutputStream(outputFilePath)) {
            fos.write(bytes);
        }

        return "https://sakura.com/api-wx/appCode/download/" + outputFileName;
    }

因为图片存在服务器上了,我们还需要下载下来
看不懂的可以看下我另一篇讲什么上传下载文件的 Java实现本地文件上传下载接口示例

 @Override
    public void download(HttpServletResponse response, String code) throws Exception {
        File downloadFile = new File("./resources/files/appcode/" + code + ".png");
        if (!downloadFile.exists() || downloadFile.length() == 0) {
            throw new BusinessException(500, "文件不存在");
        }

        // 确定文件的Content-Type
        String mimeType = Files.probeContentType(downloadFile.toPath());
        if (mimeType == null) {
            mimeType = "application/octet-stream"; // 默认类型
        }

        response.setContentType(mimeType);
        response.addHeader("Content-Length", String.valueOf(downloadFile.length()));
        response.addHeader("Content-Disposition", "attachment; filename=\"" + code + ".png\"");

        try (InputStream is = new FileInputStream(downloadFile);
             OutputStream os = response.getOutputStream()) {

            IOUtils.copy(is, os);
            os.flush(); // 确保数据已写入输出流
        } catch (IOException e) {
            log.info("下载图片发生IO异常");
            e.printStackTrace();
            throw new BusinessException(500, "文件下载失败");
        } catch (Exception e) {
            log.info("下载图片发生异常");
            e.printStackTrace();
            throw new BusinessException(500, "文件下载失败");
        }
    }

最后,小程序获取 AccessToken 是需要添加白名单的,然后第二种码在小程序没发布的时候 check_path 一定要传 false,默认是 true 会报错的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2112190.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

南京网站设计手机用的网站

近年来&#xff0c;随着移动互联网的快速发展&#xff0c;越来越多的用户通过手机浏览网页&#xff0c;这使得网站设计逐渐向移动端倾斜。在南京&#xff0c;网站设计特别注重适配手机端&#xff0c;这不仅是用户体验的提升&#xff0c;也是市场竞争的需要。一个响应式的网站能…

深度评测热门翻译工具,携手你的翻译得力助手

随着互联网技术的飞速发展&#xff0c;全球化交流日益频繁&#xff0c;跨语言沟通的需求也随之激增。对于外语水平有限的朋友来说&#xff0c;翻译器是一个必不可少的工具。今天我就分享几款我用的翻译器吧。 1.福晰在线翻译 链接直达>>https://fanyi.pdf365.cn/doc …

Java语言的Netty框架+云快充协议1.5+充电桩系统+新能源汽车充电桩系统源码

介绍 云快充协议云快充1.5协议云快充1.6云快充协议开源代码云快充底层协议云快充桩直连桩直连协议充电桩协议云快充源码 软件架构 1、提供云快充底层桩直连协议&#xff0c;版本为云快充1.5&#xff0c;对于没有对接过充电桩系统的开发者尤为合适&#xff1b; 2、包含&…

WebAPI (一)DOM树、DOM对象,操作元素样式(style className,classList)。表单元素属性。自定义属性。间歇函数定时器

文章目录 Web API基本认知一、 变量声明二、 DOM1. DOM 树2. DOM对象3. 获取DOM对象(1)、选择匹配的第一个元素(2)、选择匹配多个元素 三、 操作元素1. 操作元素内容2. 操作元素属性(1)、常用属性&#xff08;href之类的&#xff09;(2)、通过style属性操作CSS(3)、通过类名(cl…

Vivado 约束

步骤5&#xff1a;保存约束 约束管理是设计流程的重要一步&#xff0c;Vivado设计套件 为您提供了在现有约束文件中添加新约束、覆盖的灵活性 现有约束&#xff0c;或创建新的约束文件以跟踪设计更改或完成 缺少约束。 您为设计创建了一些定时异常&#xff0c;但这些异常仅存在…

​​NIFI汉化_替换logo_二次开发_Idea编译NIFI最新源码_详细过程记录_全解析_Maven编译NIFI避坑指南002

继续,执行pom.xml引入依赖以后,发现以下几种报错: 可以看到在下载aws-java-sdk-bundle 1.12.710版本的时候报错了 可以看到日志信息,就是在阿里云上下载的,因为阿里云上缺少这个jar包 aws-java-sdk-bundle-1.12.710.jar 这个jar包,我还特意去阿里云上查询了一下 https://deve…

从零到一:Java三层架构下的图书馆管理系统开发指南

引言 使用JavaSE相关知识完成一个以三层架构为设计规范的图书管理系统&#xff0c;不包括前端页面&#xff08;使用main方法Scanner()模拟用户输入&#xff09;&#xff0c;目的是为了基于一个项目快速了解三层架构的项目设计规范的实践。 开发流程 确认需求导入相关的jar包和…

jmeter 梯度测试 如何查看TPS、RT指标

TPS 服务器处理请求总数/花费的总时间 149371 &#xff08;请求量&#xff09; 113&#xff08;1分53秒&#xff09;1321/秒 跟汇总报告的吞吐量差不多&#xff0c;可以认为吞吐量TPS 平均值&#xff0c;中位数&#xff0c;最大值&#xff0c;最小值的单位都是毫秒ms 下载插…

用Git把本地仓库上传到远程仓库

用Git把本地仓库上传到远程仓库 GitHub创建远程仓库 在创建新仓库界面里输入你的仓库名后点击Create repository就好了。 创建本地项目 当你已经有一个项目后在命令行输入如下指令即可 git init git commit -m "first commit" git branch -M main git remote a…

寄存器映射及地址计算(STM32F407)

上篇文章介绍了存储器映射&#xff08;存储器映射&#xff08;STM32F407&#xff09;-CSDN博客&#xff09;&#xff0c;本文介绍寄存器映射的基本概念。 1、寄存器映射简介 寄存器是一类特殊的存储器&#xff0c;它的每个位都有特定的功能&#xff0c;可以实现对外设/功能的…

ubuntu16.04下qt5.7.1添加对openssl的支持

文章目录 前言一、编译安装openssl二、编译qt5.7.1三、配置qtcreator开发环境四、demo 前言 最近工作中要求客户端和服务端通过ssl加密通信,其中客户端是qt编程,服务端是linux编程.我的开发环境是ubuntu16.04;运行环境是debian9.13,是基于gnu的linux操作系统,64位arm架构. 一…

【数据库】|子查询

子查询 什么叫子查询&#xff1f;如何实现子查询&#xff1f; 定义&#xff1a;什么叫子查询&#xff0c;也就是先执行子查询&#xff0c;后执行父查询 ❓✅面试题&#xff1a;如何实现替换&#xff0c;执行顺序&#xff1f; 1、使用子查询&#xff0c;因为子查询会先执行子…

大语言模型LLM权重4bit向量量化(Vector Quantization)/查找表量化基本原理

参考 https://apple.github.io/coremltools/docs-guides/source/opt-palettization-overview.html https://apple.github.io/coremltools/docs-guides/source/opt-palettization-algos.html Apple Intelligence Foundation Language Models 苹果向量量化&#xff1a; DKM:…

深度学习基础--卷积的变种

随着卷积同经网络在各种问题中的广泛应用&#xff0c;卷积层也逐渐衍生出了许多变种&#xff0c;比较有代表性的有&#xff1a; 分组卷积( Group Convolution )、转置卷积 (Transposed Convolution) 、空洞卷积( Dilated/Atrous Convolution )、可变形卷积( Deformable Convolu…

协程的原理与实现:GMP源码走读

在计算机科学领域&#xff0c;尤其是在现代软件开发中&#xff0c;高并发处理能力是衡量技术架构性能的关键指标之一。Go语言&#xff0c;以其简洁的语法和内置的协程支持&#xff0c;为开发者提供了一套高效且易于使用的并发编程模型。本文深入剖析了Go语言协程的原理与其实现…

erlang学习:用ETS和DETS存储数据3,保存元组到磁盘

学习内容 ETS表把元组保存在内存里&#xff0c;而DETS提供了把Erlang元组保存到磁盘上的方法。DETS的最大文件大小是2GB。DETS文件必须先打开才能使用&#xff0c;用完后还应该正确关闭。如果没有正确关闭&#xff0c;它们就会在下次打开时自动进行修复。因为修复可能会花很长…

软件测试学习笔记丨Pytest的使用

本文转自测试人社区&#xff0c;原文链接&#xff1a;https://ceshiren.com/t/topic/22158 1. 简介 pytest是一个成熟的全功能python测试框架测试用例的skip和xfail&#xff0c;自动失败重试等处理能够支持简单的单元测试和复杂的功能测试&#xff0c;还可以用来做selenium/ap…

路由器的固定ip地址是啥意思?固定ip地址有什么好处

‌在当今数字化时代&#xff0c;‌路由器作为连接互联网的重要设备&#xff0c;‌扮演着举足轻重的角色。‌其中&#xff0c;‌路由器的固定IP地址是一个常被提及但可能让人困惑的概念。‌下面跟着虎观代理小二一起将深入探讨路由器的固定IP地址的含义&#xff0c;‌揭示其背后…

元学习之如何学习

首先第一个步骤&#xff08;如图1所示&#xff09;是我们的学习算法里要有一些要被学的东西&#xff0c;就像在 机器学习里面神经元的权重和偏置是要被学出来的一样。在元学习里面&#xff0c;我们通常会考虑要 让机器自己学习网络的架构&#xff0c;让机器自己学习初始化的参数…

echarts 水平柱图 科技风

var category [{ name: "管控", value: 2500 }, { name: "集中式", value: 8000 }, { name: "纳管", value: 3000 }, { name: "纳管", value: 3000 }, { name: "纳管", value: 3000 } ]; // 类别 var total 10000; // 数据…