微信支付小重构

This commit is contained in:
墨大叔 2024-08-01 11:15:23 +08:00
parent f72ca5ecb6
commit 6342d71a89
22 changed files with 158 additions and 258 deletions

View File

@ -1,4 +1,4 @@
package com.ruoyi.ss.wxPay.domain; package com.ruoyi.common.pay.wx.domain;
import java.math.BigDecimal; import java.math.BigDecimal;

View File

@ -1,4 +1,4 @@
package com.ruoyi.ss.wxPay.domain; package com.ruoyi.common.pay.wx.domain;
import com.wechat.pay.java.service.refund.model.AmountReq; import com.wechat.pay.java.service.refund.model.AmountReq;

View File

@ -1,7 +1,6 @@
package com.ruoyi.ss.wxPay.domain.enums; package com.ruoyi.common.pay.wx.domain.enums;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter; import lombok.Getter;
/** /**

View File

@ -1,4 +1,4 @@
package com.ruoyi.ss.wxPay.domain.enums; package com.ruoyi.common.pay.wx.domain.enums;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;

View File

@ -1,11 +1,8 @@
package com.ruoyi.ss.wxPay.service; package com.ruoyi.common.pay.wx.service;
import com.alibaba.fastjson2.JSON; import com.ruoyi.common.pay.wx.domain.Payable;
import com.ruoyi.common.utils.http.HttpUtils; import com.ruoyi.common.pay.wx.domain.RefundAble;
import com.ruoyi.ss.wxPay.domain.Payable; import com.ruoyi.common.pay.wx.domain.enums.TransferScene;
import com.ruoyi.ss.wxPay.domain.RefundAble;
import com.ruoyi.ss.wxPay.domain.enums.TransferScene;
import com.wechat.pay.java.core.notification.Notification;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse; import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.model.Transaction; import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.model.Refund; import com.wechat.pay.java.service.refund.model.Refund;
@ -21,14 +18,7 @@ import java.util.List;
* @author * @author
* 2024/3/11 * 2024/3/11
*/ */
public interface IWxPayService { public interface WxPayService {
/**
* 生成微信预支付订单并签名
* @param billNo 平台订单编号
* @return JSAPI调用
*/
PrepayWithRequestPaymentResponse prepayWithRequestPayment(String billNo);
PrepayWithRequestPaymentResponse prepayWithRequestPayment(Payable payable); PrepayWithRequestPaymentResponse prepayWithRequestPayment(Payable payable);
@ -57,11 +47,6 @@ public interface IWxPayService {
boolean isSuccess(Transaction transaction); boolean isSuccess(Transaction transaction);
/**
* 微信支付通知
*/
void payNotify(HttpServletRequest request);
/** /**
* 提现打款 * 提现打款
* @param billId 单号 * @param billId 单号

View File

@ -1,27 +1,19 @@
package com.ruoyi.ss.wxPay.service; package com.ruoyi.common.pay.wx.service;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.config.WxPayConfig; import com.ruoyi.common.config.WxPayConfig;
import com.ruoyi.common.core.redis.RedisLock; import com.ruoyi.common.core.redis.RedisLock;
import com.ruoyi.common.core.redis.enums.RedisLockKey; import com.ruoyi.common.core.redis.enums.RedisLockKey;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.pay.wx.domain.NotifyEventType; import com.ruoyi.common.pay.wx.domain.NotifyEventType;
import com.ruoyi.common.pay.wx.domain.TransferBatchStatus; import com.ruoyi.common.pay.wx.domain.TransferBatchStatus;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil; import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.SnowFlakeUtil; import com.ruoyi.common.utils.SnowFlakeUtil;
import com.ruoyi.common.utils.http.HttpUtils; import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.ss.transactionBill.domain.TransactionBill; import com.ruoyi.common.pay.wx.domain.Payable;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillPayType; import com.ruoyi.common.pay.wx.domain.RefundAble;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillStatus; import com.ruoyi.common.pay.wx.domain.enums.TransferScene;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillType;
import com.ruoyi.ss.transactionBill.service.TransactionBillService;
import com.ruoyi.ss.user.domain.SmUserVo;
import com.ruoyi.ss.user.service.ISmUserService;
import com.ruoyi.ss.wxPay.domain.Payable;
import com.ruoyi.ss.wxPay.domain.RefundAble;
import com.ruoyi.ss.wxPay.domain.enums.TransferScene;
import com.ruoyi.ss.wxPayNotify.domain.SmWxPayNotify;
import com.ruoyi.ss.wxPayNotify.mapper.SmWxPayNotifyMapper;
import com.wechat.pay.java.core.notification.Notification; import com.wechat.pay.java.core.notification.Notification;
import com.wechat.pay.java.core.notification.NotificationParser; import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam; import com.wechat.pay.java.core.notification.RequestParam;
@ -60,7 +52,7 @@ import java.util.stream.Collectors;
*/ */
@Service @Service
@Slf4j @Slf4j
public class WxPayService implements IWxPayService { public class WxPayServiceImpl implements WxPayService {
@Autowired @Autowired
private JsapiService jsapiService; private JsapiService jsapiService;
@ -71,78 +63,14 @@ public class WxPayService implements IWxPayService {
@Autowired @Autowired
private WxPayConfig wxPayConfig; private WxPayConfig wxPayConfig;
@Autowired
private TransactionBillService transactionBillService;
@Autowired
private ISmUserService smUserService;
@Autowired @Autowired
private NotificationParser notificationParser; private NotificationParser notificationParser;
@Autowired
private SmWxPayNotifyMapper smWxPayNotifyMapper;
@Autowired
private RedisLock redisLock;
@Autowired @Autowired
private RefundService refundService; private RefundService refundService;
@Autowired
private TransferBatchService transferBatchService;
@Autowired
private ScheduledExecutorService scheduledExecutorService;
private static final String CNY = "CNY"; private static final String CNY = "CNY";
@Override
@Transactional
public PrepayWithRequestPaymentResponse prepayWithRequestPayment(String billNo) {
try {
ServiceUtil.assertion(!redisLock.lock(RedisLockKey.PREPAY.getKey() + ":" + billNo), "当前订单正在支付,请刷新后重试");
TransactionBill bill = transactionBillService.selectSmTransactionBillByBillNo(billNo);
ServiceUtil.assertion(bill == null, "未查询到相关订单");
ServiceUtil.assertion(!Objects.equals(bill.getChannelId(), TransactionBillPayType.WECHAT.getType()), "该订单不是微信支付订单");
ServiceUtil.assertion(!TransactionBillStatus.UNPAID.getStatus().equals(bill.getStatus()), "只能支付未支付的订单");
ServiceUtil.assertion(!TransactionBillType.RECHARGE.getType().equals(bill.getType()), "只能支付充值订单");
// 获取JSAPI所需参数
// PrepayRequest request = new PrepayRequest();
// request.setAmount(getAmount(bill.getMoney()));
// request.setOutTradeNo(billNo);
// request.setAppid(wxPayConfig.getAppId());
// request.setMchid(wxPayConfig.getMerchantId());
// request.setDescription(getDescription(bill));
// request.setNotifyUrl(wxPayConfig.getNotifyUrl());
// request.setPayer(getPayer(user.getWxOpenId()));
//
// PrepayWithRequestPaymentResponse res = jsapiServiceExtension.prepayWithRequestPayment(request);
PrepayWithRequestPaymentResponse res = this.prepayWithRequestPayment(bill);
try {
// 支付中
transactionBillService.paying(bill.getBillId());
// 每隔20秒查询支付结果直到过期首次10秒查询
scheduledExecutorService.schedule(() -> {
transactionBillService.refreshPayResultBeforeExpire(bill.getBillNo(), 20, TimeUnit.SECONDS);
}, 10, TimeUnit.SECONDS);
} catch (Exception e) {
this.closeOrder(bill.getBillNo());
throw e;
}
return res;
} finally {
redisLock.unlock(RedisLockKey.PREPAY.getKey() + ":" + billNo);
}
}
@Override @Override
public PrepayWithRequestPaymentResponse prepayWithRequestPayment(Payable payable) { public PrepayWithRequestPaymentResponse prepayWithRequestPayment(Payable payable) {
return this.prepayWithRequestPayment(payable.payableOutTradeNo(), payable.payableMoney(), payable.payableDescription(), payable.payableOpenId(), payable.payableAttach()); return this.prepayWithRequestPayment(payable.payableOutTradeNo(), payable.payableMoney(), payable.payableDescription(), payable.payableOpenId(), payable.payableAttach());
@ -196,31 +124,6 @@ public class WxPayService implements IWxPayService {
return transaction != null && Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState()); return transaction != null && Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState());
} }
/**
* 微信支付通知
* @param request 请求
*/
@Override
public void payNotify(HttpServletRequest request) {
// 获取原始报文body
String body = HttpUtils.getBody(request);
log.info("获取原始报文body: {}", body);
// 解析通知数据
Notification notification = JSON.parseObject(body, Notification.class);
log.info("解析通知数据: {}", notification);
// 支付成功通知
if (NotifyEventType.TRANSACTION_SUCCESS.getValue().equals(notification.getEventType())) {
// 验签解密并转换成 Transaction
Transaction transaction = checkAndParse(request, body, Transaction.class);
log.info("验签、解密并转换成Transaction: {}", transaction);
if (Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())) {
// 充值成功修改订单状态
transactionBillService.rechargeSuccess(transaction.getOutTradeNo(), DateUtils.getNowDate());
}
}
}
/** /**
* 提现打款 * 提现打款
* @param billId id * @param billId id
@ -228,59 +131,60 @@ public class WxPayService implements IWxPayService {
@Override @Override
@Transactional @Transactional
public InitiateBatchTransferResponse payWithdraw(Long billId) { public InitiateBatchTransferResponse payWithdraw(Long billId) {
ServiceUtil.assertion(billId == null, "订单id不允许为空"); // ServiceUtil.assertion(billId == null, "订单id不允许为空");
TransactionBill bill = transactionBillService.selectSmTransactionBillByBillId(billId); // TransactionBill bill = transactionBillService.selectSmTransactionBillByBillId(billId);
ServiceUtil.assertion(bill == null, "单据不存在"); // ServiceUtil.assertion(bill == null, "单据不存在");
ServiceUtil.assertion(TransactionBillStatus.WITHDRAW_PASSED.getStatus().equals(bill.getStatus()), "当前提现单据状态异常"); // ServiceUtil.assertion(TransactionBillStatus.WITHDRAW_PASSED.getStatus().equals(bill.getStatus()), "当前提现单据状态异常");
ServiceUtil.assertion(StringUtils.isBlank(bill.getAccountNo()), "提现账号异常"); // ServiceUtil.assertion(StringUtils.isBlank(bill.getAccountNo()), "提现账号异常");
//
// 转账明细列表 // // 转账明细列表
List<TransferDetailInput> transferDetailList = this.buildTransferDetailList(bill.getArrivalAmount(), bill.getAccountNo(), TransferScene.WITHDRAW); // List<TransferDetailInput> transferDetailList = this.buildTransferDetailList(bill.getArrivalAmount(), bill.getAccountNo(), TransferScene.WITHDRAW);
//
// 更新微信批次明细单号 // // 更新微信批次明细单号
transactionBillService.updateWxTransferDetailIds(billId, transferDetailList.stream().map(TransferDetailInput::getOutDetailNo).collect(Collectors.toList())); // transactionBillService.updateWxTransferDetailIds(billId, transferDetailList.stream().map(TransferDetailInput::getOutDetailNo).collect(Collectors.toList()));
//
// 发起转账请求 // // 发起转账请求
InitiateBatchTransferRequest request = new InitiateBatchTransferRequest(); // InitiateBatchTransferRequest request = new InitiateBatchTransferRequest();
request.setAppid(wxPayConfig.getAppId()); // request.setAppid(wxPayConfig.getAppId());
request.setOutBatchNo(bill.getBillNo()); // request.setOutBatchNo(bill.getBillNo());
request.setBatchName("提现"); // request.setBatchName("提现");
request.setBatchRemark(String.format("用户%s提现%f元", bill.getUserId(), bill.getArrivalAmount())); // request.setBatchRemark(String.format("用户%s提现%f元", bill.getUserId(), bill.getArrivalAmount()));
request.setTotalAmount(getTransferAmount(bill.getArrivalAmount())); // request.setTotalAmount(getTransferAmount(bill.getArrivalAmount()));
request.setTotalNum(transferDetailList.size()); // request.setTotalNum(transferDetailList.size());
request.setTransferDetailList(transferDetailList); // request.setTransferDetailList(transferDetailList);
return transferBatchService.initiateBatchTransfer(request); // return transferBatchService.initiateBatchTransfer(request);
throw new ServiceException("开发中");
} }
@Override @Override
@Transactional @Transactional
public void wxTransferNotify(HttpServletRequest request) { public void wxTransferNotify(HttpServletRequest request) {
String body = HttpUtils.getBody(request); throw new ServiceException("开发中");
// 解析通知数据 // String body = HttpUtils.getBody(request);
Notification notification = JSON.parseObject(body, Notification.class); // // 解析通知数据
// Notification notification = JSON.parseObject(body, Notification.class);
// 判断是否重复通知重复通知则忽略 //
if (isRepeatNotify(notification.getId())) { // // 判断是否重复通知重复通知则忽略
return; // if (isRepeatNotify(notification.getId())) {
} // return;
// }
// 商户转账成功通知 //
if (NotifyEventType.MCHTRANSFER_BATCH_FINISHED.getValue().equals(notification.getEventType())) { // // 商户转账成功通知
// 验签解密并转换成 TransferBatchGet // if (NotifyEventType.MCHTRANSFER_BATCH_FINISHED.getValue().equals(notification.getEventType())) {
TransferBatchGet transferBatchGet = checkAndParse(request, body, TransferBatchGet.class); // // 验签解密并转换成 TransferBatchGet
TransactionBill bill = transactionBillService.selectSmTransactionBillByBillNo(transferBatchGet.getOutBatchNo()); // TransferBatchGet transferBatchGet = checkAndParse(request, body, TransferBatchGet.class);
ServiceUtil.assertion(bill == null, "订单不存在"); // TransactionBill bill = transactionBillService.selectSmTransactionBillByBillNo(transferBatchGet.getOutBatchNo());
// ServiceUtil.assertion(bill == null, "订单不存在");
// 修改订单状态 //
if (TransferBatchStatus.FINISHED.getStatus().equals(transferBatchGet.getBatchStatus())) { // // 修改订单状态
// 提现成功 // if (TransferBatchStatus.FINISHED.getStatus().equals(transferBatchGet.getBatchStatus())) {
transactionBillService.withdrawSuccess(bill.getBillId(), LocalDateTime.now()); // // 提现成功
} else if (TransferBatchStatus.CLOSED.getStatus().equals(transferBatchGet.getBatchStatus())) { // transactionBillService.withdrawSuccess(bill.getBillId(), LocalDateTime.now());
// 提现失败 // } else if (TransferBatchStatus.CLOSED.getStatus().equals(transferBatchGet.getBatchStatus())) {
transactionBillService.withdrawFailed(bill.getBillId()); // // 提现失败
} // transactionBillService.withdrawFailed(bill.getBillId());
} // }
// }
} }
@ -329,32 +233,6 @@ public class WxPayService implements IWxPayService {
return money.multiply(new BigDecimal(100)).longValue(); return money.multiply(new BigDecimal(100)).longValue();
} }
/**
* 通知是否重复
* @param notifyId 通知id
*/
private boolean isRepeatNotify(String notifyId) {
SmWxPayNotify repeat = smWxPayNotifyMapper.selectSmWxPayNotifyByNotifyId(notifyId);
return repeat != null;
}
/**
* 保存通知数据
* @param billNo 订单编号
* @param body 请求体
* @param plaintext 明文
*/
private void saveNotifyData(String billNo, Notification body, Object plaintext) {
TransactionBill bill = transactionBillService.selectSmTransactionBillByBillNo(billNo);
SmWxPayNotify data = new SmWxPayNotify();
data.setNotifyId(body.getId());
data.setBillId(bill.getBillId());
data.setBody(JSON.toJSONString(body));
data.setPlaintext(JSON.toJSONString(plaintext));
int i = smWxPayNotifyMapper.insertSmWxPayNotify(data);
ServiceUtil.assertion(i != 1, "保存通知数据失败");
}
/** /**
* 验签并解析 * 验签并解析
* @param request 请求 * @param request 请求

View File

@ -1,4 +1,4 @@
package com.ruoyi.common.wx; package com.ruoyi.common.wx.auth;
import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl; import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;

View File

@ -1,4 +1,4 @@
package com.ruoyi.common.wx; package com.ruoyi.common.wx.auth;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
@ -12,7 +12,7 @@ import org.springframework.stereotype.Service;
* 2024/7/29 * 2024/7/29
*/ */
@Service @Service
public class WxService { public class WxAuthService {
@Autowired @Autowired

View File

@ -1,4 +1,4 @@
package com.ruoyi.common.wx.vo; package com.ruoyi.common.wx.auth.vo;
public class AccessToken { public class AccessToken {
private String expires_in; //成功有效时间 private String expires_in; //成功有效时间

View File

@ -4,16 +4,14 @@ import javax.annotation.Resource;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.config.WxConfig;
import com.ruoyi.common.core.domain.entity.SmUser; import com.ruoyi.common.core.domain.entity.SmUser;
import com.ruoyi.common.core.domain.model.WxLoginBody; import com.ruoyi.common.core.domain.model.WxLoginBody;
import com.ruoyi.common.enums.UserStatus; import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.utils.ServiceUtil; import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.http.HttpUtils; import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.wx.AccessTokenUtil; import com.ruoyi.common.wx.auth.AccessTokenUtil;
import com.ruoyi.common.wx.WxService; import com.ruoyi.common.wx.auth.WxAuthService;
import com.ruoyi.ss.account.domain.Account; import com.ruoyi.ss.account.domain.Account;
import com.ruoyi.ss.store.service.IStoreService; import com.ruoyi.ss.store.service.IStoreService;
import com.ruoyi.ss.user.service.ISmUserService; import com.ruoyi.ss.user.service.ISmUserService;
@ -83,7 +81,7 @@ public class SysLoginService
private IStoreService smDeviceGroupService; private IStoreService smDeviceGroupService;
@Autowired @Autowired
private WxService wxService; private WxAuthService wxAuthService;
/** /**
* 登录验证 * 登录验证
@ -258,7 +256,7 @@ public class SysLoginService
public String wxLogin(WxLoginBody body) { public String wxLogin(WxLoginBody body) {
// 通过登录授权码获取到用户信息 // 通过登录授权码获取到用户信息
WxMaJscode2SessionResult wxMaJscode2SessionResult = wxService.wxJsCode2Session(body.getLoginCode()); WxMaJscode2SessionResult wxMaJscode2SessionResult = wxAuthService.wxJsCode2Session(body.getLoginCode());
// 通过openId查询用户判断是否微信用户 // 通过openId查询用户判断是否微信用户
SmUser user = smUserService.selectSmUserByWxOpenId(wxMaJscode2SessionResult.getOpenid()); SmUser user = smUserService.selectSmUserByWxOpenId(wxMaJscode2SessionResult.getOpenid());

View File

@ -1,11 +1,9 @@
package com.ruoyi.ss.account.service.impl; package com.ruoyi.ss.account.service.impl;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil; import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.valid.bank.BankCardInfo; import com.ruoyi.common.valid.bank.BankCardInfo;
import com.ruoyi.common.valid.bank.BankValidUtils; import com.ruoyi.common.valid.bank.BankValidUtils;
import com.ruoyi.common.wx.WxService;
import com.ruoyi.ss.account.domain.Account; import com.ruoyi.ss.account.domain.Account;
import com.ruoyi.ss.account.domain.AccountQuery; import com.ruoyi.ss.account.domain.AccountQuery;
import com.ruoyi.ss.account.domain.AccountVO; import com.ruoyi.ss.account.domain.AccountVO;

View File

@ -2,14 +2,11 @@ package com.ruoyi.ss.payBill.domain;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.common.pay.wx.domain.Payable;
import com.ruoyi.ss.wxPay.domain.Payable; import com.ruoyi.common.pay.wx.domain.enums.AttachEnums;
import com.ruoyi.ss.wxPay.domain.enums.AttachEnums;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.domain.BaseEntity;

View File

@ -15,7 +15,7 @@ import com.ruoyi.ss.timeBill.service.TimeBillService;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillPayType; import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillPayType;
import com.ruoyi.ss.user.domain.SmUserVo; import com.ruoyi.ss.user.domain.SmUserVo;
import com.ruoyi.ss.user.service.ISmUserService; import com.ruoyi.ss.user.service.ISmUserService;
import com.ruoyi.ss.wxPay.service.IWxPayService; import com.ruoyi.common.pay.wx.service.WxPayService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -44,7 +44,7 @@ public class PayBillServiceImpl implements PayBillService
private RedisLock redisLock; private RedisLock redisLock;
@Autowired @Autowired
private IWxPayService wxPayService; private WxPayService wxPayService;
@Autowired @Autowired
private TransactionTemplate transactionTemplate; private TransactionTemplate transactionTemplate;

View File

@ -2,11 +2,8 @@ package com.ruoyi.ss.refund.domain;
import java.math.BigDecimal; import java.math.BigDecimal;
import com.ruoyi.ss.wxPay.domain.RefundAble;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.domain.BaseEntity;

View File

@ -1,6 +1,6 @@
package com.ruoyi.ss.refund.domain; package com.ruoyi.ss.refund.domain;
import com.ruoyi.ss.wxPay.domain.RefundAble; import com.ruoyi.common.pay.wx.domain.RefundAble;
import com.wechat.pay.java.service.refund.model.AmountReq; import com.wechat.pay.java.service.refund.model.AmountReq;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;

View File

@ -23,7 +23,7 @@ import com.ruoyi.ss.timeBill.domain.dto.TimeBillPayDTO;
import com.ruoyi.ss.timeBill.domain.enums.TimeBillStatus; import com.ruoyi.ss.timeBill.domain.enums.TimeBillStatus;
import com.ruoyi.ss.timeBill.service.TimeBillConverter; import com.ruoyi.ss.timeBill.service.TimeBillConverter;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillPayType; import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillPayType;
import com.ruoyi.ss.wxPay.service.WxPayService; import com.ruoyi.common.pay.wx.service.WxPayServiceImpl;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse; import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -65,7 +65,7 @@ public class TimeBillServiceImpl implements TimeBillService
private PayBillService payBillService; private PayBillService payBillService;
@Autowired @Autowired
private WxPayService wxPayService; private WxPayServiceImpl wxPayService;
/** /**
* 查询时长订单 * 查询时长订单

View File

@ -8,8 +8,8 @@ import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.JsonViewProfile; import com.ruoyi.common.core.domain.JsonViewProfile;
import com.ruoyi.common.core.domain.ValidGroup; import com.ruoyi.common.core.domain.ValidGroup;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillType; import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillType;
import com.ruoyi.ss.wxPay.domain.Payable; import com.ruoyi.common.pay.wx.domain.Payable;
import com.ruoyi.ss.wxPay.domain.enums.AttachEnums; import com.ruoyi.common.pay.wx.domain.enums.AttachEnums;
import com.ruoyi.system.valid.DictValid; import com.ruoyi.system.valid.DictValid;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;

View File

@ -10,6 +10,7 @@ import com.ruoyi.ss.transactionBill.domain.dto.BillRefundDTO;
import com.ruoyi.ss.transactionBill.domain.dto.WithdrawApprovalDTO; import com.ruoyi.ss.transactionBill.domain.dto.WithdrawApprovalDTO;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillStatus; import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillStatus;
import com.ruoyi.ss.transactionBill.domain.vo.UserWithdrawServiceVO; import com.ruoyi.ss.transactionBill.domain.vo.UserWithdrawServiceVO;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -184,9 +185,11 @@ public interface TransactionBillService
/** /**
* 支付中 * 支付中
*
* @param billId * @param billId
* @return
*/ */
void paying(Long billId); int paying(Long billId);
/** /**
* 手动设备充值 * 手动设备充值
@ -272,4 +275,9 @@ public interface TransactionBillService
* 获取用户提现手续费信息 * 获取用户提现手续费信息
*/ */
UserWithdrawServiceVO getUserWithdrawService(Long userId, Long channelId); UserWithdrawServiceVO getUserWithdrawService(Long userId, Long channelId);
/**
* 微信支付
*/
PrepayWithRequestPaymentResponse wxPay(TransactionBill bill);
} }

View File

@ -42,9 +42,10 @@ import com.ruoyi.ss.user.domain.SmUserVo;
import com.ruoyi.common.enums.ServiceType; import com.ruoyi.common.enums.ServiceType;
import com.ruoyi.ss.user.mapper.SmUserMapper; import com.ruoyi.ss.user.mapper.SmUserMapper;
import com.ruoyi.ss.user.service.ISmUserService; import com.ruoyi.ss.user.service.ISmUserService;
import com.ruoyi.ss.wxPay.service.IWxPayService; import com.ruoyi.common.pay.wx.service.WxPayService;
import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.task.bill.BillDelayedManager; import com.ruoyi.task.bill.BillDelayedManager;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.model.Transaction; import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferResponse; import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -85,7 +86,7 @@ public class TransactionBillServiceImpl implements TransactionBillService {
private DeviceService deviceService; private DeviceService deviceService;
@Autowired @Autowired
private IWxPayService wxPayService; private WxPayService wxPayService;
@Autowired @Autowired
private ISmUserService userService; private ISmUserService userService;
@ -234,7 +235,14 @@ public class TransactionBillServiceImpl implements TransactionBillService {
// 若订单金额为0元则直接充值成功 // 若订单金额为0元则直接充值成功
if (order.getMoney().compareTo(BigDecimal.ZERO) == 0) { if (order.getMoney().compareTo(BigDecimal.ZERO) == 0) {
TransactionBillVO bill = this.selectSmTransactionBillByBillNo(order.getBillNo()); TransactionBillVO bill = this.selectSmTransactionBillByBillNo(order.getBillNo());
this.paying(bill.getBillId());
// 更新为支付中
transactionTemplate.execute(status -> {
int paying = this.paying(bill.getBillId());
ServiceUtil.assertion(paying != 1, "更新支付状态失败");
return paying;
});
this.rechargeSuccess(order.getBillNo(), DateUtils.getNowDate()); this.rechargeSuccess(order.getBillNo(), DateUtils.getNowDate());
} }
@ -631,13 +639,11 @@ public class TransactionBillServiceImpl implements TransactionBillService {
} }
@Override @Override
public void paying(Long billId) { public int paying(Long billId) {
ServiceUtil.assertion(billId == null, "订单id不允许为空"); if (billId == null) {
transactionTemplate.execute(status -> { return 0;
int updateCount = transactionBillMapper.paying(billId); }
ServiceUtil.assertion(updateCount != 1, "订单状态发生变化,请刷新后重试"); return transactionBillMapper.paying(billId);
return updateCount;
});
} }
/** /**
@ -1109,4 +1115,37 @@ public class TransactionBillServiceImpl implements TransactionBillService {
ChannelVO channel = channelService.selectSmChannelByChannelId(channelId); ChannelVO channel = channelService.selectSmChannelByChannelId(channelId);
return this.getUserWithdrawService(user, channel); return this.getUserWithdrawService(user, channel);
} }
@Override
public PrepayWithRequestPaymentResponse wxPay(TransactionBill bill) {
ServiceUtil.assertion(bill == null || bill.getBillId() == null, "订单不存在");
Long lockKey = bill.getBillId();
ServiceUtil.assertion(!redisLock.lock(RedisLockKey.PREPAY, lockKey), "当前订单正在支付,请稍后重试");
try {
ServiceUtil.assertion(!Objects.equals(bill.getChannelId(), TransactionBillPayType.WECHAT.getType()), "该订单不是微信支付订单");
ServiceUtil.assertion(!TransactionBillStatus.UNPAID.getStatus().equals(bill.getStatus()), "只能支付未支付的订单");
ServiceUtil.assertion(!TransactionBillType.RECHARGE.getType().equals(bill.getType()), "只能支付充值订单");
PrepayWithRequestPaymentResponse result = transactionTemplate.execute(status -> {
// 修改状态为支付中
int paying = this.paying(bill.getBillId());
ServiceUtil.assertion(paying != 1, "更新支付状态失败");
// 发起支付
return wxPayService.prepayWithRequestPayment(bill);
});
// 每隔20秒查询支付结果直到过期首次10秒查询
if (result != null) {
scheduledExecutorService.schedule(() -> {
this.refreshPayResultBeforeExpire(bill.getBillNo(), 20, TimeUnit.SECONDS);
}, 10, TimeUnit.SECONDS);
}
return result;
} finally {
redisLock.unlock(RedisLockKey.PREPAY, lockKey);
}
}
} }

View File

@ -3,12 +3,10 @@ package com.ruoyi.task.bill;
import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillStatus; import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillStatus;
import com.ruoyi.ss.transactionBill.service.TransactionBillService; import com.ruoyi.ss.transactionBill.service.TransactionBillService;
import com.ruoyi.ss.wxPay.service.IWxPayService; import com.ruoyi.common.pay.wx.service.WxPayService;
import com.ruoyi.ss.wxPay.service.WxPayService;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date; import java.util.Date;
import java.util.concurrent.Delayed; import java.util.concurrent.Delayed;
@ -25,7 +23,7 @@ public class BillDelayed implements Delayed {
private TransactionBillService transactionBillService; private TransactionBillService transactionBillService;
private IWxPayService wxPayService = SpringUtils.getBean(WxPayService.class); private WxPayService wxPayService = SpringUtils.getBean(WxPayService.class);
private String billNo; private String billNo;

View File

@ -6,14 +6,13 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.ValidGroup; import com.ruoyi.common.core.domain.ValidGroup;
import com.ruoyi.common.utils.ServiceUtil; import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.wx.WxService; import com.ruoyi.common.wx.auth.WxAuthService;
import com.ruoyi.ss.account.domain.Account; import com.ruoyi.ss.account.domain.Account;
import com.ruoyi.ss.account.domain.AccountQuery; import com.ruoyi.ss.account.domain.AccountQuery;
import com.ruoyi.ss.account.domain.AccountVO; import com.ruoyi.ss.account.domain.AccountVO;
import com.ruoyi.ss.account.domain.enums.AccountType; import com.ruoyi.ss.account.domain.enums.AccountType;
import com.ruoyi.ss.account.service.AccountService; import com.ruoyi.ss.account.service.AccountService;
import com.ruoyi.ss.account.service.AccountValidator; import com.ruoyi.ss.account.service.AccountValidator;
import com.ruoyi.web.core.annotation.MchRequired;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -35,14 +34,14 @@ public class AppAccountController extends BaseController {
private AccountValidator accountValidator; private AccountValidator accountValidator;
@Autowired @Autowired
private WxService wxService; private WxAuthService wxAuthService;
@ApiOperation("添加收款账户") @ApiOperation("添加收款账户")
@PostMapping @PostMapping
public AjaxResult addAccount(@RequestBody @Validated({ValidGroup.FrontCreate.class}) Account data) { public AjaxResult addAccount(@RequestBody @Validated({ValidGroup.FrontCreate.class}) Account data) {
// 微信获取微信openId并替换数据 // 微信获取微信openId并替换数据
if (AccountType.WECHAT.getType().equals(data.getAccountType())) { if (AccountType.WECHAT.getType().equals(data.getAccountType())) {
WxMaJscode2SessionResult result = wxService.wxJsCode2Session(data.getAccountNo()); WxMaJscode2SessionResult result = wxAuthService.wxJsCode2Session(data.getAccountNo());
ServiceUtil.assertion(result == null, "获取微信信息失败"); ServiceUtil.assertion(result == null, "获取微信信息失败");
data.setAccountNo(result.getOpenid()); data.setAccountNo(result.getOpenid());
} }
@ -57,7 +56,7 @@ public class AppAccountController extends BaseController {
// 微信获取微信openId并替换数据 // 微信获取微信openId并替换数据
if (AccountType.WECHAT.getType().equals(data.getAccountType()) && StringUtils.hasText(data.getAccountNo())) { if (AccountType.WECHAT.getType().equals(data.getAccountType()) && StringUtils.hasText(data.getAccountNo())) {
WxMaJscode2SessionResult result = wxService.wxJsCode2Session(data.getAccountNo()); WxMaJscode2SessionResult result = wxAuthService.wxJsCode2Session(data.getAccountNo());
ServiceUtil.assertion(result == null, "获取微信信息失败"); ServiceUtil.assertion(result == null, "获取微信信息失败");
data.setAccountNo(result.getOpenid()); data.setAccountNo(result.getOpenid());
} }

View File

@ -2,17 +2,17 @@ package com.ruoyi.web.controller.app;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.annotation.Anonymous; import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.pay.wx.domain.NotifyEventType; import com.ruoyi.common.pay.wx.domain.NotifyEventType;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.http.HttpUtils; import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.ss.payBill.service.PayBillService; import com.ruoyi.ss.payBill.service.PayBillService;
import com.ruoyi.ss.refund.service.RefundService; import com.ruoyi.ss.refund.service.RefundService;
import com.ruoyi.ss.transactionBill.domain.TransactionBill;
import com.ruoyi.ss.transactionBill.service.TransactionBillService; import com.ruoyi.ss.transactionBill.service.TransactionBillService;
import com.ruoyi.ss.wxPay.domain.enums.AttachEnums; import com.ruoyi.common.pay.wx.domain.enums.AttachEnums;
import com.ruoyi.ss.wxPay.service.IWxPayService; import com.ruoyi.common.pay.wx.service.WxPayService;
import com.wechat.pay.java.core.exception.ValidationException; import com.wechat.pay.java.core.exception.ValidationException;
import com.wechat.pay.java.core.notification.Notification; import com.wechat.pay.java.core.notification.Notification;
import com.wechat.pay.java.service.payments.model.Transaction; import com.wechat.pay.java.service.payments.model.Transaction;
@ -38,10 +38,10 @@ import java.util.Date;
@RestController @RestController
@RequestMapping("/app/pay") @RequestMapping("/app/pay")
@Slf4j @Slf4j
public class AppPayController { public class AppPayController extends BaseController {
@Autowired @Autowired
private IWxPayService wxPayService; private WxPayService wxPayService;
@Autowired @Autowired
private TransactionBillService transactionBillService; private TransactionBillService transactionBillService;
@ -52,10 +52,14 @@ public class AppPayController {
@Autowired @Autowired
private PayBillService payBillService; private PayBillService payBillService;
@ApiOperation("微信支付") @ApiOperation("微信支付充值订单")
@GetMapping("/wx/{billNo}") @GetMapping("/wx/{billNo}")
public AjaxResult wxPay(@PathVariable @ApiParam("订单编号") String billNo) { public AjaxResult wxPay(@PathVariable @ApiParam("订单编号") String billNo) {
return AjaxResult.success(wxPayService.prepayWithRequestPayment(billNo)); TransactionBill bill = transactionBillService.selectSmTransactionBillByBillNo(billNo);
if (bill == null || bill.getUserId() == null || !bill.getUserId().equals(getUserId())) {
return error("这不是您的订单");
}
return success(transactionBillService.wxPay(bill));
} }
// 微信支付结果通知 // 微信支付结果通知