最近在做一个从微信小程序api获取到小程序二维码,然后将二维码解析返回给第三方平台,第三方平台再根据链接生成二维码供用户扫码使用,在解析二维码的时候遇到了一些问题,在这里分享一下。
1.开发文档
https://mp.weixin.qq.com/debug/wxadoc/dev/api/qrcode.html 在开发文档中可以看到,生成的二维码大概有三种,第一种和第三种有数量限制,由于第一种目前zXing无法解析(可能我版本较低),所以采取的生成第三种小程序二维码的方式,生成出来后是这样的(width入参是430,返回结果是一个二维码的二进制流byte[])
2.裁剪处理
由于生成的二维码最下方有一行字(微信扫一扫,使用小程序),导致在解码的过程中报错,目前想到的就是对二维码进行裁剪处理,首先将byte[]转换成BufferedImage再进行裁剪
ByteArrayInputStream inputStream= new ByteArrayInputStream(qrCodeRsp.getResult());
BufferedImage image = ImageIO.read(inputStream);
/**裁剪原图 目前访问微信 微信返回的是 470*535 像素 170620*/
BufferedImage subImage = image.getSubimage(0, 0, image.getWidth(), (int) (image.getHeight() * 0.85));
这里就遇到一个问题,我们对微信的入参是430,而实际上微信接口返回的是470*535dpi的二维码,裁剪过多或者过少都会有问题,这里采用了一定比例裁剪的方式(0.85)
3.解析裁剪后图像
jar包依赖:
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.2.1</version>
</dependency>
解析二维码工具类:
package com.demo.kowalski.utils;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Created by Kowalski on 2017/6/16
* Updated by Kowalski on 2017/6/16
*/
public class QrCodeUtils {
/**
* 解析二维码(QRCode)
* @param image
* @return
*/
public static String decodeQrcode(BufferedImage image) throws NotFoundException {
MultiFormatReader formatReader = new MultiFormatReader();
BinaryBitmap binaryBitmap=new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(image)));
//定义二维码的参数:
Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
hints.put(DecodeHintType.CHARACTER_SET,"utf-8");//定义字符集
hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
Result result = formatReader.decode(binaryBitmap, hints);//开始解析
return result.getText();
}
/**
* 流图片解码
* @param input
* @return String
*/
public static String decodeQrcode(InputStream input) throws NotFoundException, IOException {
BufferedImage image = ImageIO.read(input);
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Map<DecodeHintType,Object> hints = new LinkedHashMap<DecodeHintType,Object>();
// 解码设置编码方式为:utf-8,
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
//优化精度
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
//复杂模式,开启PURE_BARCODE模式
hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
Result result = new MultiFormatReader().decode(bitmap, hints);
return result.getText();
}
}
工具类里提供了两种解析方式,一种是流一种是BufferedImage,返回结果是二维码包含的内容:
"https://mp.weixin.qq.com/a/~~IDPi5UlUcRc~6N6CY6nW1xdSyX7RhQPnEg~~"
可以看到该链接比较奇怪,本人猜测微信应该是对小程序二维码扫码时做了特殊处理(直接点击链接是进不去的),但这并不影响,因为我们传给第三方后,第三方会根据同样的规则去根据链接生成二维码,生成之后的二维码扫码结果还是指向这个链接(目前测试没有问题)