Commit e456e6ea authored by licc's avatar licc

防伪二维码接口实现

parent d05e775a
package cn.wisenergy.mapper;
import cn.wisenergy.model.app.AntiFake;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
/**
* @author 86187
*/
public interface AntiFakeMapper extends BaseMapper<AntiFake> {
/**
* 添加 二维码数据
*
* @param antiFake 二维码
* @return 1
*/
int add(AntiFake antiFake);
/**
* 编辑 二维码数据
*
* @param antiFake 二维码
* @return 1
*/
int edit(AntiFake antiFake);
/**
* 获取最大批次号
*
* @return 最大批次号
*/
String getByBestBigNumber();
/**
* 批量创建防伪二维码
* @param list 入参list
* @return list.size()
*/
int creates(List<AntiFake> list);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.wisenergy.mapper.AntiFakeMapper">
<resultMap id="antiMap" type="cn.wisenergy.model.app.AntiFake">
<id column="id" property="id"/>
<result column="product_no" property="productNo"/>
<result column="batch_number" property="batchNumber"/>
<result column="batch_no" property="batchNo"/>
<result column="produce_time" property="produceTime"/>
<result column="scan_time" property="scanTime"/>
<result column="status" property="status"/>
<result column="url" property="url"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<sql id="table">
anti_fake
</sql>
<sql id="cols_all">
id,
<include refid="cols_exclude_id"/>
</sql>
<sql id="cols_exclude_id">
product_no,batch_number,batch_no,produce_time,scan_time,status,url,create_time,update_time
</sql>
<sql id="vals">
#{productNo},#{batchNumber},#{batchNo},#{produceTime},#{scanTime},#{status},#{url},now(),now()
</sql>
<sql id="createsVal">
#{i.productNo},#{i.batchNumber},#{i.batchNo},#{i.produceTime},#{i.scanTime},#{i.status},#{i.url},now(),now()
</sql>
<sql id="updateCondition">
<if test="productNo != null">product_no = #{productNo},</if>
<if test="batchNumber != null">batch_number = #{batchNumber},</if>
<if test="batchNo != null">batch_no = #{batchNo},</if>
<if test="produceTime != null">produce_time = #{produceTime},</if>
<if test="scanTime != null">scan_time = #{scanTime},</if>
<if test="status != null">status = #{status},</if>
<if test="url != null">url = #{url},</if>
update_time =now()
</sql>
<sql id="criteria">
<if test="id != null">id = #{id}</if>
<if test="productNo != null">and product_no = #{productNo}</if>
<if test="batchNumber != null">and batch_number = #{batchNumber}</if>
<if test="batchNo != null">and anti_fake_no = #{batchNo}</if>
<if test="produceTime != null">and produce_time = #{produceTime}</if>
<if test="scanTime != null">and scan_time = #{scanTime}</if>
<if test="status != null">and status = #{status}</if>
<if test="url != null">and url = #{url}</if>
<if test="createTime != null">and create_time &gt;= #{createTime}</if>
<if test="updateTime != null">and #{updateTime} &gt;= update_time</if>
</sql>
<insert id="add" parameterType="cn.wisenergy.model.app.AntiFake" keyProperty="id" useGeneratedKeys="true">
insert into
<include refid="table"/>
(<include refid="cols_exclude_id"/>)
value(
<include refid="vals"/>
)
</insert>
<update id="edit" parameterType="cn.wisenergy.model.app.AntiFake">
UPDATE
<include refid="table"/>
<set>
<include refid="updateCondition"/>
</set>
<where>
id = #{id}
</where>
</update>
<select id="getByBestBigNumber" resultType="java.lang.String">
select MAX(batch_number)
from
<include refid="table"/>
</select>
<!-- 批量创建接口 -->
<insert id="creates" parameterType="list">
INSERT INTO
<include refid="table"/>
(<include refid="cols_exclude_id"/>)
VALUES
<foreach collection="list" item="i" index="index" separator=",">
(<include refid="createsVal"/>)
</foreach>
</insert>
</mapper>
\ No newline at end of file
package cn.wisenergy.model.app;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* @author 86187
* @ Description: 二维码防伪实体类
* @ Author : 86187
* @ Date : 2021/4/21 11:48
*/
@Data
@ApiModel("AntiFake")
public class AntiFake {
/**
* 主键id
*/
@ApiModelProperty(value = "主键id", name = "id")
private Long id;
/**
* 产品编号
*/
@ApiModelProperty(value = "产品编号", name = "productNo")
private String productNo;
/**
* 批次号
*/
@ApiModelProperty(value = "批次号", name = "batchNumber")
private String batchNumber;
/**
* 编号
*/
@ApiModelProperty(value = "编号", name = "batchNo")
private String batchNo;
/**
* 生成日期 yyyy-MM-dd
*/
@ApiModelProperty(value = "生成日期 yyyy-MM-dd", name = "produceTime")
private String produceTime;
/**
* 第一次扫码时间
*/
@ApiModelProperty(value = "第一次扫码时间", name = "scanTime")
private Date scanTime;
/**
* 状态 : 0:未扫描 1:已扫描
*/
@ApiModelProperty(value = "状态 : 0:未扫描 1:已扫描", name = "status")
private Integer status;
/**
* 二维码图片url
*/
@ApiModelProperty(value = "二维码图片url", name = "url")
private String url;
private Date createTime;
private Date updateTime;
}
......@@ -94,6 +94,17 @@
<artifactId>xxl-job-core</artifactId>
<version>2.3.0</version>
</dependency>
<!--生成二维码-->
<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>
<!--start:视频处理依赖-->
<dependency>
<groupId>org.bytedeco</groupId>
......
package cn.wisenergy.service.app;
import cn.wisenergy.common.utils.R;
import org.springframework.web.multipart.MultipartFile;
/**
* @author 86187
* @ Description: 二维码防伪接口定义
* @ Author : 86187
* @ Date : 2021/4/21 10:28
*/
public interface AntiFakeService {
/**
* 创建防伪二维码
*
* @param number 二维码数量
* @return true or false
*/
R<Boolean> createCode(Integer number) throws Exception;
/**
* 解析二维码
*
* @param file 二维码
* @return 结果
* @throws Exception 异常
*/
R<String> decode(MultipartFile file) throws Exception;
R<String> uploadImage() throws Exception;
}
package cn.wisenergy.service.app.impl;
import cn.wisenergy.common.utils.DateUtil;
import cn.wisenergy.common.utils.R;
import cn.wisenergy.mapper.AntiFakeMapper;
import cn.wisenergy.model.app.AntiFake;
import cn.wisenergy.service.app.AntiFakeService;
import cn.wisenergy.service.util.CodeUtils;
import cn.wisenergy.service.util.FileUtils;
import cn.wisenergy.service.util.QRCodeUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author 86187
*/
@Service
@Slf4j
public class AntiFakeServiceImpl extends ServiceImpl<AntiFakeMapper, AntiFake> implements AntiFakeService {
private static final String DEST_PATH = "/opt/upload/video";
@Autowired
private AntiFakeMapper antiFakeMapper;
@Override
public R<Boolean> createCode(Integer number) throws Exception {
log.info("AntiFakeServiceImpl[]createCode[]input.param.number:" + number);
if (null == number) {
return R.error("入参不能为空!");
}
//获取最大批次号
String batch = antiFakeMapper.getByBestBigNumber();
String batchNumber = "";
if (StringUtils.isBlank(batch)) {
batchNumber = "10000001";
} else {
Integer sum = Integer.parseInt(batch) + 1;
batchNumber = String.valueOf(sum);
}
int initBatchNo = 10000000;
String realTime = DateUtil.getTime(new Date(), "yyyy-MM-dd");
List<AntiFake> list = new ArrayList<>();
for (int i = 0; i < number; i++) {
int batchNo = initBatchNo + i + 1;
AntiFake antiFake = new AntiFake();
antiFake.setBatchNo(String.valueOf(batchNo));
antiFake.setBatchNumber(batchNumber);
antiFake.setProduceTime(realTime);
antiFake.setScanTime(new Date());
//生成产品编码
String productNo = CodeUtils.createProductNo(batchNumber, antiFake.getBatchNo());
antiFake.setProductNo(productNo);
antiFake.setStatus(0);
//生成二维码
String url = QRCodeUtils.encode(productNo, DEST_PATH);
antiFake.setUrl(url);
list.add(antiFake);
}
//批量添加二维码
int count = antiFakeMapper.creates(list);
if (count != list.size()) {
return R.error("生成防伪二维码失败!");
}
return R.ok(0, true);
}
@Override
public R<String> decode(MultipartFile multipartFile) throws Exception {
log.info("AntiFakeServiceImpl[]decode[]input.param.multipartFile:" + multipartFile);
if (null == multipartFile) {
return R.error("入参为空");
}
File file = FileUtils.multipartFileToFile(multipartFile);
String result = QRCodeUtils.decode(file);
return R.ok(result);
}
@Override
public R<String> uploadImage() throws Exception {
log.info("上传二维码防伪图测试");
//生成二维码
String url = QRCodeUtils.encode("2021-04022", DEST_PATH);
return R.ok(url);
}
}
package cn.wisenergy.service.util;
import cn.wisenergy.common.utils.DateUtil;
import org.apache.commons.lang.RandomStringUtils;
import java.util.Date;
/**
* 生成防伪二维码产品编号工具类
*
* @author 86187
*/
public class CodeUtils {
private static final String VALUE = "nishidamori";
public static String createProductNo(String batchNumber, String batchNo) {
//产品编号 =固定值+生产时间+生产批次+编号+随机数+校验规则
String produceTime = DateUtil.getTime(new Date(), "yyyyMMdd");
String random = getRandom();
String ruleNumber = getVerifyNumber(batchNumber, batchNo, produceTime, random);
return VALUE + produceTime + batchNumber + batchNo + random + ruleNumber;
}
/**
* 获取字符串中的数字
*
* @param str 字符串
* @return 数字
*/
private static String getNumber(String str) {
StringBuilder number = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
if (Character.isDigit(str.charAt(i))) {
number.append(i);
}
}
return number.toString();
}
/**
* 获取校验规则位
*
* @param batchNumber 批次号
* @param batchNo 编号
* @param produceTime 生成时间
* @param random 随机数
* @return 校验规则位
*/
private static String getVerifyNumber(String batchNumber, String batchNo, String produceTime, String random) {
//获取随机字符串中的数字
String number = getNumber(random);
String str = batchNumber + batchNo + produceTime + number;
char[] ar = str.toCharArray();
int value = 0;
for (char c : ar) {
value = value + Integer.parseInt(String.valueOf(c));
}
int ss = value % 9;
return String.valueOf(ss);
}
/**
* 获取八位随机字符串
*
* @return 八位随机字符串
*/
private static String getRandom() {
return RandomStringUtils.random(8, "abcdefghijklmnopqrstuvwxyz1234567890");
}
public static void main(String[] args) {
System.out.println(45 % 9);
}
}
package cn.wisenergy.service.util;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
/**
* @author 86187
*/
public class FileUtils {
/**
* MultipartFile 转 File
*
* @param file
* @throws Exception
*/
public static File multipartFileToFile(MultipartFile file) throws Exception {
File toFile = null;
if (file.equals("") || file.getSize() <= 0) {
file = null;
} else {
InputStream ins = null;
ins = file.getInputStream();
toFile = new File(file.getOriginalFilename());
inputStreamToFile(ins, toFile);
ins.close();
}
return toFile;
}
/**
* 获取流文件
*/
private static void inputStreamToFile(InputStream ins, File file) {
try {
OutputStream os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
package cn.wisenergy.service.util;
import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.OutputStream;
import java.util.Hashtable;
import java.util.Random;
import javax.imageio.ImageIO;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
public class QRCodeUtils {
private static final String CHARSET = "utf-8";
private static final String FORMAT_NAME = "JPG";
// 二维码尺寸
private static final int QRCODE_SIZE = 300;
// LOGO宽度
private static final int WIDTH = 60;
// LOGO高度
private static final int HEIGHT = 60;
private static BufferedImage createImage(String content, String imgPath,
boolean needCompress) throws Exception {
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000
: 0xFFFFFFFF);
}
}
if (imgPath == null || "".equals(imgPath)) {
return image;
}
// 插入图片
QRCodeUtils.insertImage(image, imgPath, needCompress);
return image;
}
/**
* 插入LOGO
*
* @param source 二维码图片
* @param imgPath LOGO图片地址
* @param needCompress 是否压缩
* @throws Exception
*/
private static void insertImage(BufferedImage source, String imgPath,
boolean needCompress) throws Exception {
File file = new File(imgPath);
if (!file.exists()) {
System.err.println("" + imgPath + " 该文件不存在!");
return;
}
Image src = ImageIO.read(new File(imgPath));
int width = src.getWidth(null);
int height = src.getHeight(null);
if (needCompress) { // 压缩LOGO
if (width > WIDTH) {
width = WIDTH;
}
if (height > HEIGHT) {
height = HEIGHT;
}
Image image = src.getScaledInstance(width, height,
Image.SCALE_SMOOTH);
BufferedImage tag = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(image, 0, 0, null); // 绘制缩小后的图
g.dispose();
src = image;
}
// 插入LOGO
Graphics2D graph = source.createGraphics();
int x = (QRCODE_SIZE - width) / 2;
int y = (QRCODE_SIZE - height) / 2;
graph.drawImage(src, x, y, width, height, null);
Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
graph.setStroke(new BasicStroke(3f));
graph.draw(shape);
graph.dispose();
}
/**
* 生成二维码(内嵌LOGO)
*
* @param content 内容
* @param imgPath LOGO地址
* @param destPath 存放目录
* @param needCompress 是否压缩LOGO
* @throws Exception
*/
public static String encode(String content, String imgPath, String destPath,
boolean needCompress) throws Exception {
BufferedImage image = QRCodeUtils.createImage(content, imgPath,
needCompress);
mkdirs(destPath);
String file = new Random().nextInt(99999999) + ".jpg";
ImageIO.write(image, FORMAT_NAME, new File(destPath + "/" + file));
return destPath + "/" + file;
}
/**
* 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
*
* @param destPath 存放目录
* @date 2013-12-11 上午10:16:36
*/
public static void mkdirs(String destPath) {
File file = new File(destPath);
//当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
if (!file.exists() && !file.isDirectory()) {
file.mkdirs();
}
}
/**
* 生成二维码(内嵌LOGO)
*
* @param content 内容
* @param imgPath LOGO地址
* @param destPath 存储地址
* @throws Exception
*/
public static void encode(String content, String imgPath, String destPath)
throws Exception {
QRCodeUtils.encode(content, imgPath, destPath, false);
}
/**
* 生成二维码
*
* @param content 内容
* @param destPath 存储地址
* @param needCompress 是否压缩LOGO
* @throws Exception
*/
public static void encode(String content, String destPath,
boolean needCompress) throws Exception {
QRCodeUtils.encode(content, null, destPath, needCompress);
}
/**
* 生成二维码
*
* @param content 内容
* @param destPath 存储地址
* @throws Exception
*/
public static String encode(String content, String destPath) throws Exception {
return QRCodeUtils.encode(content, null, destPath, false);
}
/**
* 生成二维码(内嵌LOGO)
*
* @param content 内容
* @param imgPath LOGO地址
* @param output 输出流
* @param needCompress 是否压缩LOGO
* @throws Exception
*/
public static void encode(String content, String imgPath,
OutputStream output, boolean needCompress) throws Exception {
BufferedImage image = QRCodeUtils.createImage(content, imgPath,
needCompress);
ImageIO.write(image, FORMAT_NAME, output);
}
/**
* 生成二维码
*
* @param content 内容
* @param output 输出流
* @throws Exception
*/
public static void encode(String content, OutputStream output)
throws Exception {
QRCodeUtils.encode(content, null, output, false);
}
/**
* 解析二维码
*
* @param file 二维码图片
* @return
* @throws Exception
*/
public static String decode(File file) throws Exception {
BufferedImage image;
image = ImageIO.read(file);
if (image == null) {
return null;
}
BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(
image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result result;
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
result = new MultiFormatReader().decode(bitmap, hints);
return result.getText();
}
/**
* 解析二维码
*
* @param path 二维码图片地址
* @return
* @throws Exception
*/
public static String decode(String path) throws Exception {
return QRCodeUtils.decode(new File(path));
}
public static void main(String[] args) throws Exception {
String text = "http://app.xitiansen.com/shop-mall/account/download"; //这里设置自定义网站url
String logoPath = "C:\\home\\image\\test.jpg";
String destPath = "opt\\upload\\image";
System.out.println(QRCodeUtils.encode(text, logoPath, destPath, true));
}
}
package cn.wisenergy.web.admin.controller.app;
import cn.wisenergy.common.utils.R;
import cn.wisenergy.service.app.AntiFakeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* @author 86187
*/
@Api(tags = "管理端-防伪二维码管理")
@RestController
@Slf4j
public class AntiFakeController {
@Autowired
private AntiFakeService antiFakeService;
@ApiOperation(value = "解析二维码", notes = "解析二维码", httpMethod = "POST")
@PostMapping(value = "/admin/decode", headers = "content-type=multipart/form-data")
public R<String> getByUserId(@RequestParam("file") MultipartFile file,
HttpServletRequest request) throws Exception {
return antiFakeService.decode(file);
}
@ApiOperation(value = "解析二维码", notes = "解析二维码", httpMethod = "POST")
@PostMapping(value = "/admin/create/code", headers = "content-type=multipart/form-data")
public R<Boolean> create(Integer number) throws Exception {
return antiFakeService.createCode(number);
}
@ApiOperation(value = "上传防伪码图片接口", notes = "上传防伪码图片接口", httpMethod = "POST", produces = "application/json; charset=UTF-8")
@RequestMapping(value = "/admin/uploadImage", method = RequestMethod.POST)
public R<String> uploadImage() throws Exception {
return antiFakeService.uploadImage();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment