From 8901fb746336147fd9e3aa9c53176dafb71d891f Mon Sep 17 00:00:00 2001 From: DaxPay Date: Sun, 24 Nov 2024 17:14:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(payment):=20=E6=B7=BB=E5=8A=A0=E5=88=86?= =?UTF-8?q?=E8=B4=A6=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增分账功能,支持支付宝和微信支付的分账操作 - 重构支付宝支付流程,使用新的SDK- 更新微信支付示例,调整相关参数 - 优化收银台配置和支付订单相关服务- 调整分账比例的验证规则,支持更灵活的比例设置 --- README.md | 43 +++++++++++-------- _doc/Task.md | 3 ++ .../receiver/AliPayAllocReceiverService.java | 7 +-- .../allocation/AllocReceiverController.java | 7 ++- .../controller/config/CheckoutConfig.java | 16 +++++++ .../controller/order/PayOrderController.java | 8 ++++ .../allocation/transaction/AllocDetail.java | 2 + .../group/AllocGroupReceiverParam.java | 6 +-- .../service/order/pay/PayOrderService.java | 17 ++++++++ 9 files changed, 81 insertions(+), 28 deletions(-) create mode 100644 daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/config/CheckoutConfig.java diff --git a/README.md b/README.md index 86f6e7700..86c3c3c53 100644 --- a/README.md +++ b/README.md @@ -76,25 +76,32 @@ ```xml - cn.daxpay.single + org.dromara.daxpay daxpay-single-sdk ${latest.version} ``` ### 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 execute = DaxPayKit.execute(param); System.out.println(JsonUtil.toJsonStr(execute)); + System.out.println(PaySignUtil.hmacSha256Sign(execute, "123456")); } } + ``` ## 🍎 系统截图 diff --git a/_doc/Task.md b/_doc/Task.md index 1f0b8c73b..c78feb30c 100644 --- a/_doc/Task.md +++ b/_doc/Task.md @@ -19,6 +19,9 @@ - 在微信支付宝时为结算页, 可以直接发起支付 - [ ] PC收银台, PC收银台可以生成聚合收银码, 也可以通道特殊方式的支付(微信扫码/支付宝PC支付) - [ ] H5收银台只在浏览器中才会出现, 在软件中会直接跳转到结算页 +- [ ] 支付码牌配置 + - [x] 一个应用支持多码牌 + - [x] 码牌不再使用应用号座位标识, 使用独立的编码 ## bugs - [x] 修复 BigDecimal 类型数据序列化和签名异常问题 diff --git a/daxpay-single-channel/daxpay-single-alipay/src/main/java/org/dromara/daxpay/channel/alipay/service/allocation/receiver/AliPayAllocReceiverService.java b/daxpay-single-channel/daxpay-single-alipay/src/main/java/org/dromara/daxpay/channel/alipay/service/allocation/receiver/AliPayAllocReceiverService.java index 628771742..7f8edcecf 100644 --- a/daxpay-single-channel/daxpay-single-alipay/src/main/java/org/dromara/daxpay/channel/alipay/service/allocation/receiver/AliPayAllocReceiverService.java +++ b/daxpay-single-channel/daxpay-single-alipay/src/main/java/org/dromara/daxpay/channel/alipay/service/allocation/receiver/AliPayAllocReceiverService.java @@ -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)) { diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/allocation/AllocReceiverController.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/allocation/AllocReceiverController.java index 1e4e29e10..88d91f1f6 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/allocation/AllocReceiverController.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/allocation/AllocReceiverController.java @@ -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 add(@RequestBody @Validated AllocReceiverAddParam param){ + public Result 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 delete(@RequestBody @Validated AllocReceiverRemoveParam param){ + public Result delete(@RequestBody AllocReceiverRemoveParam param){ + ValidationUtil.validateParam(param); paymentAssistService.initMchApp(param.getAppId()); receiverService.removeAndSync(param); return Res.ok(); diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/config/CheckoutConfig.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/config/CheckoutConfig.java new file mode 100644 index 000000000..b294f36e6 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/config/CheckoutConfig.java @@ -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 { +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/order/PayOrderController.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/order/PayOrderController.java index a4e3ef230..f2c360015 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/order/PayOrderController.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/order/PayOrderController.java @@ -97,4 +97,12 @@ public class PayOrderController { payOrderService.cancel(id); return Res.ok(); } + + @RequestPath("分账") + @Operation(summary = "分账") + @PostMapping("/allocation") + public Result allocation(@NotNull(message = "支付订单id不能为空") Long id){ + payOrderService.allocation(id); + return Res.ok(); + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/transaction/AllocDetail.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/transaction/AllocDetail.java index 07f9b2105..90fa9ebfb 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/transaction/AllocDetail.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/entity/allocation/transaction/AllocDetail.java @@ -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 { /** 分账订单ID */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/param/allocation/group/AllocGroupReceiverParam.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/param/allocation/group/AllocGroupReceiverParam.java index 0b3085871..d5ebd44b8 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/param/allocation/group/AllocGroupReceiverParam.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/param/allocation/group/AllocGroupReceiverParam.java @@ -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; } diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/order/pay/PayOrderService.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/order/pay/PayOrderService.java index 007b8a806..4b941c3eb 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/order/pay/PayOrderService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/order/pay/PayOrderService.java @@ -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); + + } }