最近在做一個從微信小程序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~~"
可以看到該鏈接比較奇怪,本人猜測微信應該是對小程序二維碼掃碼時做了特殊處理(直接點擊鏈接是進不去的),但這並不影響,因爲我們傳給第三方後,第三方會根據同樣的規則去根據鏈接生成二維碼,生成之後的二維碼掃碼結果還是指向這個鏈接(目前測試沒有問題)