mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-10-13 21:30:25 +00:00
feat(payment): 添加分账功能并优化相关服务
- 新增分账功能,支持支付宝和微信支付的分账操作 - 重构支付宝支付流程,使用新的SDK- 更新微信支付示例,调整相关参数 - 优化收银台配置和支付订单相关服务- 调整分账比例的验证规则,支持更灵活的比例设置
This commit is contained in:
43
README.md
43
README.md
@@ -76,25 +76,32 @@
|
||||
```xml
|
||||
<!-- 支付SDK -->
|
||||
<dependency>
|
||||
<groupId>cn.daxpay.single</groupId>
|
||||
<groupId>org.dromara.daxpay</groupId>
|
||||
<artifactId>daxpay-single-sdk</artifactId>
|
||||
<version>${latest.version}</version>
|
||||
</dependency>
|
||||
```
|
||||
### SDK调用示例
|
||||
```java
|
||||
package org.dromara.daxpay.test;
|
||||
package org.dromara.daxpay.single.sdk.test.trade;
|
||||
|
||||
import cn.daxpay.single.sdk.code.SignTypeEnum;
|
||||
import cn.daxpay.single.sdk.model.trade.pay.PayOrderModel;
|
||||
import cn.daxpay.single.sdk.net.DaxPayConfig;
|
||||
import cn.daxpay.single.sdk.net.DaxPayKit;
|
||||
import cn.daxpay.single.sdk.param.trade.pay.PayQueryParam;
|
||||
import cn.daxpay.single.sdk.response.DaxPayResult;
|
||||
import cn.daxpay.single.sdk.util.JsonUtil;
|
||||
import org.dromara.daxpay.single.sdk.code.ChannelEnum;
|
||||
import org.dromara.daxpay.single.sdk.code.PayMethodEnum;
|
||||
import org.dromara.daxpay.single.sdk.code.SignTypeEnum;
|
||||
import org.dromara.daxpay.single.sdk.model.trade.pay.PayResultModel;
|
||||
import org.dromara.daxpay.single.sdk.net.DaxPayConfig;
|
||||
import org.dromara.daxpay.single.sdk.net.DaxPayKit;
|
||||
import org.dromara.daxpay.single.sdk.param.channel.AlipayParam;
|
||||
import org.dromara.daxpay.single.sdk.param.channel.WechatPayParam;
|
||||
import org.dromara.daxpay.single.sdk.param.trade.pay.PayParam;
|
||||
import org.dromara.daxpay.single.sdk.response.DaxPayResult;
|
||||
import org.dromara.daxpay.single.sdk.util.JsonUtil;
|
||||
import org.dromara.daxpay.single.sdk.util.PaySignUtil;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 统一支付接口
|
||||
* @author xxm
|
||||
@@ -108,24 +115,24 @@ public class PayOrderTest {
|
||||
DaxPayConfig config = DaxPayConfig.builder()
|
||||
.serviceUrl("http://127.0.0.1:9999")
|
||||
.signSecret("123456")
|
||||
.appId("M7934041241299655")
|
||||
.appId("123")
|
||||
.signType(SignTypeEnum.HMAC_SHA256)
|
||||
.build();
|
||||
DaxPayKit.initConfig(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝支付(二维码扫码)
|
||||
/**
|
||||
* 微信支付(二维码扫码)
|
||||
*/
|
||||
@Test
|
||||
public void aliPayQrPay() {
|
||||
public void wxQrPay() {
|
||||
PayParam param = new PayParam();
|
||||
param.setClientIp("127.0.0.1");
|
||||
param.setBizOrderNo("SDK_"+ System.currentTimeMillis());
|
||||
param.setTitle("测试支付宝扫码支付");
|
||||
param.setDescription("这是支付宝扫码支付");
|
||||
param.setAmount(BigDecimal.valueOf(10));
|
||||
param.setChannel(ChannelEnum.ALI.getCode());
|
||||
param.setTitle("测试微信扫码支付");
|
||||
param.setDescription("这是支付备注");
|
||||
param.setAmount(BigDecimal.valueOf(1.00));
|
||||
param.setChannel(ChannelEnum.WECHAT.getCode());
|
||||
param.setMethod(PayMethodEnum.QRCODE.getCode());
|
||||
param.setAttach("{回调参数}");
|
||||
param.setAllocation(false);
|
||||
@@ -134,8 +141,10 @@ public class PayOrderTest {
|
||||
|
||||
DaxPayResult<PayResultModel> execute = DaxPayKit.execute(param);
|
||||
System.out.println(JsonUtil.toJsonStr(execute));
|
||||
System.out.println(PaySignUtil.hmacSha256Sign(execute, "123456"));
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 🍎 系统截图
|
||||
|
@@ -19,6 +19,9 @@
|
||||
- 在微信支付宝时为结算页, 可以直接发起支付
|
||||
- [ ] PC收银台, PC收银台可以生成聚合收银码, 也可以通道特殊方式的支付(微信扫码/支付宝PC支付)
|
||||
- [ ] H5收银台只在浏览器中才会出现, 在软件中会直接跳转到结算页
|
||||
- [ ] 支付码牌配置
|
||||
- [x] 一个应用支持多码牌
|
||||
- [x] 码牌不再使用应用号座位标识, 使用独立的编码
|
||||
|
||||
## bugs
|
||||
- [x] 修复 BigDecimal 类型数据序列化和签名异常问题
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package org.dromara.daxpay.channel.alipay.service.allocation.receiver;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alipay.api.AlipayClient;
|
||||
import com.alipay.api.AlipayResponse;
|
||||
import com.alipay.api.domain.AlipayTradeRoyaltyRelationBindModel;
|
||||
import com.alipay.api.domain.AlipayTradeRoyaltyRelationUnbindModel;
|
||||
@@ -54,7 +53,6 @@ public class AliPayAllocReceiverService {
|
||||
*/
|
||||
@SneakyThrows
|
||||
public void bind(AllocReceiver allocReceiver){
|
||||
AlipayClient alipayClient = aliPayConfigService.getAlipayClient();
|
||||
AlipayTradeRoyaltyRelationBindModel model = new AlipayTradeRoyaltyRelationBindModel();
|
||||
|
||||
RoyaltyEntity entity = new RoyaltyEntity();
|
||||
@@ -69,7 +67,7 @@ public class AliPayAllocReceiverService {
|
||||
AlipayTradeRoyaltyRelationBindRequest request = new AlipayTradeRoyaltyRelationBindRequest();
|
||||
model.setOutRequestNo(String.valueOf(allocReceiver.getId()));
|
||||
request.setBizModel(model);
|
||||
AlipayTradeRoyaltyRelationBindResponse response = alipayClient.execute(request);
|
||||
AlipayTradeRoyaltyRelationBindResponse response = aliPayConfigService.execute(request);
|
||||
this.verifyErrorMsg(response);
|
||||
}
|
||||
|
||||
@@ -78,7 +76,6 @@ public class AliPayAllocReceiverService {
|
||||
*/
|
||||
@SneakyThrows
|
||||
public void unbind(AllocReceiver allocReceiver){
|
||||
AlipayClient alipayClient = aliPayConfigService.getAlipayClient();
|
||||
AlipayTradeRoyaltyRelationUnbindModel model = new AlipayTradeRoyaltyRelationUnbindModel();
|
||||
model.setOutRequestNo(String.valueOf(allocReceiver.getId()));
|
||||
|
||||
@@ -90,7 +87,7 @@ public class AliPayAllocReceiverService {
|
||||
model.setReceiverList(Collections.singletonList(entity));
|
||||
AlipayTradeRoyaltyRelationUnbindRequest request = new AlipayTradeRoyaltyRelationUnbindRequest();
|
||||
request.setBizModel(model);
|
||||
AlipayTradeRoyaltyRelationUnbindResponse response = alipayClient.execute(request);
|
||||
AlipayTradeRoyaltyRelationUnbindResponse response = aliPayConfigService.execute(request);
|
||||
System.out.println(response);
|
||||
// 如果出现分账方不存在也视为成功
|
||||
if (Objects.equals(response.getSubCode(), AliPayCode.USER_NOT_EXIST)) {
|
||||
|
@@ -7,6 +7,7 @@ import cn.bootx.platform.core.rest.dto.LabelValue;
|
||||
import cn.bootx.platform.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.core.rest.result.PageResult;
|
||||
import cn.bootx.platform.core.rest.result.Result;
|
||||
import cn.bootx.platform.core.util.ValidationUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
@@ -62,7 +63,8 @@ public class AllocReceiverController {
|
||||
@RequestPath("添加")
|
||||
@Operation(summary = "添加")
|
||||
@PostMapping("/add")
|
||||
public Result<Void> add(@RequestBody @Validated AllocReceiverAddParam param){
|
||||
public Result<Void> add(@RequestBody AllocReceiverAddParam param){
|
||||
ValidationUtil.validateParam(param);
|
||||
paymentAssistService.initMchApp(param.getAppId());
|
||||
receiverService.addAndSync(param);
|
||||
return Res.ok();
|
||||
@@ -71,7 +73,8 @@ public class AllocReceiverController {
|
||||
@RequestPath("删除")
|
||||
@Operation(summary = "删除")
|
||||
@PostMapping("/delete")
|
||||
public Result<Void> delete(@RequestBody @Validated AllocReceiverRemoveParam param){
|
||||
public Result<Void> delete(@RequestBody AllocReceiverRemoveParam param){
|
||||
ValidationUtil.validateParam(param);
|
||||
paymentAssistService.initMchApp(param.getAppId());
|
||||
receiverService.removeAndSync(param);
|
||||
return Res.ok();
|
||||
|
@@ -0,0 +1,16 @@
|
||||
package org.dromara.daxpay.service.controller.config;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 收银台配置
|
||||
* @author xxm
|
||||
* @since 2024/11/22
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "收银台配置")
|
||||
public class CheckoutConfig {
|
||||
}
|
@@ -97,4 +97,12 @@ public class PayOrderController {
|
||||
payOrderService.cancel(id);
|
||||
return Res.ok();
|
||||
}
|
||||
|
||||
@RequestPath("分账")
|
||||
@Operation(summary = "分账")
|
||||
@PostMapping("/allocation")
|
||||
public Result<Void> allocation(@NotNull(message = "支付订单id不能为空") Long id){
|
||||
payOrderService.allocation(id);
|
||||
return Res.ok();
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package org.dromara.daxpay.service.entity.allocation.transaction;
|
||||
|
||||
import cn.bootx.platform.common.mybatisplus.function.ToResult;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
@@ -21,6 +22,7 @@ import java.time.LocalDateTime;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("pay_alloc_detail")
|
||||
public class AllocDetail extends MchAppBaseEntity implements ToResult<AllocDetailResult> {
|
||||
|
||||
/** 分账订单ID */
|
||||
|
@@ -1,14 +1,13 @@
|
||||
package org.dromara.daxpay.service.param.allocation.group;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.DecimalMax;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.Digits;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import jakarta.validation.constraints.DecimalMax;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
@@ -27,9 +26,8 @@ public class AllocGroupReceiverParam {
|
||||
|
||||
@Schema(description = "分账比例(百分之多少)")
|
||||
@NotNull(message = "分账比例不可为空")
|
||||
@Min(value = 0,message = "分账比例不可为负数")
|
||||
@DecimalMax(value = "100",message = "分账比例不可大于100%")
|
||||
@DecimalMin(value = "0.01", message = "分账比例不可小于0.01%")
|
||||
@DecimalMin(value = "0.00", message = "分账比例不可为负数")
|
||||
@Digits(integer = 3, fraction = 2, message = "分账比例最多只允许两位小数")
|
||||
private BigDecimal rate;
|
||||
}
|
||||
|
@@ -1,8 +1,12 @@
|
||||
package org.dromara.daxpay.service.service.order.pay;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import org.dromara.daxpay.core.exception.TradeNotExistException;
|
||||
import org.dromara.daxpay.core.param.allocation.transaction.AllocationParam;
|
||||
import org.dromara.daxpay.core.util.TradeNoGenerateUtil;
|
||||
import org.dromara.daxpay.service.dao.order.pay.PayOrderManager;
|
||||
import org.dromara.daxpay.service.entity.order.pay.PayOrder;
|
||||
import org.dromara.daxpay.service.service.allocation.AllocationService;
|
||||
import org.dromara.daxpay.service.service.assist.PaymentAssistService;
|
||||
import org.dromara.daxpay.service.service.trade.pay.PayCloseService;
|
||||
import org.dromara.daxpay.service.service.trade.pay.PaySyncService;
|
||||
@@ -24,6 +28,7 @@ public class PayOrderService {
|
||||
|
||||
private final PaymentAssistService paymentAssistService;
|
||||
private final PayCloseService payCloseService;
|
||||
private final AllocationService allocationService;
|
||||
|
||||
/**
|
||||
* 同步
|
||||
@@ -55,4 +60,16 @@ public class PayOrderService {
|
||||
payCloseService.closeOrder(payOrder,true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账
|
||||
*/
|
||||
public void allocation(@NotNull(message = "支付订单id不能为空") Long id) {
|
||||
PayOrder payOrder = payOrderManager.findById(id).orElseThrow(() -> new TradeNotExistException("支付订单不存在"));
|
||||
paymentAssistService.initMchApp(payOrder.getAppId());
|
||||
AllocationParam param = new AllocationParam()
|
||||
.setBizAllocNo("B"+TradeNoGenerateUtil.allocation());
|
||||
param.setAppId(payOrder.getAppId());
|
||||
allocationService.allocation(param, payOrder);
|
||||
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user