feat 支付流程拆分为三类进行分别处理, 更新配置文件

This commit is contained in:
xxm1995
2024-03-22 23:42:08 +08:00
committed by 喵呀
parent 012e08c37a
commit 70e0922073
13 changed files with 254 additions and 245 deletions

View File

@@ -7,13 +7,20 @@
- [ ] 报表功能
- [ ] 各通道收入和支付情况
- [ ] 微信新增V3版本接口
- [ ] 付款码回退到V2接口
- [ ] 付款码支付自动路由到V2接口
- [ ] 增加转账功能
- [ ] 支付宝
- [ ] 微信
- [ ] 云闪付
- [ ] 增加账户余额查询功能
- [ ] 支付宝
- [ ] 微信
- [ ] 云闪付
- [ ] 云闪付支持对账功能
- [x] 结算台DEMO增加云闪付示例
- [ ] 增加支付限额
- [ ] 各通道支持单独的限额
- [ ] 整个订单支持整体的限额
2.0.x 版本内容
- [ ] 统一关闭接口增加使用撤销关闭订单
- [ ] 增加各类日志记录,例如钱包的各项操作

View File

@@ -33,4 +33,7 @@ public class PlatformLocal {
/** 订单支付超时(分钟) */
private Integer orderTimeout;
/** 支付限额 */
private Integer limitAmount;
}

View File

@@ -15,17 +15,17 @@ import org.springframework.stereotype.Service;
public class AliPayTransferService {
private final AliPayConfigService payConfigService;
/**
* 余额查询接口
*/
@SneakyThrows
public void queryAccountAmount() {
AliPayConfig config = payConfigService.getAndCheckConfig();
payConfigService.initConfig(config);
AlipayFundAccountQueryModel model = new AlipayFundAccountQueryModel();
model.setAccountType("ACCTRANS_ACCOUNT");
model.setAlipayUserId(config.getAppId());
model.setAlipayUserId("2088441532699265");
AlipayFundAccountQueryResponse response = AliPayApi.accountQueryToResponse(model, null);
System.out.println(response);
}

View File

@@ -16,6 +16,7 @@ import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
@@ -51,13 +52,13 @@ public class PayChannelOrderService {
/**
* 切换支付订单关联的异步支付通道, 同时会设置是否支付完成状态, 并返回通道订单
* 使用单独事务
*/
@Transactional(rollbackFor = Exception.class)
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public PayChannelOrder switchAsyncPayChannel(PayOrder payOrder, PayChannelParam payChannelParam){
PayLocal payInfo = PaymentContextLocal.get().getPayInfo();
// 是否支付完成
PayStatusEnum payStatus = payInfo.isPayComplete() ? PayStatusEnum.SUCCESS : PayStatusEnum.PROGRESS;
// 判断新发起的
Optional<PayChannelOrder> payOrderChannelOpt = channelOrderManager.findByPaymentIdAndChannel(payOrder.getId(), payChannelParam.getChannel());
// 扩展信息处理
Map<String, Object> channelParam = payChannelParam.getChannelParam();
@@ -91,7 +92,10 @@ public class PayChannelOrderService {
.setChannelExtra(channelParamStr)
.setStatus(payStatus.getCode());
channelOrderManager.updateById(payChannelOrder);
payInfo.getPayChannelOrders().add(payOrderChannelOpt.get());
// 更新时一次请求有多次访问, 对上下文中的通道支付订单进行替换
List<PayChannelOrder> payChannelOrders = payInfo.getPayChannelOrders();
payChannelOrders.removeIf(o->Objects.equals(o.getChannel(),payChannelOrder.getChannel()));
payChannelOrders.add(payOrderChannelOpt.get());
return payChannelOrder;
}
}

View File

@@ -41,6 +41,7 @@ public class PaymentAssistService {
platform.setSignSecret(config.getSignSecret());
platform.setNotifyUrl(config.getNotifyUrl());
platform.setOrderTimeout(config.getOrderTimeout());
platform.setLimitAmount(config.getLimitAmount());
platform.setWebsiteUrl(config.getWebsiteUrl());
}

View File

@@ -1,7 +1,7 @@
package cn.bootx.platform.daxpay.service.core.payment.pay.service;
import cn.bootx.platform.common.core.exception.RepetitiveOperationException;
import cn.bootx.platform.common.core.function.CollectorsFunction;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.exception.pay.PayUnsupportedMethodException;
import cn.bootx.platform.daxpay.param.pay.PayChannelParam;
import cn.bootx.platform.daxpay.param.pay.PayParam;
@@ -10,8 +10,6 @@ import cn.bootx.platform.daxpay.result.pay.PayResult;
import cn.bootx.platform.daxpay.service.common.context.PayLocal;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.order.pay.builder.PayBuilder;
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrderExtra;
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderService;
@@ -34,11 +32,11 @@ import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.Optional;
import java.util.stream.Collectors;
import static cn.bootx.platform.daxpay.code.PayChannelEnum.ASYNC_TYPE;
import static cn.bootx.platform.daxpay.code.PayStatusEnum.SUCCESS;
@@ -57,72 +55,10 @@ public class PayService {
private final PayAssistService payAssistService;
private final PayChannelOrderManager channelOrderManager;
private final ClientNoticeService clientNoticeService;
private final LockTemplate lockTemplate;
/**
* 支付下单接口(同步/异步/组合支付)
* 1. 同步支付:都只会在第一次执行中就完成支付,例如钱包、储值卡都是调用完就进行了扣减,完成了支付记录
* 2. 异步支付:例如支付宝、微信,发起支付后还需要跳转第三方平台进行支付,支付后通常需要进行回调,之后才完成支付记录
* 3. 组合支付:主要是混合了同步支付和异步支付,同时异步支付只能有一个,在支付时先对同步支付进行扣减,然后异步支付回调结束后完成整个支付单
* 注意:
* 组合支付在非第一次支付的时候,只对新传入的异步支付通道进行处理,该通道的价格使用第一次发起的价格,旧的同步支付如果传入后也不做处理,
* 支付单中支付通道列表将会为 旧有的同步支付+新传入的异步支付方式(在具体支付实现中处理)
*
* 订单数据会先进行入库, 才会进行发起支付, 在调用各通道支付之前发生错误, 数据不会入库
*/
@Transactional(rollbackFor = Exception.class)
public PayResult pay(PayParam payParam) {
// 异步支付方式检查
PayUtil.validationAsyncPay(payParam);
String businessNo = payParam.getBusinessNo();
// 加锁
LockInfo lock = lockTemplate.lock("payment:pay:" + businessNo,10000,200);
if (Objects.isNull(lock)){
throw new RepetitiveOperationException("正在支付中,请勿重复支付");
}
try {
// 获取并校验支付订单状态, 如果超时, 触发支付单同步和修复动作
PayOrder payOrder = payAssistService.getOrderAndCheck(payParam.getBusinessNo());
// 初始化上下文
payAssistService.initPayContext(payOrder, payParam);
// 订单为空, 创建支付订单和通道支付订单
if (Objects.isNull(payOrder)){
// 预支付处理, 无论请求成功还是失败, 各种订单对象都会保存
List<AbsPayStrategy> strategies = SpringUtil.getBean(this.getClass()).prePay(payParam);
// 执行首次支付逻辑
return this.onePay(strategies);
} else {
// 分为同步通道全部支付成功和所有支付都是支付中状态(上次支付失败)
return this.towPay(payParam, payOrder);
}
} finally {
lockTemplate.releaseLock(lock);
}
}
/**
* 组合支付分为同步通道全部支付成功和所有支付都是支付中状态(上次支付失败)
* 单通道支付不需要区分上次支付发起是否成功
*/
private PayResult towPay(PayParam payParam, PayOrder payOrder) {
// 判断是否组合支付且同时包含异步支付
if (payOrder.isCombinationPay()&&payOrder.isAsyncPay()) {
// 同步支付通道全部支付成功, 单独走异步支付支付流程
this.onlyAsyncPay(payParam, payOrder);
// 通道订单全部支付中, 相当于上次支付异常, 重新走支付流程
return this.allPay(payParam, payOrder);
} else {
// 单通道支付走标准支付流程
return this.allPay(payParam, payOrder);
}
}
/**
* 简单下单, 可以视为不支持组合支付的下单接口
@@ -144,17 +80,143 @@ public class PayService {
/**
* 支付处理, 无论请求成功还是失败, 各种订单对象都会保存
* 1. 校验参数
* 2. 创建支付订单/通道支付订单/扩展信息
* 3, 返回数据
* 支付入口
* 支付下单接口(同步/异步/组合支付)
* 1. 同步支付:包含一个或多个同步支付通道进行支付
* 2. 异步支付:例如支付宝、微信,发起支付后还需要跳转第三方平台进行支付,支付后通常需要进行回调,之后才完成支付记录
* 3. 组合支付:主要是混合了同步支付和异步支付,同时异步支付只能有一个,在支付时先对同步支付进行扣减,然后异步支付回调结束后完成整个支付单
* 注意:
* 组合支付在非第一次支付的时候,只对新传入的异步支付通道进行处理,该通道的价格使用第一次发起的价格,旧的同步支付如果传入后也不做处理,
* 支付单中支付通道列表将会为 旧有的同步支付+新传入的异步支付方式(在具体支付实现中处理)
*
* 订单数据会先进行入库, 才会进行发起支付, 在调用各通道支付之前发生错误, 数据不会入库
*/
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public List<AbsPayStrategy> prePay(PayParam payParam){
public PayResult pay(PayParam payParam){
// 价格检测
// 异步支付方式检查
PayUtil.validationAsyncPay(payParam);
// 检查支付金额
PayUtil.validationAmount(payParam.getPayChannels());
String businessNo = payParam.getBusinessNo();
// 加锁
LockInfo lock = lockTemplate.lock("payment:pay:" + businessNo,10000,200);
if (Objects.isNull(lock)){
throw new RepetitiveOperationException("正在支付中,请勿重复支付");
}
try {
// 查询并检查订单
PayOrder payOrder = payAssistService.getOrderAndCheck(payParam.getBusinessNo());
// 初始化上下文
payAssistService.initPayContext(payOrder, payParam);
// 走首次下单逻辑还是重复发起逻辑
if (Objects.isNull(payOrder)){
// 判断不同的支付请求类型, 然后走不同的逻辑
List<PayChannelParam> payChannels = payParam.getPayChannels();
// 不包含异步支付通道
if (PayUtil.isNotSync(payChannels)){
return this.firstSyncPay(payParam);
}
// 单个异步通道支付
else if (payChannels.size() == 1 && !PayUtil.isNotSync(payChannels)) {
return this.firstAsyncPay(payParam);
}
// 包含异步通道的组合支付
else if (!PayUtil.isNotSync(payChannels)) {
return this.firstCombinationPay(payParam);
} else {
throw new PayFailureException("支付参数错误");
}
} else {
// 单个异步通道支付
// 包含异步通道的组合支付
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
/**
* 首次同步支付, 可以为一个或多个同步通道进行支付
*/
private PayResult firstSyncPay(PayParam payParam){
// 创建支付订单和扩展记录并返回支付订单对象
PayOrder payOrder = payAssistService.createPayOrder(payParam);
PayLocal payInfo = PaymentContextLocal.get().getPayInfo();
// 获取支付方式,通过工厂生成对应的策略组
List<AbsPayStrategy> strategies = PayStrategyFactory.createAsyncLast(payParam.getPayChannels());
if (CollectionUtil.isEmpty(strategies)) {
throw new PayUnsupportedMethodException();
}
// 初始化支付参数
for (AbsPayStrategy strategy : strategies) {
strategy.initPayParam(payOrder, payParam);
}
// 执行支付前处理动作
strategies.forEach(AbsPayStrategy::doBeforePayHandler);
// 生成支付通道订单
strategies.forEach(AbsPayStrategy::generateChannelOrder);
// 支付操作
strategies.forEach(AbsPayStrategy::doPayHandler);
// 支付成功操作, 进行扣款、创建记录类类似的操作
strategies.forEach(AbsPayStrategy::doSuccessHandler);
payOrder.setStatus(SUCCESS.getCode())
.setPayTime(LocalDateTime.now());
// 保存通道支付订单
payAssistService.savePayChannelOrder(strategies);
// 更新订单信息
payOrderService.updateById(payOrder);
// 支付完成 发送通知
clientNoticeService.registerPayNotice(payOrder, payInfo.getPayOrderExtra(), payInfo.getPayChannelOrders());
return PayBuilder.buildPayResultByPayOrder(payOrder);
}
/**
* 首次单个异步通道支付
*/
private PayResult firstAsyncPay(PayParam payParam){
PayLocal payInfo = PaymentContextLocal.get().getPayInfo();
// 开启新事务执行订单预保存操作, 并返回对应的支付策略组
AbsPayStrategy asyncPayStrategy = SpringUtil.getBean(this.getClass()).asyncPayPreSave(payParam);
// 支付操作
try {
asyncPayStrategy.doPayHandler();
} catch (Exception e) {
// 记录错误原因
PayOrderExtra payOrderExtra = payInfo.getPayOrderExtra();
payOrderExtra.setErrorMsg(e.getMessage());
throw e;
}
// 支付调用成功操作,
asyncPayStrategy.doSuccessHandler();
PayOrder payOrder = payInfo.getPayOrder();
// 如果支付完成, 进行订单完成处理, 同时发送回调消息
if (payInfo.isPayComplete()) {
payOrder.setGatewayOrderNo(payInfo.getGatewayOrderNo())
.setStatus(SUCCESS.getCode())
.setPayTime(LocalDateTime.now());
// TODO 使用网关返回的时间
payOrderService.updateById(payOrder);
}
// 如果支付完成 发送通知
if (Objects.equals(payOrder.getStatus(), SUCCESS.getCode())){
clientNoticeService.registerPayNotice(payOrder, payInfo.getPayOrderExtra(), payInfo.getPayChannelOrders());
}
return PayBuilder.buildPayResultByPayOrder(payOrder);
}
/**
* 首次组合支付, 包含异步支付通道
*/
private PayResult firstCombinationPay(PayParam payParam){
PayLocal payInfo = PaymentContextLocal.get().getPayInfo();
// 创建支付订单和扩展记录并返回支付订单对象
PayOrder payOrder = payAssistService.createPayOrder(payParam);
@@ -168,179 +230,106 @@ public class PayService {
strategy.initPayParam(payOrder, payParam);
}
// 执行支付前处理动作
strategies.forEach(AbsPayStrategy::doBeforePayHandler);
// 执行通道支付通道订单的生成
strategies.forEach(AbsPayStrategy::generateChannelOrder);
// 取出同步通道 然后进行支付
List<AbsPayStrategy> syncStrategies = strategies.stream()
.filter(strategy -> !ASYNC_TYPE.contains(strategy.getChannel()))
.collect(Collectors.toList());
// 初始化支付参数
for (AbsPayStrategy strategy : syncStrategies) {
strategy.initPayParam(payOrder, payParam);
}
// 执行支付前处理动作
syncStrategies.forEach(AbsPayStrategy::doBeforePayHandler);
// 生成支付通道订单
syncStrategies.forEach(AbsPayStrategy::generateChannelOrder);
// 支付操作
syncStrategies.forEach(AbsPayStrategy::doPayHandler);
// 支付成功操作, 进行扣款、创建记录类类似的操作
syncStrategies.forEach(AbsPayStrategy::doSuccessHandler);
payOrder.setStatus(SUCCESS.getCode())
.setPayTime(LocalDateTime.now());
// 保存通道支付订单
payAssistService.savePayChannelOrder(strategies);
return strategies;
}
// ------------------------- 进行异步支付 -------------------------------
// 筛选出异步通道策略类
AbsPayStrategy asyncPayStrategy = strategies.stream()
.filter(strategy -> !ASYNC_TYPE.contains(strategy.getChannel()))
.findFirst()
.orElseThrow(() -> new PayFailureException("数据和代码异常, 请排查代码"));
/**
* 发起的第一次支付请求(同步/异步)
*/
private PayResult firstPay(PayParam payParam, PayOrder payOrder) {
// 2. 价格检测
PayUtil.validationAmount(payParam.getPayChannels());
// 3. 创建支付订单和扩展记录并返回支付订单对象
payOrder = payAssistService.createPayOrder(payParam);
// 4. 调用支付方法进行发起支付
this.allPay(payParam, payOrder);
// 5. 返回支付结果
return PayBuilder.buildPayResultByPayOrder(payOrder);
}
/**
* 执行首次支付操作
*/
public PayResult onePay(List<AbsPayStrategy> strategies){
PayLocal payInfo = PaymentContextLocal.get().getPayInfo();
// 支付操作
// 支付前准备
asyncPayStrategy.doBeforePayHandler();
// 设置异步支付通道订单信息
asyncPayStrategy.generateChannelOrder();
try {
strategies.forEach(AbsPayStrategy::doPayHandler);
// 异步支付操作
asyncPayStrategy.doPayHandler();
} catch (Exception e) {
// 记录错误原因
PayOrderExtra payOrderExtra = payInfo.getPayOrderExtra();
payOrderExtra.setErrorMsg(e.getMessage());
throw e;
}
PayOrder payOrder = payInfo.getPayOrder();
// 支付调用成功操作, 进行扣款、创建记录类类似的操作
strategies.forEach(AbsPayStrategy::doSuccessHandler);
// 如果没有异步支付, 直接进行订单完成处理
if (!payOrder.isAsyncPay()) {
// 修改支付订单状态为成功
payOrder.setStatus(SUCCESS.getCode())
.setPayTime(LocalDateTime.now());
payOrderService.updateById(payOrder);
}
// 如果异步支付完成, 进行订单完成处理, 同时发送回调消息
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
if (asyncPayInfo.isPayComplete()) {
payOrder.setGatewayOrderNo(asyncPayInfo.getGatewayOrderNo())
asyncPayStrategy.doSuccessHandler();
// 如果支付完成, 进行订单完成处理, 同时发送回调消息
if (payInfo.isPayComplete()) {
payOrder.setGatewayOrderNo(payInfo.getGatewayOrderNo())
.setStatus(SUCCESS.getCode())
.setPayTime(LocalDateTime.now());
// TODO 使用网关返回的时间
payOrderService.updateById(payOrder);
}
// 如果支付完成 发送通知
if (Objects.equals(payOrder.getStatus(), SUCCESS.getCode())){
clientNoticeService.registerPayNotice(payOrder, payInfo.getPayOrderExtra(), payInfo.getPayChannelOrders());
}
// 组装返回参数
return PayBuilder.buildPayResultByPayOrder(payOrder);
}
/**
* 执行所有的支付方法
* 异步支付预报保存处理, 无论请求成功还是失败, 各种订单对象都会保存
* 1. 创建支付订单/通道支付订单/扩展信息
* 2, 返回支付列表记录
*/
private PayResult allPay(PayParam payParam, PayOrder payOrder) {
PayLocal payInfo = PaymentContextLocal.get().getPayInfo();
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public AbsPayStrategy asyncPayPreSave(PayParam payParam){
// 创建支付订单和扩展记录并返回支付订单对象
PayOrder payOrder = payAssistService.createPayOrder(payParam);
// 获取支付方式,通过工厂生成对应的策略组
List<AbsPayStrategy> strategies = PayStrategyFactory.createAsyncLast(payParam.getPayChannels());
if (CollectionUtil.isEmpty(strategies)) {
throw new PayUnsupportedMethodException();
}
// 查询通道支付订单
List<PayChannelOrder> orders = channelOrderManager.findAllByPaymentId(payOrder.getId());
Map<String, PayChannelOrder> channelOrderMap = orders.stream()
.collect(Collectors.toMap(PayChannelOrder::getChannel, Function.identity(), CollectorsFunction::retainFirst));
// 初始化支付参数
for (AbsPayStrategy strategy : strategies) {
strategy.initPayParam(payOrder, payParam);
strategy.setChannelOrder(channelOrderMap.get(strategy.getChannel().getCode()));
}
AbsPayStrategy absPayStrategy = Optional.ofNullable(strategies.get(0))
.orElseThrow(() -> new PayFailureException("数据和代码异常, 请排查代码"));
// 初始化支付的参数
absPayStrategy.initPayParam(payOrder, payParam);
// 执行支付前处理动作
strategies.forEach(AbsPayStrategy::doBeforePayHandler);
// 支付操作
try {
strategies.forEach(AbsPayStrategy::doPayHandler);
} catch (Exception e) {
// 记录错误原因
PayOrderExtra payOrderExtra = payInfo.getPayOrderExtra();
payOrderExtra.setErrorMsg(e.getMessage());
throw e;
}
// 支付调用成功操作, 进行扣款、创建记录类类似的操作
strategies.forEach(AbsPayStrategy::doSuccessHandler);
// 如果没有异步支付, 直接进行订单完成处理
if (PayUtil.isNotSync(payParam.getPayChannels())) {
// 修改支付订单状态为成功
payOrder.setStatus(SUCCESS.getCode())
.setPayTime(LocalDateTime.now());
payOrderService.updateById(payOrder);
}
// 如果异步支付完成, 进行订单完成处理, 同时发送回调消息
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
if (asyncPayInfo.isPayComplete()) {
payOrder.setGatewayOrderNo(asyncPayInfo.getGatewayOrderNo())
.setStatus(SUCCESS.getCode())
.setPayTime(LocalDateTime.now());
payOrderService.updateById(payOrder);
}
// 如果支付完成 发送通知
if (Objects.equals(payOrder.getStatus(), SUCCESS.getCode())){
clientNoticeService.registerPayNotice(payOrder, payInfo.getPayOrderExtra(), payInfo.getPayChannelOrders());
}
return PayBuilder.buildPayResultByPayOrder(payOrder);
absPayStrategy.doBeforePayHandler();
// 执行支付通道订单的生成和保存
absPayStrategy.generateChannelOrder();
return absPayStrategy;
}
/**
* 异步支付执行(非第一次请求), 只执行异步支付策略, 因为同步支付已经支付成功. 报错不影响继续发起支付
* 重复支付
*/
private PayResult onlyAsyncPay(PayParam payParam, PayOrder payOrder) {
public void repeatAsyncPay(){
// 2.获取 异步支付通道,通过工厂生成对应的策略组(只包含异步支付的策略, 同步支付已经成功不再继续执行)
PayChannelParam payChannelParam = payAssistService.getAsyncPayParam(payParam, payOrder);
List<AbsPayStrategy> payStrategyList = PayStrategyFactory.createAsyncLast(Collections.singletonList(payChannelParam));
}
// 3.初始化支付的参数
for (AbsPayStrategy payStrategy : payStrategyList) {
payStrategy.initPayParam(payOrder, payParam);
}
// 4.支付前准备
payStrategyList.forEach(AbsPayStrategy::doBeforePayHandler);
/**
*
*/
public void repeatCombinationPay(){
// 5.1发起支付
payStrategyList.forEach(AbsPayStrategy::doPayHandler);
// 5.2支付发起成功处理
payStrategyList.forEach(AbsPayStrategy::doSuccessHandler);
// 6.1 如果异步支付完成, 进行订单完成处理
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
if (asyncPayInfo.isPayComplete()) {
payOrder.setGatewayOrderNo(asyncPayInfo.getGatewayOrderNo())
.setStatus(SUCCESS.getCode())
.setPayTime(LocalDateTime.now());
}
// 6.2 更新支付订单和扩展参数
payOrderService.updateById(payOrder);
PayOrderExtra payOrderExtra = payAssistService.updatePayOrderExtra(payParam, payOrder.getId());
// 订单完成, 触发通知
if (Objects.equals(payOrder.getStatus(), SUCCESS.getCode())) {
clientNoticeService.registerPayNotice(payOrder, payOrderExtra,null);
}
// 7. 组装返回参数
return PayBuilder.buildPayResultByPayOrder(payOrder);
}
}

View File

@@ -95,7 +95,8 @@ public class AliPayStrategy extends AbsPayStrategy {
*/
@Override
public void generateChannelOrder() {
super.generateChannelOrder();
// 创建或切换支付通道订单
channelOrderService.switchAsyncPayChannel(this.getOrder(), this.getPayChannelParam());
}
/**
@@ -104,6 +105,7 @@ public class AliPayStrategy extends AbsPayStrategy {
@Override
public void doSuccessHandler() {
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
// 更新通道支付订单
PayChannelOrder payChannelOrder = channelOrderService.switchAsyncPayChannel(this.getOrder(), this.getPayChannelParam());
// 支付完成, 保存记录
if (asyncPayInfo.isPayComplete()) {

View File

@@ -98,7 +98,8 @@ public class UnionPayStrategy extends AbsPayStrategy {
*/
@Override
public void generateChannelOrder() {
super.generateChannelOrder();
// 创建或切换支付通道订单
channelOrderService.switchAsyncPayChannel(this.getOrder(), this.getPayChannelParam());
}
/**
@@ -107,6 +108,7 @@ public class UnionPayStrategy extends AbsPayStrategy {
@Override
public void doSuccessHandler() {
PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();
// 更新支付通道信息
PayChannelOrder payChannelOrder = channelOrderService.switchAsyncPayChannel(this.getOrder(), this.getPayChannelParam());
// 支付完成, 保存记录
if (asyncPayInfo.isPayComplete()) {

View File

@@ -78,6 +78,16 @@ public class WeChatPayStrategy extends AbsPayStrategy {
weChatPayService.validation(this.getPayChannelParam(), weChatPayConfig);
}
/**
* 不使用默认的生成通道支付单方法, 异步支付通道的支付订单自己管理
*/
@Override
public void generateChannelOrder() {
// 创建或切换支付通道订单
channelOrderService.switchAsyncPayChannel(this.getOrder(), this.getPayChannelParam());
}
/**
* 发起支付
*/
@@ -100,14 +110,6 @@ public class WeChatPayStrategy extends AbsPayStrategy {
}
}
/**
* 不使用默认的生成通道支付单方法, 异步支付通道的支付订单自己管理
*/
@Override
public void generateChannelOrder() {
super.generateChannelOrder();
}
/**
* 初始化微信支付
*/

View File

@@ -39,9 +39,12 @@ public class PlatformConfig extends MpBaseEntity implements EntityBaseFunction<P
@DbColumn(comment = "支付通知地址")
private String notifyUrl;
@DbColumn(comment = "同步支付通知地址")
@DbColumn(comment = "同步支付跳转地址")
private String returnUrl;
@DbColumn(comment = "支付限额")
private Integer limitAmount;
@DbColumn(comment = "订单默认超时时间(分钟)")
private Integer orderTimeout;

View File

@@ -44,11 +44,21 @@ public abstract class AbsPayStrategy implements PayStrategy{
}
/**
* 支付前处理 包含必要的校验以及对当前通道支付订单的创建和保存操作
* 支付前处理 包含必要的校验以及对当前通道支付配置信息的初始化
*/
public void doBeforePayHandler() {
}
/**
* 生成通道支付单, 如果不需要可以进行覆盖
* 异步支付通道都进行了重新, 通道支付单由自己控制
*/
public void generateChannelOrder() {
PayChannelOrder payChannelOrder = PayBuilder.buildPayChannelOrder(this.getPayChannelParam());
payChannelOrder.setPaymentId(this.getOrder().getId());
this.channelOrder = payChannelOrder;
}
/**
* 支付操作
*/
@@ -61,12 +71,4 @@ public abstract class AbsPayStrategy implements PayStrategy{
this.channelOrder.setStatus(PayStatusEnum.SUCCESS.getCode()).setPayTime(LocalDateTime.now());
}
/**
* 生成通道支付单, 如果不需要可以进行覆盖
*/
public void generateChannelOrder() {
PayChannelOrder payChannelOrder = PayBuilder.buildPayChannelOrder(this.getPayChannelParam());
payChannelOrder.setPaymentId(this.getOrder().getId());
this.channelOrder = payChannelOrder;
}
}

View File

@@ -40,12 +40,6 @@
<artifactId>daxpay-single-demo</artifactId>
<version>${daxpay.version}</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-spring-boot-starter</artifactId>
<version>4.4.0</version>
</dependency>
</dependencies>
<build>

View File

@@ -156,17 +156,17 @@ dromara:
# 支付系统配置
dax-pay:
# 服务地址
server-url: http://pay1.bootx.cn
server-url: http://localhost:9000
# 前端h5地址
front-h5-url: http://pay1.bootx.cn/h5/#
front-h5-url: http://localhost:5173/#
# 前端web地址
front-web-url: http://pay1.bootx.cn/#
front-web-url: http://localhost:9000/#
# 演示模块
demo:
# 网关地址
server-url: http://pay1.bootx.cn/server
server-url: http://localhost:9000/server
# 前端h5地址
front-h5-url: http://pay1.bootx.cn/h5/#
front-h5-url: http://localhost:5173/#
# 签名秘钥
sign-secret: 123456
# 签名方式