From 3573f6a0d64acb8fcdd89aa95f411302e7a5cabd Mon Sep 17 00:00:00 2001 From: SongZhang <2064194730@qq.com> Date: Sat, 26 Oct 2024 09:14:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=9C=B8=E7=8E=8B=E9=A4=90=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/PayController.java | 27 +- .../entity/TbFreeDineConfig.java | 150 +++++++++ .../entity/dto/OrderPayDTO.java | 23 ++ .../mapper/TbFreeDineConfigMapper.java | 18 + .../cashierservice/service/PayService.java | 312 ++++++++++-------- .../service/TbFreeDineConfigService.java | 13 + .../service/TbShopCouponService.java | 9 + .../impl/TbFreeDineConfigServiceImpl.java | 24 ++ .../service/impl/TbShopCouponServiceImpl.java | 120 ++++--- .../mapper/TbFreeDineConfigMapper.xml | 28 ++ 10 files changed, 528 insertions(+), 196 deletions(-) create mode 100644 src/main/java/com/chaozhanggui/system/cashierservice/entity/TbFreeDineConfig.java create mode 100644 src/main/java/com/chaozhanggui/system/cashierservice/entity/dto/OrderPayDTO.java create mode 100644 src/main/java/com/chaozhanggui/system/cashierservice/mapper/TbFreeDineConfigMapper.java create mode 100644 src/main/java/com/chaozhanggui/system/cashierservice/service/TbFreeDineConfigService.java create mode 100644 src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbFreeDineConfigServiceImpl.java create mode 100644 src/main/resources/mapper/TbFreeDineConfigMapper.xml diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/controller/PayController.java b/src/main/java/com/chaozhanggui/system/cashierservice/controller/PayController.java index e868891..bd9662c 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/controller/PayController.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/controller/PayController.java @@ -3,6 +3,7 @@ package com.chaozhanggui.system.cashierservice.controller; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.chaozhanggui.system.cashierservice.annotation.LimitSubmit; +import com.chaozhanggui.system.cashierservice.entity.dto.OrderPayDTO; import com.chaozhanggui.system.cashierservice.service.PayService; import com.chaozhanggui.system.cashierservice.sign.Result; import com.chaozhanggui.system.cashierservice.util.IpUtil; @@ -15,6 +16,7 @@ import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Map; +import java.util.Objects; @CrossOrigin(origins = "*") @RestController @@ -31,34 +33,23 @@ public class PayController { * 支付 * * @param request payType wechatPay:微信支付;aliPay:支付宝支付; - * @param map - * @return */ @RequestMapping("orderPay") @LimitSubmit(key = "orderPay:%s") - public Result pay(HttpServletRequest request, @RequestHeader("openId") String openId, @RequestBody Map map) { - if (ObjectUtil.isEmpty(map) || map.size() <= 0 || !map.containsKey("orderId") || ObjectUtil.isEmpty(map.get("orderId"))) { - return Result.fail("订单号不允许为空"); - } - - if (!map.containsKey("payType")) { - return Result.fail("支付类型不允许为空"); - } - - String payType = map.get("payType"); - if (StrUtil.isEmpty(payType)) { - return Result.fail("支付类型不允许为空"); - } - + public Result pay(HttpServletRequest request, @RequestHeader("openId") String openId, @RequestBody OrderPayDTO payDTO) { try { - return payService.payOrder(openId, map.get("orderId"), payType, IpUtil.getIpAddr(request)); + if (ObjectUtil.isEmpty(openId) || Objects.isNull(openId)) { + return Result.fail("付款用户[userId]参数不能为空"); + } + return payService.payOrder(openId, payDTO, IpUtil.getIpAddr(request)); } catch (Exception e) { - e.printStackTrace(); + log.error("支付失败", e); } return Result.fail("支付失败"); } + /** * 储值卡支付 * diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbFreeDineConfig.java b/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbFreeDineConfig.java new file mode 100644 index 0000000..38d8bc3 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbFreeDineConfig.java @@ -0,0 +1,150 @@ +package com.chaozhanggui.system.cashierservice.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import lombok.Data; + +/** + * 霸王餐配置信息表 + * @TableName tb_free_dine_config + */ +@TableName(value ="tb_free_dine_config") +@Data +public class TbFreeDineConfig implements Serializable { + /** + * + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * 是否启用 + */ + private Integer enable; + + /** + * 充值多少倍免单 + */ + private Integer rechargeTimes; + + /** + * 订单满多少元可以使用 + */ + private BigDecimal rechargeThreshold; + + /** + * 是否与优惠券共享 + */ + private Integer withCoupon; + + /** + * 是否与积分同享 + */ + private Integer withPoints; + + /** + * 充值说明 + */ + private String rechargeDesc; + + /** + * 使用类型 dine-in店内 takeout 自取 post快递,takeaway外卖 + */ + private String useType; + + /** + * 门店id + */ + private Integer shopId; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 修改时间 + */ + private Date updateTime; + + /** + * 可用的子门店id + */ + private String childShopIdList; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (getClass() != that.getClass()) { + return false; + } + TbFreeDineConfig other = (TbFreeDineConfig) that; + return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) + && (this.getEnable() == null ? other.getEnable() == null : this.getEnable().equals(other.getEnable())) + && (this.getRechargeTimes() == null ? other.getRechargeTimes() == null : this.getRechargeTimes().equals(other.getRechargeTimes())) + && (this.getRechargeThreshold() == null ? other.getRechargeThreshold() == null : this.getRechargeThreshold().equals(other.getRechargeThreshold())) + && (this.getWithCoupon() == null ? other.getWithCoupon() == null : this.getWithCoupon().equals(other.getWithCoupon())) + && (this.getWithPoints() == null ? other.getWithPoints() == null : this.getWithPoints().equals(other.getWithPoints())) + && (this.getRechargeDesc() == null ? other.getRechargeDesc() == null : this.getRechargeDesc().equals(other.getRechargeDesc())) + && (this.getUseType() == null ? other.getUseType() == null : this.getUseType().equals(other.getUseType())) + && (this.getShopId() == null ? other.getShopId() == null : this.getShopId().equals(other.getShopId())) + && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime())) + && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime())) + && (this.getChildShopIdList() == null ? other.getChildShopIdList() == null : this.getChildShopIdList().equals(other.getChildShopIdList())); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); + result = prime * result + ((getEnable() == null) ? 0 : getEnable().hashCode()); + result = prime * result + ((getRechargeTimes() == null) ? 0 : getRechargeTimes().hashCode()); + result = prime * result + ((getRechargeThreshold() == null) ? 0 : getRechargeThreshold().hashCode()); + result = prime * result + ((getWithCoupon() == null) ? 0 : getWithCoupon().hashCode()); + result = prime * result + ((getWithPoints() == null) ? 0 : getWithPoints().hashCode()); + result = prime * result + ((getRechargeDesc() == null) ? 0 : getRechargeDesc().hashCode()); + result = prime * result + ((getUseType() == null) ? 0 : getUseType().hashCode()); + result = prime * result + ((getShopId() == null) ? 0 : getShopId().hashCode()); + result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode()); + result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode()); + result = prime * result + ((getChildShopIdList() == null) ? 0 : getChildShopIdList().hashCode()); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getSimpleName()); + sb.append(" ["); + sb.append("Hash = ").append(hashCode()); + sb.append(", id=").append(id); + sb.append(", enable=").append(enable); + sb.append(", rechargeTimes=").append(rechargeTimes); + sb.append(", rechargeThreshold=").append(rechargeThreshold); + sb.append(", withCoupon=").append(withCoupon); + sb.append(", withPoints=").append(withPoints); + sb.append(", rechargeDesc=").append(rechargeDesc); + sb.append(", useType=").append(useType); + sb.append(", shopId=").append(shopId); + sb.append(", createTime=").append(createTime); + sb.append(", updateTime=").append(updateTime); + sb.append(", childShopIdList=").append(childShopIdList); + sb.append(", serialVersionUID=").append(serialVersionUID); + sb.append("]"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/entity/dto/OrderPayDTO.java b/src/main/java/com/chaozhanggui/system/cashierservice/entity/dto/OrderPayDTO.java new file mode 100644 index 0000000..fe92413 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/entity/dto/OrderPayDTO.java @@ -0,0 +1,23 @@ +package com.chaozhanggui.system.cashierservice.entity.dto; + +import lombok.Data; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +@Data +public class OrderPayDTO { + @NotNull(message = "订单号不允许为空") + private Integer orderId; + @NotBlank(message = "支付类型不允许为空") + private String payType; + @NotNull + private Boolean isFreeDine; + // 使用的优惠券 + private Integer couponId; + // 是否使用积分抵扣 + private Boolean usePoints; +} diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/mapper/TbFreeDineConfigMapper.java b/src/main/java/com/chaozhanggui/system/cashierservice/mapper/TbFreeDineConfigMapper.java new file mode 100644 index 0000000..a0abe2c --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/mapper/TbFreeDineConfigMapper.java @@ -0,0 +1,18 @@ +package com.chaozhanggui.system.cashierservice.mapper; + +import com.chaozhanggui.system.cashierservice.entity.TbFreeDineConfig; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author Administrator +* @description 针对表【tb_free_dine_config(霸王餐配置信息表)】的数据库操作Mapper +* @createDate 2024-10-25 14:22:41 +* @Entity com.chaozhanggui.system.cashierservice.entity.TbFreeDineConfig +*/ +public interface TbFreeDineConfigMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/service/PayService.java b/src/main/java/com/chaozhanggui/system/cashierservice/service/PayService.java index cbc689f..dab3fce 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/service/PayService.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/service/PayService.java @@ -12,9 +12,11 @@ import com.chaozhanggui.system.cashierservice.constant.TableConstant; import com.chaozhanggui.system.cashierservice.dao.*; import com.chaozhanggui.system.cashierservice.entity.Enum.OrderUseTypeEnum; import com.chaozhanggui.system.cashierservice.entity.*; +import com.chaozhanggui.system.cashierservice.entity.dto.OrderPayDTO; import com.chaozhanggui.system.cashierservice.entity.dto.ReturnGroupOrderDto; import com.chaozhanggui.system.cashierservice.entity.dto.ShopEatTypeInfoDTO; import com.chaozhanggui.system.cashierservice.entity.vo.ShopUserListVo; +import com.chaozhanggui.system.cashierservice.entity.vo.TbUserCouponVo; import com.chaozhanggui.system.cashierservice.exception.MsgException; import com.chaozhanggui.system.cashierservice.mapper.MpCashierCartMapper; import com.chaozhanggui.system.cashierservice.mapper.MpOrderDetailMapper; @@ -34,6 +36,7 @@ import com.chaozhanggui.system.cashierservice.thirdpay.resp.WxScanPayResp; import com.chaozhanggui.system.cashierservice.thirdpay.service.ThirdPayService; import com.chaozhanggui.system.cashierservice.util.*; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; @@ -51,6 +54,7 @@ import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; import java.io.IOException; import java.math.BigDecimal; +import java.math.RoundingMode; import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.*; @@ -184,10 +188,14 @@ public class PayService { private MpCashierCartMapper mpCashierCartMapper; private final MpShopTableService mpShopTableService; + private final TbFreeDineConfigService freeDineConfigService; + private final TbShopCouponService shopCouponService; - public PayService(@Qualifier("tbShopSongOrderServiceImpl") TbShopSongOrderService shopSongOrderService, MpShopTableService mpShopTableService) { + public PayService(@Qualifier("tbShopSongOrderServiceImpl") TbShopSongOrderService shopSongOrderService, MpShopTableService mpShopTableService, TbFreeDineConfigService freeDineConfigService, TbShopCouponService shopCouponService) { this.shopSongOrderService = shopSongOrderService; this.mpShopTableService = mpShopTableService; + this.freeDineConfigService = freeDineConfigService; + this.shopCouponService = shopCouponService; } @Transactional(rollbackFor = Exception.class) @@ -211,58 +219,41 @@ public class PayService { return Result.success(CodeEnum.SUCCESS, mapper.readTree(wxScanPayResp.getObjData().getPayInfo())); } - @Transactional(rollbackFor = Exception.class) - public Result payOrder(String openId, String orderId, String payType, String ip) throws Exception { - - if (ObjectUtil.isEmpty(openId) || Objects.isNull(openId)) { - return Result.fail("付款用户[userId]参数不能为空"); - } - - TbOrderInfo orderInfo = tbOrderInfoMapper.selectByPrimaryKey(Integer.valueOf(orderId)); - + /** + * 校验订单支付状态是否正常 + * @param orderInfo 订单信息 + */ + private void checkOrderPayState(TbOrderInfo orderInfo) { if (!"unpaid".equals(orderInfo.getStatus()) && !"paying".equals(orderInfo.getStatus())) { - return Result.fail("订单状态异常,不允许支付"); + throw new MsgException("订单状态异常,不允许支付"); } + if (!OrderUseTypeEnum.DINE_IN_AFTER.getValue().equals(orderInfo.getUseType()) && System.currentTimeMillis() - orderInfo.getCreatedAt() > 60 * 15 * 1000) { - return Result.fail("订单十五分钟内有效,当前已超时,请重新下单。"); + throw new MsgException("订单十五分钟内有效,当前已超时,请重新下单。"); } if (ObjectUtil.isNull(orderInfo.getMerchantId()) || ObjectUtil.isEmpty(orderInfo.getMerchantId())) { - return Result.fail("没有对应的商户"); + throw new MsgException("没有对应的商户"); } - List cashierCarts = tbCashierCartMapper.selectByOrderId(orderId, null); - if (ObjectUtil.isEmpty(cashierCarts) || ObjectUtil.isNull(cashierCarts)) { - return Result.fail("购物车信息不存在"); - } + } - StringBuffer body = new StringBuffer(); - for (TbCashierCart cashierCart : cashierCarts) { - body.append(cashierCart.getName()); - } - - TbMerchantThirdApply thirdApply = tbMerchantThirdApplyMapper.selectByPrimaryKey(Integer.valueOf(orderInfo.getMerchantId())); - - if (ObjectUtil.isEmpty(thirdApply) || ObjectUtil.isNull(thirdApply)) { - return Result.fail("支付通道不存在"); - } - if ("aliPay".equals(payType) && StrUtil.isBlank(thirdApply.getAlipaySmallAppid())) { - return Result.fail("店铺未配置支付宝小程序appId"); - } - - String userId = String.valueOf(TokenUtil.getUserId()); - TbOrderPayment payment = tbOrderPaymentMapper.selectByOrderId(orderId); + /** + * 保存订单支付详情 + * @param orderInfo 订单信息 + * @param payType 支付类型 + * @return 订单支付 + */ + private TbOrderPayment createOrderPayment(TbOrderInfo orderInfo, String payType) { + TbOrderPayment payment = tbOrderPaymentMapper.selectByOrderId(String.valueOf(orderInfo.getId())); + String payName = "wechatPay".equals(payType) ? "微信支付" : "aliPay".equals(payType) ? "支付宝支付" : "未知支付"; if (ObjectUtil.isEmpty(payment) || payment == null) { payment = new TbOrderPayment(); payment.setPayTypeId("ysk"); payment.setAmount(orderInfo.getOrderAmount()); payment.setPaidAmount(orderInfo.getPayAmount()); payment.setHasRefundAmount(BigDecimal.ZERO); - if ("wechatPay".equals(payType)) { - payment.setPayName("微信支付"); - } else if ("aliPay".equals(payType)) { - payment.setPayName("支付宝支付"); - } + payment.setPayName(payName); payment.setPayType(payType); payment.setReceived(payment.getAmount()); payment.setChangeFee(BigDecimal.ZERO); @@ -272,39 +263,89 @@ public class PayService { payment.setCreatedAt(System.currentTimeMillis()); tbOrderPaymentMapper.insert(payment); } else { - if (payType.equals("wechatPay")) { - payment.setPayName("微信支付"); - } else if (payType.equals("aliPay")) { - payment.setPayName("支付宝支付"); - } + payment.setPayName(payName); payment.setPayType(payType); payment.setUpdatedAt(System.currentTimeMillis()); tbOrderPaymentMapper.updateByPrimaryKey(payment); } - if ("ysk".equals(thirdPayType)) { - PayReq req = new PayReq(); + return payment; - req.setAppId(thirdApply.getAppId()); - req.setTimestamp(System.currentTimeMillis()); - req.setIp(ip); - req.setMercOrderNo(orderInfo.getOrderNo()); - req.setNotifyUrl(callBackurl); - req.setPayAmt(payment.getAmount().setScale(2, BigDecimal.ROUND_DOWN).toPlainString()); - req.setPayType("03"); - req.setPayWay("WXZF"); - req.setSubject("扫码点餐"); - req.setUserId(openId); + } + private JSONObject yskPay(TbMerchantThirdApply thirdApply, TbOrderInfo orderInfo, TbOrderPayment payment, String openId, String userId, String ip) { + PayReq req = new PayReq(); + req.setAppId(thirdApply.getAppId()); + req.setTimestamp(System.currentTimeMillis()); + req.setIp(ip); + req.setMercOrderNo(orderInfo.getOrderNo()); + req.setNotifyUrl(callBackurl); + req.setPayAmt(payment.getAmount().setScale(2, BigDecimal.ROUND_DOWN).toPlainString()); + req.setPayType("03"); + req.setPayWay("WXZF"); + req.setSubject("扫码点餐"); + req.setUserId(openId); + Map map = BeanUtil.transBeanMap(req); + req.setSign(MD5Util.encrypt(map, thirdApply.getAppToken(), true)); + log.info("开始发送银收客支付请求,请求: {}", req); + ResponseEntity response = restTemplate.postForEntity(url.concat("trans/pay"), req, String.class); + log.info("银收客支付请求结束,响应: {}", response); + if (response.getStatusCodeValue() == 200 && ObjectUtil.isNotEmpty(response.getBody())) { + JSONObject object = JSONObject.parseObject(response.getBody()); + if (object.get("code").equals("0")) { + payment.setTradeNumber(object.getJSONObject("data").get("orderNumber").toString()); + payment.setUpdatedAt(System.currentTimeMillis()); + tbOrderPaymentMapper.updateByPrimaryKeySelective(payment); + orderInfo.setStatus("paying"); + orderInfo.setPayOrderNo(payment.getTradeNumber()); + orderInfo.setUserId(userId); + tbOrderInfoMapper.updateByPrimaryKey(orderInfo); - Map map = BeanUtil.transBeanMap(req); - req.setSign(MD5Util.encrypt(map, thirdApply.getAppToken(), true)); + //清除缓存购物车数据 + redisUtil.deleteByKey(RedisCst.getTableCartKey(orderInfo.getTableId(), orderInfo.getTableId(), orderInfo.getUserId())); + tbCashierCartMapper.updateStatusByOrderId(orderInfo.getId().toString(), "final"); + return object.getJSONObject("data"); + } else { + throw new MsgException(object.getString("msg")); + } + } + throw new MsgException("支付失败"); + } - ResponseEntity response = restTemplate.postForEntity(url.concat("trans/pay"), req, String.class); - if (response.getStatusCodeValue() == 200 && ObjectUtil.isNotEmpty(response.getBody())) { - JSONObject object = JSONObject.parseObject(response.getBody()); - if (object.get("code").equals("0")) { - payment.setTradeNumber(object.getJSONObject("data").get("orderNumber").toString()); + private JsonNode fstPay(String body, TbMerchantThirdApply thirdApply, TbOrderInfo orderInfo, TbOrderPayment payment, String openId, String userId, String ip) throws JsonProcessingException { + String reqbody; + if (body.length() > 15) { + reqbody = body.substring(0, 6).concat("....").concat(body.substring(body.length() - 6, body.length())); + } else { + reqbody = body; + } + + String smallAppid = thirdApply.getSmallAppid(); + String appId = thirdApply.getAppId(); + String appToken = thirdApply.getAppToken(); + if ("aliPay".equals(orderInfo.getPayType())){ + smallAppid = thirdApply.getAlipaySmallAppid(); + } + String convertPayType = "aliPay".equals(orderInfo.getPayType()) ? "ALIPAY" : "WECHAT"; + PublicResp publicResp = thirdPayService.scanpay(thirdUrl, + appId, + reqbody, + reqbody, + payment.getAmount().setScale(2, RoundingMode.DOWN).multiply(new BigDecimal(100)).longValue(), + convertPayType, + smallAppid, + openId, + ip, + DateUtils.getsdfTimesSS(), + thirdApply.getStoreId(), + callFSTBack, + null, + appToken); + if (ObjectUtil.isNotNull(publicResp) && ObjectUtil.isNotEmpty(publicResp)) { + if ("000000".equals(publicResp.getCode())) { + WxScanPayResp wxScanPayResp = publicResp.getObjData(); + if ("TRADE_AWAIT".equals(wxScanPayResp.getState())) { + payment.setTradeNumber(wxScanPayResp.getPayOrderId()); payment.setUpdatedAt(System.currentTimeMillis()); tbOrderPaymentMapper.updateByPrimaryKeySelective(payment); orderInfo.setStatus("paying"); @@ -313,84 +354,87 @@ public class PayService { tbOrderInfoMapper.updateByPrimaryKey(orderInfo); //清除缓存购物车数据 - redisUtil.deleteByKey(RedisCst.getTableCartKey(orderInfo.getTableId(), orderInfo.getTableId(), orderInfo.getUserId())); - JSONObject jsonObject1 = new JSONObject(); - jsonObject1.put("status", "success"); - jsonObject1.put("msg", "成功"); - jsonObject1.put("type", ""); - jsonObject1.put("data", new JSONArray()); - jsonObject1.put("amount", 0); -// AppWebSocketServer.AppSendInfo(jsonObject1,key, "",false); - tbCashierCartMapper.updateStatusByOrderId(orderId.toString(), "final"); - return Result.success(CodeEnum.SUCCESS, object.getJSONObject("data")); + redisUtil.deleteByKey(RedisCst.getTableCartKey(orderInfo.getShopId(), orderInfo.getTableId(), orderInfo.getUserId())); + tbCashierCartMapper.updateStatusByOrderId(orderInfo.getId().toString(), "final"); + ObjectMapper mapper = new ObjectMapper(); + return mapper.readTree(wxScanPayResp.getPayInfo()); } else { - return Result.fail(object.getString("msg")); - } - } - } else { - String reqbody = ""; - - if (body.length() > 15) { - reqbody = body.substring(0, 6).concat("....").concat(body.substring(body.length() - 6, body.length())).toString(); - } else { - reqbody = body.toString(); - } - - String smallAppid = thirdApply.getSmallAppid(); - String appId = thirdApply.getAppId(); - String appToken = thirdApply.getAppToken(); - if ("aliPay".equals(payType)){ - smallAppid = thirdApply.getAlipaySmallAppid(); - } - String convertPayType = "aliPay".equals(payType) ? "ALIPAY" : "WECHAT"; - PublicResp publicResp = thirdPayService.scanpay(thirdUrl, - appId, - reqbody, - reqbody, - payment.getAmount().setScale(2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(100)).longValue(), - convertPayType, - smallAppid, - openId, - ip, - DateUtils.getsdfTimesSS(), - thirdApply.getStoreId(), - callFSTBack, - null, - appToken); - if (ObjectUtil.isNotNull(publicResp) && ObjectUtil.isNotEmpty(publicResp)) { - if ("000000".equals(publicResp.getCode())) { - WxScanPayResp wxScanPayResp = publicResp.getObjData(); - if ("TRADE_AWAIT".equals(wxScanPayResp.getState())) { - payment.setTradeNumber(wxScanPayResp.getPayOrderId()); - payment.setUpdatedAt(System.currentTimeMillis()); - tbOrderPaymentMapper.updateByPrimaryKeySelective(payment); - orderInfo.setStatus("paying"); - orderInfo.setPayOrderNo(payment.getTradeNumber()); - orderInfo.setUserId(userId); - - tbOrderInfoMapper.updateByPrimaryKey(orderInfo); - //清除缓存购物车数据 - redisUtil.deleteByKey(RedisCst.getTableCartKey(orderInfo.getShopId(), orderInfo.getTableId(), orderInfo.getUserId())); - JSONObject jsonObject1 = new JSONObject(); - jsonObject1.put("status", "success"); - jsonObject1.put("msg", "成功"); - jsonObject1.put("type", ""); - jsonObject1.put("data", new JSONArray()); - jsonObject1.put("amount", 0); - -// AppWebSocketServer.AppSendInfo(jsonObject1,key, "",false); - tbCashierCartMapper.updateStatusByOrderId(orderId.toString(), "final"); - ObjectMapper mapper = new ObjectMapper(); - return Result.success(CodeEnum.SUCCESS, mapper.readTree(wxScanPayResp.getPayInfo())); - } else { - return Result.fail(publicResp.getMsg()); - } + throw new MsgException(publicResp.getMsg()); } } } + log.error("福商通支付失败,响应: {}", publicResp); + throw new MsgException("支付失败"); + } + private void freeDinePay(OrderPayDTO payDTO, String productName, TbOrderInfo orderInfo, TbMerchantThirdApply thirdApply, String userId) { + // 获取店铺霸王餐配置 + TbFreeDineConfig freeDineConfig = freeDineConfigService.getById(orderInfo.getShopId()); + if (freeDineConfig == null || freeDineConfig.getEnable() == null || freeDineConfig.getEnable() == 0) { + throw new MsgException("店铺未开启霸王餐配置"); + } - return Result.fail("失败"); + // 校验订单金额是否满足 + if (orderInfo.getOriginAmount().compareTo(freeDineConfig.getRechargeThreshold()) < 0) { + throw new MsgException("当前订单金额未满足霸王餐最低标准"); + } + + // 校验优惠券积分同享 + if (payDTO.getCouponId() != null && freeDineConfig.getWithCoupon() == 0) { + throw new MsgException("当前店铺未开启与优惠券同享"); + } + + if (payDTO.getUsePoints() && freeDineConfig.getWithPoints() == 0) { + throw new MsgException("当前店铺未开启与积分同享"); + } + BigDecimal shouldPayAmount = orderInfo.getOriginAmount().multiply(BigDecimal.valueOf(freeDineConfig.getRechargeTimes())); + + if (payDTO.getCouponId() != null) { + List couponList = shopCouponService.getActivateCouponByAmount(Integer.valueOf(orderInfo.getShopId()), userId, shouldPayAmount); + if (couponList.stream().noneMatch(item -> item.getCouponId().equals(payDTO.getCouponId()))) { + throw new MsgException("此优惠券不可用"); + } + } + + // TODO 霸王餐积分 + if (payDTO.getUsePoints()) { + + } + TbShopInfo shopInfo = mpsh.selectById(orderInfo.getShopId()); + } + + @Transactional(rollbackFor = Exception.class) + public Result payOrder(String openId, OrderPayDTO payDTO, String ip) throws Exception { + TbOrderInfo orderInfo = tbOrderInfoMapper.selectByPrimaryKey(payDTO.getOrderId()); + checkOrderPayState(orderInfo); + + List cashierCarts = tbCashierCartMapper.selectByOrderId(String.valueOf(payDTO.getOrderId()), null); + if (ObjectUtil.isEmpty(cashierCarts) || ObjectUtil.isNull(cashierCarts)) { + return Result.fail("购物车信息不存在"); + } + + StringBuilder body = new StringBuilder(); + for (TbCashierCart cashierCart : cashierCarts) { + body.append(cashierCart.getName()); + } + + TbMerchantThirdApply thirdApply = tbMerchantThirdApplyMapper.selectByPrimaryKey(Integer.valueOf(orderInfo.getMerchantId())); + + if (ObjectUtil.isEmpty(thirdApply) || ObjectUtil.isNull(thirdApply)) { + return Result.fail("支付通道不存在"); + } + if ("aliPay".equals(payDTO.getPayType()) && StrUtil.isBlank(thirdApply.getAlipaySmallAppid())) { + return Result.fail("店铺未配置支付宝小程序appId"); + } + + String userId = String.valueOf(TokenUtil.getUserId()); + TbOrderPayment payment = createOrderPayment(orderInfo, payDTO.getPayType()); + + if ("ysk".equals(thirdPayType)) { + return Result.successWithData(yskPay(thirdApply, orderInfo, payment, openId, userId, ip)); + } else { + return Result.successWithData(fstPay(body.toString(), thirdApply, orderInfo, payment, openId, userId, ip)); + } } diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/service/TbFreeDineConfigService.java b/src/main/java/com/chaozhanggui/system/cashierservice/service/TbFreeDineConfigService.java new file mode 100644 index 0000000..ae3dc02 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/service/TbFreeDineConfigService.java @@ -0,0 +1,13 @@ +package com.chaozhanggui.system.cashierservice.service; + +import com.chaozhanggui.system.cashierservice.entity.TbFreeDineConfig; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author Administrator +* @description 针对表【tb_free_dine_config(霸王餐配置信息表)】的数据库操作Service +* @createDate 2024-10-25 14:22:41 +*/ +public interface TbFreeDineConfigService extends IService { + +} diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/service/TbShopCouponService.java b/src/main/java/com/chaozhanggui/system/cashierservice/service/TbShopCouponService.java index 77686cf..51956b0 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/service/TbShopCouponService.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/service/TbShopCouponService.java @@ -1,11 +1,14 @@ package com.chaozhanggui.system.cashierservice.service; import com.chaozhanggui.system.cashierservice.entity.TbActivateOutRecord; +import com.chaozhanggui.system.cashierservice.entity.TbOrderInfo; import com.chaozhanggui.system.cashierservice.entity.dto.CouponDto; import com.chaozhanggui.system.cashierservice.entity.dto.CouponUseDto; +import com.chaozhanggui.system.cashierservice.entity.vo.TbUserCouponVo; import com.chaozhanggui.system.cashierservice.sign.Result; import org.springframework.context.annotation.Primary; +import java.math.BigDecimal; import java.util.List; /** @@ -15,6 +18,12 @@ import java.util.List; * @since 2024-10-23 15:37:37 */ public interface TbShopCouponService { + /** + * 根据金额获取可用优惠券 + * @param amount 订单金额 + */ + List getActivateCouponByAmount(Integer shopId, String userId, BigDecimal amount); + Result find(CouponDto param); boolean use(Integer shopId,Integer orderId,Integer vipUserId,List param); diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbFreeDineConfigServiceImpl.java b/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbFreeDineConfigServiceImpl.java new file mode 100644 index 0000000..17d63f1 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbFreeDineConfigServiceImpl.java @@ -0,0 +1,24 @@ +package com.chaozhanggui.system.cashierservice.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.chaozhanggui.system.cashierservice.entity.TbFreeDineConfig; +import com.chaozhanggui.system.cashierservice.service.TbFreeDineConfigService; +import com.chaozhanggui.system.cashierservice.mapper.TbFreeDineConfigMapper; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; + +/** +* @author Administrator +* @description 针对表【tb_free_dine_config(霸王餐配置信息表)】的数据库操作Service实现 +* @createDate 2024-10-25 14:22:41 +*/ +@Service +@Primary +public class TbFreeDineConfigServiceImpl extends ServiceImpl + implements TbFreeDineConfigService{ + +} + + + + diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbShopCouponServiceImpl.java b/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbShopCouponServiceImpl.java index 856eaf4..3484c52 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbShopCouponServiceImpl.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbShopCouponServiceImpl.java @@ -5,7 +5,6 @@ import cn.hutool.core.date.DateUtil; import com.chaozhanggui.system.cashierservice.dao.*; import com.chaozhanggui.system.cashierservice.entity.*; import com.chaozhanggui.system.cashierservice.entity.dto.CouponDto; -import com.chaozhanggui.system.cashierservice.entity.dto.CouponUseDto; import com.chaozhanggui.system.cashierservice.entity.vo.TbUserCouponVo; import com.chaozhanggui.system.cashierservice.service.TbShopCouponService; import com.chaozhanggui.system.cashierservice.sign.CodeEnum; @@ -14,9 +13,6 @@ import com.google.gson.JsonObject; import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; import javax.annotation.Resource; import java.math.BigDecimal; @@ -47,6 +43,73 @@ public class TbShopCouponServiceImpl implements TbShopCouponService { @Resource private TbActivateOutRecordMapper outRecordMapper; + public List getActivateCouponByAmount(Integer shopId, String userId, BigDecimal amount) { + TbShopUser tbShopUser = shopUserMapper.selectByUserIdAndShopId(userId, String.valueOf(shopId)); + List tbUserCouponVos = inRecordMapper.queryByVipIdAndShopId(Integer.valueOf(tbShopUser.getId()), shopId); + ArrayList canUseCoupon = new ArrayList<>(); + if (CollectionUtil.isNotEmpty(tbUserCouponVos)) { + String week = DateUtil.dayOfWeekEnum(new Date()).toChinese("周"); + LocalTime now = LocalTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss"); + //券id 券使用描述 + Map coupons = new HashMap<>(); + for (TbUserCouponVo tbUserCouponVo : tbUserCouponVos) { + if (tbUserCouponVo.getType() != null && tbUserCouponVo.getType() == 1) { + if (!coupons.containsKey(tbUserCouponVo.getCouponId())) { + setCouponInfo(coupons, tbUserCouponVo, amount, week, now, formatter); + } + JsonObject couponJson = coupons.get(tbUserCouponVo.getCouponId()); + tbUserCouponVo.setUseRestrictions(couponJson.get("useRestrictions").toString()); + if (tbUserCouponVo.getType().equals(1)) { + tbUserCouponVo.setUse(couponJson.get("isUse").getAsBoolean()); + } + canUseCoupon.add(tbUserCouponVo); + } + + } + canUseCoupon.sort(Comparator.comparing(TbUserCouponVo::isUse).reversed().thenComparing(TbUserCouponVo::getExpireTime)); + } + return canUseCoupon; + } + + private void setCouponInfo( Map coupons, TbUserCouponVo tbUserCouponVo, BigDecimal amount, String week, LocalTime now, DateTimeFormatter formatter) { + JsonObject json = new JsonObject(); + boolean isUse = true; + TbShopCoupon tbShopCoupon = couponMapper.queryById(tbUserCouponVo.getCouponId()); + StringBuilder useRestrictions = new StringBuilder("每天 "); + if (tbShopCoupon.getType().equals(1)) { + if (amount.compareTo(new BigDecimal(tbShopCoupon.getFullAmount())) < 0) { + isUse = false; + } + } + if (StringUtils.isNotBlank(tbShopCoupon.getUserDays())) { + String[] split = tbShopCoupon.getUserDays().split(","); + if (split.length != 7) { + useRestrictions = new StringBuilder(tbShopCoupon.getUserDays() + " "); + } + if (!tbShopCoupon.getUserDays().contains(week)) { + isUse = false; + } + } + if (tbShopCoupon.getUseTimeType().equals("custom")) { + if (now.isBefore(tbShopCoupon.getUseStartTime()) || now.isAfter(tbShopCoupon.getUseEndTime())) { + isUse = false; + } + useRestrictions.append( + tbShopCoupon.getUseStartTime().format(formatter) + + "-" + + tbShopCoupon.getUseEndTime().format(formatter)); + } else { + useRestrictions.append("全时段"); + } + useRestrictions.append(" 可用"); + json.addProperty("isUse", isUse); + json.addProperty("useRestrictions", useRestrictions.toString()); + + coupons.put(tbUserCouponVo.getCouponId(), json); + } + + @Override public Result find(CouponDto param) { TbShopUser tbShopUser = shopUserMapper.selectByUserIdAndShopId(param.getUserId().toString(), param.getShopId().toString()); @@ -65,47 +128,14 @@ public class TbShopCouponServiceImpl implements TbShopCouponService { Map coupons = new HashMap<>(); for (TbUserCouponVo tbUserCouponVo : tbUserCouponVos) { if (!coupons.containsKey(tbUserCouponVo.getCouponId())) { - JsonObject json=new JsonObject(); - boolean isUse = true; - TbShopCoupon tbShopCoupon = couponMapper.queryById(tbUserCouponVo.getCouponId()); - StringBuilder useRestrictions = new StringBuilder("每天 "); - if(tbShopCoupon.getType().equals(1)){ - if(tbOrderInfo.getOrderAmount().compareTo(new BigDecimal(tbShopCoupon.getFullAmount()))<0){ - isUse=false; - } - } - if(StringUtils.isNotBlank(tbShopCoupon.getUserDays())){ - String[] split = tbShopCoupon.getUserDays().split(","); - if (split.length != 7) { - useRestrictions = new StringBuilder(tbShopCoupon.getUserDays() + " "); - } - if(!tbShopCoupon.getUserDays().contains(week)){ - isUse=false; - } - } - if (tbShopCoupon.getUseTimeType().equals("custom")) { - if(now.isBefore(tbShopCoupon.getUseStartTime()) || now.isAfter(tbShopCoupon.getUseEndTime())){ - isUse=false; - } - useRestrictions.append( - tbShopCoupon.getUseStartTime().format(formatter) - + "-" - + tbShopCoupon.getUseEndTime().format(formatter)); - } else { - useRestrictions.append("全时段"); - } - useRestrictions.append(" 可用"); - json.addProperty("isUse",isUse); - json.addProperty("useRestrictions",useRestrictions.toString()); - - coupons.put(tbUserCouponVo.getCouponId(), json); + setCouponInfo(coupons, tbUserCouponVo, tbOrderInfo.getAmount(), week, now, formatter); } JsonObject couponJson = coupons.get(tbUserCouponVo.getCouponId()); tbUserCouponVo.setUseRestrictions(couponJson.get("useRestrictions").toString()); - if(tbUserCouponVo.getType().equals(1)){ + if (tbUserCouponVo.getType().equals(1)) { tbUserCouponVo.setUse(couponJson.get("isUse").getAsBoolean()); } else if (tbUserCouponVo.getType().equals(2) && couponJson.get("isUse").getAsBoolean()) { - if(!pros.contains(tbUserCouponVo.getProId())){ + if (!pros.contains(tbUserCouponVo.getProId())) { tbUserCouponVo.setUse(false); } } @@ -129,14 +159,15 @@ public class TbShopCouponServiceImpl implements TbShopCouponService { /** * 使用券 + * * @param shopId * @param orderId * @param vipUserId - * @param param giveId 和 useNum 必传 + * @param param giveId 和 useNum 必传 * @return */ @Override - public boolean use(Integer shopId,Integer orderId,Integer vipUserId,List param) { + public boolean use(Integer shopId, Integer orderId, Integer vipUserId, List param) { for (TbActivateOutRecord outRecord : param) { TbActivateInRecord inRecord = inRecordMapper.queryById(outRecord.getGiveId()); inRecord.setOverNum(inRecord.getOverNum() - outRecord.getUseNum()); @@ -155,14 +186,15 @@ public class TbShopCouponServiceImpl implements TbShopCouponService { /** * 退还券 - * @param param giveId和 refNum 必传 + * + * @param param giveId和 refNum 必传 * @return */ @Override public boolean refund(List param) { for (TbActivateOutRecord outRecord : param) { outRecord.setUpdateTime(new Date()); - outRecordMapper.updateRefNum(outRecord.getId(),outRecord.getRefNum()); + outRecordMapper.updateRefNum(outRecord.getId(), outRecord.getRefNum()); TbActivateInRecord inRecord = inRecordMapper.queryById(outRecord.getGiveId()); inRecord.setOverNum(inRecord.getOverNum() + outRecord.getRefNum()); inRecordMapper.updateOverNum(inRecord.getId(), inRecord.getOverNum()); diff --git a/src/main/resources/mapper/TbFreeDineConfigMapper.xml b/src/main/resources/mapper/TbFreeDineConfigMapper.xml new file mode 100644 index 0000000..9844c15 --- /dev/null +++ b/src/main/resources/mapper/TbFreeDineConfigMapper.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + id,enable,recharge_times, + recharge_threshold,with_coupon,with_points, + recharge_desc,use_type,shop_id, + create_time,update_time,child_shop_id_list + +