文章目录
- 自定义支付二维码
- pom.xml
- application.yml
- 自定义二维码类
- AlipayService.java
- AlipayServiceImpl.java
- AlipayController.java
- qrCode.html
自定义支付二维码
继:SpringBoot支付入门
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<!--
ZXing(Zebra Crossing)核心库,提供了二维码生成和解析的基本功能
-->
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.1</version>
</dependency>
<!--
ZXing 的 JavaSE 扩展库,提供了在 Java 环境中生成和解析二维码的更高级功能,
例如将二维码保存为图像文件、从图像文件解析二维码等。
-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.4.1</version>
</dependency>
application.yml
spring:
thymeleaf:
enabled: true # 启用Thymeleaf
cache: false # 禁用Thymeleaf缓存,方便开发时查看修改的效果
prefix: classpath:/static/html/ # Thymeleaf模板文件所在目录,默认classpath:/static/html/
suffix: .html # Thymeleaf模板文件的后缀,默认为.html
自定义二维码类
package com.sin.demo.utils;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/**
* @createTime 2024/4/17 10:07
* @createAuthor SIN
* @use 二维码创建工具类
*/
public class QRCodeUtil {
private static final int WIDTH = 300; // 二维码宽度
private static final int HEIGHT = 300; // 二维码高度
private static final String FORMAT = "png"; // 二维码格式
/**
* 生成二维码
* @param text 二维码内容,一定是互联网内容,本地是无法扫的到的
* @param filePath 二维码生成地址
*/
public static void generateQRCode(String text, String filePath) {
try {
// 创建一个存储编码参数的 HashMap 对象
Map<EncodeHintType, Object> hints = new HashMap<>();
// 设置字符集为 UTF-8
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
// 设置容错级别为 M
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
// 设置边距为 2
hints.put(EncodeHintType.MARGIN, 2);
// 使用 MultiFormatWriter 类将指定文本 text 编码为二维码矩阵
BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, WIDTH, HEIGHT, hints);
// 将二维码矩阵转换为 BufferedImage 对象
BufferedImage image = toBufferedImage(bitMatrix);
// 创建一个表示目标文件的 File 对象
File file = new File(filePath);
// 将 BufferedImage 对象保存为图像文件
ImageIO.write(image, FORMAT, file);
System.out.println("二维码已生成,保存路径:" + filePath);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 将二维码矩阵转为可视化图像
* @param matrix
* @return 生成BufferdImage对象,获得二维码的可视化图像
*/
private static BufferedImage toBufferedImage(BitMatrix matrix) {
// 获取二维码的宽和高
int width = matrix.getWidth();
int height = matrix.getHeight();
// 创建一个新的BufferedImage对象,指定宽和高,已经颜色类型
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
// 获取当前坐标 (x, y) 的像素值(true 表示黑色,false 表示白色)
boolean pixel = matrix.get(x, y);
// 根据像素值设置对应位置的 RGB 值,将黑色或白色像素点绘制到 BufferedImage 对象中
int rgb = pixel ? Color.BLACK.getRGB() : Color.WHITE.getRGB();
// 设置x,y坐标和颜色
image.setRGB(x, y, rgb);
}
}
// 返回生成的 BufferedImage 对象
return image;
}
}
AlipayService.java
package com.sin.demo.service;
import com.alipay.api.AlipayApiException;
/**
* @createTime 2024/4/17 8:20
* @createAuthor SIN
* @use
*/
public interface AlipayService {
/**
* 创建支付订单
* @param outTradeNo 订单号
* @param totalAmount 支付金额
* @param subject 支付标题
* @return 返回二维码信息
* @throws AlipayApiException
*/
public String getgenerateQrCode(String outTradeNo,double totalAmount,String subject) throws AlipayApiException;
}
AlipayServiceImpl.java
package com.sin.demo.service.impl;
import com.alipay.api.AlipayApiException;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.sin.demo.service.AlipayService;
import com.sin.demo.utils.QRCodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
* @createTime 2024/4/17 8:23
* @createAuthor SIN
* @use
*/
@Service
@Slf4j
public class AlipayServiceImpl implements AlipayService {
// 从配置文件中获取参数值
@Value("${alipay.appId}")
private String appId; // 支付宝应用ID
@Value("${alipay.privateKey}")
private String privateKey; // 商户应用私钥
@Value("${alipay.publicKey}")
private String publicKey; // 支付宝公钥
@Value("${alipay.gatewayUrl}")
private String gatewayUrl; // 支付宝网关URL
@Override
public String getgenerateQrCode(String outTradeNo, double totalAmount, String subject) throws AlipayApiException {
// 创建支付宝客户端
DefaultAlipayClient client = new DefaultAlipayClient(gatewayUrl, appId, privateKey, "json", "UTF-8", publicKey, "RSA2");
// 创建预下单请求对象
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
// 设置测试业务参数
request.setBizContent(
"{\"out_trade_no\":\"" + outTradeNo + "\","
+ "\"total_amount\":\"" + totalAmount + "\","
+ "\"subject\":\"" + subject + "\"}"
);
// 执行预下单请求
AlipayTradePrecreateResponse response = client.execute(request);
// 判断预下单请求是否成功
if (response.isSuccess()) {
// 获取生成的支付二维码信息
final String qrCode = response.getQrCode();
// 打印二维码信息到控制台
System.out.println("二维码信息:" + qrCode);
// 记录生成支付二维码成功的日志
log.info("生成支付二维码成功:{}", response.getBody());
// 生成自定义二维码
QRCodeUtil.generateQRCode(qrCode,"src/main/resources/static/image/qrcode.png");
// 返回生成的支付二维码地址
return "支付宝支付二维码地址:" + qrCode;
} else {
// 记录生成支付二维码失败的日志
log.error("生成支付二维码失败:{}", response.getSubMsg());
// 返回生成支付二维码失败的信息
return "生成支付二维码失败:" + response.getSubMsg();
}
}
}
AlipayController.java
package com.sin.demo.controller;
import com.alipay.api.AlipayApiException;
import com.sin.demo.service.AlipayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
* @createTime 2024/4/17 8:28
* @createAuthor SIN
* @use
*/
@Controller
public class AlipayController {
@Autowired
private AlipayService alipayService;
@ResponseBody
@GetMapping("/generateQrCode/{outTradeNo}/{totalAmount}/{subject}")
public String getGenerateQrCode(@PathVariable("outTradeNo") String outTradeNo,
@PathVariable("totalAmount") double totalAmount,
@PathVariable("subject")String subject) throws AlipayApiException {
String s = alipayService.getgenerateQrCode(outTradeNo, totalAmount, subject);
return s;
}
@GetMapping("/getQrCode")
public String getQrCode(){
return "qrCode";
}
}
qrCode.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>支付页面</title>
</head>
<body>
<h1>支付页面</h1>
<div>
<h2>扫描下方二维码进行支付:</h2>
<img id="qrCode" src="../image/qrcode.png" alt="支付二维码">
</div>
</body>
</html>