一、基础二维码生成
1.1 编写pom
<!-- 生成二维码依赖BEGIN -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.1.0</version>
</dependency>
<!-- 生成二维码依赖END -->
1.2 编写工具类
/**
* 二维码的工具类
*/
@Slf4j
public class ZXingUtil {
private static final int BLACK = 0xFF000000; //定义int类型的常量用于存放生成二维码时的类型
private static final int WHITE = 0xFFFFFFFF;
/**
* 加密:文字-->图片 将文本变成二维数组,
*
* @param imagePath 图片路径
* @param format 文件格式及后缀名
* @param content 文本
*/
public static void encodeImage(String imagePath, String format, String content, int width, int height, String logo) throws WriterException, IOException {
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
//容错率:L(7%)<M(15%)<Q(25%)<H(35%);H容错率最高
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
//编码格式
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
//外边距
hints.put(EncodeHintType.MARGIN, 1);
/*BarcodeFormat.QR_CODE:解析什么类型的文件:要解析的二维码的类型
content:解析文件的内容
width:生成二维码的宽
height:生成二维码的高
hints:涉及到加密用到的参数: 即 编码 和容错率*/
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
// 使BufferedImage勾画QRCode (matrixWidth 是行二维码像素点)
int matrixWidth = bitMatrix.getWidth();
/*内存中的一张图片:是RenderedImage的子类,而RenderedImage是一个接口
此时需要的图片是一个二维码-->需要一个boolean[][]数组存放二维码 --->Boolean数组是由BitMatrix产生的
BufferedImage.TYPE_INT_RGB : 表示生成图片的类型: 此处是RGB模式*/
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//生成二维数组
for (int x = 0; x < matrixWidth; x++) {
for (int y = 0; y < matrixWidth; y++) {
//二维坐标整个区域:画什么颜色
img.setRGB(x, y, bitMatrix.get(x, y) ? BLACK : WHITE);
}
}
//将二维码图片转换成文件
File file = new File(imagePath);
//生成图片
ImageIO.write(logoImg(img, logo), format, file);
}
/**
* 解密,将生成的二维码转换成文字
*
* @param file:二维码文件
*/
public static String decodeImage(File file) {
//首先判断文件是否存在
if (!file.exists()) {
return "";
}
//将file转换成内存中的一张图片
BufferedImage image = null;
try {
image = ImageIO.read(file);
} catch (IOException e) {
log.error("read ZXingCode failed", e);
}
MultiFormatReader formatter = new MultiFormatReader();
assert image != null;
LuminanceSource source = new BufferedImageLuminanceSource(image);
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
//将图片的文字信息解析到result中
Result result = null;
try {
result = formatter.decode(binaryBitmap);
} catch (NotFoundException e) {
log.error("parse data from ZXingCode failed", e);
}
assert result != null;
log.info("parse data [{}] from ZXingCode", result.getText());
return result.getText();
}
/**
* 传logo和二维码,生成-->带logo的二维码
*
* @param matrixImage :二维码
* @param logo : 中间的logo
* @return BufferedImage
*/
public static BufferedImage logoImg(BufferedImage matrixImage, String logo) {
// 在二维码上画logo:产生一个二维码画板
Graphics2D g2 = matrixImage.createGraphics();
// 画logo,将String类型的logo图片存放入内存中;即 string-->BufferedImage
BufferedImage logoImage = null;
try {
logoImage = ImageIO.read(new File(logo));
} catch (IOException e) {
log.error("ZXingCode config logo read failed", e);
}
// 获取二维码的高和宽
int height = matrixImage.getHeight();
int width = matrixImage.getWidth();
/*纯log图片
logoImage:内存中的图片
在二维码的高和宽的2/5,2/5开始画log,logo占用整个二维码的高和宽的1/5,1/5*/
g2.drawImage(logoImage, width * 2 / 5, height * 2 / 5, width / 5, height / 5, null);
/*画白色的外边框
产生一个画白色圆角正方形的画笔
BasicStroke.CAP_ROUND:画笔的圆滑程度,此处设置为圆滑
BasicStroke.JOIN_ROUND:在边与边的连接点的圆滑程度,此处设置为圆滑*/
BasicStroke stroke = new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
// 将画板和画笔关联起来
g2.setStroke(stroke);
// 画一个正方形, RoundRectangle2D是一个画长方形的类
RoundRectangle2D.Float round = new RoundRectangle2D.Float(width * 2.0f / 5, height * 2.0f / 5, width * 1.0f / 5, height * 1.0f / 5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
//设置为画白色
g2.setColor(Color.WHITE);
g2.draw(round);
//画灰色的内边框,原理与画白色边框相同
BasicStroke stroke2 = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
g2.setStroke(stroke2);
RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(width * 2.0f / 5 + 2, height * 2.0f / 5 + 2, width * 1.0f / 5 - 4, height * 1.0f / 5 - 4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
//另一种设置灰色的方法:Color color = new Color(128,128,128);其中三个参数是 R G B
g2.setColor(Color.GRAY);
g2.draw(round2);
//释放内存
g2.dispose();
//刷新二维码
matrixImage.flush();
return matrixImage;
}
}
1.3 编写测试代码并测试
@SpringBootTest(classes = {AppMain.class})
public class ZXingUtilTest {
@Test
public void testDownloadImg() throws Exception {
String imagePath = "src/main/resources/zxingcode.jpeg";
String logo = "src/main/resources/avatar-mine.jpeg";
String content = "zhinian 👉🏻 只年";
ZXingUtil.encodeImage(imagePath, "JPEG", content, 430, 430, logo);
// 解密 -->将二维码内部的文字显示出来
String s = ZXingUtil.decodeImage(new File(imagePath));
System.out.printf(s);
}
}
头像和生成二维码图片如下
![](https://i-blog.csdnimg.cn/blog_migrate/2fd5860b531ded1f140eef593a3cf275.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/4ab78a7c679da23dfadad06c973ca5a5.jpeg)
支付宝扫码如下
二、回调接口
2.1 编写回调接口
@Slf4j
@RestController
public class CallBackController {
@RequestMapping("/call/doXxx")
public void doXxx() {
log.info("do callback success, are you ok?");
}
}
2.2 生成二维码
注: 此步可编写为接口生成,二维码保存文件服务器,保存返回的文件地址
@SpringBootTest(classes = {AppMain.class})
public class ZXingUtilTest {
@Test
public void testDownloadImg() throws Exception {
String imagePath = "src/main/resources/zxingcode.jpeg";
String logo = "src/main/resources/avatar-mine.jpeg";
// 同一wifi下, 电脑ip
String content = "http://192.168.1.3:8888/call/doXxx";
ZXingUtil.encodeImage(imagePath, "JPEG", content, 430, 430, logo);
// 解密 -->将二维码内部的文字显示出来
String s = ZXingUtil.decodeImage(new File(imagePath));
System.out.printf(s);
}
}
支付宝扫码
控制台输出
回调成功,oh yeah !