如题,如何把网址或者一个二维码变成一个有时效的二维码。比如五分钟之内或者十分钟之内扫描有效,过期以后扫描失效。要以分钟为单位,不要以天为单位,以天为单位的制作器不需要,本人小菜鸡,最好不要涉及太多开发、编程之类的专业性技巧,最好是傻瓜式就能制作的,比如把网址或二维码放到某个二维码编辑器里面设置有效时间就可以的这种,当然,如果涉及专业也不要紧,真的好用本人可以学习。
二维码url申请时后面加上timestamp参数,扫描后校验时间戳已经过去多长时间就可以了。
(欢迎采纳)
Part1:
JAVA 生成二维码 并设置 +失效机制
1.前言:我这里设置的失效机制用数据库记录每一张二维码的实效时间,二维码生成后上传至OSS
1.1 数据库设计
CREATE TABLE `qz_date` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`uuid` varchar(255) DEFAULT NULL COMMENT '二维码标号',
`url` varchar(255) DEFAULT NULL COMMENT '二维码地址',
`end_time` datetime DEFAULT NULL COMMENT '失效时间',
`created_at` datetime DEFAULT NULL COMMENT '创建时间',
`last_modified` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4;
2 二维码生成
2.1 导入以来
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>
2.2 生成和解析二维码工具类
@Slf4j
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;
public 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;
}
public static BufferedImage createImage(String content) 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);
}
}
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) {
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 file;
}
/**
* 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
* @date 2013-12-11 上午10:16:36
* @param destPath 存放目录
*/
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 void encode(String content, String destPath) throws Exception {
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);
String resultStr = result.getText();
return resultStr;
}
/**
* 解析二维码
*
* @param path
* 二维码图片地址
* @return
* @throws Exception
*/
public static String decode(String path) throws Exception {
return QRCodeUtils.decode(new File(path));
}
public static String upLoad(String uuid, BufferedImage image, String fileApi){
String iconUrl = null;
if (image!=null) {
InputStream inputStream = bufferedImageToInputStream(image);
Map<String, String> params = new HashMap<>(16);
params.put("token", "oh, it's ok");
String fileName = uuid + ".png";
String result = UploadFile.uploadFileStream(fileApi, fileName, inputStream, params, new HashMap<>());
Map resultMap = JSON.parseObject(result.substring(1, result.length() - 1), Map.class);
iconUrl = resultMap.get("url").toString();
}
return iconUrl;
}
private static InputStream bufferedImageToInputStream(BufferedImage image){
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
ImageIO.write(image, "png", os);
InputStream input = new ByteArrayInputStream(os.toByteArray());
return input;
} catch (IOException e) {
log.error("提示:",e);
}
return null;
}
}
3.测试
@PostMapping("/getCode")
@ApiOperation(value = "生成二维码", notes = "生成二维码")
public ApiResponse getCode(@RequestBody JSONObject par,HttpServletRequest request) throws Exception {
Integer elId = par.getInteger("elId");
String url = par.getString("url");
//二维码标识
String uuid = UUID.randomUUID().toString();
JSONObject jsonObject = new JSONObject();
jsonObject.put("url",url);
jsonObject.put("elId",elId);
jsonObject.put("qzId",uuid);
//生成二维码
BufferedImage image = QRCodeUtils.createImage(jsonObject.toJSONString());
//上传二维码到OSS
String s = QRCodeUtils.upLoad(uuid, image, fileApi);
QzDate qzDate = new QzDate();
qzDate.setUuid(uuid);
qzDate.setUrl(s);
//二维码有效期
qzDate.setEndTime(LocalDateTime.now().plusDays(3));
iQzDateService.save(qzDate);
return ApiResponse.success(s);
}
3.1 测试有效期
@PostMapping("/getBizElement")
@ApiOperation(value = "前台查询元素信息展示", notes = "前台使用")
public ApiResponse<BizResponseParam> findBizBasicElement(@RequestBody JSONObject param, HttpServletRequest req) {
Integer elId = param.getInteger("elId");
String qzDate = param.getString("uuid");
//查询二维码是否过期
QueryWrapper<QzDate> qzDateQueryWrapper = new QueryWrapper<>();
qzDateQueryWrapper.eq("uuid", qzDate);
QzDate one = iQzDateService.getOne(qzDateQueryWrapper);
LocalDateTime endTime = one.getEndTime();
LocalDateTime now = LocalDateTime.now();
ApiResponse<BizResponseParam> apiResponse = new ApiResponse<>();
if (endTime.compareTo(now)>0) {
//逻辑 。。。。
} else {
apiResponse.setErrorMsg("二维码已过期");
apiResponse.setErrorCode(500);
}
return apiResponse;
}
同时可以在二维码请求地址后面添加参数,类似我们输入的验证码,参数有实效性
可以在生成的时候吧时间戳放进去,然后扫描的时候,访问网页的时候携带这个时间戳参数,在后端根据自己的业务逻辑判断是否过期即可!!!
当然为了防止伪造二维码,可以加一些算法校验
模板
public class RecodeUtil {
public static void creatRrCode(String contents, int width, int height,HttpServletResponse response) {
Hashtable hints = new Hashtable();
//容错级别最高
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
//设置字符编码
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
//二维码空白区域,最小为0也有白边,只是很小,最小是6像素左右
hints.put(EncodeHintType.MARGIN, 1);
try {
// 1、读取文件转换为字节数组
BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height, hints);
BufferedImage image = toBufferedImage(bitMatrix);
//转换成png格式的IO流
ImageIO.write(image, "png", response.getOutputStream());
} catch (WriterException e) { // TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* image流数据处理
*
*/
public static BufferedImage toBufferedImage(BitMatrix matrix) {
int width = matrix.getWidth();
int height = matrix.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, matrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
return image;
}
}
二维码的网址后面加上个加密的当前时间参数,然后服务器解密参数读取时间后与当前时间比较,大于10钟重新生成
永久二维码很简单,按照二维码的规则生成就可以了,
带时效的话,就需要后端服务器处理了, 自己搭建或者选择第三方服务
思路类似于代理, 通过自己的服务隐藏原网址,对自己的服务可以随便设置时效, 有效期内返回源网址, 有效期外,返回错误
如果不想太麻烦或者太多功能, 你可以在二维码中写入加密信息(自己服务的地址, 时效, 原地址), 然后服务器就做一个解密判断, 这样自己的服务器就不用存储信息,
然后需要一个加密数据 并生成二维码的工具,
如果选择信息不加密就更加简单了,就是解析判断
1、二维码的构成: 网站域名+参数 ,(参数是时间戳,就是日期时间)。
2、网站接收到用户的访问,检查参数,如果参数已经大于产生时的日期时间,比如网站服务器程序,取服务器的时间,比用户传入的参数时间过了10分钟以上,就报404错误,拒绝用户访问。
3、二维码的产生,也可以在网站上按第一条规则产生。这样便于使用。
4、但如果有一个这样的web应用,你可以不用80端口,现在80端口国家要求很严格的,要备案之类的,你可以用其它端口,比如5188之类的。
可以随机生成二维码,
记录二维码生成时间,二维码预计过期时间,
然后判断扫描二维码的时间是否在生成时间与预计过期时间中间, 如果是,则扫描成功,如果不是则失败.
结合提主两次问题可以得出
1、生成二维码的网址是APP付款连接,也就不是自己的网站服务器后端
2、生成二维码5分钟失效,每天需要50 到60张二维码
有了思路也绝对能做出来,但。。。。 但是20块钱,谁穷疯了给你做这样的功能
可以参考如下链接https://www.freesion.com/article/2634285056/ 设置有效期的话,最好在二维码链接后添加上时间戳
二维彩虹二维码生成器可以帮你做到,赶快跟着下面几个步骤做起来吧:
(1)登录二维彩虹网站,选择“多链接”二维码。
(2)选择“时间”
(3)在“默认URL”中放入一个显示“此二维码已失效”的链接。
(4)选择特定的时间,将想在特定时间内有效展示的链接内容放入。
那么,如何生成这个失效链接呢?
(1)选择“H5编辑”功能。
(2)在页面标题和编辑框中都分别放入“此二维码已失效”的文本,点击生成二维码。
(3)生成二维码之后,自动来到“追踪数据”页面,找出刚刚生成的H5编辑二维码的网址链接。
(4)复制这个网址链接,放入多链接二维码中的“默认URL”中,点击生成多链接二维码。
一个在特定时间内扫描有效,过时即失效的动态二维码就可以随时开始工作了!
建议二维码设置跳转到指定网址,由该网址判断时效,有效的话再跳转到相应内容
使用草料二维码,如果需要代码请私
有专业的软件可以使用。请查看这个教程:https://www.tiaomaruanjian.com/news/6/show-12043.html
有用的话,请给一个采纳,谢谢
1.显示效果:
2.图示效果可以吗,可以的话,可以私信我实现方式呢