Explorar o código

添加微信短链生成二维码的二进制流

hxl13994548489 hai 6 meses
pai
achega
ccde0d7cc9

+ 31 - 6
linkwe-auth/src/main/java/com/linkwechat/web/controller/system/WeGroupFissionController.java

@@ -5,6 +5,7 @@ import com.linkwechat.common.annotation.InnerAuth;
 import com.linkwechat.common.core.controller.BaseController;
 import com.linkwechat.common.core.domain.AjaxResult;
 import com.linkwechat.common.core.page.TableDataInfo;
+import com.linkwechat.common.utils.QrCodeGenerator;
 import com.linkwechat.common.utils.QrcodeUtils;
 import com.linkwechat.domain.weGroupFission.dto.DistDto;
 import com.linkwechat.domain.weGroupFission.dto.WeGroupFissionDetailDto;
@@ -21,7 +22,9 @@ import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 
@@ -252,12 +255,34 @@ public class WeGroupFissionController extends BaseController {
         if(StringUtils.isBlank(createWechatGroupFissionUrlVo.getVersion())){
             return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("版本不能为空:".getBytes());
         }
-        try{
-            String url = weGroupFissionService.getWechatGroupFissionUrl(createWechatGroupFissionUrlVo);
-            byte[] qrcodeBytes = QrcodeUtils.qrcodeUrlToBytes(url);
-            return QrcodeUtils.returnQrcodeToFront(qrcodeBytes);
-        }catch (Exception e){
-            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("获取失败:".getBytes());
+        try {
+            String wechatUrl = weGroupFissionService.getWechatGroupFissionUrl(createWechatGroupFissionUrlVo);
+            log.info("生成二维码的微信链接:{}", wechatUrl);
+            byte[] qrcodeBytes = QrCodeGenerator.createQrCode(wechatUrl, "PNG", 300, 300);
+
+            HttpHeaders headers = new HttpHeaders();
+            headers.setContentType(MediaType.IMAGE_PNG);
+            headers.setContentLength(qrcodeBytes.length);
+            return new ResponseEntity<>(qrcodeBytes, headers, HttpStatus.OK);
+        } catch (Exception e) {
+            log.error("生成微信打卡二维码失败", e);
+            String errorMsg = "生成微信打卡二维码失败:" + e.getMessage();
+            return buildErrorResponse(errorMsg, HttpStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    /**
+     * 统一构建错误响应
+     */
+    private ResponseEntity<byte[]> buildErrorResponse(String errorMsg, HttpStatus status) {
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.TEXT_PLAIN);
+        try {
+            // 明确指定UTF-8编码,避免中文乱码
+            return new ResponseEntity<>(errorMsg.getBytes("UTF-8"), headers, status);
+        } catch (Exception e) {
+            // 兜底:使用默认编码
+            return new ResponseEntity<>(errorMsg.getBytes(), headers, status);
         }
     }
 }

+ 13 - 0
linkwe-common/pom.xml

@@ -333,6 +333,19 @@
             <artifactId>okhttp</artifactId>
             <version>4.4.1</version>
         </dependency>
+
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+            <version>3.5.2</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+            <version>3.5.2</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 
     <build>

+ 190 - 0
linkwe-common/src/main/java/com/linkwechat/common/utils/QrCodeGenerator.java

@@ -0,0 +1,190 @@
+
+package com.linkwechat.common.utils;
+
+import cn.hutool.core.codec.Base64;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.google.zxing.*;
+import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
+import com.google.zxing.client.j2se.MatrixToImageConfig;
+import com.google.zxing.client.j2se.MatrixToImageWriter;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.common.HybridBinarizer;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import org.springframework.stereotype.Component;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.Hashtable;
+
+/**
+ *  @version
+ *  @Description:  生成二维码的工具类型
+ */
+@Component
+public class QrCodeGenerator {
+    private static final String DEFAULT_CHAR_SET = "UTF-8";
+    private static final String DEFAULT_FORMAT_NAME = "JPG";
+    private static String EXCEL_PATH = "QRCode/";
+    private static String UPLOAD_PATH = "/upload/QRCode/";
+
+    // 二维码宽度
+    private static final int DEFAULT_QR_CODE_WIDTH = 200;
+    // 二维码高度
+    private static final int DEFAULT_QR_CODE_HEIGHT = 200;
+
+    /**
+     * 创建BitMatrix比特矩阵
+     * @Date 2023/09/24 22:29
+     * @Param contents 二维码里的内容
+     * @Param width 二维码宽度
+     * @Param height 二维码高度
+     * @return com.google.zxing.common.BitMatrix
+     */
+    public static BitMatrix createBitMatrix(String contents, int width, int height) throws WriterException, IOException {
+        if (ObjectUtil.isNull(width)) {
+            width = DEFAULT_QR_CODE_WIDTH;
+        }
+        if (ObjectUtil.isNull(height)) {
+            height = DEFAULT_QR_CODE_HEIGHT;
+        }
+
+        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
+        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 纠错等级L,M,Q,H
+        hints.put(EncodeHintType.CHARACTER_SET, DEFAULT_CHAR_SET); // 编码utf-8
+        hints.put(EncodeHintType.MARGIN, 1); // 边距
+
+        // 创建比特矩阵
+        BitMatrix bitMatrix = new MultiFormatWriter().encode(contents,
+                BarcodeFormat.QR_CODE, width, height, hints);
+        return bitMatrix;
+    }
+
+    /**
+     * 创建二维码,返回字节数组
+     * @Date 2023/09/24 22:30
+     * @Param contents 二维码里的内容
+     * @Param imageFormat 图片后缀名
+     * @Param width 二维码宽度
+     * @Param height 二维码高度
+     * @return byte[]
+     */
+    public static byte[] createQrCode(String contents, String imageFormat, int width, int height) throws WriterException, IOException {
+        if (StrUtil.isBlank(imageFormat)) {
+            imageFormat = DEFAULT_FORMAT_NAME;
+        }
+        BitMatrix bitMatrix = createBitMatrix(contents, width, height);
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        MatrixToImageWriter.writeToStream(bitMatrix, imageFormat, os);
+        return os.toByteArray();
+    }
+
+    /**
+     * 创建二维码,返回base64字符串
+     * @Date 2023/09/24 22:30
+     * @Param contents 二维码里的内容
+     * @Param imageFormat 图片后缀名
+     * @Param width 二维码宽度
+     * @Param height 二维码高度
+     * @return byte[]
+     */
+    public static String createQrCodeBase64(String contents, String imageFormat, int width, int height) throws WriterException, IOException {
+        byte[] bytes = createQrCode(contents, imageFormat, width, height);
+        return Base64.encode(bytes);
+    }
+
+    /**
+     * 解码二维码
+     * @Date 2023/09/24 22:32
+     * @Param [image]
+     * @return java.lang.String
+     */
+    public static String decodeQrCode(BufferedImage image) throws Exception {
+        if (image == null) return StrUtil.EMPTY;
+        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
+        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
+        Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
+        hints.put(DecodeHintType.CHARACTER_SET, DEFAULT_CHAR_SET);
+        Result result = new MultiFormatReader().decode(bitmap, hints);
+        return result.getText();
+    }
+
+    /**
+     * 转换为BufferedImage
+     * @Date 2023/09/24 22:32
+     * @Param [bitMatrix]
+     * @return java.awt.image.BufferedImage
+     */
+    public static BufferedImage toBufferedImage(BitMatrix bitMatrix) throws IOException, WriterException {
+        MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);
+        BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix, matrixToImageConfig);
+        return bufferedImage;
+    }
+
+    /**
+     * 给二维码添加logo
+     * @Date 2023/09/24 22:33
+     * @Param [bufferedImage, logoFile]
+     * @return java.awt.image.BufferedImage
+     */
+    public static BufferedImage addQrCodeLogo(BufferedImage bufferedImage, File logoFile) throws IOException {
+        Graphics2D graphics = bufferedImage.createGraphics();
+        int matrixWidth = bufferedImage.getWidth();
+        int matrixHeigh = bufferedImage.getHeight();
+
+        // 读取logo图片文件
+        BufferedImage logo = ImageIO.read(logoFile);
+        int logoWidth = logo.getWidth();
+        int logoHeight = logo.getHeight();
+
+        //  计算logo放置位置
+        int x = bufferedImage.getWidth() / 5 * 2;
+        int y = bufferedImage.getHeight() / 5 * 2;
+        int width = matrixWidth / 5;
+        int height = matrixHeigh / 5;
+
+        // 开始绘制图片
+        graphics.drawImage(logo, x, y, width, height, null);
+        graphics.drawRoundRect(x, y, logoWidth, logoHeight, 15, 15);
+        graphics.setStroke(new BasicStroke(5.0F, 1, 1));
+        graphics.setColor(Color.white);
+        graphics.drawRect(x, y, logoWidth, logoHeight);
+
+        graphics.dispose();
+        bufferedImage.flush();
+        return bufferedImage;
+    }
+
+    /**
+     *  @version
+     *  @author: hxl
+     *  @Date: 2024/8/13 17:55
+     *  @Description: 返回二维码图片路径
+     */
+    public static String getQrCode(String orderNo,  String url, String uploadPath) {
+        BufferedImage bufferedImage = null;
+        String fileName = orderNo + "_" + "_rwm.jpg"; // 修复文件名生成逻辑
+        String saveFilePath = uploadPath + "/" + EXCEL_PATH + fileName;
+        String resultPath = "/" + EXCEL_PATH + fileName; // 返回相对路径
+
+        // 创建File对象
+        File dir = new File(uploadPath + File.separator + EXCEL_PATH).getAbsoluteFile(); // 获取绝对路径
+        // 判断目录是否存在
+        if (!dir.exists() && !dir.mkdirs()) {
+            throw new RuntimeException("目录不存在或创建失败,请重试!!");
+        }
+
+        try {
+            bufferedImage = toBufferedImage(createBitMatrix(url, 300, 300));
+            ImageIO.write(bufferedImage, "jpg", new File(saveFilePath)); // 修改为"jpg"以匹配文件名
+        } catch (Exception e) {
+            throw new RuntimeException("转为二维码报错,请重试!!", e);
+        }
+
+        return resultPath;
+    }
+}