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<String, Object> redisTemplate;
|
@Autowired
|
private SysDictTypeMapperImpl sysDictTypeMapper;
|
@Autowired
|
private SysDictDataMapperImpl sysDictDataMapper;
|
|
|
/**
|
* 发起微信支付
|
*
|
* @param loginUser 登录用户信息
|
* @param request 请求参数
|
*/
|
@Transactional(rollbackFor = Exception.class)
|
public ExecutedResult<Map<String, Object>> 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<SysDictDataPO> 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<Map<String, Object>> 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<Map<String, Object>> 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<String> 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<String, Object> 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<String> 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<String> 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<String> 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<ResWeiXinRefund> 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<String> doPaidSuccess(String tradeNo, String thirdTradeNo, BigDecimal paidAmount, LocalDateTime payTime) {
|
ExecutedResult<TradeRecordPO> 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());
|
UserLoginPO userLoginPO = new UserLoginPO();
|
userLoginPO.setId(user.getId());
|
//将充值金额转换为水量
|
List<SysDictDataPO> feesAmount = sysDictDataMapper.getListByType("fees_amount");
|
if(ListUtil.isNotNullOrEmpty(feesAmount)){
|
SysDictDataPO sysDictDataPO = feesAmount.get(0);
|
BigDecimal bigDecimal = trade.getTradeAmount().multiply(new BigDecimal(sysDictDataPO.getDictValue())).setScale(2, BigDecimal.ROUND_DOWN);
|
userLoginPO.setBalance(bigDecimal);
|
}else {
|
//默认单价
|
BigDecimal bigDecimal = trade.getTradeAmount().multiply(new BigDecimal(3)).setScale(2, BigDecimal.ROUND_DOWN);
|
userLoginPO.setBalance(bigDecimal);
|
}
|
int modify = userLoginMapper.updateById(userLoginPO);
|
//添加资金明细记录
|
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(paidAmount);
|
changePO.setBeforeMoney(user.getBalance());
|
changePO.setAfterMoney(userLoginPO.getBalance());
|
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<TradeRecordPO> 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<RefundRecordPO> 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<String> doPaidFailed(String tradeNo, String thirdTradeNo, String reason) {
|
ExecutedResult<TradeRecordPO> 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<String> doRefundSuccess(String refundNo, String thirdRefundNo, BigDecimal refundAmount, LocalDateTime refundTime) {
|
ExecutedResult<RefundRecordPO> 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<String> doRefundFailed(String refundNo, String thirdRefundNo, String reason) {
|
ExecutedResult<RefundRecordPO> 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();
|
}
|
|
}
|