package com.lunhan.water.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.google.gson.JsonObject; import com.lunhan.water.common.ConstantFactory; import com.lunhan.water.common.ExecutedResult; import com.lunhan.water.common.config.SysConfig; import com.lunhan.water.common.enums.ELogger; import com.lunhan.water.common.enums.EYesOrNo; import com.lunhan.water.common.jwt.LoginUserDTO; import com.lunhan.water.common.util.*; import com.lunhan.water.common.wechat.WechatAuthorization; import com.lunhan.water.common.wechat.WechatPayV3Util; import com.lunhan.water.common.wechat.req.*; import com.lunhan.water.common.wechat.res.ResWeiXinRefund; import com.lunhan.water.entity.enums.*; import com.lunhan.water.entity.request.pay.ReqCreatePay; import com.lunhan.water.entity.request.pay.ReqOrderPay; import com.lunhan.water.entity.request.pay.ReqPayRefund; import com.lunhan.water.repository.impl.*; import com.lunhan.water.repository.mapper.SysDictTypeMapper; import com.lunhan.water.repository.po.*; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestBody; import javax.annotation.Resource; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @Service public class PaymentServices { // 微信公众号推送消息模板id private static final Logger log = LoggerUtil.get(PaymentServices.class); private Logger logger = LoggerUtil.get(this.getClass()); private Logger loggerPay = LoggerUtil.get(ELogger.PAY_SERVICE); @Autowired private PaymentRecordsMapperImpl paymentRecordsMapper; @Autowired private RechargeOrderMapperImpl rechargeOrderMapper; @Autowired private UserLoginMapperImpl userLoginMapper; @Autowired private RefundRecordMapperImpl refundRecordDao; @Autowired private RechargeRecordsMapperImpl dao; @Autowired private UserCapitalChangeMapperImpl capitalChangeDao; @Autowired private TradeRecordMapperImpl tradeRecordDao; @Autowired private RedisTemplate redisTemplate; @Autowired private SysDictTypeMapperImpl sysDictTypeMapper; @Autowired private SysDictDataMapperImpl sysDictDataMapper; /** * 发起微信支付 * * @param loginUser 登录用户信息 * @param request 请求参数 */ @Transactional(rollbackFor = Exception.class) public ExecutedResult> weiXinPay(LoginUserDTO loginUser, ReqCreatePay request) { //判断token是否存在,如果不存在,说明重复提交订单 // String redisToken = redisTemplate.opsForValue().get(request.getPayToken()).toString(); // if (StringUtil.isNullOrEmpty(redisToken)) { // throw new RuntimeException("请勿重复提交充值订单!"); // } // //删除token // redisTemplate.delete(request.getPayToken()); EBusinessType type = EBusinessType.getByValue(request.getBusinessType()); if (Objects.isNull(type)) { return ExecutedResult.failed("业务不支持." + request.getBusinessType()); } String callbackUrl = SysConfig.weiXinPay.getNotifyBasicUrl() + String.format("/notify/pay/%s/%s/%s", EPaymentChannel.WE_CHAT.getValue(), EPayWay.SCAN_DYNAMIC.getValue(), request.getBusinessType() ); //查询支付用户信息 UserLoginPO user = userLoginMapper.get4Openid(loginUser.getUserId()); if (Objects.isNull(user)) { return ExecutedResult.failed("用户信息不存在!"); } switch (type) { case RECHARGE: //查询充值订单 RechargeOrderPO rechargeOrderPO = rechargeOrderMapper.getByOrderNo(request.getBusinessNo()); if (Objects.isNull(rechargeOrderPO)) { return ExecutedResult.failed("未查询到充值订单!"); } //修改充值订单为支付中 rechargeOrderPO.setPayState(EPayState.PAYING.getValue()); rechargeOrderMapper.updateById(rechargeOrderPO); //获取订单金额 request.setTradeAmount(rechargeOrderPO.getPaymentAmount()); request.setWechatOpenid(user.getWxOpenId()); request.setBusinessComment("用户充值"); //添加充值记录 RechargeRecordsPO item = new RechargeRecordsPO(); item.setUserId(user.getId()); //将充值金额转换为水量 List feesAmount = sysDictDataMapper.getListByType("fees_amount"); if(ListUtil.isNotNullOrEmpty(feesAmount)){ SysDictDataPO sysDictDataPO = feesAmount.get(0); BigDecimal bigDecimal = request.getTradeAmount().multiply(new BigDecimal(sysDictDataPO.getDictValue())).setScale(2, BigDecimal.ROUND_DOWN); item.setRechargeWater(bigDecimal); }else { //默认单价 BigDecimal bigDecimal =request.getTradeAmount().multiply(new BigDecimal(3)).setScale(2, BigDecimal.ROUND_DOWN); item.setRechargeWater(bigDecimal); } item.setRechargeOrder(request.getBusinessNo()); item.setRechargeType(ERechargeType.MOBILE.getDesc()); item.setPaymentMethod(EPayType.WX_PAY.getDesc()); item.setRechargeStatus(EYesOrNo.NO.getValue()); item.setRechargeAmount(request.getTradeAmount()); item.setComment("余额充值"); item.setCreateTime(LocalDateTimeUtil.nowTimeStamp()); item.setCreateUser(loginUser.getUserId()); item.setCreateUserName(loginUser.getNickName()); dao.insert(item); break; } Long now = LocalDateTimeUtil.nowTimeStamp(); String nowView = LocalDateTimeUtil.nowDateTimeFullStr(); // 生成支付流水记录 TradeRecordPO trade = new TradeRecordPO(); trade.setTradeNo("TN" + SnowFlakeUtil.getId()); trade.setTradeAmount(request.getTradeAmount()); trade.setBusinessType(request.getBusinessType()); trade.setBusinessNo(request.getBusinessNo()); trade.setBusinessComment(request.getBusinessComment()); trade.setPaymentChannel(EPaymentChannel.WE_CHAT.getValue()); trade.setChannelName(EPaymentChannel.WE_CHAT.getDesc()); trade.setPayWay(EPayWay.SCAN_DYNAMIC.getValue()); trade.setPayWayName(EPayWay.SCAN_DYNAMIC.getDesc()); // 这里不需要通知第三方,回调地址为空 trade.setCallbackUrl(""); trade.setThirdTradeNo(""); trade.setSubmitTime(0L); trade.setSubmitTimeView(""); trade.setPayState(EPayState.WAITING.getValue()); trade.setCreateTime(LocalDateTimeUtil.nowTimeStamp()); int createTrade = tradeRecordDao.insert(trade); if (createTrade < 1) { return ExecutedResult.failed("发起支付失败: 创建支付流水失败."); } // 发起微信支付 ExecutedResult> doWeiXinPay = this.doWeiXinPay(request, trade.getTradeNo(), callbackUrl); if (doWeiXinPay.isFailed()) { return ExecutedResult.failed(doWeiXinPay.getMsg(), doWeiXinPay.getMsgCode()); } TradeRecordPO upd = new TradeRecordPO(); upd.setId(trade.getId()); upd.setPayState(EPayState.PAYING.getValue()); upd.setSubmitTime(now); upd.setSubmitTimeView(nowView); int modifyTrade = tradeRecordDao.updateById(upd); if (modifyTrade < 1) { return ExecutedResult.failed("回写微信支付状态失败!"); } return doWeiXinPay; } /** * 发起微信支付 * * @param request 支付请求参数 * @param tradeCode 支付流水号 * @param callbackUrl 支付结果通知地址 */ private ExecutedResult> doWeiXinPay(ReqCreatePay request, String tradeCode, String callbackUrl) { String merchantId = SysConfig.weiXinPay.getMerchantId(); // 支付证书序列号 String certificateSerialNo = SysConfig.weiXinPay.getCertificateSn(); // 支付证书私钥存放路径 String privateKeyPath = SysConfig.weiXinPay.getPrivateKeyPath(); String appID = SysConfig.weiXinPay.getAppID(); ReqCreateWechatPay reqPay = new ReqCreateWechatPay(); reqPay.setAppid(appID); reqPay.setMchid(merchantId); reqPay.setOut_trade_no(tradeCode); reqPay.setDescription(request.getBusinessComment()); reqPay.setNotify_url(""); if (StringUtil.isNotNullOrEmpty(callbackUrl)) { reqPay.setNotify_url(callbackUrl); } // 微信支付,金额单位为“分”,这里需要乘以100 Long amount = Long.parseLong(NumericUtil.toNumberString(request.getTradeAmount().multiply(new BigDecimal(ConstantFactory.NUM100)), 0)); reqPay.setAmount(new CreatePay_Amount() {{ setTotal(amount); }}); reqPay.setPayer(new CreatePay_Payer() {{ setOpenid(request.getWechatOpenid()); }}); WechatAuthorization author = new WechatAuthorization( merchantId, certificateSerialNo, privateKeyPath ); String wxTradeCode = ""; try { loggerPay.info("发起微信支付: " + SerializeUtil.toJson(reqPay)); ExecutedResult createPay = WechatPayV3Util.createPay(reqPay, author); loggerPay.info("发起微信支付-结果: " + SerializeUtil.toJson(createPay)); if (createPay.isFailed()) { return ExecutedResult.failed("发起第三方支付失败: " + createPay.getMsg(), createPay.getMsgCode()); } wxTradeCode = createPay.getData(); } catch (Exception e) { return ExecutedResult.failed("发起第三方支付失败: " + e.getMessage()); } String prepayId = wxTradeCode; Map result = new HashMap<>(); String timeStamp = LocalDateTimeUtil.nowTimeStampStr(); String randomStr = RandVerifyCode.complexCode(10); result.put("appId", appID); result.put("timeStamp", timeStamp); result.put("nonceStr", randomStr); prepayId = "prepay_id=" + prepayId; result.put("package", prepayId); result.put("signType", "RSA"); String signText = appID + "\n" + timeStamp + "\n" + randomStr + "\n" + prepayId + "\n"; String paySign = author.sign(signText.getBytes(StandardCharsets.UTF_8)); result.put("paySign", paySign); loggerPay.info("发起微信支付-返回前端: " + SerializeUtil.toJson(result)); return ExecutedResult.success(result); } /** * 支付退款 * * @param request 请求参数 * @return 退款流水号 */ public ExecutedResult weiXinRefund(ReqPayRefund request) { TradeRecordPO trade = tradeRecordDao.get4Business(request.getBusinessType(), request.getBusinessNo()); if (Objects.isNull(trade) || !Objects.equals(trade.getBusinessNo(), request.getBusinessNo())) { return ExecutedResult.failed("支付流水不存在!" + request.getBusinessNo()); } Long now = LocalDateTimeUtil.nowTimeStamp(); String nowView = LocalDateTimeUtil.nowDateTimeFullStr(); // 添加退款记录 RefundRecordPO refund = new RefundRecordPO(); refund.setRefundNo("RN" + SnowFlakeUtil.getId()); refund.setTradeNo(trade.getTradeNo()); refund.setTradeAmount(trade.getPaidAmount()); refund.setRefundAmount(request.getRefundAmount()); refund.setBusinessType(request.getBusinessType()); refund.setBusinessNo(request.getBusinessNo()); refund.setBusinessComment(request.getBusinessComment()); refund.setPaymentChannel(trade.getPaymentChannel()); refund.setChannelName(trade.getChannelName()); refund.setPayWay(trade.getPayWay()); refund.setPayWayName(trade.getPayWayName()); // 这里不需要通知第三方,回调地址为空 refund.setCallbackUrl(""); refund.setThirdRefundNo(""); refund.setSubmitTime(0L); refund.setSubmitTimeView(""); refund.setNotifyTime(0L); refund.setNotifyTimeView(""); refund.setRefundTime(0L); refund.setRefundTimeView(""); refund.setThirdRefundAmount(BigDecimal.ZERO); refund.setClosedTime(0L); refund.setClosedTimeView(""); refund.setClosedComment(""); refund.setComment(""); refund.setRefundState(ERefundState.WAITING.getValue()); refund.setCreateTime(now); int addRefund = refundRecordDao.insert(refund); if (addRefund < 1) { return ExecutedResult.failed("创建退款失败!"); } ExecutedResult doWeiXinRefund = this.doWeiXinRefund(request, trade, refund.getRefundNo(), SysConfig.weiXinPay.getNotifyBasicUrl() + String.format("/notify/refund/%s/%s/%s", refund.getPaymentChannel(), refund.getPayWay(), refund.getBusinessType()) ); if (doWeiXinRefund.isFailed()) { return ExecutedResult.failed(doWeiXinRefund.getMsg(), doWeiXinRefund.getMsgCode()); } RefundRecordPO upd = new RefundRecordPO(); upd.setId(refund.getId()); upd.setRefundState(ERefundState.REFUNDING.getValue()); upd.setSubmitTime(now); upd.setSubmitTimeView(nowView); int modifyRefund = refundRecordDao.updateById(upd); if (modifyRefund < 1) { return ExecutedResult.failed("回写退款状态失败!"); } return ExecutedResult.success(refund.getRefundNo()); } private ExecutedResult doWeiXinRefund(ReqPayRefund request, TradeRecordPO trade, String refundNo, String callbackUrl) { String certificateSerialNo = SysConfig.weiXinPay.getCertificateSn(); // 支付证书私钥存放路径 String privateKeyPath = SysConfig.weiXinPay.getPrivateKeyPath(); Integer total = Integer.parseInt(NumericUtil.toNumberString(trade.getPaidAmount().multiply(new BigDecimal(ConstantFactory.NUM100.toString())), 0)); Integer refundAmount = Integer.parseInt(NumericUtil.toNumberString(request.getRefundAmount().multiply(new BigDecimal(ConstantFactory.NUM100.toString())), 0)); WeiXinRefund_Amount amount = new WeiXinRefund_Amount(); amount.setTotal(total); amount.setRefund(refundAmount); amount.setCurrency("CNY"); ReqCreateWeiXinRefund reqWeiXinRefund = new ReqCreateWeiXinRefund(); reqWeiXinRefund.setTransaction_id(trade.getThirdTradeNo()); reqWeiXinRefund.setOut_refund_no(refundNo); reqWeiXinRefund.setAmount(amount); reqWeiXinRefund.setReason(request.getBusinessComment()); reqWeiXinRefund.setNotify_url(callbackUrl); WechatAuthorization author = new WechatAuthorization( SysConfig.weiXinPay.getMerchantId(), certificateSerialNo, privateKeyPath ); try { ExecutedResult createRefund = WechatPayV3Util.createRefund(reqWeiXinRefund, author); if (createRefund.isFailed()) { return ExecutedResult.failed("发起第三方支付失败: " + createRefund.getMsg(), createRefund.getMsgCode()); } // 这里不回写微信的退款流水号,统一到退款通知时回写 } catch (Exception e) { return ExecutedResult.failed("发起第三方支付失败: " + e.getMessage()); } return ExecutedResult.success(); } /** * 执行支付成功 * * @param tradeNo 支付流水号 * @param thirdTradeNo 第三方支付流水号 * @param paidAmount 实际支付金额 * @param payTime 支付完成时间 */ public ExecutedResult doPaidSuccess(String tradeNo, String thirdTradeNo, BigDecimal paidAmount, LocalDateTime payTime) { ExecutedResult checkTrade = this.checkTrade(tradeNo); if (checkTrade.isFailed()) { return ExecutedResult.failed(checkTrade.getMsg()); } TradeRecordPO trade = checkTrade.getData(); // 重复通知 if (Objects.equals(trade.getPayState(), EPayState.SUCCESS.getValue())) { return ExecutedResult.success(); } if (!Objects.equals(trade.getPayState(), EPayState.PAYING.getValue())) { return ExecutedResult.success(); } EBusinessType type = EBusinessType.getByValue(trade.getBusinessType()); switch (type) { case RECHARGE: //充值订单 RechargeRecordsPO recordsPO = dao.getByRechargeOrder(trade.getBusinessNo()); LoggerUtil.get(ELogger.PAY_SERVICE).info(trade.getBusinessNo() + ", 查找支付流水: " + SerializeUtil.toJson(recordsPO)); if (recordsPO.getRechargeStatus() == 0) { //修改充值记录中的充值状态=1 recordsPO.setRechargeStatus(1); dao.updateById(recordsPO); RechargeOrderPO rechargeOrderPO = rechargeOrderMapper.getByOrderNo(trade.getBusinessNo()); if (Objects.nonNull(rechargeOrderPO)) { //修改充值订单为已充值 rechargeOrderPO.setPayType(EPayType.WX_PAY.getValue()); rechargeOrderPO.setPayTime(LocalDateTimeUtil.nowTimeStamp()); rechargeOrderPO.setPayState(EPayState.SUCCESS.getValue()); rechargeOrderMapper.updateById(rechargeOrderPO); //修改用户余额 UserLoginPO user = userLoginMapper.getById(rechargeOrderPO.getUserId()); //将充值金额转换为水量 BigDecimal afterMoney=BigDecimal.ZERO; BigDecimal bigDecimal=BigDecimal.ZERO; List feesAmount = sysDictDataMapper.getListByType("fees_amount"); if(ListUtil.isNotNullOrEmpty(feesAmount)){ SysDictDataPO sysDictDataPO = feesAmount.get(0); bigDecimal = trade.getTradeAmount().multiply(new BigDecimal(sysDictDataPO.getDictValue())).setScale(2, BigDecimal.ROUND_DOWN); afterMoney=user.getBalance().add(bigDecimal); }else { //默认单价 bigDecimal= trade.getTradeAmount().multiply(new BigDecimal(3)).setScale(2, BigDecimal.ROUND_DOWN); afterMoney=user.getBalance().add(bigDecimal); } user.setBalance(afterMoney); int modify = userLoginMapper.updateById(user); //添加资金明细记录 UserCapitalChangePO changePO = new UserCapitalChangePO(); changePO.setUserId(user.getId()); changePO.setBusiness(ECapitalChange.MOBILE_Recharge.getValue()); changePO.setBusinessName(ECapitalChange.MOBILE_Recharge.getDesc()); changePO.setBusinessCode(recordsPO.getRechargeOrder()); changePO.setChangeMoney(bigDecimal); changePO.setBeforeMoney(user.getBalance()); changePO.setAfterMoney(afterMoney); changePO.setDescription("微信充值"); changePO.setCreateTime(LocalDateTimeUtil.nowTimeStamp()); changePO.setCreateUser("0"); changePO.setCreateUserName("系统"); int addCapitalChange = capitalChangeDao.insert(changePO); LoggerUtil.get(ELogger.PAY_SERVICE).info("添加资金变动: " + addCapitalChange); } } break; } Long now = LocalDateTimeUtil.nowTimeStamp(); String nowView = LocalDateTimeUtil.nowDateTimeFullStr(); TradeRecordPO upd = new TradeRecordPO(); upd.setId(trade.getId()); upd.setNotifyTime(now); upd.setNotifyTimeView(nowView); upd.setThirdTradeNo(thirdTradeNo); upd.setPayState(EPayState.SUCCESS.getValue()); upd.setPaidTime(LocalDateTimeUtil.getTimeStamp(payTime).getTime()); upd.setPaidTimeView(LocalDateTimeUtil.toFormatFullString(payTime)); upd.setPaidAmount(paidAmount); upd.setCanRefund(EYesOrNo.YES.getValue()); int updateTrade = tradeRecordDao.updateById(upd); if (updateTrade < 1) { return ExecutedResult.failed("修改支付流水状态失败!"); } if (StringUtil.isNotNullOrEmpty(trade.getBusinessCallbackUrl())) { JsonObject data = new JsonObject(); data.addProperty("isSuccess", Boolean.TRUE); data.addProperty("errorMsg", ""); data.addProperty("businessNo", trade.getBusinessNo()); data.addProperty("tradeAmount", trade.getTradeAmount()); data.addProperty("paidAmount", paidAmount); String timeStr = ""; if (Objects.isNull(payTime)) { timeStr = LocalDateTimeUtil.toFormatString(payTime); } data.addProperty("paidTime", timeStr); ThreadPoolUtil.getDefaultPool().execute(() -> { try { logger.info("通知业务方支付结果: " + data); String response = HttpUtil.postJson(trade.getBusinessCallbackUrl(), data, new HashMap<>()); logger.info("通知业务方支付结果-返回: " + response); } catch (Exception e) { logger.error("通知业务方支付结果失败!", e); } }); } return ExecutedResult.success(); } /** * 校验支付流水号是否存在 * * @param tradeNo 支付流水号 */ public ExecutedResult checkTrade(String tradeNo) { TradeRecordPO trade = tradeRecordDao.get4TradeNo(tradeNo); if (Objects.isNull(trade) || !Objects.equals(trade.getTradeNo(), tradeNo)) { return ExecutedResult.failed("支付流水不存在!" + tradeNo); } return ExecutedResult.success(trade); } /** * 校验退款流水号是否存在 * * @param refundNo 退款流水号 */ public ExecutedResult checkRefund(String refundNo) { RefundRecordPO refund = refundRecordDao.get4RefundNo(refundNo); if (Objects.isNull(refund) || !Objects.equals(refund.getRefundNo(), refundNo)) { return ExecutedResult.failed("退款流水不存在!" + refundNo); } return ExecutedResult.success(refund); } /** * 执行支付失败 * * @param tradeNo 支付流水号 * @param thirdTradeNo 第三方支付流水号 * @param reason 失败原因 */ public ExecutedResult doPaidFailed(String tradeNo, String thirdTradeNo, String reason) { ExecutedResult checkTrade = this.checkTrade(tradeNo); if (checkTrade.isFailed()) { return ExecutedResult.failed(checkTrade.getMsg()); } TradeRecordPO trade = checkTrade.getData(); // 重复通知 if (Objects.equals(trade.getPayState(), EPayState.FAILED.getValue())) { return ExecutedResult.success(); } if (!Objects.equals(trade.getPayState(), EPayState.PAYING.getValue())) { return ExecutedResult.success(); } Long now = LocalDateTimeUtil.nowTimeStamp(); String nowView = LocalDateTimeUtil.nowDateTimeFullStr(); EBusinessType type = EBusinessType.getByValue(trade.getBusinessType()); switch (type) { case RECHARGE: //充值订单 RechargeRecordsPO recordsPO = dao.getByRechargeOrder(trade.getBusinessNo()); LoggerUtil.get(ELogger.PAY_SERVICE).info(trade.getBusinessNo() + ", 查找支付流水: " + SerializeUtil.toJson(recordsPO)); if (recordsPO != null) { RechargeRecordsPO updRecharge = new RechargeRecordsPO(); updRecharge.setId(recordsPO.getId()); updRecharge.setComment("充值失败!" + reason); dao.updateById(updRecharge); } break; } TradeRecordPO upd = new TradeRecordPO(); upd.setId(trade.getId()); upd.setNotifyTime(now); upd.setNotifyTimeView(nowView); upd.setThirdTradeNo(thirdTradeNo); upd.setPayState(EPayState.FAILED.getValue()); upd.setClosedComment("微信返回支付失败: " + reason); int updateTrade = tradeRecordDao.updateById(upd); if (updateTrade < 1) { return ExecutedResult.failed("修改支付流水状态失败!"); } if (StringUtil.isNotNullOrEmpty(trade.getBusinessCallbackUrl())) { JsonObject data = new JsonObject(); data.addProperty("isSuccess", Boolean.FALSE); data.addProperty("errorMsg", reason); data.addProperty("businessNo", trade.getBusinessNo()); data.addProperty("tradeAmount", trade.getTradeAmount()); data.addProperty("paidAmount", BigDecimal.ZERO); data.addProperty("paidTime", ""); ThreadPoolUtil.getDefaultPool().execute(() -> { try { logger.info("通知业务方支付结果: " + data); String response = HttpUtil.postJson(trade.getBusinessCallbackUrl(), data, new HashMap<>()); logger.info("通知业务方支付结果-返回: " + response); } catch (Exception e) { logger.error("通知业务方支付结果失败!", e); } }); } return ExecutedResult.success(); } /** * 执行退款成功 * * @param refundNo 退款流水号 * @param thirdRefundNo 第三方退款流水号 * @param refundAmount 实际退款金额 * @param refundTime 退款成功时间 * @return */ public ExecutedResult doRefundSuccess(String refundNo, String thirdRefundNo, BigDecimal refundAmount, LocalDateTime refundTime) { ExecutedResult checkTrade = this.checkRefund(refundNo); if (checkTrade.isFailed()) { return ExecutedResult.failed(checkTrade.getMsg()); } RefundRecordPO refund = checkTrade.getData(); Long now = LocalDateTimeUtil.nowTimeStamp(); String nowView = LocalDateTimeUtil.nowDateTimeFullStr(); RefundRecordPO upd = new RefundRecordPO(); upd.setId(refund.getId()); upd.setNotifyTime(now); upd.setNotifyTimeView(nowView); upd.setThirdRefundNo(thirdRefundNo); upd.setRefundState(ERefundState.SUCCESS.getValue()); upd.setRefundTime(LocalDateTimeUtil.getTimeStamp(refundTime).getTime()); upd.setRefundTimeView(LocalDateTimeUtil.toFormatFullString(refundTime)); upd.setRefundAmount(refundAmount); int updateTrade = refundRecordDao.updateById(upd); if (updateTrade < 1) { return ExecutedResult.failed("修改退款流水状态失败!"); } if (StringUtil.isNotNullOrEmpty(refund.getCallbackUrl())) { JsonObject data = new JsonObject(); data.addProperty("isSuccess", Boolean.TRUE); data.addProperty("errorMsg", ""); data.addProperty("businessNo", refund.getBusinessNo()); data.addProperty("paidAmount", refund.getTradeAmount()); data.addProperty("tradeAmount", refund.getRefundAmount()); data.addProperty("refundAmount", refundAmount); String timeStr = ""; if (Objects.isNull(refundTime)) { timeStr = LocalDateTimeUtil.toFormatString(refundTime); } data.addProperty("refundTime", timeStr); ThreadPoolUtil.getDefaultPool().execute(() -> { try { logger.info("通知业务方退款结果: " + data); String response = HttpUtil.postJson(refund.getBusinessCallbackUrl(), data, new HashMap<>()); logger.info("通知业务方退款结果-返回: " + response); } catch (Exception e) { logger.error("通知业务方退款结果失败!", e); } }); } return ExecutedResult.success(); } /** * 执行退款失败 * * @param refundNo 退款流水号 * @param thirdRefundNo 第三方退款流水号 * @param reason 失败原因 */ public ExecutedResult doRefundFailed(String refundNo, String thirdRefundNo, String reason) { ExecutedResult checkTrade = this.checkRefund(refundNo); if (checkTrade.isFailed()) { return ExecutedResult.failed(checkTrade.getMsg()); } RefundRecordPO refund = checkTrade.getData(); Long now = LocalDateTimeUtil.nowTimeStamp(); String nowView = LocalDateTimeUtil.nowDateTimeFullStr(); RefundRecordPO upd = new RefundRecordPO(); upd.setId(refund.getId()); upd.setNotifyTime(now); upd.setNotifyTimeView(nowView); upd.setThirdRefundNo(thirdRefundNo); upd.setRefundState(ERefundState.FAILED.getValue()); upd.setClosedComment("微信返回退款失败: " + reason); int updateTrade = refundRecordDao.updateById(upd); if (updateTrade < 1) { return ExecutedResult.failed("修改退款流水状态失败!"); } if (StringUtil.isNotNullOrEmpty(refund.getBusinessCallbackUrl())) { JsonObject data = new JsonObject(); data.addProperty("isSuccess", Boolean.FALSE); data.addProperty("errorMsg", reason); data.addProperty("businessNo", refund.getBusinessNo()); data.addProperty("paidAmount", refund.getTradeAmount()); data.addProperty("tradeAmount", refund.getRefundAmount()); data.addProperty("refundAmount", BigDecimal.ZERO); data.addProperty("refundTime", ""); ThreadPoolUtil.getDefaultPool().execute(() -> { try { logger.info("通知业务方退款结果: " + data); String response = HttpUtil.postJson(refund.getBusinessCallbackUrl(), data, new HashMap<>()); logger.info("通知业务方退款结果-返回: " + response); } catch (Exception e) { logger.error("通知业务方退款结果失败!", e); } }); } return ExecutedResult.success(); } }