From f10bbd184efab3fc7d9927366f3b7ec4048a0088 Mon Sep 17 00:00:00 2001 From: lhb <495598773@qq.com> Date: Wed, 30 Apr 2025 16:33:22 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E5=B0=8F=E7=A8=8B=E5=BA=8F=E9=80=80?= =?UTF-8?q?=E6=AC=BE=E5=8F=8A=E5=85=AC=E4=BC=97=E5=8F=B7=E6=8E=A8=E9=80=81?= =?UTF-8?q?=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/core/entity/cloud/TradeDetail.java | 2 +- .../entity/cloud/request/PrePayRequest.java | 39 ++++++++++++ .../order/WalletAccountController.java | 13 ++-- .../entity/request/PageListTradeRequest.java | 9 ++- .../hd/cloud/service/TradeService.java | 4 ++ .../cloud/service/WalletAccountService.java | 2 + .../cloud/service/impl/TradeServiceImpl.java | 56 +++++++++++++++++ .../impl/WalletAccountServiceImpl.java | 12 ++++ .../newthread/GZHTemplateMessageService.java | 5 ++ .../WechatPayNotifyHandleService.java | 41 ++++++++++++ .../hd/cloud/service/rpc/WechatService.java | 4 ++ .../hd/wechat/config/GZHProperties.java | 2 + .../controller/WechatPayController.java | 63 +++++++++++++++++-- .../gzh/GZHMessageSendController.java | 7 +++ .../evotech/hd/wechat/entity/PrePayVO.java | 12 ++++ .../WalletRechargeTemplateData.java | 24 +++++++ .../gzh/GZHMessageTemplateService.java | 39 ++++++++++++ .../service/impl/WechatPayServiceImpl.java | 14 ++++- .../hd/wechat/service/rpc/CloudService.java | 17 +++-- .../utils/wechatpay/WechatPayComponent.java | 47 ++++++++++++++ 20 files changed, 396 insertions(+), 16 deletions(-) create mode 100644 base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/request/PrePayRequest.java diff --git a/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/TradeDetail.java b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/TradeDetail.java index 784805c..98935c9 100644 --- a/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/TradeDetail.java +++ b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/TradeDetail.java @@ -34,7 +34,7 @@ public class TradeDetail extends BaseEntity implements Serializable { @Schema(description = "交易人编码") private String traderCode; - @Schema(description = "交易类型:1-充值,2-订单消费,3-提现") + @Schema(description = "交易类型:1-充值,2-订单消费,9-提现") private Integer tradeType; @Schema(description = "变动金额的钱包账户,钱包金额不变时不需要") diff --git a/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/request/PrePayRequest.java b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/request/PrePayRequest.java new file mode 100644 index 0000000..8874375 --- /dev/null +++ b/base-commons/common-core/src/main/java/com/evotech/hd/common/core/entity/cloud/request/PrePayRequest.java @@ -0,0 +1,39 @@ +package com.evotech.hd.common.core.entity.cloud.request; + +import com.evotech.hd.common.core.entity.BasePageRequest; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; + + +@Data +@Schema(name = "查询资金账户请求参数", hidden = true) +@EqualsAndHashCode(callSuper=false) +public class PrePayRequest extends BasePageRequest { + + @Schema(description = "用户编码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank + private String wuid; + @Schema(description = "支付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull + @Min(1) + @Max(100000000) + private Integer total; + @Schema(description = "商户订单号") + private String outTradeNo; + @Schema(description = "微信支付订单号") + private String transactionId; + @Schema(description = "退款原因") + private String reason; + @Schema(description = "金额") + private Integer money; + @Schema(description = "支付方式") + private Integer payType; + @Schema(description = "交易类型") + private Integer tradeType; + +} diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/controller/order/WalletAccountController.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/controller/order/WalletAccountController.java index 62d9df5..73d1069 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/controller/order/WalletAccountController.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/controller/order/WalletAccountController.java @@ -5,11 +5,9 @@ import java.util.List; import com.evotech.hd.common.core.entity.cloud.vo.WalletAccountVO; import com.evotech.hd.common.core.entity.wechat.WechatPayAttach; import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.constraints.NotBlank; import org.springdoc.core.annotations.ParameterObject; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import com.evotech.hd.cloud.service.WalletAccountService; import com.evotech.hd.common.core.entity.Result; @@ -109,4 +107,11 @@ public class WalletAccountController { public Result updateName(@ParameterObject WalletAccount wa) { return walletAccountService.updateName(wa); } + + @Operation(summary = "获取钱包对象") + @PostMapping("/getDetailById") + @ApiOperationSupport(order = 12) + public WalletAccount getDetailById(@NotBlank @RequestParam String outTradeNo) { + return walletAccountService.getDetailById(outTradeNo); + } } diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/entity/request/PageListTradeRequest.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/entity/request/PageListTradeRequest.java index 70302f6..c2b77de 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/entity/request/PageListTradeRequest.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/entity/request/PageListTradeRequest.java @@ -3,6 +3,7 @@ package com.evotech.hd.cloud.entity.request; import com.evotech.hd.common.core.entity.BasePageRequest; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; import lombok.Data; import lombok.EqualsAndHashCode; @@ -11,6 +12,9 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = false) public class PageListTradeRequest extends BasePageRequest { + @Schema(description = "用户编码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank + private String wuid; @Schema(description = "换电站编码") private String stationCode; @@ -23,7 +27,10 @@ public class PageListTradeRequest extends BasePageRequest { @Schema(description = "交易编码") private String outTradeNo; - @Schema(description = "交易类型:1-充值,2-订单消费,3-提现") + @Schema(description = "交易类型:1-充值,2-订单消费,9-提现") private Integer tradeType; + @Schema(description = "支付方式:1-账户余额,2-微信,3-支付宝,4-网银,5 -充电补偿") + private Integer payType; + } diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/TradeService.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/TradeService.java index 6914891..766370e 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/TradeService.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/TradeService.java @@ -15,7 +15,11 @@ public interface TradeService { public Result update(TradeDetail td); public Result> list(PageListTradeRequest pltr); + + public List tradeList(PageListTradeRequest pltr); public Result wechatPayNotifyHandle(TradeDetail tradeDetail); + public Result wechatBackNotifyHandle(TradeDetail tradeDetail); + } diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/WalletAccountService.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/WalletAccountService.java index 4ffb45c..f3958c5 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/WalletAccountService.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/WalletAccountService.java @@ -32,4 +32,6 @@ public interface WalletAccountService { public Result getPayAttach(String wuid); public Result updateName(WalletAccount wa); + + public WalletAccount getDetailById(String outTradeNo); } diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/TradeServiceImpl.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/TradeServiceImpl.java index 2497504..96101d3 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/TradeServiceImpl.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/TradeServiceImpl.java @@ -7,7 +7,9 @@ import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.evotech.hd.cloud.service.newthread.GZHTemplateMessageService; import com.evotech.hd.common.core.dao.cloud.OrderSwapBatteryDao; +import com.evotech.hd.common.core.entity.cloud.BatteryStation; import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery; +import com.evotech.hd.common.core.entity.resource.ProxyOperater; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; @@ -74,7 +76,9 @@ public class TradeServiceImpl implements TradeService { page = tradeDetailDao.selectPage(page, new QueryWrapper() .eq(StringUtils.hasText(pltr.getStationCode()), "station_code", pltr.getStationCode()) .like(StringUtils.hasText(pltr.getAccountName()), "account_name", pltr.getAccountName()) + .eq(pltr.getWuid() != null, "trader_code", pltr.getWuid()) .eq(pltr.getTradeType() != null, "trade_type", pltr.getTradeType()) + .eq(pltr.getPayType() != null, "pay_type", pltr.getPayType()) .eq(StringUtils.hasText(pltr.getAccountCode()), "account_code", pltr.getAccountCode()) .eq(StringUtils.hasText(pltr.getOutTradeNo()), "out_trade_no", pltr.getOutTradeNo()) .ne("del_flag", 1) @@ -85,6 +89,20 @@ public class TradeServiceImpl implements TradeService { return new Result>().success(page); } + + public List tradeList(PageListTradeRequest pltr) { + List list = tradeDetailDao.selectList(new LambdaQueryWrapper() + .eq(TradeDetail::getTradeType, pltr.getTradeType()) + .eq(TradeDetail::getPayType, pltr.getPayType()) + .eq(TradeDetail::getTraderCode, pltr.getWuid()) + .select(TradeDetail::getPkId, TradeDetail::getTradeAmount, TradeDetail::getOutTradeNo, TradeDetail::getTransactionId).orderByDesc(TradeDetail::getPayTime)); + if (list.isEmpty()) { + return null; + } + return list; + } + + @Override @Transactional(rollbackFor = Exception.class) public Result wechatPayNotifyHandle(TradeDetail tradeDetail) { @@ -141,4 +159,42 @@ public class TradeServiceImpl implements TradeService { } } + + @Override + @Transactional(rollbackFor = Exception.class) + public Result wechatBackNotifyHandle(TradeDetail tradeDetail) { + try { + // 1. 参数校验 + if (tradeDetail == null || !StringUtils.hasText(tradeDetail.getOutTradeNo())) { + log.error("微信支付回调参数异常: {}", JSONUtil.toJsonStr(tradeDetail)); + return new Result().error("参数异常"); + } + + // 2. 幂等性检查 + boolean isProcessed = tradeDetailDao.exists(new QueryWrapper() + .eq("out_trade_no", tradeDetail.getOutTradeNo()) + .eq("transaction_id", tradeDetail.getTransactionId()) + .eq("pay_result", tradeDetail.getPayResult())); + + if (isProcessed) { + log.info("重复的退款微信支付回调, outTradeNo: {}", tradeDetail.getOutTradeNo()); + return new Result().error("退款重复消息"); + } + + // 3. 记录交易 + add(tradeDetail); + + // 4. 业务处理 + payNotifyHandleService.payNotifyBussinessHandle(tradeDetail); + + return new Result().success("OK"); + } catch (Exception e) { + log.error("处理微信退款回调异常, outTradeNo: {}, 异常信息: {}", + tradeDetail.getOutTradeNo(), + e.getMessage(), + e); + throw new RuntimeException("处理支付回调失败", e); + } + } + } diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/WalletAccountServiceImpl.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/WalletAccountServiceImpl.java index 9e942a7..811abac 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/WalletAccountServiceImpl.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/impl/WalletAccountServiceImpl.java @@ -325,5 +325,17 @@ public class WalletAccountServiceImpl implements WalletAccountService { return wechatPayAttach; } + @Override + public WalletAccount getDetailById(String outTradeNo) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(WalletAccountDetail::getTradeNo, outTradeNo).eq(WalletAccountDetail::getTradeType, 1); + WalletAccountDetail walletAccountDetail = walletAccountDetailDao.selectOne(queryWrapper); + + + LambdaQueryWrapper queryWrapper1 = new LambdaQueryWrapper<>(); + queryWrapper1.eq(WalletAccount::getCode, walletAccountDetail.getCode()); + return walletAccountDao.selectOne(queryWrapper1); + } + } diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/newthread/GZHTemplateMessageService.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/newthread/GZHTemplateMessageService.java index d7da2f1..c374968 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/newthread/GZHTemplateMessageService.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/newthread/GZHTemplateMessageService.java @@ -37,4 +37,9 @@ public class GZHTemplateMessageService { wechatService.rechargeMessage(trade, money); } + @Async("taskExecutor") + public void backMessageSend(TradeDetail trade, Integer money) { + wechatService.backMessage(trade, money); + } + } diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/newthread/WechatPayNotifyHandleService.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/newthread/WechatPayNotifyHandleService.java index 657093e..aadf7b4 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/newthread/WechatPayNotifyHandleService.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/newthread/WechatPayNotifyHandleService.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.evotech.hd.cloud.dao.WalletAccountDao; import com.evotech.hd.cloud.dao.WalletAccountDetailDao; import com.evotech.hd.cloud.service.TaxPointService; +import com.evotech.hd.cloud.service.WalletAccountService; import com.evotech.hd.common.core.dao.cloud.OrderSwapBatteryDao; import com.evotech.hd.common.core.dao.cloud.PreOrderRelationSwapOrderDao; import com.evotech.hd.common.core.entity.cloud.*; @@ -35,6 +36,8 @@ public class WechatPayNotifyHandleService { private PreOrderRelationSwapOrderDao preOrderRelationSwapOrderDao; @Resource TaxPointService taxPointService; + @Resource + private WalletAccountService walletAccountService; // @Async("taskExecutor") @@ -88,6 +91,44 @@ public class WechatPayNotifyHandleService { nativePayHandle(tradeDetail); } + } else if (tradeDetail.getTradeType() == 9) { + // 提现 + WalletAccount wallet = walletAccountService.getDetailById(tradeDetail.getOutTradeNo()); + if (wallet == null) { + return; + } + // 添加明细 + WalletAccountDetail wad = new WalletAccountDetail(); + // TODO 写一个算法,计算充值的减多少,赠送的减多少,总金额减多少 + wad.setTradeRechargeAmount(tradeDetail.getTradeAmount());//交易金额 + wad.setTradeGiftAmount(0); + wad.setTradeTotalAmount(wad.getTradeRechargeAmount() + wad.getTradeGiftAmount());//交易总金额 + + wad.setPreTotalAmount(wallet.getTotalAmount()); + wad.setPreRechargeAmount(wallet.getRechargeAmount()); + wad.setPreGiftAmount(wallet.getGiftAmount()); + + wad.setAfterRechargeAmount(wad.getPreRechargeAmount() - Math.abs(wad.getTradeRechargeAmount())); + wad.setAfterTotalAmount(wad.getPreTotalAmount() - Math.abs(wad.getTradeTotalAmount())); + wad.setAfterGiftAmount(wad.getPreGiftAmount() - Math.abs(wad.getTradeGiftAmount())); + + wad.setTradeGiftAmount(0); + wad.setCode(tradeDetail.getWallet()); + wad.setTradeType(tradeDetail.getTradeType()); + wad.setTradeNo(tradeDetail.getOutTradeNo()); + + wad.setCtime(new Date()); + walletAccountDetailDao.insert(wad); + // 改余额 + wallet.setTotalAmount(wad.getAfterTotalAmount()); + wallet.setRechargeAmount(wad.getAfterRechargeAmount()); + wallet.setGiftAmount(wad.getAfterGiftAmount()); + wallet.setUptime(null); + walletAccountDao.updateById(wallet); + + // 发送公众号消息 + templateMessageService.backMessageSend(tradeDetail, wallet.getTotalAmount()); + } else { } diff --git a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/rpc/WechatService.java b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/rpc/WechatService.java index dd32d8d..85f2536 100644 --- a/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/rpc/WechatService.java +++ b/cloud-manage-server/src/main/java/com/evotech/hd/cloud/service/rpc/WechatService.java @@ -50,4 +50,8 @@ public interface WechatService { consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE}) public Result orderQuery(@RequestParam Integer type, @RequestParam String outTradeNo); + @PostMapping(value = "/gzh/msg/send/back", + consumes = {MediaType.APPLICATION_JSON_VALUE}) + public Result backMessage(@RequestBody TradeDetail trade, @RequestParam Integer money); + } diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/config/GZHProperties.java b/wechat-server/src/main/java/com/evotech/hd/wechat/config/GZHProperties.java index 4ee7fba..78fad08 100644 --- a/wechat-server/src/main/java/com/evotech/hd/wechat/config/GZHProperties.java +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/config/GZHProperties.java @@ -33,4 +33,6 @@ public class GZHProperties { private String WalletRechargeTemplateId; private String orderToPayTemplateId2; + + private String WalletBackTemplateId; } diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/controller/WechatPayController.java b/wechat-server/src/main/java/com/evotech/hd/wechat/controller/WechatPayController.java index 2d08258..2d6083a 100644 --- a/wechat-server/src/main/java/com/evotech/hd/wechat/controller/WechatPayController.java +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/controller/WechatPayController.java @@ -1,5 +1,8 @@ package com.evotech.hd.wechat.controller; +import com.evotech.hd.common.core.entity.cloud.TradeDetail; +import com.evotech.hd.common.core.entity.cloud.request.PrePayRequest; +import com.evotech.hd.wechat.service.rpc.CloudService; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -20,6 +23,11 @@ import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.constraints.NotBlank; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + @Tag(name = "微信支付") @RestController @RequestMapping("/wechatpay") @@ -29,6 +37,8 @@ public class WechatPayController { @Resource private WechatPayService wechatPayService; + @Resource + private CloudService cloudService; @Operation(summary = "小程序预支付订单") @@ -57,13 +67,18 @@ public class WechatPayController { @Operation(summary = "退款") - @PostMapping("/refunds") + @PostMapping("/xcx/refunds") @ApiOperationSupport(order = 4) - public Result refunds(String outTradeNo, String transactionId, String reason, Integer money, Integer total) { + public Result refunds(@RequestBody PrePayVO prePay) { + String outTradeNo = prePay.getOutTradeNo(); + String transactionId = prePay.getTransactionId(); + String reason = prePay.getReason(); + Integer money = prePay.getMoney(); + Integer total = prePay.getTotal(); return wechatPayService.refunds(outTradeNo, transactionId, reason, money, total); } - - + + @Operation(summary = "退款回调地址") @PostMapping("/refundsback/msg") @ApiOperationSupport(order = 5) @@ -88,6 +103,46 @@ public class WechatPayController { public Result dayTradebill(@RequestParam @NotBlank String day) { return wechatPayService.dayTradebill(day); } + + @Operation(summary = "全部余额退款") + @PostMapping("/xcx/refundsBalance") + @ApiOperationSupport(order = 8) + public Result refundsBalance(@RequestBody PrePayRequest prePay) { + //total=账户总金额;按总金额扣减支付成功的充值订单按时间倒序进行扣减,直到总金额扣减为零为止 + /** + * 1、先查询该账户下所有有效的充值订单集合 + * 2、按订单支付金额和总金额比较 + */ + //交易类型:1-充值,2-订单消费,9-提现 + prePay.setTradeType(1); + //支付方式:1-账户余额,2-微信 + prePay.setPayType(2); + List listTradeDetail = cloudService.tradeList(prePay); + + //退款总金额 + int totals = prePay.getTotal(); + // 遍历集合 + for (TradeDetail tradeDetail : listTradeDetail) { + int tradeAmount = tradeDetail.getTradeAmount();//订单交易金额 + totals = totals - tradeAmount; + //如果总价大于订单单价,则退款 + if (totals >= 0) { + String outTradeNo = tradeDetail.getOutTradeNo(); + String transactionId = tradeDetail.getTransactionId(); + String reason = "多笔余额申请退款"; + Integer total = tradeAmount; + return wechatPayService.refunds(outTradeNo, transactionId, reason, tradeAmount, tradeAmount); + }else{//部分退款 + String outTradeNo = tradeDetail.getOutTradeNo(); + String transactionId = tradeDetail.getTransactionId(); + String reason = "余额申请退款"; + Integer total = tradeAmount; + return wechatPayService.refunds(outTradeNo, transactionId, reason, total, tradeAmount); + } + + } + return new Result().success("ok"); + } } diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/controller/gzh/GZHMessageSendController.java b/wechat-server/src/main/java/com/evotech/hd/wechat/controller/gzh/GZHMessageSendController.java index 100f634..df4fc4c 100644 --- a/wechat-server/src/main/java/com/evotech/hd/wechat/controller/gzh/GZHMessageSendController.java +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/controller/gzh/GZHMessageSendController.java @@ -68,4 +68,11 @@ public class GZHMessageSendController { return gzhMessageTemplateService.sendTemplateMessageRecharge(trade, money); } + @Operation(summary = "提现成功推送公众号消息") + @PostMapping("/back") + @ApiOperationSupport(order = 5) + public Result sendTemplateMessageBack(@RequestBody TradeDetail trade, @RequestParam Integer money) { + return gzhMessageTemplateService.sendTemplateMessageBack(trade, money); + } + } diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/entity/PrePayVO.java b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/PrePayVO.java index 1a8dc85..d8ae35e 100644 --- a/wechat-server/src/main/java/com/evotech/hd/wechat/entity/PrePayVO.java +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/PrePayVO.java @@ -63,4 +63,16 @@ public class PrePayVO { @Schema(description = "用户设备型号") private String deviceId; + @Schema(description = "商户订单号") + private String outTradeNo; + @Schema(description = "微信支付订单号") + private String transactionId; + @Schema(description = "退款原因") + private String reason; + @Schema(description = "金额") + private Integer money; + @Schema(description = "支付方式") + private String payType; + @Schema(description = "交易类型") + private String tradeType; } diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/WalletRechargeTemplateData.java b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/WalletRechargeTemplateData.java index 79bc244..f3cdfe5 100644 --- a/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/WalletRechargeTemplateData.java +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/entity/gzh/templatemessage/WalletRechargeTemplateData.java @@ -16,6 +16,12 @@ public class WalletRechargeTemplateData { private JSONObject time4; private JSONObject amount5; + + private JSONObject amount2; + + private JSONObject amount3; + + private JSONObject time1; public void setThing3(String value1) { @@ -42,4 +48,22 @@ public class WalletRechargeTemplateData { this.amount5 = jo; } + public void setAmount2(String value5) { + JSONObject jo = new JSONObject(); + jo.set("value", value5); + this.amount2 = jo; + } + + public void setAmount3(String value6) { + JSONObject jo = new JSONObject(); + jo.set("value", value6); + this.amount3 = jo; + } + + public void setTime1(String value7) { + JSONObject jo = new JSONObject(); + jo.set("value", value7); + this.time1 = jo; + } + } diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHMessageTemplateService.java b/wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHMessageTemplateService.java index fd4c66d..2d75a24 100644 --- a/wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHMessageTemplateService.java +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/service/gzh/GZHMessageTemplateService.java @@ -232,4 +232,43 @@ public class GZHMessageTemplateService { return new Result().error(CodeMsg.WECHAT_API_ERROR, jo); } + /** + * 充值成功推送公众号消息 + * @return + */ + public Result sendTemplateMessageBack(TradeDetail trade, Integer money) { + if (!StringUtils.hasText(trade.getTraderCode())) { + return null; + } + WechatUser wuser = wechatUserDao.selectOne(new QueryWrapper().eq("wuid", trade.getTraderCode())); + if (wuser == null) { + return null; + } + if (!StringUtils.hasText(wuser.getGzhOpenid())) { + return new Result().error("未关注公众号!"); + } + MessageTemplateSendData sendData = new MessageTemplateSendData(); + sendData.setTouser(wuser.getGzhOpenid()); + String templateId = gzhProperties.getWalletBackTemplateId();//模版配置 + sendData.setTemplate_id(templateId); + + Miniprogram miniprogram = new Miniprogram(); + miniprogram.setAppid(xcxProperties.getAppid()); + miniprogram.setPath(orderPage); + sendData.setMiniprogram(miniprogram); + + WalletRechargeTemplateData data = new WalletRechargeTemplateData(); + data.setThing3(trade.getTrader());//账号名称 + data.setAmount2(new BigDecimal(trade.getTradeAmount()).divide(new BigDecimal(100)).setScale(2) + "");//退款金额 + data.setTime1(DateUtil.format(trade.getPayTime(), DatePattern.NORM_DATETIME_FORMATTER));//到账时间 + data.setAmount3(new BigDecimal(money).divide(new BigDecimal(100)).setScale(2) + "");//可用余额 + sendData.setData(JSONUtil.parseObj(data)); + String res = TemplateMessageUtil.templateMessageSend(gzhAccessTokenService.gzhAccessToken(), sendData); + JSONObject jo = JSONUtil.parseObj(res); + if (jo.getInt("errcode") == 0) { + return new Result().success(jo); + } + return new Result().error(CodeMsg.WECHAT_API_ERROR, jo); + } + } diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/service/impl/WechatPayServiceImpl.java b/wechat-server/src/main/java/com/evotech/hd/wechat/service/impl/WechatPayServiceImpl.java index 3bcc16c..560d341 100644 --- a/wechat-server/src/main/java/com/evotech/hd/wechat/service/impl/WechatPayServiceImpl.java +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/service/impl/WechatPayServiceImpl.java @@ -210,6 +210,7 @@ public class WechatPayServiceImpl implements WechatPayService { @Override public Result refunds(String outTradeNo, String transactionId, String reason, Integer money, Integer total) { + try { RefundService refundService = new RefundService.Builder().config(config).build(); // CreateRequest request = new CreateRequest(); @@ -217,15 +218,22 @@ public class WechatPayServiceImpl implements WechatPayService { request.setTransactionId(transactionId); request.setReason(reason); request.setOutRefundNo("HD1001REFUND" + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_FORMATTER) + RandomUtil.randomInt(1000, 10000)); - request.setNotifyUrl(xcxProperties.getRefundNotifyUrl()); +// request.setNotifyUrl(xcxProperties.getRefundNotifyUrl()); + request.setNotifyUrl("https://www.famhub.cn/gateway/wechat/wechatpay/refundsback/msg"); AmountReq amount = new AmountReq(); amount.setRefund(Long.valueOf(money)); amount.setCurrency("CNY"); amount.setTotal(Long.valueOf(total)); request.setAmount(amount); Refund refund = refundService.create(request); - + return new Result().success(refund); + + } catch (Exception e) { + e.printStackTrace(); + return new Result().error("剩余金额请联系客服人员进行继续退款!"); + } + } @Override @@ -265,6 +273,8 @@ public class WechatPayServiceImpl implements WechatPayService { } // 4. 业务处理逻辑 System.out.println("\r\n=====>>>>>" + JSONUtil.toJsonPrettyStr(refund)); + wechatPayComponent.wechatBackBussinessHandle(refund); + return new ResponseEntity("", HttpStatus.OK); } diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/service/rpc/CloudService.java b/wechat-server/src/main/java/com/evotech/hd/wechat/service/rpc/CloudService.java index 35c59a8..a3043a9 100644 --- a/wechat-server/src/main/java/com/evotech/hd/wechat/service/rpc/CloudService.java +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/service/rpc/CloudService.java @@ -3,12 +3,10 @@ package com.evotech.hd.wechat.service.rpc; import com.evotech.hd.common.core.entity.BasePageRequest; import com.evotech.hd.common.core.entity.Result; import com.evotech.hd.common.core.entity.cloud.*; -import com.evotech.hd.common.core.entity.cloud.request.BatterySwapResponse; -import com.evotech.hd.common.core.entity.cloud.request.PageListSwapOrderPreRequest; -import com.evotech.hd.common.core.entity.cloud.request.PageListSwapOrderRequest; -import com.evotech.hd.common.core.entity.cloud.request.PageListWalletRequest; +import com.evotech.hd.common.core.entity.cloud.request.*; import com.evotech.hd.common.core.entity.cloud.vo.BatteryStationVO; import com.evotech.hd.common.core.entity.wechat.WechatPayAttach; +import com.evotech.hd.wechat.entity.PrePayVO; import jakarta.validation.constraints.NotBlank; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.SpringQueryMap; @@ -101,4 +99,15 @@ public interface CloudService { @GetMapping(value = "/company/list", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE}) public Result> companylist(@RequestParam BasePageRequest bpr); + + @GetMapping(value = "/trade/tradeList", + consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE}) + public List tradeList(@SpringQueryMap PrePayRequest prePay); + + @PostMapping(value = "/wallet/getDetailById", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE}) + public WalletAccount getDetailById(@RequestParam String outTradeNo); + + @PostMapping(value = "/trade/wechatpay/backnotify", + consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE}) + public void wechatBackNotifyHandle(TradeDetail tradeDetail); } diff --git a/wechat-server/src/main/java/com/evotech/hd/wechat/utils/wechatpay/WechatPayComponent.java b/wechat-server/src/main/java/com/evotech/hd/wechat/utils/wechatpay/WechatPayComponent.java index cf0a4d1..41524fc 100644 --- a/wechat-server/src/main/java/com/evotech/hd/wechat/utils/wechatpay/WechatPayComponent.java +++ b/wechat-server/src/main/java/com/evotech/hd/wechat/utils/wechatpay/WechatPayComponent.java @@ -9,6 +9,7 @@ import com.evotech.hd.common.core.dao.wechat.WechatUserDao; import com.evotech.hd.common.core.entity.Result; import com.evotech.hd.common.core.entity.cloud.TradeDetail; import com.evotech.hd.common.core.entity.cloud.WalletAccount; +import com.evotech.hd.common.core.entity.cloud.WalletAccountDetail; import com.evotech.hd.common.core.entity.wechat.WechatPayAttach; import com.evotech.hd.common.core.entity.wechat.WechatPayPreOrder; import com.evotech.hd.common.core.entity.wechat.WechatUser; @@ -18,6 +19,7 @@ import com.evotech.hd.common.core.enums.WechatPayApiTypeEnums; import com.evotech.hd.wechat.service.rpc.CloudService; import com.wechat.pay.java.service.payments.model.Transaction; import com.wechat.pay.java.service.payments.model.Transaction.TradeTypeEnum; +import com.wechat.pay.java.service.refund.model.Refund; import jakarta.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,6 +41,7 @@ public class WechatPayComponent { private CloudService cloudService; + /** * 校验并创建钱包账户 * @param wuid 用户ID @@ -155,4 +158,48 @@ public class WechatPayComponent { cloudService.wechatPayNotifyHandle(tradeDetail); } + + /** + * 微信退款申请回调业务处理 + * @param refund + */ + public void wechatBackBussinessHandle(Refund refund) { + // 1. 生成交易信息 + TradeDetail tradeDetail = new TradeDetail(); + BeanUtils.copyProperties(refund, tradeDetail);//transactionId + WalletAccount walletAccount = cloudService.getDetailById(refund.getOutTradeNo()); + + WechatUser wuser = wechatUserDao.selectOne(new QueryWrapper().eq("wuid", walletAccount.getOwnerId())); + if (wuser != null) { + tradeDetail.setPayer(wuser.getWuid()); + } + + tradeDetail.setAppid(wuser.getAppid()); + tradeDetail.setWechatPayApiType("JSAPI"); + + tradeDetail.setTradeType(9); + //交易人 + tradeDetail.setTrader(wuser.getName()); + //交易人编码 + tradeDetail.setTraderCode(wuser.getWuid()); + tradeDetail.setOutTradeNo(refund.getOutTradeNo());//OutRefundNo + //变动金额的钱包账户 + tradeDetail.setWallet(walletAccount.getCode()); + + tradeDetail.setDescription(refund.getUserReceivedAccount()); + + tradeDetail.setOrderNo(refund.getRefundId());//refundId + tradeDetail.setOrderCount(1); + + tradeDetail.setTradeAmount(Integer.valueOf(refund.getAmount().getTotal().toString())); + tradeDetail.setPayType(PayTypeEnums.WECHAT.getCode()); + + tradeDetail.setPayResult(refund.getUserReceivedAccount()); + tradeDetail.setPayMsg("余额退款"); + tradeDetail.setPayTime(DateUtil.parseISO8601(refund.getSuccessTime())); + // 2. 处理订单,看要不要异步 + log.info("请求时间{} 处理订单开始{}" ,new Date() ,JSONUtil.toJsonStr(tradeDetail)); + cloudService.wechatBackNotifyHandle(tradeDetail); + } + }