From 1de2f8a6b79d20905b71877a32e2368ccc256e8c Mon Sep 17 00:00:00 2001 From: zengtao01 Date: Fri, 26 Jul 2024 14:33:43 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=80=E6=AC=BE=E6=8F=90=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/enums/ErrorCodeConstants.java | 2 + .../controller/admin/card/CardController.java | 12 + .../admin/user/vo/MemberUserListVO.java | 1 + .../app/card/AppCardController.java | 5 +- .../dal/dataobject/order/DishOrderDO.java | 1 + .../dal/mysql/user/MemberUserMapper.java | 1 + .../module/member/enums/CostTypeEnum.java | 4 +- .../member/job/BalanceDeductionJob.java | 45 +- .../member/service/card/CardService.java | 4 + .../member/service/card/CardServiceImpl.java | 90 +++- .../diningplates/DiningPlatesServiceImpl.java | 21 + .../admin/notify/PayNotifyController.java | 55 +- .../pay/dal/dataobject/card/DivideCardDO.java | 76 +++ .../pay/dal/dataobject/divide/DivideDO.java | 22 +- .../dataobject/divideinfo/DivideInfoDO.java | 5 + .../refundrecord/RefundRecordDO.java | 19 +- .../pay/dal/mysql/card/DivideCardMapper.java | 16 + .../pay/dal/mysql/divide/DivideMapper.java | 3 - .../refundrecord/RefundRecordMapper.java | 6 +- .../framework/pay/core/WalletPayClient.java | 7 + .../pay/service/divide/DivideService.java | 16 +- .../pay/service/divide/DivideServiceImpl.java | 473 +++++++++++++++--- .../service/divideinfo/DivideInfoService.java | 2 + .../divideinfo/DivideInfoServiceImpl.java | 6 + .../service/order/PayOrderServiceImpl.java | 1 + .../refundrecord/RefundRecordService.java | 1 + .../framework/pay/core/client/PayClient.java | 11 + .../dto/divide/PayDivideBackRespDto.java | 51 ++ .../dto/divide/PayDivideBackUnifiedDto.java | 47 ++ .../dto/refund/PayRefundUnifiedReqDTO.java | 5 +- .../core/client/impl/AbstractPayClient.java | 24 + .../impl/alipay/AlipayAppPayClient.java | 7 + .../impl/alipay/AlipayBarPayClient.java | 7 + .../client/impl/alipay/AlipayPcPayClient.java | 7 + .../client/impl/alipay/AlipayQrPayClient.java | 7 + .../impl/alipay/AlipayWapPayClient.java | 7 + .../core/client/impl/mock/MockPayClient.java | 7 + .../impl/weixin/AbstractWxPayClient.java | 46 +- .../divide/PayDivideRefundStatusRespEnum.java | 24 + .../enums/divide/PayDivideStatusRespEnum.java | 2 + .../service/dishes/DishesServiceImpl.java | 11 + 41 files changed, 1038 insertions(+), 119 deletions(-) create mode 100644 yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/card/DivideCardDO.java create mode 100644 yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/card/DivideCardMapper.java create mode 100644 yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/divide/PayDivideBackRespDto.java create mode 100644 yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/divide/PayDivideBackUnifiedDto.java create mode 100644 yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/divide/PayDivideRefundStatusRespEnum.java diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java index 6745d3f0..b7a99fef 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java @@ -69,6 +69,7 @@ public interface ErrorCodeConstants { ErrorCode CUSTOMER_TRAFFIC_NOT_EXISTS = new ErrorCode(1_004_013_010, "订单明细不存在"); ErrorCode DEVICE_WARN_NOT_EXISTS = new ErrorCode(1_004_013_011, "订单明细不存在"); ErrorCode DISH_STATISTICS_NOT_EXISTS = new ErrorCode(1_004_013_012, "订单明细不存在"); + ErrorCode CASH_AMOUNT_NOT_ENOUGH = new ErrorCode(1_004_013_002, "现金充值余额不足"); ErrorCode DINING_PLATES_NOT_EXISTS = new ErrorCode(1_004_099_000, "餐盘不存在"); @@ -79,6 +80,7 @@ public interface ErrorCodeConstants { ErrorCode FACE_NOT_BIND_USER = new ErrorCode(1_004_099_005, "人脸未绑定"); ErrorCode CARD_NOT_BIND_USER = new ErrorCode(1_004_099_006, "该卡未绑定用户"); ErrorCode INSUFFICIENT_BALANCE = new ErrorCode(1_004_099_007, "余额不足30元,请充值"); + ErrorCode EXIST_TO_COMPLETE_ORDER = new ErrorCode(1_004_099_008, "存在未支付完的订单"); ErrorCode CARD_ALREADY_BIND = new ErrorCode(1_004_099_008, "卡号已绑定"); ErrorCode ORDER_NOT_COMPLETE = new ErrorCode(1_004_099_009, "订单未完成"); ErrorCode NEED_ADD_USER = new ErrorCode(1_007_901_004, "请先添加人员"); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/card/CardController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/card/CardController.java index b037b469..ee51461e 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/card/CardController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/card/CardController.java @@ -160,5 +160,17 @@ public class CardController { return success(cardService.rechargeByAdmin(vo)); } + @GetMapping("/getCashMoney") + @Operation(summary = "获取现金充值") + public CommonResult getCashMoney(Long userId) { + return success(cardService.getCashMoney(userId)); + } + + @GetMapping("/cashDraw") + @Operation(summary = "现金提现") + public CommonResult cashDraw(Long userId,BigDecimal money) { + return success(cardService.cashDraw(userId,money)); + } + } \ No newline at end of file diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserListVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserListVO.java index f4ebc1da..8279f54e 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserListVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserListVO.java @@ -17,4 +17,5 @@ public class MemberUserListVO extends PageParam { @Schema(description = "小组id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long groupId; private String name; + private String mobile; } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/card/AppCardController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/card/AppCardController.java index bf7f8c20..d73eaff1 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/card/AppCardController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/card/AppCardController.java @@ -25,7 +25,6 @@ import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.validation.Valid; import java.math.BigDecimal; -import java.math.RoundingMode; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -100,8 +99,8 @@ public class AppCardController { @Operation(summary = "充值") //@PreAuthorize("@ss.hasPermission('member:card:update')") public CommonResult recharge(BigDecimal money,BigDecimal giftMoney) { - BigDecimal bigDecimal = money.divide(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP); - return success(cardService.recharge(bigDecimal,CardDO.ADD,giftMoney)); + //BigDecimal bigDecimal = money.divide(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP); + return success(cardService.recharge(money,CardDO.ADD,giftMoney)); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/order/DishOrderDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/order/DishOrderDO.java index f079ba08..10b17b14 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/order/DishOrderDO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/order/DishOrderDO.java @@ -30,6 +30,7 @@ public class DishOrderDO extends BaseDO { public final static String COMPLETE = "1"; public final static String INCOMPLETE = "0"; + public final static String TOCOMPLETE = "2"; /** diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java index e8fd2abe..e72f3a52 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java @@ -106,6 +106,7 @@ public interface MemberUserMapper extends BaseMapperX { // 分页查询 return selectPage(listVO, new LambdaQueryWrapperX() .likeIfPresent(MemberUserDO::getNickname, listVO.getName()) + .likeIfPresent(MemberUserDO::getMobile,listVO.getMobile()) .notIn(CollectionUtil.isNotEmpty(listVO.getIds()) ,MemberUserDO::getId, listVO.getIds()) .orderByDesc(MemberUserDO::getId)); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/enums/CostTypeEnum.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/enums/CostTypeEnum.java index fcdb354f..b8ed54f3 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/enums/CostTypeEnum.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/enums/CostTypeEnum.java @@ -17,7 +17,9 @@ public enum CostTypeEnum { NOON("3", "午餐"), NIGHT("4", "晚餐"), ADMIN_PAY("5","管理后台充值"), - REFUND("6","退款") + REFUND("6","退款"), + WITHDRAW("7","微信提现"), + CASH_WITHDRAW("8","现金提现"), ; /** diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/job/BalanceDeductionJob.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/job/BalanceDeductionJob.java index 3cda3228..d939b108 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/job/BalanceDeductionJob.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/job/BalanceDeductionJob.java @@ -54,7 +54,7 @@ public class BalanceDeductionJob implements JobHandler { List diningPlatesToCharging = platesService.getDiningPlatesToCharging(EXPIRATION_TIME); int size = 0; - if(CollectionUtil.isNotEmpty(diningPlatesToCharging)){ + if (CollectionUtil.isNotEmpty(diningPlatesToCharging)) { List ids = diningPlatesToCharging.stream().map(DiningPlatesDO::getId).collect(Collectors.toList()); List orderIds = diningPlatesToCharging.stream().map(DiningPlatesDO::getOrderId).collect(Collectors.toList()); //先更改状态防止重复消费 @@ -74,29 +74,38 @@ public class BalanceDeductionJob implements JobHandler { BigDecimal money = oldCardDO.getMoney(); + + BigDecimal wxAmount = oldCardDO.getWxAmount(); BigDecimal giftAmount = oldCardDO.getGiftAmount(); BigDecimal cashAmount = oldCardDO.getCashAmount(); cardDO.setMoney(money.subtract(total).setScale(2, BigDecimal.ROUND_HALF_UP)); - if(total.compareTo(wxAmount)<=0){ - cardDO.setWxAmount(wxAmount.subtract(total).setScale(2, BigDecimal.ROUND_HALF_UP)); - dishOrderDO.setWxAmount(total); - }else { - cardDO.setWxAmount(BigDecimal.ZERO); - dishOrderDO.setWxAmount(wxAmount); - BigDecimal total1 = total.subtract(wxAmount).setScale(2, BigDecimal.ROUND_HALF_UP); - if(total1.compareTo(cashAmount)<=0){ - cardDO.setCashAmount(cashAmount.subtract(total1).setScale(2, BigDecimal.ROUND_HALF_UP)); - dishOrderDO.setCashAmount(total1); - }else { - cardDO.setCashAmount(BigDecimal.ZERO); - dishOrderDO.setCashAmount(cashAmount); - BigDecimal total2 = total1.subtract(cashAmount).setScale(2, BigDecimal.ROUND_HALF_UP); + if (total.compareTo(money) > 0) { + dishOrderDO.setOrderStatus(DishOrderDO.TOCOMPLETE); + } else { + dishOrderDO.setOrderStatus(DishOrderDO.COMPLETE); + //计算金额 + if (total.compareTo(wxAmount) <= 0) { + cardDO.setWxAmount(wxAmount.subtract(total).setScale(2, BigDecimal.ROUND_HALF_UP)); + dishOrderDO.setWxAmount(total); + } else { + cardDO.setWxAmount(BigDecimal.ZERO); + dishOrderDO.setWxAmount(wxAmount); + BigDecimal total1 = total.subtract(wxAmount).setScale(2, BigDecimal.ROUND_HALF_UP); + if (total1.compareTo(cashAmount) <= 0) { + cardDO.setCashAmount(cashAmount.subtract(total1).setScale(2, BigDecimal.ROUND_HALF_UP)); + dishOrderDO.setCashAmount(total1); + } else { + cardDO.setCashAmount(BigDecimal.ZERO); + dishOrderDO.setCashAmount(cashAmount); + BigDecimal total2 = total1.subtract(cashAmount).setScale(2, BigDecimal.ROUND_HALF_UP); - cardDO.setGiftAmount(giftAmount.subtract(total2).setScale(2, BigDecimal.ROUND_HALF_UP)); - dishOrderDO.setGiftAmount(total2); + cardDO.setGiftAmount(giftAmount.subtract(total2).setScale(2, BigDecimal.ROUND_HALF_UP)); + dishOrderDO.setGiftAmount(total2); + } } + } cardDO.setUserId(userId); @@ -104,8 +113,8 @@ public class BalanceDeductionJob implements JobHandler { cardDO.setFlag(CardDO.MINUS); cardService.insertOne(cardDO); list.add(cardDO); + dishOrderDO.setTotalMoney(total); - dishOrderDO.setOrderStatus(DishOrderDO.COMPLETE); dishOrderDO.setUpdateTime(LocalDateTime.now()); stringRedisTemplate.delete(dishOrderDO.getDiningPlatesNum()); }); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/card/CardService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/card/CardService.java index 248f9ff5..5eb7bd93 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/card/CardService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/card/CardService.java @@ -100,4 +100,8 @@ public interface CardService { FaceVo getFaceData(String faceId); void refund(Long userId,BigDecimal money,Long orderId); + + BigDecimal getCashMoney(Long userId); + + Boolean cashDraw(Long userId,BigDecimal money); } \ No newline at end of file diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/card/CardServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/card/CardServiceImpl.java index 0aeda7bd..fdf77d2a 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/card/CardServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/card/CardServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.member.service.card; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.exception.ErrorCode; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -19,6 +20,7 @@ import cn.iocoder.yudao.module.member.dal.mysql.group.MemberGroupMapper; import cn.iocoder.yudao.module.member.dal.mysql.order.DishOrderMapper; import cn.iocoder.yudao.module.member.enums.CostTypeEnum; import cn.iocoder.yudao.module.member.util.MemberConstants; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -35,8 +37,7 @@ import java.util.List; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.CARD_NOT_EXISTS; -import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.NEED_ADD_USER; +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*; /** * 余额变动明细 Service 实现类 @@ -115,6 +116,7 @@ public class CardServiceImpl implements CardService { BigDecimal oldMoney = BigDecimal.ZERO; BigDecimal wxOldMoney= BigDecimal.ZERO; BigDecimal giftOldMoney= BigDecimal.ZERO; + BigDecimal cashAmount= BigDecimal.ZERO; if (ObjectUtil.isNotEmpty(lastCardDO) && lastCardDO.getMoney() != null) { oldMoney = lastCardDO.getMoney(); } @@ -124,11 +126,24 @@ public class CardServiceImpl implements CardService { if (ObjectUtil.isNotEmpty(lastCardDO) && lastCardDO.getGiftAmount() != null) { giftOldMoney = lastCardDO.getGiftAmount(); } + if (ObjectUtil.isNotEmpty(lastCardDO) && lastCardDO.getGiftAmount() != null) { + cashAmount = lastCardDO.getCashAmount(); + } cardDO.setMoney(oldMoney.add(money).setScale(2, BigDecimal.ROUND_HALF_UP)); - cardDO.setWxAmount(wxOldMoney.add(money).setScale(2, BigDecimal.ROUND_HALF_UP)); - cardDO.setGiftAmount(giftOldMoney.add(giftMoney).setScale(2, BigDecimal.ROUND_HALF_UP)); - return cardMapper.insert(cardDO) > 0; + cardDO.setCashAmount(cashAmount); + cardDO.setGiftAmount(giftOldMoney); + cardDO.setWxAmount(giftOldMoney); + if(cardDO.getMoney().compareTo(BigDecimal.ZERO) >0){ + BigDecimal wxAmount = money; + if(giftMoney!=null){ + cardDO.setGiftAmount(giftOldMoney.add(giftMoney).setScale(2, BigDecimal.ROUND_HALF_UP)); + wxAmount = wxAmount.subtract(giftMoney); + } + cardDO.setWxAmount(wxOldMoney.add(wxAmount).setScale(2, BigDecimal.ROUND_HALF_UP)); + } + int i =cardMapper.insert(cardDO); + return i > 0; } @Override @@ -233,10 +248,16 @@ public class CardServiceImpl implements CardService { add.setType(CostTypeEnum.ADMIN_PAY.getCode()); BigDecimal oldMoney = cardDO.getMoney(); add.setMoney(oldMoney.add(vo.getMoney()).setScale(2, BigDecimal.ROUND_HALF_UP)); - BigDecimal cashOldMoney = cardDO.getCashAmount(); - add.setCashAmount(cashOldMoney.add(vo.getMoney()).setScale(2, BigDecimal.ROUND_HALF_UP)); + + if(cardDO.getMoney().compareTo(BigDecimal.ZERO) >0){ + BigDecimal cashOldMoney = cardDO.getCashAmount(); + add.setCashAmount(cashOldMoney.add(vo.getMoney()).setScale(2, BigDecimal.ROUND_HALF_UP)); + add.setWxAmount(cardDO.getWxAmount()); + add.setGiftAmount(cardDO.getGiftAmount()); + } addList.add(add); } + //添加新的用户金额 if (CollectionUtil.isNotEmpty(newIds)) { for (Long id : newIds) { @@ -304,4 +325,59 @@ public class CardServiceImpl implements CardService { } cardMapper.insert(cardDO); } + + + public BigDecimal checkOrder(Long userId) { + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + + wrapper.eq(DishOrderDO::getUserId,userId); + wrapper.eq(DishOrderDO::getOrderStatus,DishOrderDO.TOCOMPLETE); + + List dishOrderDOS = dishOrderMapper.selectList(wrapper); + + if(CollectionUtil.isNotEmpty(dishOrderDOS)){ + BigDecimal reduce = dishOrderDOS.stream().map(DishOrderDO::getTotalMoney).reduce(BigDecimal.ZERO, BigDecimal::add); + return reduce; + }else { + return BigDecimal.ZERO; + } + } + + @Override + public BigDecimal getCashMoney(Long userId) { + CardDO lastCardDO = cardMapper.selectOne(Wrappers.lambdaQuery().eq(CardDO::getUserId, userId) + .orderByDesc(CardDO::getCreateTime).last(MemberConstants.LIMIT_ONE)); + if(ObjectUtil.isNotEmpty(lastCardDO)){ + return lastCardDO.getCashAmount(); + } + return BigDecimal.ZERO; + } + + @Override + public Boolean cashDraw(Long userId,BigDecimal money) { + CardDO lastCardDO = cardMapper.selectOne(Wrappers.lambdaQuery().eq(CardDO::getUserId, userId) + .orderByDesc(CardDO::getCreateTime).last(MemberConstants.LIMIT_ONE)); + if(ObjectUtil.isEmpty(lastCardDO) || lastCardDO.getCashAmount().compareTo(BigDecimal.ZERO)<1 + || money.compareTo(lastCardDO.getCashAmount())>0){ + throw exception(CASH_AMOUNT_NOT_ENOUGH); + } + CardDO cardDO = new CardDO(); + cardDO.setUserId(userId); + cardDO.setFlag(CardDO.MINUS); + cardDO.setChangeMoney(money); + cardDO.setType(CostTypeEnum.CASH_WITHDRAW.getCode()); + + BigDecimal oldMoney = lastCardDO.getMoney(); + BigDecimal oldWxAmount = lastCardDO.getWxAmount(); + BigDecimal oldCashAmount = lastCardDO.getCashAmount(); + BigDecimal oldGiftAmount = lastCardDO.getGiftAmount(); + + cardDO.setWxAmount(oldWxAmount); + cardDO.setGiftAmount(oldGiftAmount); + cardDO.setMoney(oldMoney.subtract(money)); + cardDO.setCashAmount(oldCashAmount.subtract(money)); + int insert = cardMapper.insert(cardDO); + return insert>0; + } } \ No newline at end of file diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/diningplates/DiningPlatesServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/diningplates/DiningPlatesServiceImpl.java index 2411d6aa..aac3547f 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/diningplates/DiningPlatesServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/diningplates/DiningPlatesServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.member.service.diningplates; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.exception.ErrorCode; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender; @@ -167,6 +168,9 @@ public class DiningPlatesServiceImpl implements DiningPlatesService { .eq(MemberUserDO::getCardId, cardId) .last(MemberConstants.LIMIT_ONE)); checkMemberUser(memberUserDO, false); + //订单验证 + checkOrder(memberUserDO.getId()); + //余额验证 BigDecimal money = cardService.getMoneyByUserId(memberUserDO.getId()); checkMoney(money); @@ -208,6 +212,8 @@ public class DiningPlatesServiceImpl implements DiningPlatesService { .eq(MemberUserDO::getFaceId, faceId) .last(MemberConstants.LIMIT_ONE)); checkMemberUser(memberUserDO, true); + //订单验证 + checkOrder(memberUserDO.getId()); //余额验证 BigDecimal money = cardService.getMoneyByUserId(memberUserDO.getId()); checkMoney(money); @@ -293,6 +299,21 @@ public class DiningPlatesServiceImpl implements DiningPlatesService { } } + public void checkOrder(Long userId) { + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + + wrapper.eq(DishOrderDO::getUserId,userId); + wrapper.eq(DishOrderDO::getOrderStatus,DishOrderDO.TOCOMPLETE); + + List dishOrderDOS = dishOrderMapper.selectList(wrapper); + BigDecimal moneyByUserId = cardService.getMoneyByUserId(userId); + ErrorCode code = new ErrorCode(1_004_099_008, "存在未支付完的订单,待支付金额:"+moneyByUserId.abs()+"元"); + if(CollectionUtil.isNotEmpty(dishOrderDOS)){ + throw exception(code); + } + } + @Override public List getDiningPlatesNum(LocalDateTime localDateTime, Integer time) { diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java index 38f190ce..cd372022 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java @@ -3,33 +3,49 @@ package cn.iocoder.yudao.module.pay.controller.admin.notify; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; +import cn.iocoder.yudao.framework.pay.core.enums.divide.PayDivideRefundStatusRespEnum; +import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO; import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO; import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskRespVO; import cn.iocoder.yudao.module.pay.convert.notify.PayNotifyTaskConvert; import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.divide.DivideDO; import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.refundrecord.RefundRecordDO; +import cn.iocoder.yudao.module.pay.dal.mysql.refundrecord.RefundRecordMapper; import cn.iocoder.yudao.module.pay.service.app.PayAppService; import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; +import cn.iocoder.yudao.module.pay.service.divide.DivideService; import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; import cn.iocoder.yudao.module.pay.service.order.PayOrderService; import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.annotation.security.PermitAll; import javax.validation.Valid; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -50,11 +66,17 @@ public class PayNotifyController { @Resource private PayRefundService refundService; @Resource + private RefundRecordMapper refundRecordMapper; + @Resource private PayNotifyService notifyService; @Resource private PayAppService appService; @Resource private PayChannelService channelService; + @Resource + private DivideService divideService; + @Resource + private StringRedisTemplate notifyRedisTemplate; @PostMapping(value = "/order/{channelId}") @Operation(summary = "支付渠道的统一【支付】回调") @@ -91,10 +113,37 @@ public class PayNotifyController { log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); throw exception(CHANNEL_NOT_FOUND); } - // 2. 解析通知数据 PayRefundRespDTO notify = payClient.parseRefundNotify(params, body); - refundService.notifyRefund(channelId, notify); + RefundRecordDO refundRecordDO = refundRecordMapper.selectOne(Wrappers.lambdaUpdate() + .eq(RefundRecordDO::getOutRefundNo, notify.getOutRefundNo()) + .last("limit 1")); + String status = ""; + if(PayRefundStatusRespEnum.SUCCESS.getStatus().equals(notify.getStatus())){ + status = PayDivideRefundStatusRespEnum.SUCCESS.getStatus(); + + }else{ + status = PayDivideRefundStatusRespEnum.ABNORMAL.getStatus(); + } + refundRecordDO.setStatus(status); + if("0".equals(refundRecordDO.getNotifyStatus()) && "20".equals(refundRecordDO.getStatus())){ + //扣除积分 + divideService.subtractWx(refundRecordDO.getTotalPrice(),Long.valueOf(refundRecordDO.getUserId())); + //更改订单 + String jsonString = notifyRedisTemplate.opsForValue().get("R" + notify.getOutRefundNo()); + DivideDO divideDO1 = JsonUtils.parseObject(jsonString, DivideDO.class); + divideService.updateDivideById(divideDO1); + //分账回退 + if (divideDO1.getBackPrice()!=0){ + ArrayList divideDOS = new ArrayList<>(); + divideDOS.add(divideDO1); + divideService.returnMoney(divideDOS); + } + + } + refundRecordDO.setNotifyStatus("1"); + refundRecordMapper.updateById(refundRecordDO); + //refundService.notifyRefund(channelId, notify); return "success"; } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/card/DivideCardDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/card/DivideCardDO.java new file mode 100644 index 00000000..192801da --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/card/DivideCardDO.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.pay.dal.dataobject.card; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.math.BigDecimal; + +/** + * 余额变动明细 DO + * + * @author 开发账号 + */ +@TableName("member_card") +@KeySequence("member_card_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DivideCardDO extends BaseDO { + + public final static String ADD = "1"; + public final static String MINUS = "0"; + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 用户Id + */ + private Long userId; + /** + * 余额 + */ + private BigDecimal money; + /** + * 加减标志(0:减,1:加) + */ + private String flag; + /** + * 变动金额 + */ + private BigDecimal changeMoney; + + /** + * 消费类型 + */ + private String type; + + /** + * 赠送金额 + */ + private BigDecimal giftAmount; + + /** + * 现金金额 + */ + private BigDecimal cashAmount; + + /** + * 微信充值金额 + */ + private BigDecimal wxAmount; + +} \ No newline at end of file diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/divide/DivideDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/divide/DivideDO.java index c366f3b8..4d0c9d4a 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/divide/DivideDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/divide/DivideDO.java @@ -58,6 +58,11 @@ public class DivideDO extends BaseDO { * 待分金额,单位:分 */ private Integer unPrice; + + /** + * 待退款金额,单位:分 + */ + private Integer unRePrice; /** * 分账状态 */ @@ -68,6 +73,11 @@ public class DivideDO extends BaseDO { */ private String refundStatus; + /** + * 是否解冻 + */ + private String unfreezeStatus; + /** * 商户分账单号 */ @@ -82,7 +92,17 @@ public class DivideDO extends BaseDO { private String orderId; /** - * 退款金额 + * 已用于退款金额 */ private Integer refundPrice; + + /** + * 分账回退金额 + */ + private Integer backPrice; + + /** + * 用于分账的金额 + */ + private Integer psPrice; } \ No newline at end of file diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/divideinfo/DivideInfoDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/divideinfo/DivideInfoDO.java index 92cf866d..25cf1ce5 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/divideinfo/DivideInfoDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/divideinfo/DivideInfoDO.java @@ -39,6 +39,11 @@ public class DivideInfoDO extends BaseDO { * 商户分账单号 */ private String outOrderNo; + + /** + * 微信分账单号 + */ + private String orderId; /** * 分账个人接收方姓名 */ diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refundrecord/RefundRecordDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refundrecord/RefundRecordDO.java index 3b4621ea..358bbf3c 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refundrecord/RefundRecordDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refundrecord/RefundRecordDO.java @@ -1,11 +1,15 @@ package cn.iocoder.yudao.module.pay.dal.dataobject.refundrecord; -import lombok.*; -import java.util.*; -import java.time.LocalDateTime; -import java.time.LocalDateTime; -import com.baomidou.mybatisplus.annotation.*; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; /** * 退款记录 DO @@ -68,4 +72,9 @@ public class RefundRecordDO extends BaseDO { */ private String refundId; + /** + * 是否回调 + */ + private String notifyStatus; + } \ No newline at end of file diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/card/DivideCardMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/card/DivideCardMapper.java new file mode 100644 index 00000000..07dfefe9 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/card/DivideCardMapper.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.pay.dal.mysql.card; + + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.pay.dal.dataobject.card.DivideCardDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 余额变动明细 Mapper + * + * @author 开发账号 + */ +@Mapper +public interface DivideCardMapper extends BaseMapperX { + +} \ No newline at end of file diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/divide/DivideMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/divide/DivideMapper.java index 604be72d..a93cade3 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/divide/DivideMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/divide/DivideMapper.java @@ -41,7 +41,4 @@ public interface DivideMapper extends BaseMapperX { int orderCount(Long userId); - - - } \ No newline at end of file diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/refundrecord/RefundRecordMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/refundrecord/RefundRecordMapper.java index e28c6763..b8222808 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/refundrecord/RefundRecordMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/refundrecord/RefundRecordMapper.java @@ -1,13 +1,11 @@ package cn.iocoder.yudao.module.pay.dal.mysql.refundrecord; -import java.util.*; - import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.pay.controller.admin.refundrecord.vo.RefundRecordPageReqVO; import cn.iocoder.yudao.module.pay.dal.dataobject.refundrecord.RefundRecordDO; import org.apache.ibatis.annotations.Mapper; -import cn.iocoder.yudao.module.pay.controller.admin.refundrecord.vo.*; /** * 退款记录 Mapper diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/WalletPayClient.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/WalletPayClient.java index 766cc255..96a14e1c 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/WalletPayClient.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/WalletPayClient.java @@ -4,6 +4,8 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.map.MapUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackRespDto; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideRespDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; @@ -204,4 +206,9 @@ public class WalletPayClient extends AbstractPayClient { return null; } + @Override + protected PayDivideBackRespDto doUnifiedDivideback(PayDivideBackUnifiedDto reqDTO) throws Throwable { + return null; + } + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divide/DivideService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divide/DivideService.java index a03d9fff..af5ab16a 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divide/DivideService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divide/DivideService.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.pay.controller.app.divide.vo.DrawMoneyVO; import cn.iocoder.yudao.module.pay.dal.dataobject.divide.DivideDO; import javax.validation.Valid; +import java.util.List; /** * 分账单 Service 接口 @@ -70,7 +71,20 @@ public interface DivideService { /** - * 解冻剩余资金 + * 提现(退款) */ Boolean drawMoney( DrawMoneyVO drawMoneyVO); + + /** + * 扣除wx充值 + */ + void subtractWx(Integer amount,Long userId); + + + /** + * 分账回退 + */ + void returnMoney(List backList); + + void updateDivideById(DivideDO divideDO); } \ No newline at end of file diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divide/DivideServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divide/DivideServiceImpl.java index 0279ee25..48d5d8ca 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divide/DivideServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divide/DivideServiceImpl.java @@ -4,20 +4,31 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.pay.core.client.PayClient; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackRespDto; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideRespDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideUnifiedDto; +import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; +import cn.iocoder.yudao.framework.pay.core.enums.divide.PayDivideRefundStatusRespEnum; import cn.iocoder.yudao.framework.pay.core.enums.divide.PayDivideStatusRespEnum; import cn.iocoder.yudao.module.pay.controller.admin.divide.vo.DividePageReqVO; import cn.iocoder.yudao.module.pay.controller.admin.divide.vo.DivideSaveReqVO; import cn.iocoder.yudao.module.pay.controller.app.divide.vo.DrawMoneyVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.card.DivideCardDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; import cn.iocoder.yudao.module.pay.dal.dataobject.divide.DivideDO; import cn.iocoder.yudao.module.pay.dal.dataobject.dividecompany.DivideCompanyDO; import cn.iocoder.yudao.module.pay.dal.dataobject.divideinfo.DivideInfoDO; import cn.iocoder.yudao.module.pay.dal.dataobject.dividerecord.DivideRecordDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.refundrecord.RefundRecordDO; +import cn.iocoder.yudao.module.pay.dal.mysql.card.DivideCardMapper; import cn.iocoder.yudao.module.pay.dal.mysql.divide.DivideMapper; import cn.iocoder.yudao.module.pay.dal.mysql.dividerecord.DivideRecordMapper; +import cn.iocoder.yudao.module.pay.dal.mysql.refundrecord.RefundRecordMapper; import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; @@ -26,6 +37,8 @@ import cn.iocoder.yudao.module.pay.service.divideinfo.DivideInfoService; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingV3Request; import com.github.binarywang.wxpay.bean.profitsharing.result.ProfitSharingV3Result; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -34,9 +47,9 @@ import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; @@ -48,6 +61,7 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; */ @Service @Validated +@Slf4j public class DivideServiceImpl implements DivideService { @Resource @@ -70,6 +84,14 @@ public class DivideServiceImpl implements DivideService { @Resource private DivideRecordMapper divideRecordMapper; + @Resource + private RefundRecordMapper refundRecordMapper; + + @Resource + private DivideCardMapper divideCardMapper; + + @Resource + private StringRedisTemplate divideRedisTemplate; @Override @@ -150,6 +172,11 @@ public class DivideServiceImpl implements DivideService { public int startDivide() { BigDecimal today = divideMapper.getToday(); + + if (today == null) { + return 0; + } + int money = today.multiply(new BigDecimal("100")).intValue(); LocalDateTime now = LocalDateTime.now(); LocalDateTime thirtyDaysAgo = now.minusDays(30); @@ -157,32 +184,41 @@ public class DivideServiceImpl implements DivideService { List divideDOS = divideMapper.selectList(Wrappers.lambdaQuery() .eq(DivideDO::getStatus, PayDivideStatusRespEnum.WAITING.getStatus()) - .ge(DivideDO::getCreateTime,thirtyDaysAgo) + .eq(DivideDO::getUnfreezeStatus,"0") + .ge(DivideDO::getCreateTime, thirtyDaysAgo) .orderByAsc(DivideDO::getCreateTime)); - if(CollectionUtil.isEmpty(divideDOS)){ + if (CollectionUtil.isEmpty(divideDOS)) { return 0; } List divideList = new ArrayList<>(); int sum = 0; - for(DivideDO divideDO: divideDOS){ - Integer totalPrice = divideDO.getTotalPrice()-divideDO.getCpPrice(); + for (DivideDO divideDO : divideDOS) { + Integer totalPrice = divideDO.getTotalPrice() - divideDO.getCpPrice(); - sum = sum+totalPrice; - if(sum divideRecordDOList = divideRecordMapper.getList(); - if(CollectionUtil.isEmpty(divideRecordDOList)){ + if (CollectionUtil.isEmpty(divideRecordDOList)) { return 0; } - Stream transactionIdList = divideRecordDOList.stream().map(DivideRecordDO::getTransactionId); - Stream OutOrderNoList = divideRecordDOList.stream().map(DivideRecordDO::getOutOrderNo); + List transactionIdList = divideRecordDOList.stream().map(DivideRecordDO::getTransactionId).collect(Collectors.toList()); + List OutOrderNoList = divideRecordDOList.stream().map(DivideRecordDO::getOutOrderNo).collect(Collectors.toList()); List divideDOS = divideMapper.selectList(Wrappers.lambdaQuery() .in(DivideDO::getChannelOrderNo, transactionIdList) - .in(DivideDO::getNo,OutOrderNoList)); + .in(DivideDO::getNo, OutOrderNoList)); - if(CollectionUtil.isEmpty(divideDOS)){ + if (CollectionUtil.isEmpty(divideDOS)) { return 0; } @@ -254,11 +292,11 @@ public class DivideServiceImpl implements DivideService { payDivideUnifiedDto.setTransactionId(divideDO.getChannelOrderNo()) .setOutOrderNo(divideDO.getNo()); PayDivideRespDto payDivideRespDto = client.unifiedDivideResult(payDivideUnifiedDto); - updateDivideInfo(payDivideRespDto.getReceivers(),divideDO.getNo()); + updateDivideInfo(payDivideRespDto.getReceivers(), divideDO.getNo(),payDivideRespDto.getOrderId()); - if(divideDO.getTotalPrice().equals(divideDO.getCpPrice())) { + if (divideDO.getTotalPrice().equals(divideDO.getCpPrice())) { divideDO.setStatus(PayDivideStatusRespEnum.COMPLETE.getStatus()); - }else{ + } else { divideDO.setNo(noRedisDAO.generate(payProperties.getOrderNoPrefix())); } } @@ -266,15 +304,24 @@ public class DivideServiceImpl implements DivideService { return divideDOS.size(); } - void updateDivideInfo(List receivers,String outOrderNo){ - List list = new ArrayList<>(); - for (ProfitSharingV3Result.Receiver receiver:receivers){ + void updateDivideInfo(List receivers, String outOrderNo,String orderId) { + List list1 = divideCompanyService.getList(); + List accountList = list1.stream().map(DivideCompanyDO::getAccount).collect(Collectors.toList()); + + List list = new ArrayList<>(); + for (ProfitSharingV3Result.Receiver receiver : receivers) { + if(!accountList.contains(receiver.getAccount())){ + continue; + } + DivideInfoDO divideInfo = divideInfoService.getDivideInfo(outOrderNo, receiver.getAccount()); + divideInfo.setResult(receiver.getResult()) .setFailReason(receiver.getFailReason()) .setDetailId(receiver.getDetailId()) .setDCreateTime(receiver.getCreateTime()) - .setDFinishTime(receiver.getFinishTime()); + .setDFinishTime(receiver.getFinishTime()) + .setOrderId(orderId); list.add(divideInfo); } divideInfoService.updateList(list); @@ -284,14 +331,14 @@ public class DivideServiceImpl implements DivideService { public int getDivideFreeze() { List divideDOS = divideMapper.selectList(Wrappers.lambdaQuery() .eq(DivideDO::getStatus, PayDivideStatusRespEnum.COMPLETE.getStatus())); - if(CollectionUtil.isEmpty(divideDOS)){ + if (CollectionUtil.isEmpty(divideDOS)) { return 0; } for (DivideDO divideDO : divideDOS) { PayClient client = channelService.getPayClient(divideDO.getChannelId()); PayDivideUnifiedDto payDivideUnifiedDto = new PayDivideUnifiedDto(); - if(checkSuccess(divideDO.getNo())){ + if (checkSuccess(divideDO.getNo())) { payDivideUnifiedDto.setTransactionId(divideDO.getChannelOrderNo()) .setOutOrderNo(divideDO.getNo()); client.unifiedDivideFreeze(payDivideUnifiedDto); @@ -302,10 +349,10 @@ public class DivideServiceImpl implements DivideService { return divideDOS.size(); } - boolean checkSuccess(String outOrderNo){ + boolean checkSuccess(String outOrderNo) { List divideList = divideInfoService.getDivideList(outOrderNo); - for (DivideInfoDO divideInfoDO:divideList){ - if(!"SUCCESS".equals(divideInfoDO.getResult())){ + for (DivideInfoDO divideInfoDO : divideList) { + if (!"SUCCESS".equals(divideInfoDO.getResult())) { return false; } } @@ -317,32 +364,41 @@ public class DivideServiceImpl implements DivideService { //判断订单是否完成 int i = divideMapper.orderCount(drawMoneyVO.getUserId()); - if(i>0){ + if (i > 0) { throw new ServiceException(ORDER_NOT_COMPLETE); } //判断是否有金额可退款 BigDecimal wxAmount = divideMapper.getWxAmount(drawMoneyVO.getUserId()); - int money = wxAmount.multiply(new BigDecimal("100")).intValue(); - if(money<=0){ + if(wxAmount == null){ throw new ServiceException(WX_ACCOUNT_NO); } + int money = wxAmount.multiply(new BigDecimal("100")).intValue(); + if (money <= 0) { + throw new ServiceException(WX_ACCOUNT_NO); + } + LocalDateTime now = LocalDateTime.now(); // 获取当前时间 + LocalDateTime threeYearsAgo = now.minusDays(365); + //查询最近的充值订单,时间倒序退款 List divideDOS = divideMapper.selectList(Wrappers.lambdaQuery() .eq(DivideDO::getChannelUserId, drawMoneyVO.getChannelUserId()) - .eq(DivideDO::getRefundStatus,"0") + .eq(DivideDO::getRefundStatus, "0") + .ge(DivideDO::getCreateTime,threeYearsAgo) .orderByDesc(DivideDO::getCreateTime)); //筛选出未分账的订单 - List unDivideList = divideDOS.stream().filter(vo -> vo.getCpPrice() == 0).collect(Collectors.toList()); + List unDivideList = divideDOS.stream().filter(vo -> vo.getPsPrice() == 0).collect(Collectors.toList()); //筛选出已分账的订单 - List divideList = divideDOS.stream().filter(vo -> vo.getCpPrice().equals(vo.getTotalPrice())).collect(Collectors.toList()); + List divideCpList = divideDOS.stream().filter(vo -> vo.getPsPrice() != 0).collect(Collectors.toList()); + + //筛选出分账完的订单 + List divideList = divideCpList.stream().filter(vo -> vo.getTotalPrice().equals(vo.getCpPrice())).collect(Collectors.toList()); //剩下的是未分账完 的订单 - divideDOS.removeAll(unDivideList); - divideDOS.removeAll(divideList); + divideCpList.removeAll(divideList); //需要回退的订单 List backList = new ArrayList<>(); @@ -353,54 +409,329 @@ public class DivideServiceImpl implements DivideService { //先从未分账的订单计算 - for (DivideDO divideDO: unDivideList){ - Integer totalPrice = divideDO.getTotalPrice()-divideDO.getCpPrice(); + for (DivideDO divideDO : unDivideList) { + Integer totalPrice = divideDO.getTotalPrice() - divideDO.getCpPrice(); + sum = sum + totalPrice; - sum = sum+totalPrice; - - if(sum<=money){ - divideDO.setRefundPrice(totalPrice); - divideDO.setCpPrice(divideDO.getCpPrice()+totalPrice); + if (sum < money) { + divideDO.setUnRePrice(totalPrice); + divideDO.setRefundPrice(totalPrice+divideDO.getCpPrice()); + divideDO.setCpPrice(divideDO.getCpPrice() + totalPrice); noBackList.add(divideDO); - }else { - int leftMoney = money+totalPrice- sum; - divideDO.setRefundPrice(leftMoney); - divideDO.setCpPrice(divideDO.getCpPrice()+leftMoney); + } else if (sum == money) { + divideDO.setUnRePrice(totalPrice); + divideDO.setRefundPrice(totalPrice+divideDO.getCpPrice()); + divideDO.setCpPrice(divideDO.getCpPrice() + totalPrice); + noBackList.add(divideDO); + break; + } else { + int leftMoney = money + totalPrice - sum; + divideDO.setUnRePrice(leftMoney); + divideDO.setRefundPrice(divideDO.getCpPrice() + leftMoney); + divideDO.setCpPrice(divideDO.getCpPrice() + leftMoney); noBackList.add(divideDO); break; } } //从分账完的订单进行退款 - if(sum list = new ArrayList(); + + int failNum = 0; + //调用退款接口 + if(CollectionUtil.isNotEmpty(noBackList)){ + for (DivideDO divideDO : noBackList) { + String outRefundNo = noRedisDAO.generate(payProperties.getRefundNoPrefix()); + RefundRecordDO refundRecordDO = new RefundRecordDO(); + refundRecordDO.setOutTradeNo(divideDO.getNo()); + refundRecordDO.setOutRefundNo(outRefundNo); + refundRecordDO.setTransactionId(divideDO.getChannelOrderNo()); + refundRecordDO.setChannelId(divideDO.getChannelId()); + refundRecordDO.setChannelUserId(divideDO.getChannelUserId()); + refundRecordDO.setChannelCode(divideDO.getChannelCode()); + refundRecordDO.setUserId(String.valueOf(drawMoneyVO.getUserId())); + refundRecordDO.setTotalPrice(divideDO.getUnRePrice()); + + PayChannelDO channel = channelService.validPayChannel(divideDO.getChannelId()); + + PayClient client = channelService.getPayClient(divideDO.getChannelId()); + PayRefundUnifiedReqDTO payRefundUnifiedReqDTO = new PayRefundUnifiedReqDTO(); + payRefundUnifiedReqDTO.setTransactionId(divideDO.getChannelOrderNo()) + .setReason("提现").setRefundPrice(divideDO.getUnRePrice()) + .setOutRefundNo(outRefundNo).setPayPrice(divideDO.getTotalPrice()) + .setNotifyUrl(genChannelRefundNotifyUrl(channel)); + PayRefundRespDTO payRefundRespDTO = client.unifiedRefund(payRefundUnifiedReqDTO); + + String channelRefundNo = payRefundRespDTO.getChannelRefundNo(); + refundRecordDO.setRefundId(channelRefundNo); + if(cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum.WAITING.getStatus().equals(payRefundRespDTO.getStatus())){ + refundRecordDO.setStatus(PayDivideRefundStatusRespEnum.PROCESSING.getStatus()); + } else if (cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum.SUCCESS.getStatus().equals(payRefundRespDTO.getStatus())) { + refundRecordDO.setStatus(PayDivideRefundStatusRespEnum.SUCCESS.getStatus()); + }else { + failNum++; + refundRecordDO.setStatus(PayDivideRefundStatusRespEnum.ABNORMAL.getStatus()); + } + refundRecordMapper.insert(refundRecordDO); + if(divideDO.getRefundPrice().equals(divideDO.getTotalPrice())){ + divideDO.setRefundStatus("1"); + } + if(divideDO.getTotalPrice().equals(divideDO.getCpPrice())){ + divideDO.setStatus(PayDivideStatusRespEnum.CASH.getStatus()); + } + String jsonString = JsonUtils.toJsonString(divideDO); + //DivideDO divideDO1 = JsonUtils.parseObject(jsonString, DivideDO.class); + divideRedisTemplate.opsForValue().set("R"+outRefundNo,jsonString); + //divideMapper.updateById(divideDO); + + //list.add(refundRecordDO); + } + } + + //调用退款接口 + if(CollectionUtil.isNotEmpty(backList)){ + for (DivideDO divideDO : backList) { + String outRefundNo = noRedisDAO.generate(payProperties.getRefundNoPrefix()); + RefundRecordDO refundRecordDO = new RefundRecordDO(); + refundRecordDO.setOutTradeNo(divideDO.getNo()); + refundRecordDO.setOutRefundNo(outRefundNo); + refundRecordDO.setTransactionId(divideDO.getChannelOrderNo()); + refundRecordDO.setChannelId(divideDO.getChannelId()); + refundRecordDO.setChannelUserId(divideDO.getChannelUserId()); + refundRecordDO.setChannelCode(divideDO.getChannelCode()); + refundRecordDO.setUserId(String.valueOf(drawMoneyVO.getUserId())); + refundRecordDO.setTotalPrice(divideDO.getUnRePrice()); + + PayChannelDO channel = channelService.validPayChannel(divideDO.getChannelId()); + + PayClient client = channelService.getPayClient(divideDO.getChannelId()); + PayRefundUnifiedReqDTO payRefundUnifiedReqDTO = new PayRefundUnifiedReqDTO(); + payRefundUnifiedReqDTO.setTransactionId(divideDO.getChannelOrderNo()) + .setReason("提现").setRefundPrice(divideDO.getUnRePrice()) + .setOutRefundNo(outRefundNo).setPayPrice(divideDO.getTotalPrice()) + .setNotifyUrl(genChannelRefundNotifyUrl(channel)); + PayRefundRespDTO payRefundRespDTO = client.unifiedRefund(payRefundUnifiedReqDTO); + + String channelRefundNo = payRefundRespDTO.getChannelRefundNo(); + refundRecordDO.setRefundId(channelRefundNo); + if(cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum.WAITING.getStatus().equals(payRefundRespDTO.getStatus())){ + refundRecordDO.setStatus(PayDivideRefundStatusRespEnum.PROCESSING.getStatus()); + } else if (cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum.SUCCESS.getStatus().equals(payRefundRespDTO.getStatus())) { + refundRecordDO.setStatus(PayDivideRefundStatusRespEnum.SUCCESS.getStatus()); + }else { + failNum++; + refundRecordDO.setStatus(PayDivideRefundStatusRespEnum.ABNORMAL.getStatus()); + } + //list.add(refundRecordDO); + refundRecordMapper.insert(refundRecordDO); + if(divideDO.getRefundPrice().equals(divideDO.getTotalPrice())){ + divideDO.setRefundStatus("1"); + } + if(divideDO.getTotalPrice().equals(divideDO.getCpPrice())){ + divideDO.setStatus(PayDivideStatusRespEnum.CASH.getStatus()); + } + String jsonString = JsonUtils.toJsonString(divideDO); + //DivideDO divideDO1 = JsonUtils.parseObject(jsonString, DivideDO.class); + divideRedisTemplate.opsForValue().set("R"+outRefundNo,jsonString); + + //divideMapper.updateById(divideDO); + } + } + + //分账回退 + //if(CollectionUtil.isNotEmpty(backList)){ + // returnMoney(backList); + //} + //refundRecordMapper.insertBatch(list); + + // todo:清空 + return failNum>0?false:true; } + private String genChannelRefundNotifyUrl(PayChannelDO channel) { + return payProperties.getRefundNotifyUrl() + "/" + channel.getId(); + } + + @Override + public void returnMoney(List backList){ + List companyList = divideCompanyService.getList(); + Map companyMap = companyList.stream().collect(Collectors.toMap(DivideCompanyDO::getName, vo -> vo)); + + + for(DivideDO divideDO:backList){ + PayClient client = channelService.getPayClient(divideDO.getChannelId()); + //查询出分账的具体条数 + List divideListByTi = divideInfoService.getDivideListByTi(divideDO.getChannelOrderNo()); + //全部回退 + if(divideDO.getRefundPrice().equals(divideDO.getTotalPrice())){ + + for(DivideInfoDO divideInfoDO : divideListByTi){ + doReturn(client,divideInfoDO,companyMap.get(divideInfoDO.getName()).getAccount()); + } + }else{ + Integer refundPrice = divideDO.getRefundPrice(); + //算出每个公司应回退的金额 + for(DivideCompanyDO companyDO:companyList){ + int backmoney = (int) Math.ceil(refundPrice* Double.valueOf(companyDO.getProportion())); + + List baList = divideListByTi.stream().filter(vo -> vo.getName().equals(companyDO.getName())).collect(Collectors.toList()); + int sum = 0; + for (DivideInfoDO infoDO : baList){ + sum = sum+infoDO.getAmount(); + if(sumlambdaQuery() + .eq(DivideCardDO::getUserId, userId) + .orderByDesc(DivideCardDO::getCreateTime) + .last("limit 1")); + + BigDecimal changeMoney = new BigDecimal(amount).divide(new BigDecimal("100")); + //获取最新余额 + DivideCardDO cardDO = new DivideCardDO(); + cardDO.setUserId(userId); + cardDO.setFlag(DivideCardDO.MINUS); + cardDO.setChangeMoney(changeMoney); + cardDO.setType("7"); + BigDecimal oldMoney = lastCardDO.getMoney(); + BigDecimal wxOldMoney= lastCardDO.getWxAmount(); + + cardDO.setMoney(oldMoney.subtract(changeMoney).setScale(2, BigDecimal.ROUND_HALF_UP)); + cardDO.setWxAmount(wxOldMoney.subtract(changeMoney).setScale(2, BigDecimal.ROUND_HALF_UP)); + cardDO.setGiftAmount(lastCardDO.getGiftAmount()); + divideCardMapper.insert(cardDO); + } + + @Override + public void updateDivideById(DivideDO divideDO) { + divideMapper.updateById(divideDO); + } } \ No newline at end of file diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divideinfo/DivideInfoService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divideinfo/DivideInfoService.java index 7713f70e..35a9f83f 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divideinfo/DivideInfoService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divideinfo/DivideInfoService.java @@ -60,4 +60,6 @@ public interface DivideInfoService { List getDivideList(String outOrderNo); void updateList(List list); + + List getDivideListByTi(String transactionId); } \ No newline at end of file diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divideinfo/DivideInfoServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divideinfo/DivideInfoServiceImpl.java index b8db8aa2..c51a6a47 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divideinfo/DivideInfoServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/divideinfo/DivideInfoServiceImpl.java @@ -105,4 +105,10 @@ public class DivideInfoServiceImpl implements DivideInfoService { return divideInfoMapper.selectList(Wrappers.lambdaQuery() .eq(DivideInfoDO::getOutOrderNo, outOrderNo)); } + + @Override + public List getDivideListByTi(String transactionId) { + return divideInfoMapper.selectList(Wrappers.lambdaQuery() + .eq(DivideInfoDO::getTransactionId, transactionId)); + } } \ No newline at end of file diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java index 22df5de1..a026732b 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java @@ -380,6 +380,7 @@ public class PayOrderServiceImpl implements PayOrderService { //3.添加分账 order.setChannelOrderNo(notify.getChannelOrderNo()); + order.setChannelUserId(notify.getChannelUserId()); addDivide(channel,order); return false; } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refundrecord/RefundRecordService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refundrecord/RefundRecordService.java index b27046a4..7e6a1b38 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refundrecord/RefundRecordService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refundrecord/RefundRecordService.java @@ -52,4 +52,5 @@ public interface RefundRecordService { */ PageResult getRefundRecordPage(RefundRecordPageReqVO pageReqVO); + } \ No newline at end of file diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java index bbcdaf85..11eb69b3 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.framework.pay.core.client; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackRespDto; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideRespDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; @@ -125,4 +127,13 @@ public interface PayClient { PayDivideRespDto unifiedDivideFreeze(PayDivideUnifiedDto reqDTO); + + /** + * 分账回退 + * + * @param reqDTO 分账参数 + * @return 分账 + */ + PayDivideBackRespDto unifiedDivideback(PayDivideBackUnifiedDto reqDTO); + } diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/divide/PayDivideBackRespDto.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/divide/PayDivideBackRespDto.java new file mode 100644 index 00000000..a5f23ef8 --- /dev/null +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/divide/PayDivideBackRespDto.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.framework.pay.core.client.dto.divide; + +import lombok.Data; + +/** + * @author zt + * @description + * @since 2024/7/17 + */ +@Data +public class PayDivideBackRespDto { + private String subMchId; + private String orderId; + private String outOrderNo; + private String outReturnNo; + private String returnId; + private String returnMchid; + private Long amount; + private String description; + private String result; + private String failReason; + private String createTime; + private String finishTime; + + + private String channelErrorCode; + /** + * 调用渠道报错时,错误信息 + */ + private String channelErrorMsg; + + /** + * 原始的异步通知结果 + */ + private Object rawData; + + /** + * 创建【FAILURE】状态的退款返回 + */ + public static PayDivideBackRespDto failureOf(String channelErrorCode, String channelErrorMsg, + String transactionId, Object rawData) { + PayDivideBackRespDto respDTO = new PayDivideBackRespDto(); + //respDTO.status = PayRefundStatusRespEnum.FAILURE.getStatus(); + respDTO.channelErrorCode = channelErrorCode; + respDTO.channelErrorMsg = channelErrorMsg; + // 相对通用的字段 + respDTO.orderId = transactionId; + respDTO.rawData = rawData; + return respDTO; + } +} diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/divide/PayDivideBackUnifiedDto.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/divide/PayDivideBackUnifiedDto.java new file mode 100644 index 00000000..c48ad46a --- /dev/null +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/divide/PayDivideBackUnifiedDto.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.framework.pay.core.client.dto.divide; + +import lombok.Data; + +/** + * @author zt + * @description + * @since 2024/7/17 + */ +@Data +public class PayDivideBackUnifiedDto { + + /** + * 应用ID + */ + private String appid; + + /** + * 微信分账单号 + */ + private String orderId; + + /** + * 商户分账单号 + */ + private String outOrderNo; + + /** + * 商户回退单号 + */ + private String outReturnNo; + + /** + * 回退商户号 + */ + private String returnMchid; + + /** + * 回退金额 + */ + private Long amount; + + /** + * 回退描述 + */ + private String description; +} diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/refund/PayRefundUnifiedReqDTO.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/refund/PayRefundUnifiedReqDTO.java index 4f5e203d..45f36ceb 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/refund/PayRefundUnifiedReqDTO.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/refund/PayRefundUnifiedReqDTO.java @@ -28,9 +28,12 @@ public class PayRefundUnifiedReqDTO { * * 对应 PayOrderExtensionDO 的 no 字段 */ - @NotEmpty(message = "外部订单编号不能为空") + //@NotEmpty(message = "外部订单编号不能为空") private String outTradeNo; + @NotEmpty(message = "微信订单编号不能为空") + private String transactionId; + /** * 外部退款号 * diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java index ab279a76..a7eecb2d 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java @@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackRespDto; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideRespDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; @@ -313,4 +315,26 @@ public abstract class AbstractPayClient implemen } protected abstract PayDivideRespDto dounifiedDivideFreeze(PayDivideUnifiedDto reqDTO) throws Throwable; + + @Override + public PayDivideBackRespDto unifiedDivideback(PayDivideBackUnifiedDto reqDTO) { + ValidationUtils.validate(reqDTO); + // 执行统一下单 + PayDivideBackRespDto resp; + try { + resp = doUnifiedDivideback(reqDTO); + } catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可 + throw ex; + } catch (Throwable ex) { + // 系统异常,则包装成 PayException 异常抛出 + log.error("[unifiedOrder][客户端({}) request({}) 发起支付异常]", + getId(), toJsonString(reqDTO), ex); + throw buildPayException(ex); + } + return resp; + } + + protected abstract PayDivideBackRespDto doUnifiedDivideback(PayDivideBackUnifiedDto reqDTO) + throws Throwable; + } diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java index 1ad43277..21ab5b03 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackRespDto; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideRespDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; @@ -73,4 +75,9 @@ public class AlipayAppPayClient extends AbstractAlipayPayClient { protected PayDivideRespDto dounifiedDivideFreeze(PayDivideUnifiedDto reqDTO) throws Throwable { return null; } + + @Override + protected PayDivideBackRespDto doUnifiedDivideback(PayDivideBackUnifiedDto reqDTO) throws Throwable { + return null; + } } diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java index 5a0c935f..871a9b49 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java @@ -3,6 +3,8 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackRespDto; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideRespDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; @@ -99,4 +101,9 @@ public class AlipayBarPayClient extends AbstractAlipayPayClient { protected PayDivideRespDto dounifiedDivideFreeze(PayDivideUnifiedDto reqDTO) throws Throwable { return null; } + + @Override + protected PayDivideBackRespDto doUnifiedDivideback(PayDivideBackUnifiedDto reqDTO) throws Throwable { + return null; + } } diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java index b907fb7c..db0d2d05 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java @@ -2,6 +2,8 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; import cn.hutool.core.util.ObjectUtil; import cn.hutool.http.Method; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackRespDto; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideRespDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; @@ -83,4 +85,9 @@ public class AlipayPcPayClient extends AbstractAlipayPayClient { protected PayDivideRespDto dounifiedDivideFreeze(PayDivideUnifiedDto reqDTO) throws Throwable { return null; } + + @Override + protected PayDivideBackRespDto doUnifiedDivideback(PayDivideBackUnifiedDto reqDTO) throws Throwable { + return null; + } } diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java index 94d43578..7cdeed07 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackRespDto; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideRespDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; @@ -80,4 +82,9 @@ public class AlipayQrPayClient extends AbstractAlipayPayClient { protected PayDivideRespDto dounifiedDivideFreeze(PayDivideUnifiedDto reqDTO) throws Throwable { return null; } + + @Override + protected PayDivideBackRespDto doUnifiedDivideback(PayDivideBackUnifiedDto reqDTO) throws Throwable { + return null; + } } diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java index 19997a76..e59b3459 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; import cn.hutool.http.Method; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackRespDto; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideRespDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; @@ -73,4 +75,9 @@ public class AlipayWapPayClient extends AbstractAlipayPayClient { protected PayDivideRespDto dounifiedDivideFreeze(PayDivideUnifiedDto reqDTO) throws Throwable { return null; } + + @Override + protected PayDivideBackRespDto doUnifiedDivideback(PayDivideBackUnifiedDto reqDTO) throws Throwable { + return null; + } } diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java index 6eb023be..a37fc05c 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.mock; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackRespDto; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideRespDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; @@ -94,4 +96,9 @@ public class MockPayClient extends AbstractPayClient { return null; } + @Override + protected PayDivideBackRespDto doUnifiedDivideback(PayDivideBackUnifiedDto reqDTO) throws Throwable { + return null; + } + } diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java index cee0725b..24c02f3f 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java @@ -8,6 +8,8 @@ import cn.hutool.core.date.TemporalAccessorUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.io.FileUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackRespDto; +import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideBackUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideRespDto; import cn.iocoder.yudao.framework.pay.core.client.dto.divide.PayDivideUnifiedDto; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; @@ -23,8 +25,10 @@ import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Result; import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result; +import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingReturnV3Request; import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingUnfreezeV3Request; import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingV3Request; +import com.github.binarywang.wxpay.bean.profitsharing.result.ProfitSharingReturnV3Result; import com.github.binarywang.wxpay.bean.profitsharing.result.ProfitSharingUnfreezeV3Result; import com.github.binarywang.wxpay.bean.profitsharing.result.ProfitSharingV3Result; import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryRequest; @@ -314,7 +318,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient list = updateReqVO.getDishesNutritionList(); List dishesRawList = updateReqVO.getDishesRawList();