mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-09-03 11:06:46 +00:00
feat 各种分账各种问题解决和优化
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cn.daxpay.single</groupId>
|
||||
<artifactId>daxpay-single</artifactId>
|
||||
<version>2.0.6</version>
|
||||
<version>2.0.7</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>daxpay-single-admin</artifactId>
|
||||
|
@@ -95,7 +95,7 @@ public class AllocationOrderController {
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@InitPaymentContext(PaymentApiCode.SYNC_REFUND)
|
||||
@InitPaymentContext(PaymentApiCode.ALLOCATION_FINISH)
|
||||
@Operation(summary = "分账完结")
|
||||
@PostMapping("/finish")
|
||||
public ResResult<Void> finish(String allocationNo){
|
||||
|
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cn.daxpay.single</groupId>
|
||||
<artifactId>daxpay-single</artifactId>
|
||||
<version>2.0.6</version>
|
||||
<version>2.0.7</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>daxpay-single-core</artifactId>
|
||||
|
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cn.daxpay.single</groupId>
|
||||
<artifactId>daxpay-single</artifactId>
|
||||
<version>2.0.6</version>
|
||||
<version>2.0.7</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>daxpay-single-gateway</artifactId>
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package cn.daxpay.single.gateway.controller;
|
||||
|
||||
import cn.bootx.platform.common.core.annotation.IgnoreAuth;
|
||||
import cn.daxpay.single.service.core.channel.alipay.service.AliPayNoticeReceiverService;
|
||||
import com.ijpay.alipay.AliPayApi;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -15,33 +16,29 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 网关消息通知
|
||||
* 支付通道消息通知
|
||||
* @author xxm
|
||||
* @since 2024/4/16
|
||||
*/
|
||||
@IgnoreAuth
|
||||
@Tag(name = "三方支付网关消息通知")
|
||||
@Tag(name = "执法通道网关消息通知")
|
||||
@RestController
|
||||
@RequestMapping("/gateway/notice")
|
||||
@RequestMapping("/callback/notice")
|
||||
@RequiredArgsConstructor
|
||||
public class PayNoticeReceiverController {
|
||||
|
||||
private final AliPayNoticeReceiverService aliPayNoticeReceiverService;
|
||||
|
||||
@Operation(summary = "支付宝消息通知")
|
||||
@PostMapping("/alipay")
|
||||
public String aliPayNotice(HttpServletRequest request) {
|
||||
Map<String, String> map = AliPayApi.toMap(request);
|
||||
// 通过 msg_method 获取消息类型
|
||||
String msgMethod = map.get("msg_method");
|
||||
// 通过 biz_content 获取值
|
||||
String bizContent = map.get("biz_content");
|
||||
|
||||
return "success";
|
||||
return aliPayNoticeReceiverService.noticeReceiver(map);
|
||||
}
|
||||
|
||||
@Operation(summary = "微信消息通知")
|
||||
@PostMapping("/wechat")
|
||||
public Map<String, Objects> wechatPayNotice() {
|
||||
public Map<String, Objects> wechatPayNotice(HttpServletRequest request) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cn.daxpay.single</groupId>
|
||||
<artifactId>daxpay-single</artifactId>
|
||||
<version>2.0.6</version>
|
||||
<version>2.0.7</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>daxpay-single-service</artifactId>
|
||||
|
@@ -113,7 +113,7 @@ public interface AliPayCode {
|
||||
String ALLOC_FAIL = "FAIL";
|
||||
|
||||
/** 异步分账 */
|
||||
String ALLOC_ASYNC = "ASYNC";
|
||||
String ALLOC_ASYNC = "async";
|
||||
/** 同步分账 */
|
||||
String ALLOC_SYNC = "SYNC";
|
||||
String ALLOC_SYNC = "sync";
|
||||
}
|
||||
|
@@ -49,7 +49,7 @@ public class AliPayAllocationService {
|
||||
public void allocation(AllocationOrder allocationOrder, List<AllocationOrderDetail> orderDetails){
|
||||
// 分账主体参数
|
||||
AlipayTradeOrderSettleModel model = new AlipayTradeOrderSettleModel();
|
||||
model.setOutRequestNo(allocationOrder.getOrderNo());
|
||||
model.setOutRequestNo(allocationOrder.getAllocationNo());
|
||||
model.setTradeNo(allocationOrder.getOutOrderNo());
|
||||
model.setRoyaltyMode(AliPayCode.ALLOC_ASYNC);
|
||||
|
||||
@@ -79,12 +79,12 @@ public class AliPayAllocationService {
|
||||
public void finish(AllocationOrder allocationOrder, List<AllocationOrderDetail> orderDetails ){
|
||||
// 分账主体参数
|
||||
AlipayTradeOrderSettleModel model = new AlipayTradeOrderSettleModel();
|
||||
model.setOutRequestNo(String.valueOf(allocationOrder.getOrderNo()));
|
||||
model.setOutRequestNo(String.valueOf(allocationOrder.getAllocationNo()));
|
||||
model.setTradeNo(allocationOrder.getOutOrderNo());
|
||||
model.setRoyaltyMode(AliPayCode.ALLOC_ASYNC);
|
||||
// 分账完结参数
|
||||
SettleExtendParams extendParams = new SettleExtendParams();
|
||||
extendParams.setRoyaltyFinish("true");
|
||||
extendParams.setRoyaltyFinish(Boolean.TRUE.toString());
|
||||
model.setExtendParams(extendParams);
|
||||
|
||||
// 分账子参数 根据Id排序
|
||||
@@ -109,7 +109,7 @@ public class AliPayAllocationService {
|
||||
public AllocRemoteSyncResult sync(AllocationOrder allocationOrder, List<AllocationOrderDetail> allocationOrderDetails){
|
||||
AlipayTradeOrderSettleQueryModel model = new AlipayTradeOrderSettleQueryModel();
|
||||
model.setTradeNo(allocationOrder.getOutOrderNo());
|
||||
model.setOutRequestNo(allocationOrder.getOrderNo());
|
||||
model.setOutRequestNo(allocationOrder.getAllocationNo());
|
||||
AlipayTradeOrderSettleQueryRequest request = new AlipayTradeOrderSettleQueryRequest();
|
||||
request.setBizModel(model);
|
||||
AlipayTradeOrderSettleQueryResponse response = AliPayApi.execute(request);
|
||||
|
@@ -0,0 +1,95 @@
|
||||
package cn.daxpay.single.service.core.channel.alipay.service;
|
||||
|
||||
import cn.bootx.platform.common.core.util.CertUtil;
|
||||
import cn.daxpay.single.service.core.channel.alipay.entity.AliPayConfig;
|
||||
import cn.daxpay.single.service.core.payment.allocation.service.AllocationCallbackService;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.AlipayConstants;
|
||||
import com.alipay.api.internal.util.AlipaySignature;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static cn.daxpay.single.service.code.AliPayCode.APP_ID;
|
||||
import static cn.daxpay.single.service.code.AliPayCode.AUTH_TYPE_KEY;
|
||||
|
||||
/**
|
||||
* 支付宝通知消息接收
|
||||
* @author xxm
|
||||
* @since 2024/5/31
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AliPayNoticeReceiverService {
|
||||
|
||||
private final AllocationCallbackService allocationCallbackService;
|
||||
|
||||
private final AliPayConfigService aliPayConfigService;
|
||||
|
||||
/**
|
||||
* 消息通知处理
|
||||
*/
|
||||
public String noticeReceiver(Map<String, String> map) {
|
||||
|
||||
// 首先进行验签
|
||||
if (!this.verifyNotify(map)){
|
||||
log.error("支付宝消息通知验签失败");
|
||||
return "fail";
|
||||
}
|
||||
|
||||
// 通过 msg_method 获取消息类型
|
||||
String msgMethod = map.get("msg_method");
|
||||
// 通过 biz_content 获取值
|
||||
String bizContent = map.get("biz_content");
|
||||
|
||||
// 分账结果通知
|
||||
if ("alipay.trade.order.settle.notify".equals(msgMethod)) {
|
||||
// 转换成对象
|
||||
|
||||
// 获取分账号
|
||||
|
||||
// 调用统一分账回调处理
|
||||
|
||||
// 分账完成
|
||||
|
||||
}
|
||||
// 返回处理成功
|
||||
return "success";
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验消息通知
|
||||
*/
|
||||
private boolean verifyNotify(Map<String, String> params) {
|
||||
String callReq = JSONUtil.toJsonStr(params);
|
||||
log.info("支付宝消息通知报文: {}", callReq);
|
||||
String appId = params.get(APP_ID);
|
||||
if (StrUtil.isBlank(appId)) {
|
||||
log.error("支付宝消息通知报文appId为空");
|
||||
return false;
|
||||
}
|
||||
AliPayConfig alipayConfig = aliPayConfigService.getConfig();
|
||||
if (Objects.isNull(alipayConfig)) {
|
||||
log.error("支付宝支付配置不存在");
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if (Objects.equals(alipayConfig.getAuthType(), AUTH_TYPE_KEY)) {
|
||||
return AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), CharsetUtil.UTF_8, AlipayConstants.SIGN_TYPE_RSA2);
|
||||
}
|
||||
else {
|
||||
return AlipaySignature.verifyV1(params, CertUtil.getCertByContent(alipayConfig.getAlipayCert()), CharsetUtil.UTF_8, AlipayConstants.SIGN_TYPE_RSA2);
|
||||
}
|
||||
} catch (AlipayApiException e) {
|
||||
log.error("支付宝验签失败", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -21,6 +21,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.daxpay.single.code.AllocReceiverTypeEnum.WX_MERCHANT;
|
||||
import static cn.daxpay.single.code.AllocReceiverTypeEnum.WX_PERSONAL;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -36,7 +37,7 @@ public class WeChatPayAllocationReceiverService {
|
||||
* 校验参数是否合法
|
||||
*/
|
||||
public boolean validation(AllocationReceiver allocationReceiver){
|
||||
List<String> list = Arrays.asList(WX_MERCHANT.getCode(), WX_MERCHANT.getCode());
|
||||
List<String> list = Arrays.asList(WX_PERSONAL.getCode(), WX_MERCHANT.getCode());
|
||||
String receiverType = allocationReceiver.getReceiverType();
|
||||
return list.contains(receiverType);
|
||||
}
|
||||
|
@@ -75,7 +75,7 @@ public class WeChatPayAllocationService {
|
||||
.appid(config.getWxAppId())
|
||||
.nonce_str(WxPayKit.generateStr())
|
||||
.transaction_id(allocationOrder.getOutOrderNo())
|
||||
.out_order_no(allocationOrder.getOrderNo())
|
||||
.out_order_no(allocationOrder.getAllocationNo())
|
||||
.receivers(JSON.toJSONString(list))
|
||||
.build()
|
||||
.createSign(config.getApiKeyV2(), SignType.HMACSHA256);
|
||||
@@ -96,8 +96,9 @@ public class WeChatPayAllocationService {
|
||||
.appid(config.getWxAppId())
|
||||
.nonce_str(WxPayKit.generateStr())
|
||||
.transaction_id(allocationOrder.getOutOrderNo())
|
||||
.out_order_no(allocationOrder.getOrderNo())
|
||||
.description("分账完成")
|
||||
// 分账要使用单独的的流水号, 不能与分账号相同
|
||||
.out_order_no(allocationOrder.getAllocationNo()+'F')
|
||||
.description("分账已完成")
|
||||
.build()
|
||||
.createSign(config.getApiKeyV2(), SignType.HMACSHA256);
|
||||
|
||||
@@ -117,7 +118,7 @@ public class WeChatPayAllocationService {
|
||||
.mch_id(config.getWxMchId())
|
||||
.nonce_str(WxPayKit.generateStr())
|
||||
.transaction_id(allocationOrder.getOutOrderNo())
|
||||
.out_order_no(allocationOrder.getOrderNo())
|
||||
.out_order_no(allocationOrder.getAllocationNo())
|
||||
.build()
|
||||
.createSign(config.getApiKeyV2(), SignType.HMACSHA256);
|
||||
String xmlResult = WxPayApi.profitSharingQuery(params);
|
||||
|
@@ -0,0 +1,24 @@
|
||||
package cn.daxpay.single.service.core.payment.allocation.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 分账回调处理
|
||||
* @author xxm
|
||||
* @since 2024/5/31
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AllocationCallbackService {
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void callback(String allocationNo){
|
||||
|
||||
}
|
||||
}
|
@@ -3,6 +3,7 @@ package cn.daxpay.single.service.core.payment.allocation.service;
|
||||
import cn.bootx.platform.common.core.exception.DataNotExistException;
|
||||
import cn.bootx.platform.common.core.exception.RepetitiveOperationException;
|
||||
import cn.bootx.platform.common.core.util.CollUtil;
|
||||
import cn.daxpay.single.code.AllocDetailResultEnum;
|
||||
import cn.daxpay.single.code.AllocOrderStatusEnum;
|
||||
import cn.daxpay.single.code.PayOrderAllocStatusEnum;
|
||||
import cn.daxpay.single.exception.pay.PayFailureException;
|
||||
@@ -35,11 +36,15 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.daxpay.single.code.AllocOrderStatusEnum.ALLOCATION_END;
|
||||
import static cn.daxpay.single.code.AllocOrderStatusEnum.FINISH_FAILED;
|
||||
|
||||
/**
|
||||
* 分账服务
|
||||
* @author xxm
|
||||
@@ -151,13 +156,13 @@ public class AllocationService {
|
||||
}
|
||||
try {
|
||||
// 需要是分账中分账中或者完成状态才能重新分账
|
||||
List<String> list = Arrays.asList(AllocOrderStatusEnum.ALLOCATION_END.getCode(),
|
||||
List<String> list = Arrays.asList(ALLOCATION_END.getCode(),
|
||||
AllocOrderStatusEnum.ALLOCATION_FAILED.getCode(),
|
||||
AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode());
|
||||
if (!list.contains(order.getStatus())){
|
||||
throw new PayFailureException("分账单状态错误,无法重试");
|
||||
}
|
||||
List<AllocationOrderDetail> details = allocationOrderDetailManager.findAllByOrderId(order.getId());
|
||||
List<AllocationOrderDetail> details = this.getDetails(order.getId());
|
||||
// 创建分账策略并初始化
|
||||
AbsAllocationStrategy allocationStrategy = AllocationFactory.create(order.getChannel());
|
||||
allocationStrategy.initParam(order, details);
|
||||
@@ -209,10 +214,11 @@ public class AllocationService {
|
||||
*/
|
||||
public AllocationResult finish(AllocationOrder allocationOrder) {
|
||||
// 只有分账结束后才可以完结
|
||||
if (!AllocOrderStatusEnum.ALLOCATION_END.getCode().equals(allocationOrder.getStatus())){
|
||||
if (!Arrays.asList(ALLOCATION_END.getCode(),FINISH_FAILED.getCode()).contains(allocationOrder.getStatus())) {
|
||||
throw new PayFailureException("分账单状态错误");
|
||||
}
|
||||
List<AllocationOrderDetail> details = allocationOrderDetailManager.findAllByOrderId(allocationOrder.getId());
|
||||
List<AllocationOrderDetail> details = this.getDetails(allocationOrder.getId());
|
||||
|
||||
// 创建分账策略并初始化
|
||||
AbsAllocationStrategy allocationStrategy = AllocationFactory.create(allocationOrder.getChannel());
|
||||
allocationStrategy.initParam(allocationOrder, details);
|
||||
@@ -224,11 +230,12 @@ public class AllocationService {
|
||||
allocationStrategy.finish();
|
||||
// 完结状态
|
||||
allocationOrder.setStatus(AllocOrderStatusEnum.FINISH.getCode())
|
||||
.setFinishTime(LocalDateTime.now())
|
||||
.setErrorMsg(null);
|
||||
} catch (Exception e) {
|
||||
log.error("分账完结错误:", e);
|
||||
// 失败
|
||||
allocationOrder.setStatus(AllocOrderStatusEnum.FINISH_FAILED.getCode())
|
||||
allocationOrder.setStatus(FINISH_FAILED.getCode())
|
||||
.setErrorMsg(e.getMessage());
|
||||
}
|
||||
allocationOrderManager.updateById(allocationOrder);
|
||||
@@ -293,4 +300,15 @@ public class AllocationService {
|
||||
}
|
||||
return orderAndDetail;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取发起分账或完结的明细
|
||||
*/
|
||||
private List<AllocationOrderDetail> getDetails(Long allocOrderId){
|
||||
List<AllocationOrderDetail> details = allocationOrderDetailManager.findAllByOrderId(allocOrderId);
|
||||
// 过滤掉忽略的条目
|
||||
return details.stream()
|
||||
.filter(detail -> !Objects.equals(detail.getResult(), AllocDetailResultEnum.IGNORE.getCode()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@
|
||||
<groupId>cn.daxpay.single</groupId>
|
||||
<artifactId>daxpay-single</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>2.0.6</version>
|
||||
<version>2.0.7</version>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<!-- 二方库版本 -->
|
||||
<bootx-platform.version>1.3.6.2</bootx-platform.version>
|
||||
<daxpay.version>2.0.6</daxpay.version>
|
||||
<daxpay.version>2.0.7</daxpay.version>
|
||||
<!-- 三方库 -->
|
||||
<slf4j.version>1.7.30</slf4j.version>
|
||||
<redisson.version>3.16.8</redisson.version>
|
||||
|
Reference in New Issue
Block a user