parent
4d7e6c3650
commit
4a4c5623aa
12
pom.xml
12
pom.xml
|
|
@ -112,6 +112,18 @@
|
|||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- zxing生成二维码 -->
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>3.5.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>javase</artifactId>
|
||||
<version>3.5.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
|
|
|
|||
|
|
@ -9,10 +9,7 @@ import com.chaozhanggui.system.cashierservice.service.PayService;
|
|||
import com.chaozhanggui.system.cashierservice.util.DateUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Date;
|
||||
|
|
@ -69,6 +66,11 @@ public class NotifyController {
|
|||
|
||||
}
|
||||
|
||||
@RequestMapping("test")
|
||||
public void test(@RequestParam String payOrderNO){
|
||||
payService.test(payOrderNO);
|
||||
}
|
||||
|
||||
@RequestMapping("notifyCallBack")
|
||||
public String notifyCallBack(HttpServletRequest request){
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ public interface TbShopUserMapper {
|
|||
int updateByPrimaryKeySelective(TbShopUser record);
|
||||
|
||||
int updateByPrimaryKey(TbShopUser record);
|
||||
int upUserBYId(TbShopUser record);
|
||||
|
||||
|
||||
TbShopUser selectByUserIdAndShopId(@Param("userId") String userId,@Param("shopId") String shopId);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.chaozhanggui.system.cashierservice.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
|
@ -60,4 +61,12 @@ public class TbCashierCart implements Serializable {
|
|||
private TbProductSpec tbProductSpec;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public String getSkuName() {
|
||||
if(StringUtils.isNotBlank(skuName)){
|
||||
return skuName;
|
||||
}else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.chaozhanggui.system.cashierservice.netty;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Slf4j
|
||||
public class ConnectionDebouncerHandler extends ChannelDuplexHandler {
|
||||
private static final Map<Channel, Long> lastConnectionTimes = new ConcurrentHashMap<>();
|
||||
private static final long debounceIntervalMillis = 5*1000; // 防抖时间间隔,单位:毫秒
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
Channel channel = ctx.channel();
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
Long lastConnectionTime = lastConnectionTimes.get(channel);
|
||||
if (lastConnectionTime == null || (currentTimeMillis - lastConnectionTime) > debounceIntervalMillis) {
|
||||
// 允许新连接
|
||||
lastConnectionTimes.put(channel, currentTimeMillis);
|
||||
super.channelActive(ctx); // 将事件传递给下一个处理器
|
||||
} else {
|
||||
|
||||
channel.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ public class HeartbeatHandler extends ChannelDuplexHandler {
|
|||
super.userEventTriggered(ctx, evt);
|
||||
} else if (event.state() == IdleState.WRITER_IDLE) {
|
||||
// log.info("发送心跳");
|
||||
ctx.channel().writeAndFlush(new TextWebSocketFrame("Heartbeat")).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
|
||||
ctx.channel().writeAndFlush(new TextWebSocketFrame("{\"type\":\"heartbeat\"}")).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
|
||||
// ctx.writeAndFlush(HEARTBEAT_SEQUENCE.duplicate()).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -11,14 +11,10 @@ import io.netty.handler.ssl.SslContextBuilder;
|
|||
import io.netty.handler.stream.ChunkedWriteHandler;
|
||||
import io.netty.handler.timeout.IdleStateHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Component
|
||||
|
|
@ -35,6 +31,8 @@ public class PushToAppChannelInitializer extends ChannelInitializer<NioSocketCha
|
|||
pipeline.addLast(new IdleStateHandler(30, 10, 120, TimeUnit.SECONDS));
|
||||
pipeline.addLast(new HeartbeatHandler());
|
||||
|
||||
// 添加连接防抖处理器(没用)
|
||||
// pipeline.addLast(new ConnectionDebouncerHandler());
|
||||
//本地试调时使用
|
||||
// SslContext sslContext = SslContextBuilder.forServer(loadResourceAsByteArrayInputStream("\\pem\\fullchain.pem"), loadResourceAsByteArrayInputStream("\\pem\\privkey.key")).build();
|
||||
// pipeline.addLast(sslContext.newHandler(ch.alloc()));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,187 @@
|
|||
package com.chaozhanggui.system.cashierservice.netty;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.chaozhanggui.system.cashierservice.netty.config.NettyChannelHandlerAdapter;
|
||||
import com.chaozhanggui.system.cashierservice.util.JSONUtil;
|
||||
import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
/**
|
||||
* 客户端
|
||||
*/
|
||||
@Slf4j
|
||||
@Sharable
|
||||
@Component
|
||||
public class PushToClientChannelHandlerAdapter extends NettyChannelHandlerAdapter {
|
||||
|
||||
/**
|
||||
* [shopId, [clientId, ctx]]
|
||||
*/
|
||||
private static Map<String, ConcurrentHashMap<String, ChannelHandlerContext>> webSocketMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* [ctx, shopId:clientId]
|
||||
*/
|
||||
private static Map<ChannelHandlerContext, String> clientIdMap = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
private String clientId = "";
|
||||
private String shopId = "";
|
||||
|
||||
public PushToClientChannelHandlerAdapter() {
|
||||
}
|
||||
|
||||
public static PushToClientChannelHandlerAdapter getInstance() {
|
||||
return new PushToClientChannelHandlerAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
log.info("netty连接client 长连接激活");
|
||||
super.channelActive(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) {
|
||||
log.info("netty连接client 长连接关闭:{}, {}",clientId,shopId);
|
||||
ctx.close();
|
||||
removeCtx(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除ctx
|
||||
*/
|
||||
private void removeCtx(ChannelHandlerContext ctx) {
|
||||
// shopId:clientId
|
||||
String key = clientIdMap.get(ctx);
|
||||
if (StringUtils.isNotBlank(key)) {
|
||||
String[] split = key.split(":");
|
||||
ConcurrentHashMap<String, ChannelHandlerContext> tableMap = webSocketMap.get(split[0]);
|
||||
if (tableMap != null && !tableMap.isEmpty() && tableMap.size() > 0) {
|
||||
tableMap.remove(split[1]);
|
||||
if (tableMap.isEmpty() || tableMap.size() == 0) {
|
||||
webSocketMap.remove(split[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
clientIdMap.remove(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelReadComplete(ChannelHandlerContext ctx) {
|
||||
super.channelReadComplete(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
super.exceptionCaught(ctx, cause);
|
||||
removeCtx(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, String msg) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
if (StringUtils.isNotEmpty(msg)) {
|
||||
jsonObject = JSONObject.parseObject(msg);
|
||||
}else {
|
||||
log.info("netty连接client 接收到空数据:{}",msg);
|
||||
}
|
||||
String type = jsonObject.getString("type");
|
||||
if(type.equals("heartbeat")){//心跳
|
||||
log.info("netty连接client 接收到心跳数据:shop:{} clientId:{} meg:{}",shopId,clientId,msg);
|
||||
}else {
|
||||
if (type.equals("connect")) {
|
||||
String clientId = jsonObject.getString("clientId");
|
||||
String shopId = jsonObject.getString("shopId");
|
||||
if (StringUtils.isBlank(type) || StringUtils.isBlank(shopId) || StringUtils.isBlank(clientId)) {
|
||||
log.info("netty连接client 建立连接请求失败:{}",jsonObject);
|
||||
channelInactive(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("netty连接client 接收到数据 建立连接参数 param:{}",jsonObject);
|
||||
this.clientId=clientId;
|
||||
this.shopId=shopId;
|
||||
if (webSocketMap.containsKey(shopId)) {
|
||||
ConcurrentHashMap<String, ChannelHandlerContext> clientSocketMap = webSocketMap.get(shopId);
|
||||
clientSocketMap.put(clientId, ctx);
|
||||
} else {
|
||||
ConcurrentHashMap<String, ChannelHandlerContext> clientSocketMap = new ConcurrentHashMap<>();
|
||||
clientSocketMap.put(clientId, ctx);
|
||||
webSocketMap.put(shopId,clientSocketMap);
|
||||
}
|
||||
clientIdMap.put(ctx, shopId + ":" + clientId);
|
||||
JSONObject jsonObject1 = new JSONObject();
|
||||
jsonObject1.put("status", "success");
|
||||
jsonObject1.put("msg", "连接成功");
|
||||
jsonObject1.put("type", "connect");
|
||||
sendMesToApp(jsonObject1.toString(), ctx);
|
||||
}
|
||||
}
|
||||
//业务逻辑代码处理框架。。。
|
||||
ctx.flush();
|
||||
}
|
||||
|
||||
public void sendMesToApp(String str, ChannelHandlerContext ctx) {
|
||||
sendMessage(ctx, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message 发送的消息内容
|
||||
* @param shopId 店铺Id
|
||||
* @param clientId 客户端Id
|
||||
* @param userFlag
|
||||
* 为true 单发给clientId
|
||||
* 为false 群发 shopId为空 发给所有人
|
||||
*/
|
||||
@Async
|
||||
public void AppSendInfo(String message, String shopId,String clientId, boolean userFlag) {
|
||||
log.info("netty连接client 发送消息 shopId:{} clientId:{} userFlag:{} message:{}",shopId,clientId,userFlag, JSONUtil.toJSONString(message));
|
||||
if (userFlag) {
|
||||
if (webSocketMap.containsKey(shopId)) {
|
||||
ConcurrentHashMap<String, ChannelHandlerContext> webSockets = webSocketMap.get(shopId);
|
||||
if(!webSockets.isEmpty()){
|
||||
if (StringUtils.isNotBlank(clientId)) {
|
||||
ChannelHandlerContext ctx = webSockets.get(clientId);
|
||||
if (ctx != null) {
|
||||
sendMesToApp(message,ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (StringUtils.isEmpty(shopId)) {
|
||||
// 向所有用户发送信息
|
||||
for (ConcurrentHashMap<String, ChannelHandlerContext> value : webSocketMap.values()) {
|
||||
for (ChannelHandlerContext ctx : value.values()) {
|
||||
sendMesToApp(message,ctx);
|
||||
}
|
||||
}
|
||||
} else if (webSocketMap.containsKey(shopId)) {
|
||||
ConcurrentHashMap<String, ChannelHandlerContext> webSockets = webSocketMap.get(shopId);
|
||||
if(!webSockets.isEmpty()) {
|
||||
for (String user : webSockets.keySet()) {
|
||||
ChannelHandlerContext ctx = webSockets.get(user);
|
||||
if (ctx != null) {
|
||||
log.info("netty连接client 发送消息 桌码群发 clientId:{}",user);
|
||||
sendMesToApp(message,ctx);
|
||||
}else {
|
||||
log.info("netty连接client 发送消息 桌码群发 clientId:{} 失败",user);
|
||||
}
|
||||
}
|
||||
}else {
|
||||
log.info("netty连接client 发送消息 桌码群发 clientId:{} 失败",clientId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package com.chaozhanggui.system.cashierservice.netty;
|
||||
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||
import io.netty.handler.codec.http.HttpServerCodec;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.stream.ChunkedWriteHandler;
|
||||
import io.netty.handler.timeout.IdleStateHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import java.io.InputStream;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class PushToClientChannelInitializer extends ChannelInitializer<NioSocketChannel> {
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void initChannel(NioSocketChannel ch) throws SSLException {
|
||||
ChannelPipeline pipeline = ch.pipeline();
|
||||
|
||||
// 添加心跳处理器 多久没收到消息 断开 心跳时间(秒) 读写空闲时间(秒)
|
||||
pipeline.addLast(new IdleStateHandler(30, 10, 120, TimeUnit.SECONDS));
|
||||
pipeline.addLast(new HeartbeatHandler());
|
||||
// 添加连接防抖处理器(没用)
|
||||
// pipeline.addLast(new ConnectionDebouncerHandler());
|
||||
//本地试调时使用 wss
|
||||
// SslContext sslContext = SslContextBuilder.forServer(loadResourceAsByteArrayInputStream("\\pem\\fullchain.pem"), loadResourceAsByteArrayInputStream("\\pem\\privkey.key")).build();
|
||||
// pipeline.addLast(sslContext.newHandler(ch.alloc()));
|
||||
|
||||
// 添加HttpServerCodec用于处理HTTP编解码
|
||||
pipeline.addLast(new HttpServerCodec());
|
||||
pipeline.addLast(new ChunkedWriteHandler());
|
||||
pipeline.addLast(new HttpObjectAggregator(65536));
|
||||
pipeline.addLast(new WebSocketServerProtocolHandler("/client"));
|
||||
ch.pipeline().addLast(new PushToClientChannelHandlerAdapter());
|
||||
}
|
||||
|
||||
|
||||
public static InputStream loadResourceAsByteArrayInputStream(String path) {
|
||||
InputStream inputStream = PushToClientChannelInitializer.class.getClassLoader().getResourceAsStream(path);
|
||||
return inputStream;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.chaozhanggui.system.cashierservice.netty.config;
|
||||
|
||||
import com.chaozhanggui.system.cashierservice.netty.PushToAppChannelInitializer;
|
||||
import com.chaozhanggui.system.cashierservice.netty.PushToClientChannelInitializer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
|
@ -18,6 +19,9 @@ public class NettyConfig {
|
|||
@Value("${netty.server.port}")
|
||||
private int port;
|
||||
|
||||
@Value("${netty.server.client-port}")
|
||||
private int clientPort;
|
||||
|
||||
/**
|
||||
* 接收者的线程数
|
||||
*/
|
||||
|
|
@ -31,8 +35,11 @@ public class NettyConfig {
|
|||
|
||||
@Resource
|
||||
private PushToAppChannelInitializer pushToAppChannelInitializer;
|
||||
@Resource
|
||||
private PushToClientChannelInitializer pushToClientChannelInitializer;
|
||||
@PostConstruct
|
||||
public void startCameraNetty() {
|
||||
NettyUtils.getInstance().initNetty(port, parentGroupThreads, childGroupThreads, pushToAppChannelInitializer);
|
||||
NettyUtils.getInstance().initNetty(clientPort, parentGroupThreads, childGroupThreads, pushToClientChannelInitializer);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,9 +116,15 @@ public class LoginService {
|
|||
tbUserInfoMapper.updateByPrimaryKeySelective(userInfo);
|
||||
List<TbShopUser> tbShopUsers = tbShopUserMapper.selectAllByUserId(userInfo.getId().toString());
|
||||
for (TbShopUser tbShopUser : tbShopUsers) {
|
||||
tbShopUser.setTelephone(phone);
|
||||
tbShopUser.setUserId("");
|
||||
tbShopUser.setUpdatedAt(System.currentTimeMillis());
|
||||
tbShopUserMapper.updateByPrimaryKey(tbShopUser);
|
||||
tbShopUserMapper.upUserBYId(tbShopUser);
|
||||
}
|
||||
List<TbShopUser> tbShopUsers1 = tbShopUserMapper.selectByPhone(telephone);
|
||||
for (TbShopUser tbShopUser : tbShopUsers1) {
|
||||
tbShopUser.setUpdatedAt(System.currentTimeMillis());
|
||||
tbShopUser.setUserId(userInfo.getId().toString());
|
||||
tbShopUserMapper.upUserBYId(tbShopUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.chaozhanggui.system.cashierservice.entity.vo.ShopUserListVo;
|
|||
import com.chaozhanggui.system.cashierservice.exception.MsgException;
|
||||
import com.chaozhanggui.system.cashierservice.model.PayReq;
|
||||
import com.chaozhanggui.system.cashierservice.model.TradeQueryReq;
|
||||
import com.chaozhanggui.system.cashierservice.netty.PushToClientChannelHandlerAdapter;
|
||||
import com.chaozhanggui.system.cashierservice.rabbit.RabbitProducer;
|
||||
import com.chaozhanggui.system.cashierservice.redis.RedisCst;
|
||||
import com.chaozhanggui.system.cashierservice.redis.RedisUtil;
|
||||
|
|
@ -148,6 +149,9 @@ public class PayService {
|
|||
if(!"unpaid".equals(orderInfo.getStatus())&&!"paying".equals(orderInfo.getStatus())){
|
||||
return Result.fail("订单状态异常,不允许支付");
|
||||
}
|
||||
if (System.currentTimeMillis() - orderInfo.getCreatedAt() > 60 * 15 * 1000) {
|
||||
return Result.fail("订单十五分钟内有效,当前已超时,请重新下单。");
|
||||
}
|
||||
|
||||
if(ObjectUtil.isNull(orderInfo.getMerchantId())||ObjectUtil.isEmpty(orderInfo.getMerchantId())){
|
||||
return Result.fail("没有对应的商户");
|
||||
|
|
@ -304,6 +308,9 @@ public class PayService {
|
|||
if (ObjectUtil.isEmpty(orderInfo)) {
|
||||
return Result.fail("订单信息不存在");
|
||||
}
|
||||
if (System.currentTimeMillis() - orderInfo.getCreatedAt() > 60 * 15 * 1000) {
|
||||
return Result.fail("订单十五分钟内有效,当前已超时,请重新下单。");
|
||||
}
|
||||
|
||||
|
||||
TbUserInfo userInfo= tbUserInfoMapper.selectByPrimaryKey(Integer.valueOf(orderInfo.getUserId()));
|
||||
|
|
@ -321,7 +328,7 @@ public class PayService {
|
|||
|
||||
|
||||
if (!"unpaid".equals(orderInfo.getStatus()) && !"paying".equals(orderInfo.getStatus()) ) {
|
||||
return Result.fail("订单出状态异常");
|
||||
return Result.fail("订单状态异常");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -384,7 +391,7 @@ public class PayService {
|
|||
producer.putOrderCollect(jsonObject.toJSONString());
|
||||
|
||||
producer.printMechine(orderId);
|
||||
|
||||
sendOrderToClient(orderInfo);
|
||||
return Result.success(CodeEnum.SUCCESS,"1");
|
||||
}
|
||||
|
||||
|
|
@ -717,7 +724,8 @@ public class PayService {
|
|||
|
||||
log.info("发送打印数据");
|
||||
producer.printMechine(orderInfo.getId() + "");
|
||||
|
||||
sendOrderToClient(orderInfo);
|
||||
redisUtil.deleteByKey(RedisCst.ORDER_EXPIRED.concat(orderInfo.getId().toString()));
|
||||
return Result.success(CodeEnum.SUCCESS,orderId);
|
||||
case "REFUND_ING":
|
||||
cartStatus="refunding";
|
||||
|
|
@ -751,11 +759,6 @@ public class PayService {
|
|||
}
|
||||
|
||||
|
||||
// if("0".equals(userInfo.getIsPwd())){
|
||||
// return Result.fail("用户支付密码未设置");
|
||||
// }
|
||||
|
||||
|
||||
TbShopInfo shopInfo= tbShopInfoMapper.selectByPrimaryKey(Integer.valueOf(shopId));
|
||||
if(ObjectUtil.isEmpty(shopInfo)){
|
||||
return Result.fail("对应的店铺信息不存在");
|
||||
|
|
@ -872,7 +875,8 @@ public class PayService {
|
|||
|
||||
log.info("发送打印数据");
|
||||
producer.printMechine(orderInfo.getId() + "");
|
||||
|
||||
sendOrderToClient(orderInfo);
|
||||
redisUtil.deleteByKey(RedisCst.ORDER_EXPIRED.concat(orderInfo.getId().toString()));
|
||||
return "SUCCESS";
|
||||
|
||||
}
|
||||
|
|
@ -917,6 +921,8 @@ public class PayService {
|
|||
coupons.put("type","buy");
|
||||
coupons.put("orderId",orderInfo.getId().toString());
|
||||
producer.printCoupons(coupons.toJSONString());
|
||||
sendOrderToClient(orderInfo);
|
||||
redisUtil.deleteByKey(RedisCst.ORDER_EXPIRED.concat(orderInfo.getId().toString()));
|
||||
return "SUCCESS";
|
||||
|
||||
}
|
||||
|
|
@ -979,7 +985,11 @@ public class PayService {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void test(String payOrderNO) {
|
||||
TbOrderInfo orderInfo = tbOrderInfoMapper.selectByPayOrderNo(payOrderNO);
|
||||
sendOrderToClient(orderInfo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1170,6 +1180,34 @@ public class PayService {
|
|||
return "SUCCESS";
|
||||
}
|
||||
|
||||
public void sendOrderToClient(TbOrderInfo orderInfo) {
|
||||
List<TbCashierCart> tbCashierCarts = tbCashierCartMapper.selectByOrderId(orderInfo.getId().toString(), null);
|
||||
JSONObject client = new JSONObject();
|
||||
JSONObject order = new JSONObject();
|
||||
order.put("orderNo",orderInfo.getOrderNo());
|
||||
order.put("masterId",StringUtils.isNotBlank(orderInfo.getMasterId())?orderInfo.getMasterId():"");
|
||||
order.put("tableName",StringUtils.isNotBlank(orderInfo.getTableName())?orderInfo.getTableName():"");
|
||||
client.put("carts", tbCashierCarts);
|
||||
client.put("type", "order");
|
||||
client.put("amount", orderInfo.getPayAmount());
|
||||
client.put("remark", StringUtils.isNotBlank(orderInfo.getRemark())?orderInfo.getRemark():"");
|
||||
client.put("orderInfo", order);
|
||||
client.put("createdAt", orderInfo.getCreatedAt());
|
||||
client.put("outNumber", StringUtils.isNotBlank(orderInfo.getOutNumber())?orderInfo.getOutNumber():"");
|
||||
// client.put("outNumberCode", "");
|
||||
// if(StringUtils.isNotBlank(orderInfo.getOutNumber())){
|
||||
// try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
|
||||
// QrCodeUtils.createCodeToOutputStream(orderInfo.getOutNumber(), outputStream);
|
||||
// String s = Base64Utils.encodeToString(outputStream.toByteArray());
|
||||
// client.put("outNumberCode", s);
|
||||
// } catch (Exception e) {
|
||||
// log.info("生成 失败");
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
PushToClientChannelHandlerAdapter.getInstance().AppSendInfo(client.toString(), orderInfo.getShopId(), "", false);
|
||||
}
|
||||
|
||||
|
||||
// public Result returnOrder(){
|
||||
//
|
||||
|
|
|
|||
|
|
@ -0,0 +1,115 @@
|
|||
package com.chaozhanggui.system.cashierservice.util;
|
||||
|
||||
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 org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.filechooser.FileSystemView;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 二维码工具类
|
||||
*
|
||||
* @author GYJ
|
||||
*/
|
||||
public class QrCodeUtils {
|
||||
|
||||
//CODE_WIDTH:二维码宽度,单位像素
|
||||
private static final int CODE_WIDTH = 400;
|
||||
//CODE_HEIGHT:二维码高度,单位像素
|
||||
private static final int CODE_HEIGHT = 400;
|
||||
//FRONT_COLOR:二维码前景色,0x000000 表示黑色
|
||||
private static final int FRONT_COLOR = 0x000000;
|
||||
//BACKGROUND_COLOR:二维码背景色,0xFFFFFF 表示白色
|
||||
//演示用 16 进制表示,和前端页面 CSS 的取色是一样的,注意前后景颜色应该对比明显,如常见的黑白
|
||||
private static final int BACKGROUND_COLOR = 0xFFFFFF;
|
||||
|
||||
public static void createCodeToFile(String content, File codeImgFileSaveDir, String fileName) {
|
||||
try {
|
||||
if (StringUtils.isBlank(content) || StringUtils.isBlank(fileName)) {
|
||||
return;
|
||||
}
|
||||
content = content.trim();
|
||||
if (codeImgFileSaveDir==null || codeImgFileSaveDir.isFile()) {
|
||||
//二维码图片存在目录为空,默认放在桌面...
|
||||
codeImgFileSaveDir = FileSystemView.getFileSystemView().getHomeDirectory();
|
||||
}
|
||||
if (!codeImgFileSaveDir.exists()) {
|
||||
//二维码图片存在目录不存在,开始创建...
|
||||
codeImgFileSaveDir.mkdirs();
|
||||
}
|
||||
|
||||
//核心代码-生成二维码
|
||||
BufferedImage bufferedImage = getBufferedImage(content);
|
||||
|
||||
File codeImgFile = new File(codeImgFileSaveDir, fileName);
|
||||
ImageIO.write(bufferedImage, "png", codeImgFile);
|
||||
|
||||
System.out.println("二维码图片生成成功:" + codeImgFile.getPath());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成二维码并输出到输出流, 通常用于输出到网页上进行显示,输出到网页与输出到磁盘上的文件中,区别在于最后一句 ImageIO.write
|
||||
* write(RenderedImage im,String formatName,File output):写到文件中
|
||||
* write(RenderedImage im,String formatName,OutputStream output):输出到输出流中
|
||||
* @param content :二维码内容
|
||||
* @param outputStream :输出流,比如 HttpServletResponse 的 getOutputStream
|
||||
*/
|
||||
public static void createCodeToOutputStream(String content, OutputStream outputStream) {
|
||||
try {
|
||||
if (StringUtils.isBlank(content)) {
|
||||
return;
|
||||
}
|
||||
content = content.trim();
|
||||
//核心代码-生成二维码
|
||||
BufferedImage bufferedImage = getBufferedImage(content);
|
||||
|
||||
//区别就是这一句,输出到输出流中,如果第三个参数是 File,则输出到文件中
|
||||
ImageIO.write(bufferedImage, "png", outputStream);
|
||||
|
||||
System.out.println("二维码图片生成到输出流成功...");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
//核心代码-生成二维码
|
||||
private static BufferedImage getBufferedImage(String content) throws WriterException {
|
||||
|
||||
//com.google.zxing.EncodeHintType:编码提示类型,枚举类型
|
||||
Map<EncodeHintType, Object> hints = new HashMap();
|
||||
|
||||
//EncodeHintType.CHARACTER_SET:设置字符编码类型
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
|
||||
|
||||
//EncodeHintType.ERROR_CORRECTION:设置误差校正
|
||||
//ErrorCorrectionLevel:误差校正等级,L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction
|
||||
//不设置时,默认为 L 等级,等级不一样,生成的图案不同,但扫描的结果是一样的
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
|
||||
|
||||
//EncodeHintType.MARGIN:设置二维码边距,单位像素,值越小,二维码距离四周越近
|
||||
hints.put(EncodeHintType.MARGIN, 1);
|
||||
|
||||
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
|
||||
BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, CODE_WIDTH, CODE_HEIGHT, hints);
|
||||
BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_BGR);
|
||||
for (int x = 0; x < CODE_WIDTH; x++) {
|
||||
for (int y = 0; y < CODE_HEIGHT; y++) {
|
||||
bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR);
|
||||
}
|
||||
}
|
||||
return bufferedImage;
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ websocket:
|
|||
netty:
|
||||
server:
|
||||
port: 9999
|
||||
client-port: 9998
|
||||
# 接收者的线程数
|
||||
parent-group-threads: 10
|
||||
# 客户端的线程数
|
||||
|
|
|
|||
|
|
@ -380,6 +380,15 @@
|
|||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
|
||||
|
||||
<update id="upUserBYId" parameterType="com.chaozhanggui.system.cashierservice.entity.TbShopUser">
|
||||
update tb_shop_user
|
||||
set
|
||||
user_id = #{userId,jdbcType=VARCHAR},
|
||||
updated_at = #{updatedAt,jdbcType=BIGINT}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
|
||||
<select id="selectByUserIdAndShopId" resultMap="BaseResultMap">
|
||||
select * from tb_shop_user where user_id=#{userId} and shop_id=#{shopId}
|
||||
</select>
|
||||
|
|
|
|||
Loading…
Reference in New Issue