介绍
微信官网小程序二维码API:https://developers.weixin.qq.com/miniprogram/dev/api/qrcode.html
为满足不同需求和场景,这里提供了三个接口,开发者可挑选适合自己的接口。
A接口,生成小程序码,可接受path参数较长,生成个数受限。
B接口,生成小程序码,可接受页面参数较短,生成个数不受限。
C接口,生成二维码,可接受path参数较长,生成个数受限。
接口A:https://api.weixin.qq.com/wxa/getwxacode?access_token=ACCESS_TOKEN
接口B:https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN
该接口主要用于获取二维码(不带参数)
接口C:https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=ACCESS_TOKEN
注意事项
代码
1.获取小程序token、生成小程序二维码 工具类
import com.alibaba.fastjson.JSONObject; import javax.servlet.http.HttpServletRequest; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.util.LinkedHashMap; import java.util.Map; public class CreateQrcore { /* * 获取 token * 普通的 get 可获 token */ public static String getToken() { try { Map<String, String> map = new LinkedHashMap<>(); map.put("grant_type", "client_credential"); map.put("appid", "appid"); map.put("secret", "secret"); String rt = UrlUtil.sendPost("https://api.weixin.qq.com/cgi-bin/token", map); System.out.println("what is:" + rt); JSONObject json = JSONObject.parseObject(rt); if (json.getString("access_token") != null || json.getString("access_token") != "") { return json.getString("access_token"); } else { return null; } } catch (Exception e) { e.printStackTrace(); return null; } } /** * 生成带参小程序二维码 * * @param scene 要输入的内容 * @param accessToken token */ public static void postMiniqrQr(String scene, String accessToken, String path) { try { URL url = new URL("https://api.weixin.qq.com/wxa/getwxacode?access_token=" + accessToken); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); // conn.setConnectTimeout(10000);//连接超时 单位毫秒 // conn.setReadTimeout(2000);//读取超时 单位毫秒 // 发送POST请求必须设置如下两行 httpURLConnection.setDoOutput(true); // 打开写入属性 httpURLConnection.setDoInput(true); // 打开读取属性 httpURLConnection.setRequestMethod("POST");// 提交方式 // 不得不说一下这个提交方式转换!!真的坑。。改了好长时间!!一定要记得加响应头 httpURLConnection.setRequestProperty("Content-Type", "application/x-javascript; charset=UTF-8");// 设置响应头 // 获取URLConnection对象对应的输出流 PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream()); // 发送请求参数 JSONObject paramJson = new JSONObject(); // paramJson.put("scene", scene); // 你要放的内容 paramJson.put("path", "pages/index/index?scene=" + scene); paramJson.put("width", 430); // 宽度 paramJson.put("auto_color", true); printWriter.write(paramJson.toString()); // flush输出流的缓冲 printWriter.flush(); BufferedInputStream bis = new BufferedInputStream(httpURLConnection.getInputStream()); File file = new File(path); if (!file.exists()) { file.mkdir(); } //创建一个空文件 OutputStream os = new FileOutputStream(new File(path + scene + ".jpg")); //ByteArrayOutputStream os = new ByteArrayOutputStream(); int len; byte[] arr = new byte[1024]; while ((len = bis.read(arr)) != -1) { os.write(arr, 0, len); os.flush(); } os.close(); // 上传云储存 //InputStream is = new ByteArrayInputStream(os.toByteArray()); //retMap = UploadUtils.upload(is); } catch (Exception e) { e.printStackTrace(); } } /* * 获取 二维码图片 * */ public static String getminiqrQr(String accessToken, HttpServletRequest request, String serialNum) { String p = "E://code"; //二维码生产的地址 本地F盘code文件夹 System.out.println(p); String codeUrl = p + "/" + serialNum + ".png"; String twoCodeUrl = serialNum + ".png"; try { URL url = new URL("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + accessToken); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setRequestMethod("POST");// 提交模式 // conn.setConnectTimeout(10000);//连接超时 单位毫秒 // conn.setReadTimeout(2000);//读取超时 单位毫秒 // 发送POST请求必须设置如下两行 httpURLConnection.setDoOutput(true); httpURLConnection.setDoInput(true); // 获取URLConnection对象对应的输出流 PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream()); // 发送请求参数 JSONObject paramJson = new JSONObject(); paramJson.put("scene", serialNum);//这就是你二维码里携带的参数 String型 名称不可变 paramJson.put("path", "pages/index/index"); //这是设置扫描二维码后跳转的页面 paramJson.put("width", 430); paramJson.put("is_hyaline", false); paramJson.put("auto_color", false); System.out.println("httpURLConnection" + httpURLConnection); System.out.println("paramJson.toString()" + paramJson.toString()); printWriter.write(paramJson.toString()); // flush输出流的缓冲 printWriter.flush(); //开始获取数据 BufferedInputStream bis = new BufferedInputStream(httpURLConnection.getInputStream()); OutputStream os = new FileOutputStream(new File(codeUrl)); int len; byte[] arr = new byte[1024]; while ((len = bis.read(arr)) != -1) { os.write(arr, 0, len); os.flush(); } os.close(); } catch (Exception e) { e.printStackTrace(); } return codeUrl; } }
2.添加水印工具类
import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; public class WaterMarkUtils { private static BufferedImage image; private static int imageWidth = 430; //图片的宽度 private static int imageHeight = 480; //图片的高度 //生成图片文件 @SuppressWarnings("restriction") public static void createImage(String fileLocation) { BufferedOutputStream bos = null; if (image != null) { try { FileOutputStream fos = new FileOutputStream(fileLocation); bos = new BufferedOutputStream(fos); // JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos); // encoder.encode(image); ImageIO.write(image, "jpg", bos); bos.close(); } catch (Exception e) { e.printStackTrace(); } finally { if (bos != null) {//关闭输出流 try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } } public static void graphicsGeneration(String scene, String path) { int H_title = 50; //头部高度 int H_mainPic = 430; //轮播广告高度 image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB); //设置图片的背景色 Graphics2D main = image.createGraphics(); main.setColor(Color.white); main.fillRect(0, 0, imageWidth, imageHeight); //***********************页面头部 Graphics title = image.createGraphics(); //设置区域颜色 title.setColor(new Color(255, 255, 255)); //填充区域并确定区域大小位置 title.fillRect(0, 0, imageWidth, H_title); //设置字体颜色,先设置颜色,再填充内容 title.setColor(Color.BLACK); //设置字体 Font titleFont = new Font("楷体", Font.BOLD, 40); title.setFont(titleFont); FontMetrics fm = sun.font.FontDesignMetrics.getMetrics(titleFont); int x = (430 - fm.stringWidth(scene)) / 2; title.drawString(scene, x, (H_title) / 2 + 20); //***********************插入中间广告图 Graphics mainPic = image.getGraphics(); BufferedImage bimg = null; try { bimg = javax.imageio.ImageIO.read(new java.io.File(path + scene + ".jpg")); } catch (Exception ignored) { } if (bimg != null) { mainPic.drawImage(bimg, 0, H_title, imageWidth, H_mainPic, null); mainPic.dispose(); } createImage(path + scene + ".jpg"); } public static void main(String[] args) { WaterMarkUtils cg = new WaterMarkUtils(); try { graphicsGeneration("464646", "E:\code\test.jpg"); } catch (Exception e) { e.printStackTrace(); } } }
3.打包下载工具类
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.nio.charset.Charset; import java.nio.file.Files; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Objects; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; /** * @author xqli7 * @date 2019/1/23 16:14 */ public final class ZipUtils { private static final Logger LOG = LoggerFactory.getLogger(ZipUtils.class); private static final int BUFFER = 2048; private static final int TRANS_BUFFER = 10240; private ZipUtils() { throw new IllegalStateException("Utility class"); } /** * 将存放在sourceFilePath目录下的源文件,打包成fileName名称的zip文件并存放到zipFilePath路径下 * * @param sourceFilePath 待压缩的文件路径 * @param zipFilePath 压缩后存放路径 * @param fileName 压缩后文件的名称 * @return */ public static boolean fileToZip(String sourceFilePath, String zipFilePath, String fileName) { boolean flag = false; File sourceFile = new File(sourceFilePath); if (!sourceFile.exists()) { LOG.info("待压缩的文件目录:{}不存在.", sourceFilePath); sourceFile.mkdir(); } File zipFile = new File(zipFilePath + File.separator + fileName + ".zip"); if (zipFile.exists()) { LOG.info("{}目录下存在名字为:{}.zip打包文件", zipFilePath, fileName); zipFile.delete(); } File[] sourceFiles = sourceFile.listFiles(); if (null == sourceFiles || sourceFiles.length < 1) { LOG.info("待压缩的文件目录:{}里面不存在文件,无需压缩.", sourceFilePath); } else { try ( FileOutputStream fos = new FileOutputStream(zipFile); ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(fos)) ) { byte[] bytes = new byte[TRANS_BUFFER]; loopCreateZip(sourceFiles, zos, bytes); flag = true; } catch (Exception e) { LOG.error("", e); } } return flag; } /** * 递归删除文件、文件夹 * * @param file */ public static void deleteDirectory(File file) { File[] list = file.listFiles(); int i = 0; if (list != null && list.length > 0) { for (File f : list) { if (f.isDirectory()) { //删除子文件夹 deleteDirectory(new File(f.getPath())); } else { //删除文件 f.delete(); i++; } } //重新遍历一下文件夹内文件是否已删除干净,删除干净后则删除文件夹。 if (Objects.requireNonNull(file.listFiles()).length <= 0) { file.delete(); } } } private static void loopCreateZip(File[] sourceFiles, ZipOutputStream zos, byte[] bytes) throws IOException { for (int i = 0; i < sourceFiles.length; i++) { // 创建ZIP实体,并添加进压缩包 ZipEntry zipEntry = new ZipEntry(sourceFiles[i].getName()); zos.putNextEntry(zipEntry); // 读取待压缩的文件并写进压缩包里 try ( FileInputStream fis = new FileInputStream(sourceFiles[i]); BufferedInputStream bis = new BufferedInputStream(fis, TRANS_BUFFER) ) { int read = 0; while ((read = bis.read(bytes, 0, TRANS_BUFFER)) != -1) { zos.write(bytes, 0, read); } } catch (IOException e) { LOG.error("", e); } } } /** * 读取zip包中的文本文件以及文件内容 * * @param filePath * @return * @throws IOException */ public static boolean readZipFile(String filePath) { File sourceFile = new File(filePath); if (!sourceFile.exists()) { LOG.info("待读取的文件:{}不存在.", filePath); return false; } try ( FileInputStream fis = new FileInputStream(sourceFile); ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis)); ) { ZipEntry entry; while ((entry = zis.getNextEntry()) != null) { LOG.info("Extracting:{} ", entry); // write the files to the disk write(entry, zis); } } catch (Exception e) { LOG.error("", e); } return true; } private static void write(ZipEntry entry, ZipInputStream zis) { int count; byte[] data = new byte[BUFFER]; try ( BufferedOutputStream dest = new BufferedOutputStream(new FileOutputStream(entry.getName()), BUFFER) ) { while ((count = zis.read(data, 0, BUFFER)) != -1) { dest.write(data, 0, count); } dest.flush(); } catch (Exception e) { LOG.error("", e); } } /** * 对zip文件进行解压 * * @param sourcePath 解压文件路径 * @param targetDir 解压目标地址 * @return */ @SuppressWarnings("unchecked") public static List<File> unzip(String sourcePath, String targetDir) { List<File> files = new ArrayList<>(); File targetDirFile = new File(targetDir); if (!Files.exists(targetDirFile.toPath())) { targetDirFile.mkdir(); } File file = new File(sourcePath); ZipFile zipFile = null; try { zipFile = new ZipFile(file, Charset.forName("GBK")); ZipEntry entry; File entryFile; int bufferSize = 1024; byte[] buffer = new byte[bufferSize]; Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zipFile.entries(); while (entries.hasMoreElements()) { entry = entries.nextElement(); if (entry.isDirectory()) { return null; } entryFile = new File(targetDir + File.separator + entry.getName()); try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(entryFile)); BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry)) ) { int length; while ((length = bis.read(buffer, 0, bufferSize)) != -1) { bos.write(buffer, 0, length); } bos.flush(); files.add(entryFile); } catch (Exception e) { LOG.error("文件读取出错", e); return null; } } return files; } catch (IOException e) { LOG.error("zip文件读取错误", e); return null; } finally { try { if (zipFile != null) { zipFile.close(); } } catch (IOException e) { LOG.error("流关闭异常", e); } } } /** * @param fileName 文件名 * @param path 文件保存路径(含文件名称) * @param response * @return */ public static String downLoadZip(String tempPath, HttpServletResponse response) { try { int read = 0; byte[] buffer = new byte[1024]; //创建输出流,下载zip OutputStream out = response.getOutputStream(); FileInputStream in = new FileInputStream(new File(tempPath + "test.zip")); //设置响应头,控制浏览器下载该文件 response.setHeader("Content-Type", "application/octet-stream"); response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode("test.zip", "UTF-8")); while ((read = in.read(buffer)) != -1) { out.write(buffer, 0, read); } out.flush(); out.close(); File zipFile = new File(tempPath + "/test.zip"); if (zipFile.exists()) { zipFile.delete(); } File file = new File(tempPath); deleteDirectory(file); } catch (Exception e) { System.out.println(e); } return null; } }
代码调用
@PostMapping("download") public void download(@NotBlank(message = "{required}") String serialNums, HttpServletResponse response) throws FebsException, IOException { try {
//生成token String accessToken = CreateQrcore.getToken(); System.out.println("accessToken;" + accessToken); String[] ids = serialNums.split(StringPool.COMMA); for (String serialNum : ids) { //生成二维码 CreateQrcore.postMiniqrQr(serialNum, accessToken, tempPath); //添加图片 WaterMarkUtils.graphicsGeneration(serialNum, tempPath); } //创建压缩包 ZipUtils.fileToZip(tempPath, tempPath, "test"); //下载压缩包 ZipUtils.downLoadZip(tempPath, response); } catch (Exception e) { message = "导出二维码失败"; log.error(message, e); throw new FebsException(message); } }
参考:https://blog.csdn.net/qq_36466653/article/details/80106903