线下订单驱动开门
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
package com.sv.mapper;
|
||||
|
||||
import com.sv.entity.BarcodeEnterLog;
|
||||
import com.sv.entity.BarcodeOffline;
|
||||
|
||||
public interface BarcodeEnterLogMapper {
|
||||
int deleteByPrimaryKey(Integer id);
|
||||
|
||||
int insert(BarcodeEnterLog record);
|
||||
|
||||
int insertSelective(BarcodeEnterLog record);
|
||||
|
||||
BarcodeEnterLog selectByPrimaryKey(Integer id);
|
||||
|
||||
int updateByPrimaryKeySelective(BarcodeEnterLog record);
|
||||
|
||||
int updateByPrimaryKey(BarcodeEnterLog record);
|
||||
|
||||
BarcodeEnterLog findLastByBarcode(String barcode);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.sv.mapper;
|
||||
|
||||
import com.sv.entity.BarcodeOffline;
|
||||
|
||||
public interface BarcodeOfflineMapper {
|
||||
int deleteByPrimaryKey(Integer id);
|
||||
|
||||
int insert(BarcodeOffline record);
|
||||
|
||||
int insertSelective(BarcodeOffline record);
|
||||
|
||||
BarcodeOffline selectByPrimaryKey(Integer id);
|
||||
|
||||
int updateByPrimaryKeySelective(BarcodeOffline record);
|
||||
|
||||
int updateByPrimaryKey(BarcodeOffline record);
|
||||
|
||||
BarcodeOffline selectByBarcode(String barcode);
|
||||
}
|
||||
@@ -294,7 +294,7 @@ public class VenueService extends BaseServiceImpl {
|
||||
}
|
||||
if (useCard != null) {
|
||||
//使用会员卡入场
|
||||
logger.info("用户" + member.getNickname() + "使用" + useCard.getCardType() + "入场");
|
||||
logger.info("用户" + member.getNickname() + "使用" + useCard.getCardType() + "核销");
|
||||
// 会员卡入场,增加记录
|
||||
createMemberMoneyLog(MoneyLogEnum.JOIN.value, venue.getPrice(), member.getId(), member.getPlatformId(), PayTypeEnum.MEMBER_CARD.value, useCard.getCardType(),
|
||||
venue.getId(), venue.getType());
|
||||
@@ -305,21 +305,21 @@ public class VenueService extends BaseServiceImpl {
|
||||
}
|
||||
}else {
|
||||
//查无可用会员卡
|
||||
logger.info("用户" + member.getNickname() + "您好!请先购买会员卡再进场");
|
||||
logger.info("用户" + member.getNickname() + "您好!请先购买会员卡再出场核销");
|
||||
result.setFlg(1);
|
||||
result.setMsg("未查询到会员卡,请先购买");
|
||||
result.setMsg("未查询到会员卡,请先购买会员卡");
|
||||
}
|
||||
}else {
|
||||
//判断余额是否够 TODO 应该从入场订单里面去取
|
||||
//判断余额是否够
|
||||
String time = DateUtilCard.nowTime().toString();
|
||||
VenuePrice venuePrice = venuePriceService.findPrice(venueId, time);
|
||||
if (memberService.isMoneyEnough(member.getId(), venuePrice.getPrice())) {
|
||||
logger.info("用户" + member.getNickname() + "使用余额进场");
|
||||
logger.info("用户" + member.getNickname() + "使用余额核销订单");
|
||||
createMemberMoneyLog(MoneyLogEnum.JOIN.value, venuePrice.getPrice(), member.getId(), member.getPlatformId(), PayTypeEnum.BALANCE.value, null,
|
||||
venue.getId(), venue.getType());
|
||||
} else {
|
||||
//余额不足
|
||||
logger.error("用户" + member.getNickname() + "余额不足进场失败");
|
||||
logger.error("用户" + member.getNickname() + "余额不足核销失败");
|
||||
result.setFlg(1);
|
||||
result.setMsg("余额不足,请先充值");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.sv.service.common;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Component
|
||||
public class DoorLockUtil {
|
||||
|
||||
private final static String DOOR_LOCK = "DOOR_LOCK_";
|
||||
private final static String DOOR_BARCODE_LOCK = "DOOR_BARCODE_LOCK_";
|
||||
private final static Integer LOCK_TIMEOUT = 30;
|
||||
|
||||
@Resource
|
||||
RedisCache redisCache;
|
||||
|
||||
/**
|
||||
* 门禁有人扫码之后,需要锁定门禁30s
|
||||
* @return
|
||||
*/
|
||||
public boolean checkDoorLock(String doorSn){
|
||||
String doorKey = DOOR_LOCK + doorSn;
|
||||
if (redisCache.getCacheObject(doorKey) == null){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 门禁有人扫码之后,需要锁定门禁30s
|
||||
* @param doorSn
|
||||
*/
|
||||
public void lockDoor(String doorSn){
|
||||
String doorKey = DOOR_LOCK + doorSn;
|
||||
redisCache.setCacheObject(doorKey,true,LOCK_TIMEOUT, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 门禁有人扫码之后,需要锁定门禁30s
|
||||
* @return
|
||||
*/
|
||||
public boolean checkBarcode(String doorSn){
|
||||
String doorKey = DOOR_BARCODE_LOCK + doorSn;
|
||||
if (redisCache.getCacheObject(doorKey) == null){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 门禁有人扫码之后,需要锁定门禁30s
|
||||
* @param doorSn
|
||||
*/
|
||||
public void lockBarcode(String doorSn){
|
||||
String doorKey = DOOR_BARCODE_LOCK + doorSn;
|
||||
redisCache.setCacheObject(doorKey,true,LOCK_TIMEOUT, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
}
|
||||
264
service/src/main/java/com/sv/service/common/RedisCache.java
Normal file
264
service/src/main/java/com/sv/service/common/RedisCache.java
Normal file
@@ -0,0 +1,264 @@
|
||||
package com.sv.service.common;
|
||||
|
||||
import org.springframework.data.redis.core.BoundSetOperations;
|
||||
import org.springframework.data.redis.core.HashOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ValueOperations;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* spring redis 工具类
|
||||
*
|
||||
* @author quinn
|
||||
**/
|
||||
@Component
|
||||
public class RedisCache
|
||||
{
|
||||
@Resource
|
||||
public RedisTemplate redisTemplate;
|
||||
|
||||
/**
|
||||
* 缓存基本的对象,Integer、String、实体类等
|
||||
*
|
||||
* @param key 缓存的键值
|
||||
* @param value 缓存的值
|
||||
*/
|
||||
public <T> void setCacheObject(final String key, final T value)
|
||||
{
|
||||
redisTemplate.opsForValue().set(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存基本的对象,Integer、String、实体类等
|
||||
*
|
||||
* @param key 缓存的键值
|
||||
* @param value 缓存的值
|
||||
* @param timeout 时间
|
||||
* @param timeUnit 时间颗粒度
|
||||
*/
|
||||
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
|
||||
{
|
||||
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置有效时间
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param timeout 超时时间
|
||||
* @return true=设置成功;false=设置失败
|
||||
*/
|
||||
public boolean expire(final String key, final long timeout)
|
||||
{
|
||||
return expire(key, timeout, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置有效时间
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param timeout 超时时间
|
||||
* @param unit 时间单位
|
||||
* @return true=设置成功;false=设置失败
|
||||
*/
|
||||
public boolean expire(final String key, final long timeout, final TimeUnit unit)
|
||||
{
|
||||
return redisTemplate.expire(key, timeout, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取有效时间
|
||||
*
|
||||
* @param key Redis键
|
||||
* @return 有效时间
|
||||
*/
|
||||
public long getExpire(final String key)
|
||||
{
|
||||
return redisTemplate.getExpire(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断 key是否存在
|
||||
*
|
||||
* @param key 键
|
||||
* @return true 存在 false不存在
|
||||
*/
|
||||
public Boolean hasKey(String key)
|
||||
{
|
||||
return redisTemplate.hasKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得缓存的基本对象。
|
||||
*
|
||||
* @param key 缓存键值
|
||||
* @return 缓存键值对应的数据
|
||||
*/
|
||||
public <T> T getCacheObject(final String key)
|
||||
{
|
||||
ValueOperations<String, T> operation = redisTemplate.opsForValue();
|
||||
return operation.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除单个对象
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
public void deleteObject(final String key)
|
||||
{
|
||||
redisTemplate.delete(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除集合对象
|
||||
*
|
||||
* @param collection 多个对象
|
||||
* @return
|
||||
*/
|
||||
public void deleteObject(final Collection collection)
|
||||
{
|
||||
redisTemplate.delete(collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存List数据
|
||||
*
|
||||
* @param key 缓存的键值
|
||||
* @param dataList 待缓存的List数据
|
||||
* @return 缓存的对象
|
||||
*/
|
||||
public <T> long setCacheList(final String key, final List<T> dataList)
|
||||
{
|
||||
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
|
||||
return count == null ? 0 : count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得缓存的list对象
|
||||
*
|
||||
* @param key 缓存的键值
|
||||
* @return 缓存键值对应的数据
|
||||
*/
|
||||
public <T> List<T> getCacheList(final String key)
|
||||
{
|
||||
return redisTemplate.opsForList().range(key, 0, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存Set
|
||||
*
|
||||
* @param key 缓存键值
|
||||
* @param dataSet 缓存的数据
|
||||
* @return 缓存数据的对象
|
||||
*/
|
||||
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
|
||||
{
|
||||
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
|
||||
Iterator<T> it = dataSet.iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
setOperation.add(it.next());
|
||||
}
|
||||
return setOperation;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得缓存的set
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public <T> Set<T> getCacheSet(final String key)
|
||||
{
|
||||
return redisTemplate.opsForSet().members(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存Map
|
||||
*
|
||||
* @param key
|
||||
* @param dataMap
|
||||
*/
|
||||
public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
|
||||
{
|
||||
if (dataMap != null) {
|
||||
redisTemplate.opsForHash().putAll(key, dataMap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得缓存的Map
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public <T> Map<String, T> getCacheMap(final String key)
|
||||
{
|
||||
return redisTemplate.opsForHash().entries(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 往Hash中存入数据
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param hKey Hash键
|
||||
* @param value 值
|
||||
*/
|
||||
public <T> void setCacheMapValue(final String key, final String hKey, final T value)
|
||||
{
|
||||
redisTemplate.opsForHash().put(key, hKey, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Hash中的数据
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param hKey Hash键
|
||||
* @return Hash中的对象
|
||||
*/
|
||||
public <T> T getCacheMapValue(final String key, final String hKey)
|
||||
{
|
||||
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
|
||||
return opsForHash.get(key, hKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取多个Hash中的数据
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param hKeys Hash键集合
|
||||
* @return Hash对象集合
|
||||
*/
|
||||
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
|
||||
{
|
||||
return redisTemplate.opsForHash().multiGet(key, hKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除Hash中的某条数据
|
||||
*
|
||||
* @param key Redis键
|
||||
* @param hKey Hash键
|
||||
* @return 是否成功
|
||||
*/
|
||||
public boolean deleteCacheMapValue(final String key, final String hKey)
|
||||
{
|
||||
return redisTemplate.opsForHash().delete(key, hKey) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得缓存的基本对象列表
|
||||
*
|
||||
* @param pattern 字符串前缀
|
||||
* @return 对象列表
|
||||
*/
|
||||
public Collection<String> keys(final String pattern)
|
||||
{
|
||||
return redisTemplate.keys(pattern);
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,16 @@ import com.common.DeviceDTO;
|
||||
import com.enums.DeviceStatusEnum;
|
||||
import com.enums.EnterEnum;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.sv.entity.BarcodeOffline;
|
||||
import com.sv.entity.Device;
|
||||
import com.sv.exception.oms.OmsException;
|
||||
import com.sv.mapper.BarcodeOfflineMapper;
|
||||
import com.sv.mapper.DeviceMapper;
|
||||
import com.sv.service.api.util.DateUtilCard;
|
||||
import com.ydd.framework.core.common.Pagination;
|
||||
import com.ydd.framework.core.common.dto.ResponseDTO;
|
||||
import com.ydd.framework.core.service.impl.BaseServiceImpl;
|
||||
import org.apache.commons.lang.time.DateUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpEntity;
|
||||
@@ -21,6 +25,7 @@ import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -40,6 +45,9 @@ public class DeviceService extends BaseServiceImpl {
|
||||
@Resource
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Resource
|
||||
private BarcodeOfflineMapper barcodeOfflineMapper;
|
||||
|
||||
|
||||
/**
|
||||
* 创建门禁设备
|
||||
@@ -206,7 +214,6 @@ public class DeviceService extends BaseServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* find by DeviceName
|
||||
*/
|
||||
@@ -214,5 +221,16 @@ public class DeviceService extends BaseServiceImpl {
|
||||
return deviceMapper.findByDevice(venueId);
|
||||
}
|
||||
|
||||
public void makeDeviceBarcode(String deviceName, Integer venueId, String barcode) {
|
||||
BarcodeOffline barcodeOffline = new BarcodeOffline();
|
||||
Date startTime = new Date();
|
||||
barcodeOffline.setStartTime(startTime);
|
||||
barcodeOffline.setEndTime(DateUtils.addHours(startTime,2));
|
||||
barcodeOffline.setVenueId(venueId);
|
||||
barcodeOffline.setDeviceName(deviceName);
|
||||
barcodeOffline.setBarcode(barcode);
|
||||
barcodeOfflineMapper.insert(barcodeOffline);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
109
service/src/main/java/com/sv/service/utils/VenueBarcodeUtil.java
Normal file
109
service/src/main/java/com/sv/service/utils/VenueBarcodeUtil.java
Normal file
@@ -0,0 +1,109 @@
|
||||
package com.sv.service.utils;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import com.ydd.framework.core.exception.ServiceException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Hashtable;
|
||||
|
||||
public class VenueBarcodeUtil {
|
||||
|
||||
private static final int BLACK = 0xFF000000;
|
||||
private static final int WHITE = 0xFFFFFFFF;
|
||||
private static final int margin = 0;
|
||||
|
||||
public static String generateBarcode(String barcodeValue,String fileName) {
|
||||
try {
|
||||
String geneFilePath = "/Users/limqhz/home/test/" + fileName;
|
||||
makeBarcode(geneFilePath,barcodeValue);
|
||||
return geneFilePath;
|
||||
}catch (WriterException e) {
|
||||
throw new ServiceException("生成二维码图片文件有问题");
|
||||
}
|
||||
}
|
||||
|
||||
private static void makeBarcode(String path, String barcodeValue) throws WriterException {
|
||||
//二维码内容
|
||||
String content = barcodeValue;
|
||||
String format = "jpg";
|
||||
int width = 200; // 二维码宽度
|
||||
int height = 200;// 二维码高度
|
||||
// 设置二维码矩阵的信息
|
||||
BitMatrix bitMatrix = setBitMatrix(content, width, height);
|
||||
// 设置输出流
|
||||
OutputStream outStream = null;
|
||||
try {
|
||||
outStream = new FileOutputStream(new File(path));
|
||||
// 目前 针对容错等级为H reduceWhiteArea 二维码空白区域的大小 根据实际情况设置,如果二维码内容长度不固定的话 需要自己根据实际情况计算reduceWhiteArea的大小
|
||||
writeToFile(bitMatrix, format, outStream, 5);
|
||||
outStream.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
try {
|
||||
outStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置生成二维码矩阵信息
|
||||
* @param content 二维码图片内容
|
||||
* @param width 二维码图片宽度
|
||||
* @param height 二维码图片高度
|
||||
* @throws WriterException
|
||||
*/
|
||||
private static BitMatrix setBitMatrix(String content, int width, int height) throws WriterException {
|
||||
BitMatrix bitMatrix = null;
|
||||
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 指定编码方式,避免中文乱码
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 指定纠错等级 如果二维码里面的内容比较多的话推荐使用H 容错率30%, 这样可以避免一些扫描不出来的问题
|
||||
hints.put(EncodeHintType.MARGIN, margin); // 指定二维码四周白色区域大小 官方的这个方法目前没有没有作用默认设置为0
|
||||
bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
|
||||
return bitMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param matrix
|
||||
* @param format
|
||||
* @param outStream
|
||||
* @param reduceWhiteArea 二维码空白区域设置
|
||||
* @throws IOException
|
||||
*/
|
||||
|
||||
private static void writeToFile(BitMatrix matrix, String format, OutputStream outStream, int reduceWhiteArea) throws IOException {
|
||||
BufferedImage image = toBufferedImage(matrix, reduceWhiteArea);
|
||||
ImageIO.write(image, format, outStream);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param matrix
|
||||
* @param reduceWhiteArea
|
||||
* @return
|
||||
*/
|
||||
private static BufferedImage toBufferedImage(BitMatrix matrix, int reduceWhiteArea) {
|
||||
int width = matrix.getWidth();
|
||||
int height = matrix.getHeight();
|
||||
BufferedImage image = new BufferedImage(width - 2 * reduceWhiteArea, height - 2 * reduceWhiteArea, BufferedImage.TYPE_3BYTE_BGR);
|
||||
for (int x = reduceWhiteArea; x < width - reduceWhiteArea; x++) {
|
||||
for (int y = reduceWhiteArea; y < height - reduceWhiteArea; y++) {
|
||||
image.setRGB(x - reduceWhiteArea, y - reduceWhiteArea, matrix.get(x, y) ? BLACK : WHITE);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user