篮球通过微信支付下订单,出场10分钟结束订单,该退钱退钱

This commit is contained in:
2023-12-31 02:16:06 +08:00
parent a304d49cb4
commit e155801472
13 changed files with 485 additions and 271 deletions

View File

@@ -2,12 +2,12 @@ package com.sv.api.controller;
import com.enums.EnterEnum;
import com.enums.PayTypeEnum;
import com.sv.api.context.PlatformContext;
import com.sv.dto.BasketEnterResult;
import com.sv.entity.Device;
import com.sv.entity.Order;
import com.sv.entity.Venue;
import com.sv.service.api.OrderService;
import com.sv.service.api.VenueEnterService;
import com.sv.service.api.VenueService;
import com.sv.service.common.BarcodeService;
import com.sv.service.common.DoorLockUtil;
@@ -40,6 +40,8 @@ public class VenueController extends BaseApiController {
@Resource
private VenueService venueService;
@Resource
private VenueEnterService venueEnterService;
@Resource
private BarcodeService barcodeService;
@Resource
private DoorLockUtil doorLockUtil;
@@ -112,15 +114,15 @@ public class VenueController extends BaseApiController {
OrderService orderService;
/**
* 判断是否支付成功
* @param venueId 场馆Id
* @param orderSn 订单号
* @return
*/
@RequestMapping(value = "/member/isPayed", method = RequestMethod.POST)
public ResponseDTO isPayed(@RequestParam("venueId") Integer venueId,String orderSn) {
public ResponseDTO isPayed(@RequestParam("orderSn") String orderSn) {
Integer memberId = getMemberIdByAccessToken();
Order order = orderService.findOrderSn(orderSn, memberId);
boolean isPayed = false;
if (orderSn != null && order.getPayStatus() != null && PayStatusEnum.PAYED.getValue() == order.getPayStatus()) {
if (order != null && order.getPayStatus() != null && PayStatusEnum.PAYED.getValue() == order.getPayStatus()) {
isPayed = true;
}
return ResponseDTO.ok().addAttribute("isPayed", isPayed);
@@ -147,7 +149,7 @@ public class VenueController extends BaseApiController {
throw new ServiceException("有人正在使用门禁,请稍后再试");
}
Integer memberId = getMemberIdByAccessToken();
join = venueService.join(memberId, venueId);
join = venueEnterService.join(memberId, venueId);
return ResponseDTO.ok().addAttribute("join", join);
}
@@ -172,7 +174,7 @@ public class VenueController extends BaseApiController {
throw new ServiceException("有人正在使用门禁,请稍后再试");
}
Integer memberId = getMemberIdByAccessToken();
out = venueService.out(memberId, venueId);
out = venueEnterService.out(memberId, venueId);
return ResponseDTO.ok().addAttribute("out", out);
}
@@ -185,11 +187,8 @@ public class VenueController extends BaseApiController {
@RequestMapping(value = "/venue/generate/barcode", method = RequestMethod.POST)
public ResponseDTO generateBarcode(@RequestParam("orderSn") String orderSn,@RequestParam("venueId") Integer venueId,Integer enterFlag) {
Device byDevice = deviceService.findByDevice(venueId);
BasketEnterResult join = new BasketEnterResult();
if (byDevice == null) {
join.setFlg(999);
join.setMsg("通讯异常,门禁设备离线中");
return ResponseDTO.ok().addAttribute("join", join);
throw new ServiceException("门禁通讯异常");
}
String doorSn = byDevice.getName();
boolean lockStat = doorLockUtil.checkDoorLock(doorSn);
@@ -206,17 +205,14 @@ public class VenueController extends BaseApiController {
}
/**
* 余额充值
* 篮球入场下订单
*/
@RequestMapping(value = "/venue/basketball/pay", method = RequestMethod.POST)
@AccessToken
public ResponseDTO recharge(@RequestParam("venueId") Integer venueId){
public ResponseDTO basketPay(@RequestParam("venueId") Integer venueId,@RequestParam("payMoney") Double payMoney){
Device byDevice = deviceService.findByDevice(venueId);
BasketEnterResult join = new BasketEnterResult();
if (byDevice == null) {
join.setFlg(999);
join.setMsg("通讯异常,门禁设备离线中");
return ResponseDTO.ok().addAttribute("join", join);
throw new ServiceException("门禁通讯异常");
}
String doorSn = byDevice.getName();
boolean lockStat = doorLockUtil.checkDoorLock(doorSn);
@@ -225,7 +221,7 @@ public class VenueController extends BaseApiController {
}
Integer memberId = getMemberIdByAccessToken();
return ResponseDTO.ok().
addAttribute("pay",orderService.createEnterVenueOrder(venueId, memberId, PayTypeEnum.WEI_XIN,new BigDecimal(10)));
addAttribute("pay",orderService.createEnterVenueOrder(venueId, memberId, PayTypeEnum.WEI_XIN, new BigDecimal(payMoney)));
}
}

View File

@@ -5,6 +5,7 @@ import com.enums.EnterEnum;
import com.sv.dto.BasketEnterResult;
import com.sv.netty.netty.service.MessageService;
import com.sv.netty.utils.JsonUtils;
import com.sv.service.api.VenueEnterService;
import com.sv.service.api.VenueService;
import com.sv.service.common.BarcodeService;
import com.sv.service.common.DoorLockUtil;
@@ -20,7 +21,7 @@ import javax.annotation.Resource;
public class VenueJoinTest {
@Resource
VenueService venueService;
VenueEnterService venueEnterService;
@Resource
MessageService messageService;
@Resource
@@ -30,7 +31,7 @@ public class VenueJoinTest {
@Test
public void testJoin(){
BasketEnterResult join = venueService.join(535, 32);
BasketEnterResult join = venueEnterService.join(535, 32);
System.out.println(JsonUtils.encode(join));
if (join.getFlg() == 0) {
String barcode = barcodeService.newBarcode("doorSn", "",EnterEnum.ENTER, 32, 535);
@@ -46,7 +47,7 @@ public class VenueJoinTest {
@Test
public void testOut(){
BasketEnterResult out = venueService.out(535, 32);
BasketEnterResult out = venueEnterService.out(535, 32);
System.out.println(JsonUtils.encode(out));
if (out.getFlg() == 0) {
String barcode = barcodeService.newBarcode("doorSn","", EnterEnum.OUT, 32, 535);

View File

@@ -32,7 +32,7 @@ public class WxServiceTest {
public void refund(){
// wechatPayService.createUnifiedOrder("testlmq20231224",new BigDecimal(0.02),"127.0.0.1","JSAPI", 535);
// 根据orderSn查出对应订单信息
String orderSn = "231228000925924610";
String orderSn = "231231014749545739";
Integer memberId = 535;
Order order = orderService.findOrderSn(orderSn,memberId);
if (order == null){

View File

@@ -5,7 +5,7 @@ import java.math.BigDecimal;
public class BasketEnterResult implements Serializable {
/**
* 返回的字符串,根据结果显示
* 返回的字符串,根据结果显示 999-门禁异常 2-需要支付 0-成功 888-友情提示(十分钟内请及时进场)
*/
private Integer flg;

View File

@@ -19,7 +19,20 @@ public class BarcodeOrderTime {
private Integer status;
public BarcodeOrderTime(Integer id, Integer memberId, Integer venueId, Date createdTime, Date modifiedTime, Date orderStart, Date orderEnd, Integer status) {
/**
* 入场 paying = 0 不需要退款
* 出场未结算 paying = 1 需要退款
*/
private Integer paying;
/**
* 0- 按次
* 1- 按时
*/
private Integer payMoney;
private String orderSn;
public BarcodeOrderTime(Integer id, Integer memberId, Integer venueId, Date createdTime, Date modifiedTime, Date orderStart, Date orderEnd, Integer status ,Integer paying, Integer payMoney, String orderSn) {
this.id = id;
this.memberId = memberId;
this.venueId = venueId;
@@ -28,6 +41,9 @@ public class BarcodeOrderTime {
this.orderStart = orderStart;
this.orderEnd = orderEnd;
this.status = status;
this.paying = paying;
this.payMoney = payMoney;
this.orderSn = orderSn;
}
public BarcodeOrderTime() {
@@ -97,4 +113,28 @@ public class BarcodeOrderTime {
public void setStatus(Integer status) {
this.status = status;
}
}
public Integer getPaying() {
return paying;
}
public void setPaying(Integer paying) {
this.paying = paying;
}
public Integer getPayMoney() {
return payMoney;
}
public void setPayMoney(Integer payMoney) {
this.payMoney = payMoney;
}
public String getOrderSn() {
return orderSn;
}
public void setOrderSn(String orderSn) {
this.orderSn = orderSn;
}
}

View File

@@ -4,8 +4,17 @@ import com.enums.BarCodeStatusEnum;
import com.enums.StayEnum;
import com.sv.entity.BarcodeOrderTime;
import com.sv.entity.MemberEnterStatus;
import com.sv.entity.MemberRefund;
import com.sv.entity.Order;
import com.sv.mapper.BarcodeOrderTimeMapper;
import com.sv.mapper.MemberEnterStatusMapper;
import com.sv.mapper.MemberRefundMapper;
import com.sv.mapper.OrderMapper;
import com.sv.service.api.config.WechatPayService;
import com.sv.service.api.util.DateUtilCard;
import com.sv.service.oms.OrderService;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
@@ -13,6 +22,7 @@ import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@@ -29,6 +39,12 @@ public class BarcodeTimeOrderTask {
@Resource
BarcodeOrderTimeMapper barcodeOrderTimeMapper;
@Resource
OrderMapper orderMapper;
@Resource
MemberRefundMapper memberRefundMapper;
@Resource
WechatPayService wechatPayService;
@Scheduled(cron = "0 0/5 * * * ?")
public void execute(){
@@ -46,4 +62,51 @@ public class BarcodeTimeOrderTask {
}
}
@Scheduled(cron = "0 0/2 * * * ?")
public void refundOrder(){
logger.error("执行BarcodeTimeOrderTask.refundOrder");
// 查询用户已经过期的按次入场订单
List<BarcodeOrderTime> barcodeOrderTimes = barcodeOrderTimeMapper.needPayOrderList();
if (barcodeOrderTimes != null && barcodeOrderTimes.size() > 0){
Date date = new Date();
for (BarcodeOrderTime barcodeOrderTime : barcodeOrderTimes) {
int minutes = DateUtilCard.diffMinute(barcodeOrderTime.getModifiedTime(), date);
if (minutes < 10) {
continue;
}
barcodeOrderTime.setPaying(0);
barcodeOrderTime.setModifiedTime(date);
barcodeOrderTimeMapper.updateByPrimaryKey(barcodeOrderTime);
if (barcodeOrderTime.getPayMoney() <= 0) {
continue;
}
Order order = orderMapper.findOrderSn(barcodeOrderTime.getOrderSn(), barcodeOrderTime.getMemberId());
if (order != null) {
// 找到订单
logger.info("用户" + barcodeOrderTime.getMemberId() + "的订单" + barcodeOrderTime.getOrderSn() + "需要退款" + barcodeOrderTime.getPayMoney());
MemberRefund memberRefund = new MemberRefund();
memberRefund.setMemberId(barcodeOrderTime.getMemberId());
memberRefund.setLessonId(1);
memberRefund.setMoney(order.getPrice());
memberRefund.setOrderSn(barcodeOrderTime.getOrderSn());
memberRefund.setTransactionId(order.getTradeSn());
memberRefund.setOrderId(order.getId());
memberRefund.setOutRefundNo(createSn());//商户退款单号
memberRefund.setPlatformId(1);
memberRefundMapper.insert(memberRefund);
wechatPayService.refundInputMoney(memberRefund,new BigDecimal(barcodeOrderTime.getPayMoney()));
}
}
}
}
/**
* 生成订单号
*
* @return
*/
private String createSn() {
return DateFormatUtils.format(new Date(), "yyMMddHHmmss") + RandomStringUtils.randomNumeric(6);
}
}

View File

@@ -25,4 +25,8 @@ CREATE TABLE `sv_member_enter_status` (
-- 20231228 待执行
ALTER TABLE sv_barcode
ADD COLUMN order_sn varchar(200) NOT NULL AFTER barcode;
ADD COLUMN order_sn varchar(200) AFTER barcode;
ALTER TABLE `smart_venue`.`sv_barcode_order_time`
ADD COLUMN `paying` int(11) NULL COMMENT '入场 paying = 0 出场未结算 paying = 1' AFTER `status`,
ADD COLUMN `pay_money` int(11) NULL COMMENT '退款金额' AFTER `paying`,
ADD COLUMN `order_sn` varchar(200) NULL COMMENT '退款订单号' AFTER `pay_money`;

View File

@@ -25,4 +25,6 @@ public interface BarcodeOrderTimeMapper {
List<BarcodeOrderTime> endOrderList(@Param("currentDate") Date currentDate);
}
List<BarcodeOrderTime> needPayOrderList();
}

View File

@@ -1,6 +1,6 @@
package com.sv.service.api;
import com.enums.MoneyLogEnum;
import com.enums.BarCodeStatusEnum;
import com.enums.OrderPayEnum;
import com.enums.OrderTypeEnum;
import com.enums.PayTypeEnum;
@@ -9,10 +9,14 @@ import com.sv.dto.api.wechat.BaseResult;
import com.sv.dto.api.wechat.OrderPaySignResponse;
import com.sv.entity.*;
import com.sv.exception.api.ExceptionCodeTemplate;
import com.sv.mapper.BarcodeOrderTimeMapper;
import com.sv.mapper.OrderMapper;
import com.sv.mapper.VenueMapper;
import com.sv.mapper.VenuePriceMapper;
import com.sv.service.api.config.WechatPayService;
import com.sv.service.api.util.DateUtilCard;
import com.ydd.framework.core.common.Pagination;
import com.ydd.framework.core.common.utils.RequestUtils;
import com.ydd.framework.core.exception.ServiceException;
import com.ydd.framework.core.service.impl.BaseServiceImpl;
import com.ydd.oms.entity.enums.PayStatusEnum;
@@ -28,6 +32,7 @@ import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
@@ -56,9 +61,8 @@ public class OrderService extends BaseServiceImpl {
private MemberAuthService memberAuthService;
@Resource
private MemberService memberService;
@Resource
private MemberMoneyLogService memberMoneyLogService;
private VenuePriceMapper venuePriceMapper;
/**
* 创建订单
@@ -246,28 +250,52 @@ public class OrderService extends BaseServiceImpl {
* @param memberId
* @return
*/
public OrderPaySignResponse.WechatPayParam createEnterVenueOrder(Integer venueId, Integer memberId,PayTypeEnum payTypeEnum,BigDecimal price){
public OrderPaySignResponse.WechatPayParam createEnterVenueOrder(Integer venueId, Integer memberId, PayTypeEnum payTypeEnum, BigDecimal price){
Venue venue = venueMapper.findById(venueId);
if (venue == null) {
throw new ServiceException("未找到该场馆");
}
Member member = memberService.findById(memberId);
memberService.verify(member);
// 判断用户是否使用微信登录
MemberAuth memberAuth = memberAuthService.findByMemberId(memberId);
if (memberAuth == null){
throw new ServiceException(ExceptionCodeTemplate.BUY_ERROR);
}
List<VenuePrice> priceList = venuePriceMapper.findPrice(venueId);
if(priceList == null || priceList.size() <= 0) {
throw new ServiceException("价格非法!");
}
boolean checkPrice = false;
for (VenuePrice venuePrice : priceList) {
if (price.divideAndRemainder(price)[1].compareTo(BigDecimal.ZERO) == 0) {
// 取余数为0
checkPrice = true;
}
}
if (!checkPrice) {
throw new ServiceException("价格非法!");
}
//创建订单
Order order = new Order();
order.setOrderSn(createSn());
order.setPayType(payTypeEnum.value);
order.setPrice(price);
order.setPayTime(new Date());
order.setPayStatus(PayStatusEnum.PAYED.value);
order.setPayStatus(PayStatusEnum.NOT_PAY.value);
order.setType(OrderTypeEnum.BASKETBALL_ORDER.value);
order.setPlatformId(venue.getPlatformId());
order.setMemberId(memberId);
order.setParentOrderId(venueId); /** 篮球入场这里输入场馆ID */
orderMapper.insert(order);
//扣除用户余额 目前篮球订单不支持余额支付
// if(payTypeEnum.value.equals(PayTypeEnum.BALANCE.value)) {
// memberMoneyLogService.create(memberId, venue.getPlatformId(), MoneyLogEnum.JOIN.value, price.negate(), PayTypeEnum.BALANCE.value, null, venue.getId(), venue.getType(), null);
// }
OrderPaySignResponse.WechatPayParam wechatPayParam = memberCardOrderService.createUnifiedOrder(order.getOrderSn(), memberId,"ip","入场结算订单");
OrderPaySignResponse.WechatPayParam wechatPayParam = memberCardOrderService.createUnifiedOrder(order.getOrderSn(), memberId, RequestUtils.getIp(),"入场结算订单");
return wechatPayParam;
}
}

View File

@@ -0,0 +1,260 @@
package com.sv.service.api;
import com.enums.*;
import com.github.pagehelper.PageHelper;
import com.sv.dto.BasketEnterResult;
import com.sv.dto.api.MemberCardDTO;
import com.sv.dto.api.MemberCardVenuesDTO;
import com.sv.dto.api.VenueDTO;
import com.sv.entity.*;
import com.sv.exception.api.ExceptionCodeTemplate;
import com.sv.mapper.BarcodeOrderTimeMapper;
import com.sv.mapper.VenueMapper;
import com.sv.service.api.util.DateUtilCard;
import com.sv.service.api.util.GeoHashUtils;
import com.ydd.framework.core.common.Pagination;
import com.ydd.framework.core.common.utils.ValidationUtils;
import com.ydd.framework.core.exception.ServiceException;
import com.ydd.framework.core.service.impl.BaseServiceImpl;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
/**
* Service - 场馆
*
* @author zuojie.Liang
* @since 2018-08-02
*/
@Transactional
@Component
public class VenueEnterService extends BaseServiceImpl {
private final Logger logger = LoggerFactory.getLogger(VenueEnterService.class);
@Resource
private VenueMapper venueMapper;
@Resource
private MemberCardService memberCardService;
@Resource
private MemberService memberService;
@Resource
private MemberEnterVenueLogService memberEnterVenueLogService;
@Resource
private MemberMoneyLogService memberMoneyLogService;
@Resource
private VenuePriceService venuePriceService;
@Resource
BarcodeOrderTimeMapper barcodeOrderTimeMapper;
/**
* api 接口
* 我要进场
*/
public BasketEnterResult join(Integer memberId, Integer venueId) {
BasketEnterResult basketEnterResult = new BasketEnterResult();
basketEnterResult.setFlg(0);
// 判断用户是否登录
if (memberId == null) {
throw new ServiceException(com.ydd.framework.core.exception.ExceptionCodeTemplate.NEED_LOGIN);
}
//参数校验
ValidationUtils.assertNotNull(venueId);
// 2. 查询该场馆需要的费用,并比较用户余额是否足够
// 查询当前时间内,场馆对应的价格
String time = DateUtilCard.nowTime().toString();
Venue venue = venueMapper.findById(venueId);
VenuePrice venuePrice = venuePriceService.findPrice(venueId, time);
if (venuePrice == null) {
throw new ServiceException(ExceptionCodeTemplate.VENUE_ERROR);
}
BigDecimal price = venuePrice.getPrice();
if (PayStyleEnum.HOUR.getValue() == venue.getPayStyle()){
// 按时入场余额需要包含两个小时的场地费
price = price.multiply(new BigDecimal(2));
}
if (venuePrice == null) {
throw new ServiceException(ExceptionCodeTemplate.VENUE_ERROR);
}
int effOrder = barcodeOrderTimeMapper.findEffOrder(new Date(), memberId, venueId);
if (effOrder <= 0) {
if (price.compareTo(BigDecimal.ZERO) > 0) {
basketEnterResult.setFlg(2);
basketEnterResult.setMsg("订单金额"+ price + "元,请确认!");
basketEnterResult.setMoney(price);
}else {
// 不需要交钱,则不需要微信支付,直接展示二维码
Integer timePayHour = 2;
if(PayStyleEnum.TIME.getValue() == venue.getPayStyle()){
// 按次入场先收钱,且多久不收钱,出场不收钱
// 该用户上次订单的是否逾期
timePayHour = venue.getTimePayHour();
if (timePayHour == null) {
timePayHour = 4;
}
}
createBarcodeTimeOrder(memberId,venueId,timePayHour,"000");
}
} else {
// 还沿用原来订单
BarcodeOrderTime lastOrder = barcodeOrderTimeMapper.findLastOrder(memberId, venueId);
if (lastOrder != null) {
lastOrder.setPaying(0);
lastOrder.setModifiedTime(new Date());
barcodeOrderTimeMapper.updateByPrimaryKey(lastOrder);
}
}
// 3.判断用户有没有人脸识别的图像,根据用户ID查找一个用户只能有一条
// MemberFaceInfo memberFaceInfo = memberFaceInfoService.findByMemberId(memberId);
// if (memberFaceInfo == null) {
// flag = 1;
// return flag;
// }
return basketEnterResult;
}
/**
* 我要出场
* @param memberId
* @param venueId
* @return
*/
public BasketEnterResult out(Integer memberId, Integer venueId) {
BasketEnterResult result = new BasketEnterResult();
result.setFlg(0);
// 判断用户是否登录
if (memberId == null) {
throw new ServiceException(com.ydd.framework.core.exception.ExceptionCodeTemplate.NEED_LOGIN);
}
//参数校验
ValidationUtils.assertNotNull(venueId);
Venue venue = venueMapper.findById(venueId);
// 查询当前时间内,场馆对应的价格(健身房没有价格)
Member member = memberService.findByMember(memberId);
memberService.verify(member);
/**
* 篮球出场核心逻辑
*/
//判断余额是否够
// 1、找到入场时间
if(PayStyleEnum.HOUR.getValue() == venue.getPayStyle()){
// 按次出场不扣钱
BigDecimal price = BigDecimal.ZERO;
BarcodeOrderTime lastOrder = barcodeOrderTimeMapper.findLastOrder(memberId, venueId);
String enterTime = DateUtilCard.getTimeFromDate(lastOrder.getOrderStart());
Date dateNow = new Date();
if (dateNow.after(lastOrder.getOrderEnd())) {
// 当前时间已经超过订单结束日期,则该订单需要重新补收费
// 取入场的价格
VenuePrice venuePriceEnter = venuePriceService.findPrice(venueId, enterTime);
if (venuePriceEnter == null) {
throw new ServiceException(ExceptionCodeTemplate.VENUE_ERROR);
}
// 按时出场选择按照分钟四舍五入到角扣款
price = venuePriceEnter.getPrice();
int minutes = DateUtilCard.diffMinute(lastOrder.getOrderStart(), dateNow);
int hours = (minutes - 1) / 60;
// 需要补收的价格
price = price.multiply(new BigDecimal(hours - 1));
if (price.compareTo(BigDecimal.ZERO) > 0 ) {
result.setFlg(2);
result.setMoney(price);
result.setMsg("您此次入场超过2小时需补交" + price + "");
} else {
// 不需要补交钱且需要退钱
lastOrder.setPaying(1);
lastOrder.setPayMoney(price.intValue());
lastOrder.setModifiedTime(new Date());
barcodeOrderTimeMapper.updateByPrimaryKey(lastOrder);
result.setFlg(888);
result.setMsg("如要继续订单请在10分钟内进入否则将结束订单");
}
}
}
return result;
}
// 记录入场记录
/**
*
* @param type
* @param price
* @param memberId
* @param platformId
* @param payType
* @param cardType
* @param venueId
* @param venueType
*/
public void createMemberMoneyLog(Integer type, BigDecimal price, Integer memberId, Integer platformId, Integer payType, String cardType,
Integer venueId, Integer venueType) {
memberMoneyLogService.create(memberId,platformId == null ? 1 : platformId,type,price.negate(),payType,cardType,venueId,venueType,null);
}
public void addNumber(Integer venueId, Integer number, Integer memberId) {
if (number > 0 && venueMapper.countByMember(memberId, venueId) <= 0) {
venueMapper.addNumber(number, venueId);
venueMapper.addMember(memberId, venueId);
} else if (number < 0 && venueMapper.countByMember(memberId, venueId) > 0) {
venueMapper.addNumber(number, venueId);
venueMapper.deleteMember(memberId, venueId);
}
}
/**
* 按次入场订单入库
* @param memberId
* @param venueId
* @param timePayHour
*/
private void createBarcodeTimeOrder(Integer memberId, Integer venueId, Integer timePayHour,String orderSn) {
Date startDate = new Date();
Date endDate = DateUtilCard.addHours(startDate, timePayHour);
// 如果是一个小时则默认给15分钟宽限期
if (timePayHour == 1) {
endDate = DateUtilCard.addMinute(endDate,15);
}
BarcodeOrderTime barcodeOrderTime = new BarcodeOrderTime();
barcodeOrderTime.setMemberId(memberId);
barcodeOrderTime.setVenueId(venueId);
barcodeOrderTime.setOrderStart(startDate);
barcodeOrderTime.setOrderEnd(endDate);
barcodeOrderTime.setStatus(BarCodeStatusEnum.INIT.getValue());
barcodeOrderTime.setOrderSn(orderSn);
barcodeOrderTimeMapper.insert(barcodeOrderTime);
}
/**
* 支付成功
* @param order
*/
public void paySuccess(Order order) {
Integer memberId = order.getMemberId();
Integer venueId = order.getParentOrderId();
Venue venue = venueMapper.findById(venueId);
createMemberMoneyLog(MoneyLogEnum.JOIN.value, order.getPrice(), memberId, order.getPlatformId(), PayTypeEnum.WEI_XIN.value, null,venue.getId(), venue.getType());
Integer timePayHour = 2;
if(PayStyleEnum.TIME.getValue() == venue.getPayStyle()){
// 按次入场先收钱,且多久不收钱,出场不收钱
// 该用户上次订单的是否逾期
timePayHour = venue.getTimePayHour();
if (timePayHour == null) {
timePayHour = 4;
}
}
createBarcodeTimeOrder(memberId,venueId,timePayHour,order.getOrderSn());
}
}

View File

@@ -210,193 +210,6 @@ public class VenueService extends BaseServiceImpl {
return venueDTOS;
}
/**
* api 接口
* 我要进场
*/
@Transactional(rollbackFor = Exception.class)
public BasketEnterResult join(Integer memberId, Integer venueId) {
BasketEnterResult basketEnterResult = new BasketEnterResult();
basketEnterResult.setFlg(0);
// 判断用户是否登录
if (memberId == null) {
throw new ServiceException(com.ydd.framework.core.exception.ExceptionCodeTemplate.NEED_LOGIN);
}
//参数校验
ValidationUtils.assertNotNull(venueId);
// 1.判断用户有没有该馆的会员卡(有效期内,如果有免费卡和别的卡,优先使用别的卡),有不判断余额
List<MemberCard> memberCards = memberCardService.findByMemberId(venueId, memberId);
// 2. 查询该场馆需要的费用,并比较用户余额是否足够
// 查询当前时间内,场馆对应的价格
String time = DateUtilCard.nowTime().toString();
Venue venue = venueMapper.findById(venueId);
VenuePrice venuePrice = venuePriceService.findPrice(venueId, time);
if (venuePrice == null) {
throw new ServiceException(ExceptionCodeTemplate.VENUE_ERROR);
}
BigDecimal price = venuePrice.getPrice();
if (PayStyleEnum.HOUR.getValue() == venue.getPayStyle()){
// 按时入场余额需要包含两个小时的场地费
price = price.multiply(new BigDecimal(2));
}
if (venuePrice == null) {
throw new ServiceException(ExceptionCodeTemplate.VENUE_ERROR);
}
if (memberCards.size() == 0) {
Member member = memberService.findById(memberId);
if (member.getMoney().compareTo(price) == -1) {
basketEnterResult.setFlg(2);
// if (PayStyleEnum.HOUR.getValue() == venue.getPayStyle()){
// // 按时入场余额需要包含两个小时的场地费
// barCodeResult.setMsg("请保证账户至少有两个小时余额:" + price + "元,余额不足,请先充值");
// }else {
// barCodeResult.setMsg("此次订单金额为:" + price + "元,余额不足,请先充值");
// }
basketEnterResult.setMsg("此次订单金额为:" + price + "元,余额不足,请先充值");
return basketEnterResult;
}
Integer timePayHour = 1;
if(PayStyleEnum.TIME.getValue() == venue.getPayStyle()){
// 按次入场先收钱,且多久不收钱,出场不收钱
// 该用户上次订单的是否逾期
timePayHour = venue.getTimePayHour();
if (timePayHour == null) {
timePayHour = 4;
}
}
int effOrder = barcodeOrderTimeMapper.findEffOrder(new Date(), memberId, venueId);
if (effOrder <= 0) {
// 单次订单已超时 需要重新付费
synchronized (("scancode-in" + memberId).intern()) {
if (memberService.isMoneyEnough(memberId, price)) {
logger.info("用户" + memberId + "使用余额核销订单");
createBarcodeTimeOrder(memberId,venueId,timePayHour);
createMemberMoneyLog(MoneyLogEnum.JOIN.value, price, memberId, 1, PayTypeEnum.BALANCE.value, null,
venue.getId(), venue.getType());
} else {
//余额不足
logger.error("用户" + memberId + "余额不足核销失败");
basketEnterResult.setMsg("此次订单金额为:" + price + "元,余额不足,请先充值");
}
}
}
}
// 3.判断用户有没有人脸识别的图像,根据用户ID查找一个用户只能有一条
// MemberFaceInfo memberFaceInfo = memberFaceInfoService.findByMemberId(memberId);
// if (memberFaceInfo == null) {
// flag = 1;
// return flag;
// }
return basketEnterResult;
}
/**
* 我要出场
* @param memberId
* @param venueId
* @return
*/
@Transactional(rollbackFor = Exception.class)
public BasketEnterResult out(Integer memberId, Integer venueId) {
BasketEnterResult result = new BasketEnterResult();
result.setFlg(0);
// 判断用户是否登录
if (memberId == null) {
throw new ServiceException(com.ydd.framework.core.exception.ExceptionCodeTemplate.NEED_LOGIN);
}
//参数校验
ValidationUtils.assertNotNull(venueId);
Venue venue = venueMapper.findById(venueId);
synchronized (("scancode-out" + memberId).intern()) {
// 查询当前时间内,场馆对应的价格(健身房没有价格)
Member member = memberService.findByMember(memberId);
memberService.verify(member);
//进场之前 查看是否有会员卡
List<MemberCard> cards = memberCardService.findByMemberId(venue.getId(), member.getId());
if (cards.size() > 0) {
MemberCard useCard = null;
//有会员卡 查看是否有免费卡
List<MemberCard> freeCard = cards.stream().filter(free -> VipTypeEnum.FREECARD.value.equals(free.getCardType())).collect(Collectors.toList());
//有会员卡 查看是否有单次卡
List<MemberCard> onceCard = cards.stream().filter(free ->
VipTypeEnum.ONCECARD.value.equals(free.getCardType()) || VipTypeEnum.PUB_ONCECARD.value.equals(free.getCardType())).collect(Collectors.toList());
boolean canUseFree = false;
if (freeCard !=null && freeCard.size() > 0){
for (MemberCard f : freeCard){
if (memberEnterVenueLogService.isFreeCardUseful(f.getId())){
canUseFree = true;
// 如果有一张可以用的免费卡就用免费卡
useCard = f;
}
}
}
if (!canUseFree) {
if (onceCard != null && onceCard.size() > 0)
// 不能用免费卡,优先单次卡,取第一张可用的单次卡
useCard = onceCard.get(0);
} else {
// 单次卡和免费卡都不能用,随意用一张季卡或者年卡
useCard = cards.get(0);
}
if (useCard != null) {
//使用会员卡入场
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());
// 如果是单次卡,清除单次卡
if (VipTypeEnum.ONCECARD.value.equals(useCard.getCardType())
|| VipTypeEnum.PUB_ONCECARD.value.equals(useCard.getCardType())){
memberCardService.delete(useCard.getId());
}
}else {
//查无可用会员卡
logger.info("用户" + member.getNickname() + "您好!请先购买会员卡再出场核销");
result.setFlg(1);
result.setMsg("未查询到会员卡,请先购买会员卡");
}
}else {
/**
* 篮球出场核心逻辑
*/
//判断余额是否够
// 1、找到入场时间
if(PayStyleEnum.HOUR.getValue() == venue.getPayStyle()){
// 按次出场不扣钱
BigDecimal price = BigDecimal.ZERO;
BarcodeOrderTime lastOrder = barcodeOrderTimeMapper.findLastOrder(memberId, venueId);
String enterTime = DateUtilCard.getTimeFromDate(lastOrder.getOrderStart());
Date dateNow = new Date();
if (dateNow.after(lastOrder.getOrderEnd())) {
// 当前时间已经超过订单结束日期,则该订单需要重新补收费
// 取入场的价格
VenuePrice venuePriceEnter = venuePriceService.findPrice(venueId, enterTime);
if (venuePriceEnter == null) {
throw new ServiceException(ExceptionCodeTemplate.VENUE_ERROR);
}
// 按时出场选择按照分钟四舍五入到角扣款
price = venuePriceEnter.getPrice();
int minutes = DateUtilCard.diffMinute(lastOrder.getOrderStart(), dateNow);
int hours = (minutes - 1) / 60;
// 需要补收的价格
price = price.multiply(new BigDecimal(hours));
if (memberService.isMoneyEnough(member.getId(), price)) {
logger.info("用户" + member.getId() + "使用余额核销订单");
createMemberMoneyLog(MoneyLogEnum.JOIN.value, price, member.getId(), member.getPlatformId(), PayTypeEnum.BALANCE.value, null,
venue.getId(), venue.getType());
} else {
//余额不足
logger.error("用户" + member.getId() + "需补交金额,余额不足核销失败");
result.setFlg(2);
result.setMsg("您此次入场超过一小时,需补交" + price + "元,余额不足,请先充值");
}
}
}
}
}
return result;
}
/**
* api
* 查询我的会员卡
@@ -444,45 +257,5 @@ public class VenueService extends BaseServiceImpl {
return StringUtils.isNotBlank(longitude) && StringUtils.isNotBlank(latitude);
}
// 记录入场记录
@Transactional
public void createMemberMoneyLog(Integer type, BigDecimal price, Integer memberId, Integer platformId, Integer payType, String cardType,
Integer venueId, Integer venueType) {
memberMoneyLogService.create(memberId,platformId == null ? 1 : platformId,type,price.negate(),payType,cardType,venueId,venueType,null);
}
/**
* 按次入场订单入库
* @param memberId
* @param venueId
* @param timePayHour
*/
private void createBarcodeTimeOrder(Integer memberId, Integer venueId, Integer timePayHour) {
Date startDate = new Date();
Date endDate = DateUtilCard.addHours(startDate, timePayHour);
// 如果是一个小时则默认给15分钟宽限期
if (timePayHour == 1) {
endDate = DateUtilCard.addMinute(endDate,15);
}
BarcodeOrderTime barcodeOrderTime = new BarcodeOrderTime();
barcodeOrderTime.setMemberId(memberId);
barcodeOrderTime.setVenueId(venueId);
barcodeOrderTime.setOrderStart(startDate);
barcodeOrderTime.setOrderEnd(endDate);
barcodeOrderTime.setStatus(BarCodeStatusEnum.INIT.getValue());
barcodeOrderTimeMapper.insert(barcodeOrderTime);
}
@Transactional(rollbackFor = Exception.class)
public void addNumber(Integer venueId, Integer number, Integer memberId) {
if (number > 0 && venueMapper.countByMember(memberId, venueId) <= 0) {
venueMapper.addNumber(number, venueId);
venueMapper.addMember(memberId, venueId);
} else if (number < 0 && venueMapper.countByMember(memberId, venueId) > 0) {
venueMapper.addNumber(number, venueId);
venueMapper.deleteMember(memberId, venueId);
}
}
}

View File

@@ -50,6 +50,8 @@ public class WechatPayService extends BaseServiceImpl {
private MemberLessonTicketService memberLessonTicketService;
@Resource
private MemberRefundService memberRefundService;
@Resource
private VenueEnterService venueEnterService;
/**
* 创建微信支付的统一订单
@@ -175,6 +177,11 @@ public class WechatPayService extends BaseServiceImpl {
memberLessonTicketService.paySuccess(order);
}
//篮球入场订单
if (order.getType().intValue() == OrderTypeEnum.BASKETBALL_ORDER.value){
venueEnterService.paySuccess(order);
}
}
}
}

View File

@@ -11,13 +11,16 @@
<arg column="order_start" jdbcType="TIMESTAMP" javaType="java.util.Date" />
<arg column="order_end" jdbcType="TIMESTAMP" javaType="java.util.Date" />
<arg column="status" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="paying" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="pay_money" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="order_sn" jdbcType="VARCHAR" javaType="java.lang.String" />
</constructor>
</resultMap>
<sql id="Base_Column_List" >
id, member_id, venue_id, created_time, modified_time, order_start, order_end, status
id, member_id, venue_id, created_time, modified_time, order_start, order_end, status, paying, pay_money, order_sn
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
select
<include refid="Base_Column_List" />
from sv_barcode_order_time
where id = #{id,jdbcType=INTEGER}
@@ -27,12 +30,12 @@
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.sv.entity.BarcodeOrderTime" >
insert into sv_barcode_order_time (id, member_id, venue_id,
created_time, modified_time, order_start,
order_end, status)
values (#{id,jdbcType=INTEGER}, #{memberId,jdbcType=INTEGER}, #{venueId,jdbcType=INTEGER},
#{createdTime,jdbcType=TIMESTAMP}, #{modifiedTime,jdbcType=TIMESTAMP}, #{orderStart,jdbcType=TIMESTAMP},
#{orderEnd,jdbcType=TIMESTAMP}, #{status,jdbcType=INTEGER})
insert into sv_barcode_order_time (id, member_id, venue_id,
created_time, modified_time, order_start,
order_end, status,paying ,pay_money)
values (#{id,jdbcType=INTEGER}, #{memberId,jdbcType=INTEGER}, #{venueId,jdbcType=INTEGER},
#{createdTime,jdbcType=TIMESTAMP}, #{modifiedTime,jdbcType=TIMESTAMP}, #{orderStart,jdbcType=TIMESTAMP},
#{orderEnd,jdbcType=TIMESTAMP}, #{status,jdbcType=INTEGER}, #{paying,jdbcType=INTEGER}, #{payMoney,jdbcType=INTEGER}, #{orderSn,jdbcType=VARCHAR})
</insert>
<insert id="insertSelective" parameterType="com.sv.entity.BarcodeOrderTime" >
insert into sv_barcode_order_time
@@ -61,6 +64,15 @@
<if test="status != null" >
status,
</if>
<if test="status != null" >
paying,
</if>
<if test="payMoney != null" >
pay_money,
</if>
<if test="orderSn != null" >
order_sn,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
@@ -87,6 +99,15 @@
<if test="status != null" >
#{status,jdbcType=INTEGER},
</if>
<if test="paying != null" >
#{paying,jdbcType=INTEGER},
</if>
<if test="payMoney != null" >
#{payMoney,jdbcType=INTEGER},
</if>
<if test="orderSn != null" >
#{orderSn,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.sv.entity.BarcodeOrderTime" >
@@ -113,6 +134,15 @@
<if test="status != null" >
status = #{status,jdbcType=INTEGER},
</if>
<if test="paying != null" >
paying = #{paying,jdbcType=INTEGER},
</if>
<if test="payMoney != null" >
pay_money = #{payMoney,jdbcType=INTEGER},
</if>
<if test="orderSn != null" >
order_sn = #{orderSn,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
@@ -124,8 +154,11 @@
modified_time = #{modifiedTime,jdbcType=TIMESTAMP},
order_start = #{orderStart,jdbcType=TIMESTAMP},
order_end = #{orderEnd,jdbcType=TIMESTAMP},
status = #{status,jdbcType=INTEGER}
where id = #{id,jdbcType=INTEGER}
status = #{status,jdbcType=INTEGER},
paying = #{paying,jdbcType=INTEGER},
pay_money = #{payMoney,jdbcType=INTEGER}
order_sn = #{orderSn,jdbcType=INTEGER}
where id = #{id,jdbcType=VARCHAR}
</update>
<select id="findEffOrder" resultType="int">
@@ -149,4 +182,11 @@
where status = 0 and order_end &lt;= #{currentDate}
</select>
</mapper>
<select id="needPayOrderList" resultMap="BaseResultMap" >
select
<include refid="Base_Column_List" />
from sv_barcode_order_time
where paying = 1
</select>
</mapper>