|
|
@@ -4,8 +4,12 @@ import cn.hutool.core.collection.CollUtil;
|
|
|
import cn.hutool.core.collection.CollectionUtil;
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
+import cn.hutool.json.JSON;
|
|
|
+import com.aliyun.oss.ServiceException;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
+import com.google.gson.Gson;
|
|
|
import com.google.gson.JsonObject;
|
|
|
+import com.zsElectric.boot.business.UserRefundsOrderInfo;
|
|
|
import com.zsElectric.boot.business.mapper.*;
|
|
|
import com.zsElectric.boot.business.model.entity.*;
|
|
|
import com.zsElectric.boot.business.model.form.applet.LevelOrderForm;
|
|
|
@@ -14,15 +18,15 @@ import com.zsElectric.boot.business.model.vo.UserInfoVO;
|
|
|
import com.zsElectric.boot.business.service.*;
|
|
|
import com.zsElectric.boot.common.constant.SystemConstants;
|
|
|
import com.zsElectric.boot.core.exception.BusinessException;
|
|
|
-import com.zsElectric.boot.core.pay.WXPayUtility;
|
|
|
-import com.zsElectric.boot.core.pay.WechatConstants;
|
|
|
-import com.zsElectric.boot.core.pay.WechatPayV3Utils;
|
|
|
-import com.zsElectric.boot.core.pay.WechatUrlConstants;
|
|
|
+import com.zsElectric.boot.core.pay.*;
|
|
|
import com.zsElectric.boot.security.util.SecurityUtils;
|
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import netscape.javascript.JSObject;
|
|
|
+import org.apache.commons.lang3.RandomStringUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
@@ -65,12 +69,14 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
|
|
|
private final UserAccountMapper userAccountMapper;
|
|
|
|
|
|
- private final UserAccountLogMapper userAccountLogMapper;
|
|
|
+ private final UserAccountService userAccountService;
|
|
|
|
|
|
private final WechatPayV3Utils wechatPayV3Utils;
|
|
|
|
|
|
private final ChargeOrderInfoMapper chargeOrderInfoMapper;
|
|
|
|
|
|
+ private final UserRefundsOrderInfoMapper userRefundsOrderInfoMapper;
|
|
|
+
|
|
|
// 声明一个可重入锁
|
|
|
private final ReentrantLock lock = new ReentrantLock();
|
|
|
|
|
|
@@ -144,6 +150,7 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
|
|
|
/**
|
|
|
* 创建订单
|
|
|
+ *
|
|
|
* @param levelOrderForm
|
|
|
* @return
|
|
|
*/
|
|
|
@@ -151,7 +158,7 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
public UserPayForm createOrder(LevelOrderForm levelOrderForm) {
|
|
|
Long userId = SecurityUtils.getUserId();
|
|
|
String userOpenId = userInfoMapper.getAppletUserInfo(userId).getOpenid();
|
|
|
- String orderNo = createOrderNo("SP",userId);
|
|
|
+ String orderNo = createOrderNo("SP", userId);
|
|
|
//创建订单
|
|
|
UserOrderInfo orderInfo = new UserOrderInfo();
|
|
|
orderInfo.setUserId(userId);
|
|
|
@@ -168,13 +175,14 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
//查询档位
|
|
|
RechargeLevel level = rechargeLevelMapper.selectById(levelOrderForm.getLevelId());
|
|
|
|
|
|
- Map<String, Object> result = payment(userOpenId,orderNo,level.getMoney());
|
|
|
+ Map<String, Object> result = payment(userOpenId, orderNo, level.getMoney());
|
|
|
payForm.setParams(result);
|
|
|
return payForm;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 支付订单
|
|
|
+ *
|
|
|
* @param orderId
|
|
|
* @return
|
|
|
*/
|
|
|
@@ -188,13 +196,14 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
//查询档位
|
|
|
RechargeLevel level = rechargeLevelMapper.selectById(orderInfo.getLevelId());
|
|
|
|
|
|
- Map<String, Object> result = payment(orderInfo.getOpenid(),orderInfo.getOrderNo(),level.getMoney());
|
|
|
+ Map<String, Object> result = payment(orderInfo.getOpenid(), orderInfo.getOrderNo(), level.getMoney());
|
|
|
payForm.setParams(result);
|
|
|
return payForm;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 订单查询
|
|
|
+ *
|
|
|
* @param orderNo
|
|
|
* @return
|
|
|
*/
|
|
|
@@ -213,7 +222,9 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
if (ObjectUtil.isNotEmpty(orderInfo) && Objects.equals(orderInfo.getOrderStatus(), SystemConstants.STATUS_ONE)) {
|
|
|
String transactionId = res.get("transaction_id").getAsString();
|
|
|
LocalDateTime payTime = LocalDateTime.now();
|
|
|
- BigDecimal payMoney = new BigDecimal(res.get("amount").getAsJsonObject().get("total").getAsString());
|
|
|
+ // 微信返回的金额单位是分,需要转换为元
|
|
|
+ BigDecimal payMoney = new BigDecimal(res.get("amount").getAsJsonObject().get("total").getAsString())
|
|
|
+ .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
|
|
|
|
|
|
//执行业务操作
|
|
|
this.successPayOrder(orderInfo, transactionId, payTime, payMoney);
|
|
|
@@ -233,6 +244,7 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
|
|
|
/**
|
|
|
* 微信支付回调
|
|
|
+ *
|
|
|
* @param request
|
|
|
* @param response
|
|
|
* @return
|
|
|
@@ -265,7 +277,9 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
if (Objects.equals(orderInfo.getOrderStatus(), SystemConstants.STATUS_ONE)) {
|
|
|
String transactionId = res.get("transaction_id").getAsString();
|
|
|
LocalDateTime payTime = LocalDateTime.now();
|
|
|
- BigDecimal payMoney = new BigDecimal(res.get("amount").getAsJsonObject().get("total").getAsString());
|
|
|
+ // 微信返回的金额单位是分,需要转换为元
|
|
|
+ BigDecimal payMoney = new BigDecimal(res.get("amount").getAsJsonObject().get("total").getAsString())
|
|
|
+ .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
|
|
|
|
|
|
//执行业务操作
|
|
|
this.successPayOrder(orderInfo, transactionId, payTime, payMoney);
|
|
|
@@ -279,10 +293,10 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
result.put("code", "FAIL");
|
|
|
result.put("message", "失败");
|
|
|
return result;
|
|
|
- }finally {
|
|
|
+ } finally {
|
|
|
lock.unlock();
|
|
|
}
|
|
|
- }else {
|
|
|
+ } else {
|
|
|
result.put("code", "FAIL");
|
|
|
result.put("message", "失败");
|
|
|
return result;
|
|
|
@@ -291,6 +305,7 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
|
|
|
/**
|
|
|
* 支付成功业务处理
|
|
|
+ *
|
|
|
* @param orderInfo
|
|
|
* @param transactionId
|
|
|
* @param payTime
|
|
|
@@ -298,7 +313,7 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
* @throws Exception
|
|
|
*/
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
- protected void successPayOrder(UserOrderInfo orderInfo, String transactionId, LocalDateTime payTime, BigDecimal orderMoney) throws Exception{
|
|
|
+ protected void successPayOrder(UserOrderInfo orderInfo, String transactionId, LocalDateTime payTime, BigDecimal orderMoney) throws Exception {
|
|
|
//修改订单状态为已支付
|
|
|
orderInfo.setOrderStatus(SystemConstants.STATUS_TWO);
|
|
|
orderInfo.setPayTime(payTime);
|
|
|
@@ -308,30 +323,19 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
|
|
|
//账户变动及日志记录
|
|
|
Long userId = orderInfo.getUserId();
|
|
|
- UserAccount userAccount = userAccountMapper.selectById(userId);
|
|
|
- //账户变动日志
|
|
|
- UserAccountLog accountLog = new UserAccountLog();
|
|
|
- accountLog.setBeforeBalance(userAccount.getBalance());
|
|
|
- //增加
|
|
|
- BigDecimal finalBalance = BigDecimal.ZERO;
|
|
|
- finalBalance = userAccount.getBalance().add(orderMoney);
|
|
|
- userAccount.setBalance(finalBalance);
|
|
|
- userAccountMapper.updateById(userAccount);
|
|
|
- //日志
|
|
|
- accountLog.setUserId(userId);
|
|
|
- accountLog.setChangeType(SystemConstants.CHANGE_TYPE_ADD);
|
|
|
- accountLog.setChangeNote(SystemConstants.ACCOUNT_LOG_PAY_NOTE);
|
|
|
- accountLog.setChangeId(orderInfo.getId());
|
|
|
- accountLog.setAccountType(SystemConstants.ACCOUNT_TYPE_PERSONAL);
|
|
|
- accountLog.setChangeBalance(finalBalance);
|
|
|
- userAccountLogMapper.insert(accountLog);
|
|
|
-
|
|
|
- //平订单超充金额
|
|
|
- orderBackTax(userAccount);
|
|
|
+ UserAccount userAccount = userAccountService.updateAccountBalanceAndLog(
|
|
|
+ userId,
|
|
|
+ orderMoney,
|
|
|
+ SystemConstants.CHANGE_TYPE_ADD,
|
|
|
+ SystemConstants.ACCOUNT_LOG_PAY_NOTE,
|
|
|
+ orderInfo.getId()
|
|
|
+ );
|
|
|
+
|
|
|
+ //平订单超充金额(使用更新后的账户信息)
|
|
|
+ orderBackTax(userId, userAccount);
|
|
|
}
|
|
|
|
|
|
- private void orderBackTax(UserAccount userAccount) {
|
|
|
- Long userId = SecurityUtils.getUserId();
|
|
|
+ private void orderBackTax(Long userId, UserAccount userAccount) {
|
|
|
//查询超充订单
|
|
|
List<ChargeOrderInfo> chargeOrderInfoList = chargeOrderInfoMapper.selectList(Wrappers.<ChargeOrderInfo>lambdaQuery()
|
|
|
.eq(ChargeOrderInfo::getUserId, userId)
|
|
|
@@ -339,10 +343,50 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
.orderByAsc(ChargeOrderInfo::getCreateTime)
|
|
|
);
|
|
|
if (CollUtil.isNotEmpty(chargeOrderInfoList)) {
|
|
|
+ //余额减去超充金额(使用更新后的余额)
|
|
|
BigDecimal balance = userAccount.getBalance();
|
|
|
for (ChargeOrderInfo chargeOrderInfo : chargeOrderInfoList) {
|
|
|
- balance = balance.subtract(chargeOrderInfo.getTotalMaspMoney());
|
|
|
- //todo
|
|
|
+
|
|
|
+ if (balance.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ BigDecimal deductAmount; // 本次扣除金额
|
|
|
+
|
|
|
+ if (balance.compareTo(chargeOrderInfo.getTotalMaspMoney()) < 0) {
|
|
|
+ //余额不足,部分补缴
|
|
|
+ deductAmount = balance;
|
|
|
+ chargeOrderInfo.setAlreadyMaspMoney(deductAmount);
|
|
|
+ chargeOrderInfo.setMaspDesc("部分补缴");
|
|
|
+ chargeOrderInfo.setMaspStatus(SystemConstants.STATUS_TWO);
|
|
|
+ chargeOrderInfoMapper.updateById(chargeOrderInfo);
|
|
|
+
|
|
|
+ //账户变动及日志记录
|
|
|
+ userAccountService.updateAccountBalanceAndLog(
|
|
|
+ userId,
|
|
|
+ deductAmount.negate(),
|
|
|
+ SystemConstants.CHANGE_TYPE_REDUCE,
|
|
|
+ SystemConstants.ACCOUNT_LOG_BACK_TAX_NOTE,
|
|
|
+ chargeOrderInfo.getId()
|
|
|
+ );
|
|
|
+
|
|
|
+ balance = BigDecimal.ZERO;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //余额足够,完成补缴
|
|
|
+ deductAmount = chargeOrderInfo.getTotalMaspMoney();
|
|
|
+ balance = balance.subtract(deductAmount);
|
|
|
+ chargeOrderInfo.setAlreadyMaspMoney(deductAmount);
|
|
|
+ chargeOrderInfo.setMaspDesc("完成补缴");
|
|
|
+ chargeOrderInfo.setMaspStatus(SystemConstants.STATUS_TWO);
|
|
|
+ chargeOrderInfoMapper.updateById(chargeOrderInfo);
|
|
|
+
|
|
|
+ //账户变动及日志记录
|
|
|
+ userAccountService.updateAccountBalanceAndLog(
|
|
|
+ userId,
|
|
|
+ deductAmount.negate(),
|
|
|
+ SystemConstants.CHANGE_TYPE_REDUCE,
|
|
|
+ SystemConstants.ACCOUNT_LOG_BACK_TAX_NOTE,
|
|
|
+ chargeOrderInfo.getId()
|
|
|
+ );
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -350,6 +394,7 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
|
|
|
/**
|
|
|
* 取消订单
|
|
|
+ *
|
|
|
* @param orderId
|
|
|
* @return
|
|
|
*/
|
|
|
@@ -369,6 +414,7 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
|
|
|
/**
|
|
|
* 账户退款
|
|
|
+ *
|
|
|
* @return
|
|
|
*/
|
|
|
@Override
|
|
|
@@ -377,27 +423,216 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
|
|
|
//查询账户余额
|
|
|
UserAccount userAccount = userAccountMapper.selectOne(Wrappers.<UserAccount>lambdaQuery().eq(UserAccount::getUserId, SecurityUtils.getUserId()).last("limit 1"));
|
|
|
- if(userAccount.getBalance().compareTo(BigDecimal.ZERO) == 0){
|
|
|
+ if (userAccount.getBalance().compareTo(BigDecimal.ZERO) == 0) {
|
|
|
throw new BusinessException("账户余额为 0");
|
|
|
}
|
|
|
BigDecimal refundMoney = userAccount.getBalance();
|
|
|
|
|
|
- //账户变动及日志记录
|
|
|
- UserAccountLog accountLog = new UserAccountLog();
|
|
|
- accountLog.setBeforeBalance(userAccount.getBalance());
|
|
|
- //账户余额清空
|
|
|
- userAccount.setBalance(BigDecimal.ZERO);
|
|
|
- userAccountMapper.updateById(userAccount);
|
|
|
- //日志
|
|
|
- accountLog.setUserId(SecurityUtils.getUserId());
|
|
|
- accountLog.setChangeType(SystemConstants.CHANGE_TYPE_REDUCE);
|
|
|
- accountLog.setChangeNote(SystemConstants.ACCOUNT_LOG_REFUND_NOTE);
|
|
|
- //accountLog.setChangeId();
|
|
|
- accountLog.setAccountType(SystemConstants.ACCOUNT_TYPE_PERSONAL);
|
|
|
- accountLog.setChangeBalance(BigDecimal.ZERO);
|
|
|
- userAccountLogMapper.insert(accountLog);
|
|
|
-
|
|
|
- return "";
|
|
|
+ //查询一年内已支付的所有券订单
|
|
|
+ List<UserOrderInfo> userOrderInfoList = baseMapper.selectList(Wrappers.<UserOrderInfo>lambdaQuery()
|
|
|
+ .eq(UserOrderInfo::getOrderStatus, SystemConstants.STATUS_TWO)
|
|
|
+ .between(UserOrderInfo::getCreateTime, LocalDateTime.now().minusYears(1), LocalDateTime.now())
|
|
|
+ );
|
|
|
+
|
|
|
+ if (CollUtil.isEmpty(userOrderInfoList)) {
|
|
|
+ log.info("当前用户一年内未支付任何券订单,无法进行退款操作!");
|
|
|
+ throw new BusinessException("无法进行退款操作,请联系客服处理!");
|
|
|
+ }
|
|
|
+ for (UserOrderInfo userOrderInfo : userOrderInfoList) {
|
|
|
+ if(refundMoney.compareTo(BigDecimal.ZERO) == 0){
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if ((userOrderInfo.getOrderMoney().subtract(userOrderInfo.getRefundMoney())).compareTo(refundMoney) > 0) {
|
|
|
+ //退款金额大于订单金额,则直接退退款金额
|
|
|
+ refundOrder(userOrderInfo,refundMoney, "账户退款", SystemConstants.STATUS_ONE);
|
|
|
+ //账户变动及日志记录
|
|
|
+ userAccountService.updateAccountBalanceAndLog(
|
|
|
+ SecurityUtils.getUserId(),
|
|
|
+ refundMoney,
|
|
|
+ SystemConstants.CHANGE_TYPE_REDUCE,
|
|
|
+ SystemConstants.ACCOUNT_LOG_REFUND_NOTE,
|
|
|
+ userOrderInfo.getId()
|
|
|
+ );
|
|
|
+ //修改订单状态
|
|
|
+ userOrderInfo.setOrderStatus(SystemConstants.STATUS_FOUR);
|
|
|
+ this.updateById(userOrderInfo);
|
|
|
+ refundMoney = BigDecimal.ZERO;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if ((userOrderInfo.getOrderMoney().subtract(userOrderInfo.getRefundMoney())).compareTo(refundMoney) < 0) {
|
|
|
+ //退款金额小于订单金额,则先退订单金额
|
|
|
+ refundOrder(userOrderInfo,userOrderInfo.getOrderMoney().subtract(userOrderInfo.getRefundMoney()), "账户退款", SystemConstants.STATUS_ONE);
|
|
|
+ //账户变动及日志记录
|
|
|
+ userAccountService.updateAccountBalanceAndLog(
|
|
|
+ SecurityUtils.getUserId(),
|
|
|
+ userOrderInfo.getOrderMoney().subtract(userOrderInfo.getRefundMoney()),
|
|
|
+ SystemConstants.CHANGE_TYPE_REDUCE,
|
|
|
+ SystemConstants.ACCOUNT_LOG_REFUND_NOTE,
|
|
|
+ userOrderInfo.getId()
|
|
|
+ );
|
|
|
+ //修改订单状态
|
|
|
+ userOrderInfo.setOrderStatus(SystemConstants.STATUS_FOUR);
|
|
|
+ this.updateById(userOrderInfo);
|
|
|
+ refundMoney = refundMoney.subtract(userOrderInfo.getOrderMoney());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return "账户退款,预计3个工作日内分一笔或多笔退还!如未收到,请联系客服!";
|
|
|
+ }
|
|
|
+
|
|
|
+ public void refundOrder(UserOrderInfo userOrderInfo, BigDecimal refundAmount, String reason, Integer type) {
|
|
|
+ log.info("进入退款接口------>");
|
|
|
+ log.info("执行操作的 原支付交易对应的商户订单号:{}", userOrderInfo.getOrderNo());
|
|
|
+
|
|
|
+ //退款单号
|
|
|
+ String out_refund_no = createOrderNo("TK",userOrderInfo.getId());
|
|
|
+ // 创建退款订单
|
|
|
+ UserRefundsOrderInfo userRefundsOrderInfo = new UserRefundsOrderInfo();
|
|
|
+ userRefundsOrderInfo.setOrderId(userOrderInfo.getId());
|
|
|
+ userRefundsOrderInfo.setOrderNo(userOrderInfo.getOrderNo());
|
|
|
+ userRefundsOrderInfo.setOutRefundNo(out_refund_no);
|
|
|
+ userRefundsOrderInfo.setReason(reason);
|
|
|
+ userRefundsOrderInfo.setAmount(refundAmount);
|
|
|
+ userRefundsOrderInfo.setType(type);
|
|
|
+ userRefundsOrderInfo.setCreateTime(LocalDateTime.now());
|
|
|
+
|
|
|
+ Map<String,Object> params = new HashMap<String,Object>();
|
|
|
+ params.put("transaction_id", userOrderInfo.getTransactionId());
|
|
|
+ params.put("out_trade_no", userOrderInfo.getOrderNo());//商户订单号
|
|
|
+ params.put("out_refund_no", out_refund_no);//商户退款单号
|
|
|
+ params.put("reason", reason);//退款原因
|
|
|
+ params.put("notify_url", WechatUrlConstants.PAY_V3_REFUND_NOTIFY);//退款通知
|
|
|
+
|
|
|
+ Map<String,Object> amount = new HashMap<String,Object>();
|
|
|
+ amount.put("refund", amount_fee(refundAmount));//退款金额
|
|
|
+ amount.put("currency", "CNY");
|
|
|
+ amount.put("total", amount_fee(userOrderInfo.getOrderMoney()));//原订单金额
|
|
|
+ params.put("amount", amount);
|
|
|
+ // 执行请求POST 请求发送到微信退款接口
|
|
|
+ Gson gson = new Gson();
|
|
|
+ JsonObject res = wechatPayV3Utils.sendPost(WechatUrlConstants.PAY_V3_REFUND, gson.toJsonTree(params).getAsJsonObject());
|
|
|
+
|
|
|
+ log.info("最终拿到的微信支付通知数据:" + res);
|
|
|
+
|
|
|
+ final String status = res.get("status").getAsString();
|
|
|
+ switch (status) {
|
|
|
+ case "SUCCESS":
|
|
|
+ log.info("订单:{},退款成功!原因:{}", userOrderInfo.getOrderNo(), reason);
|
|
|
+ //修改订单状态
|
|
|
+ userOrderInfo.setOrderStatus(SystemConstants.STATUS_FIVE);
|
|
|
+ userOrderInfo.setRefundMoney(userOrderInfo.getRefundMoney().add(refundAmount));
|
|
|
+ userOrderInfo.setRefundTime(LocalDateTime.now());
|
|
|
+ this.updateById(userOrderInfo);
|
|
|
+ break;
|
|
|
+ case "CLOSED":
|
|
|
+ log.info("退款关闭");
|
|
|
+ break;
|
|
|
+ case "PROCESSING":
|
|
|
+ log.info("退款处理中");
|
|
|
+ //修改订单状态
|
|
|
+ userOrderInfo.setRefundMoney(userOrderInfo.getRefundMoney().add(refundAmount));
|
|
|
+ this.updateById(userOrderInfo);
|
|
|
+ break;
|
|
|
+ case "ABNORMAL":
|
|
|
+ log.info("订单:{},退款异常", userOrderInfo.getOrderNo());
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ userRefundsOrderInfo.setRefundId(res.get("refund_id").getAsString());
|
|
|
+ userRefundsOrderInfo.setNotifyRequest(res.toString());
|
|
|
+ userRefundsOrderInfo.setTransactionId(res.get("transaction_id").getAsString());
|
|
|
+ userRefundsOrderInfo.setAcceptedTime(LocalDateTime.now());
|
|
|
+ userRefundsOrderInfoMapper.insert(userRefundsOrderInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> refundCallback(HttpServletRequest request, HttpServletResponse response) {
|
|
|
+
|
|
|
+ WechatRefundCallback refundCallback = new WechatRefundCallback() {
|
|
|
+ @Override
|
|
|
+ public void success(WechatCallbackRefundData refundData) {
|
|
|
+ log.info("微信支付退款成功!");
|
|
|
+
|
|
|
+ UserOrderInfo userOrderInfo = baseMapper.selectOne(Wrappers.lambdaQuery(UserOrderInfo.class).eq(UserOrderInfo::getOrderNo, refundData.getOrderNo()));
|
|
|
+ userOrderInfo.setOrderStatus(SystemConstants.STATUS_FIVE);
|
|
|
+ userOrderInfo.setRefundTime(refundData.getSuccessTime());
|
|
|
+ baseMapper.updateById(userOrderInfo);
|
|
|
+
|
|
|
+ UserRefundsOrderInfo userRefundsOrderInfo = userRefundsOrderInfoMapper.selectOne(Wrappers.<UserRefundsOrderInfo>lambdaQuery()
|
|
|
+ .eq(UserRefundsOrderInfo::getOrderId, userOrderInfo.getId())
|
|
|
+ .eq(UserRefundsOrderInfo::getRefundId, refundData.getTransactionRefundId())
|
|
|
+ .last("limit 1")
|
|
|
+ );
|
|
|
+ userRefundsOrderInfo.setStatus(refundData.getStatus());
|
|
|
+ userRefundsOrderInfo.setSuccessTime(refundData.getSuccessTime());
|
|
|
+ userRefundsOrderInfoMapper.updateById(userRefundsOrderInfo);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void fail(WechatCallbackRefundData refundData) {
|
|
|
+ log.info("微信支付退款失败!");
|
|
|
+
|
|
|
+ UserOrderInfo userOrderInfo = baseMapper.selectOne(Wrappers.lambdaQuery(UserOrderInfo.class).eq(UserOrderInfo::getOrderNo, refundData.getOrderNo()));
|
|
|
+
|
|
|
+ UserRefundsOrderInfo userRefundsOrderInfo = userRefundsOrderInfoMapper.selectOne(Wrappers.<UserRefundsOrderInfo>lambdaQuery()
|
|
|
+ .eq(UserRefundsOrderInfo::getOrderId, userOrderInfo.getId())
|
|
|
+ .eq(UserRefundsOrderInfo::getRefundId, refundData.getTransactionRefundId())
|
|
|
+ .last("limit 1")
|
|
|
+ );
|
|
|
+ userRefundsOrderInfo.setStatus(refundData.getStatus());
|
|
|
+ userRefundsOrderInfo.setSuccessTime(refundData.getSuccessTime());
|
|
|
+ userRefundsOrderInfoMapper.updateById(userRefundsOrderInfo);
|
|
|
+
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
+ if (lock.tryLock()) {
|
|
|
+ // 2.签名验证
|
|
|
+ //验签及解析返回数据
|
|
|
+ JsonObject res = wechatPayV3Utils.getCallbackData(request);
|
|
|
+ if (res == null) {
|
|
|
+ result.put("code", "FAIL");
|
|
|
+ result.put("message", "失败");
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ log.info("最终拿到的微信支付通知数据:" + res);
|
|
|
+
|
|
|
+ // 4.封装微信返回的数据
|
|
|
+ WechatCallbackRefundData refundData = getRefundCallbackData(res);
|
|
|
+ if ("SUCCESS".equals(refundData.getStatus())) {
|
|
|
+ refundCallback.success(refundData);
|
|
|
+ } else {
|
|
|
+ // 特殊情况退款失败业务处理,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往商户平台-交易中心,手动处理此笔退款
|
|
|
+ refundCallback.fail(refundData);
|
|
|
+ }
|
|
|
+ // 5.成功应答
|
|
|
+ response.setStatus(200);
|
|
|
+ result.put("code", "SUCCESS");
|
|
|
+ result.put("message", "成功");
|
|
|
+ } else {
|
|
|
+ result.put("code", "FAIL");
|
|
|
+ result.put("message", "失败");
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static WechatCallbackRefundData getRefundCallbackData(JsonObject res) {
|
|
|
+ WechatCallbackRefundData refundData = new WechatCallbackRefundData();
|
|
|
+ String successTime = res.get("success_time").getAsString();
|
|
|
+ if (StringUtils.isNoneBlank(successTime)) {
|
|
|
+ refundData.setSuccessTime(successTime);
|
|
|
+ }
|
|
|
+ refundData.setOrderNo(res.get("out_trade_no").getAsString());
|
|
|
+ refundData.setRefundId(res.get("out_refund_no").getAsString());
|
|
|
+ refundData.setTransactionId(res.get("transaction_id").getAsString());
|
|
|
+ refundData.setTransactionRefundId(res.get("refund_id").getAsString());
|
|
|
+ refundData.setChannel(res.get("channel").getAsString());
|
|
|
+ final String status = res.get("refund_status").getAsString();
|
|
|
+ refundData.setStatus(status);
|
|
|
+ String refundMoney = res.getAsJsonObject("amount").get("refund").getAsString();
|
|
|
+ refundData.setRefundMoney(new BigDecimal(refundMoney).movePointLeft(2));
|
|
|
+ log.info("refundData:{}", refundData);
|
|
|
+ return refundData;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -417,19 +652,20 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
|
|
|
/**
|
|
|
* 构建支付表单返回给前端支撑JsApi支付调用
|
|
|
+ *
|
|
|
* @param openId
|
|
|
* @param orderNo
|
|
|
* @param amount
|
|
|
* @return
|
|
|
*/
|
|
|
- private Map<String, Object> payment(String openId, String orderNo,BigDecimal amount) {
|
|
|
+ private Map<String, Object> payment(String openId, String orderNo, BigDecimal amount) {
|
|
|
//15分钟超时限制
|
|
|
Calendar calendar = Calendar.getInstance();
|
|
|
calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) + 15);
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
|
|
|
//构建微信支付参数
|
|
|
Map<String, Object> params = new HashMap<>();
|
|
|
- params.put("appid", WechatConstants.WECHAT_MP_APPID); //小程序appid
|
|
|
+ params.put("appid", WechatConstants.WECHAT_APPID); //小程序appid
|
|
|
params.put("mchid", WechatConstants.WECHAT_MCH_ID); //商户号
|
|
|
params.put("description", "订单业务"); //商品描述
|
|
|
params.put("out_trade_no", orderNo); //商户订单号
|
|
|
@@ -451,7 +687,45 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
payer.put("openid", openId);
|
|
|
params.put("payer", payer);
|
|
|
|
|
|
- return params;
|
|
|
+ //小程序支付拉起参数
|
|
|
+ Gson gson = new Gson();
|
|
|
+ return wechatPay(gson.toJsonTree(params).getAsJsonObject());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 小程序支付拉起
|
|
|
+ *
|
|
|
+ * @param params
|
|
|
+ * @return
|
|
|
+ * @throws ServiceException
|
|
|
+ */
|
|
|
+ public Map<String, Object> wechatPay(JsonObject params) throws ServiceException {
|
|
|
+
|
|
|
+ //发起请求
|
|
|
+ JsonObject res = wechatPayV3Utils.sendPost(WechatUrlConstants.PAY_V3_JSAPI, params);
|
|
|
+ log.info("wechatPay res:{}", res.toString());
|
|
|
+ if (StrUtil.isEmpty(res.get("prepay_id").getAsString())) {
|
|
|
+ throw new ServiceException("支付发起失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ //返回给小程序拉起微信支付的参数
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
+ result.put("appId", WechatConstants.WECHAT_APPID); //小程序appid
|
|
|
+ sb.append(result.get("appId")).append("\n");
|
|
|
+ result.put("timeStamp", (new Date().getTime() / 1000) + ""); //时间戳
|
|
|
+ sb.append(result.get("timeStamp")).append("\n");
|
|
|
+ result.put("nonceStr", RandomStringUtils.randomAlphanumeric(32)); //32位随机字符串
|
|
|
+ sb.append(result.get("nonceStr")).append("\n");
|
|
|
+ result.put("package", "prepay_id=" + res.get("prepay_id").getAsString()); //预支付id 格式为 prepay_id=xxx
|
|
|
+ sb.append(result.get("package")).append("\n");
|
|
|
+ //签名
|
|
|
+ result.put("paySign", wechatPayV3Utils.signRSA(sb.toString()));
|
|
|
+ result.put("signType", "RSA"); //加密方式 固定RSA
|
|
|
+ result.put("out_trade_no", params.get("out_trade_no").getAsString()); //商户订单号 此参数不是小程序拉起支付所需的参数 因此不参与签名
|
|
|
+
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -492,13 +766,4 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
|
|
|
return money + "";
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 分转元,转换为bigDecimal在转成double
|
|
|
- *
|
|
|
- * @return
|
|
|
- */
|
|
|
- public static double changeF2Y3(int price) {
|
|
|
- return BigDecimal.valueOf(Long.valueOf(price)).divide(new BigDecimal("100")).doubleValue();
|
|
|
- }
|
|
|
-
|
|
|
}
|