diff --git a/_doc/Task.md b/_doc/Task.md index 46ce3f25..e9f599c8 100644 --- a/_doc/Task.md +++ b/_doc/Task.md @@ -1,3 +1,10 @@ +2.0.0 +- x 参数签名机制 +- x 开放接口供第三方调用 +- 增加回调机制 +- 增加消息通知机制 +- 支付超时取消支付单 + 1.0.1 - x 钱包支持多商户和多应用 - x 储值卡支持多商户和多应用 diff --git a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/PayCommonParam.java b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/PayCommonParam.java index c1c34f13..c4d231e0 100644 --- a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/PayCommonParam.java +++ b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/PayCommonParam.java @@ -1,6 +1,8 @@ package cn.bootx.platform.daxpay.param.pay; +import cn.bootx.platform.daxpay.serializer.TimestampToLocalDateTimeDeserializer; import cn.bootx.platform.daxpay.util.PayUtil; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -42,10 +44,6 @@ public abstract class PayCommonParam { @Schema(description = "异步通知地址") private String notifyUrl; - /** 签名类型 */ - @Schema(description = "签名类型") - private String signType; - /** 签名 */ @Schema(description = "签名") private String sign; @@ -58,6 +56,7 @@ public abstract class PayCommonParam { /** 请求时间,时间戳转时间 */ @Schema(description = "请求时间,传输时间戳") @NotNull(message = "请求时间必填") + @JsonDeserialize(using = TimestampToLocalDateTimeDeserializer.class) private LocalDateTime reqTime; diff --git a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/PayParam.java b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/PayParam.java index e1ce4256..b58aa213 100644 --- a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/PayParam.java +++ b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/PayParam.java @@ -1,12 +1,14 @@ package cn.bootx.platform.daxpay.param.pay; +import cn.bootx.platform.daxpay.serializer.TimestampToLocalDateTimeDeserializer; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import javax.validation.Valid; import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.time.LocalDateTime; import java.util.List; @@ -32,15 +34,15 @@ public class PayParam extends PayCommonParam{ @Schema(description = "支付描述") private String description; - /** 过期时间 */ @Schema(description = "过期时间") + @JsonDeserialize(using = TimestampToLocalDateTimeDeserializer.class) private LocalDateTime expiredTime; @Schema(description = "用户付款中途退出返回商户网站的地址(部分支付场景中可用)") private String quitUrl; @Schema(description = "支付方式信息参数") - @NotEmpty(message = "支付方式信息参数不可为空") + @NotNull(message = "支付方式信息参数不可为空") @Valid private List payWays; } diff --git a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/RefundModeParam.java b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/RefundChannelParam.java similarity index 97% rename from daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/RefundModeParam.java rename to daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/RefundChannelParam.java index 77edfc68..fe71c4eb 100644 --- a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/RefundModeParam.java +++ b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/RefundChannelParam.java @@ -20,7 +20,7 @@ import javax.validation.constraints.NotNull; @Data @Accessors(chain = true) @Schema(title = "分通道退款参数") -public class RefundModeParam { +public class RefundChannelParam { /** * @see PayChannelEnum#getCode() diff --git a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/RefundParam.java b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/RefundParam.java index 41cdfa02..0c67c8ef 100644 --- a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/RefundParam.java +++ b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/RefundParam.java @@ -40,7 +40,7 @@ public class RefundParam extends PayCommonParam { */ @Valid @Schema(description = "退款参数列表") - private List refundModes; + private List refundModes; @Schema(description = "退款原因") private String reason; diff --git a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/SimplePayParam.java b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/SimplePayParam.java index 991d342e..32ea1945 100644 --- a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/SimplePayParam.java +++ b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/param/pay/SimplePayParam.java @@ -6,13 +6,15 @@ import cn.bootx.platform.daxpay.param.channel.AliPayParam; import cn.bootx.platform.daxpay.param.channel.VoucherPayParam; import cn.bootx.platform.daxpay.param.channel.WalletPayParam; import cn.bootx.platform.daxpay.param.channel.WeChatPayParam; +import cn.bootx.platform.daxpay.serializer.TimestampToLocalDateTimeDeserializer; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; -import java.math.BigDecimal; +import java.time.LocalDateTime; /** * 简单下单参数 @@ -35,6 +37,13 @@ public class SimplePayParam extends PayCommonParam{ @Schema(description = "支付描述") private String description; + @Schema(description = "过期时间") + @JsonDeserialize(using = TimestampToLocalDateTimeDeserializer.class) + private LocalDateTime expiredTime; + + @Schema(description = "用户付款中途退出返回商户网站的地址(部分支付场景中可用)") + private String quitUrl; + /** * @see PayChannelEnum#getCode() */ @@ -51,7 +60,7 @@ public class SimplePayParam extends PayCommonParam{ @Schema(description = "支付金额") @NotNull(message = "支付金额不可为空") - private BigDecimal amount; + private Integer amount; /** * @see AliPayParam diff --git a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/result/pay/PayCommonResult.java b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/result/pay/PayCommonResult.java new file mode 100644 index 00000000..77d16da2 --- /dev/null +++ b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/result/pay/PayCommonResult.java @@ -0,0 +1,20 @@ +package cn.bootx.platform.daxpay.result.pay; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 支付通用返回参数 + * @author xxm + * @since 2023/12/25 + */ +@Data +@Schema(title = "") +public class PayCommonResult { + + @Schema(description = "请求ID") + private String reqId; + + @Schema(description = "商户扩展参数,回调时会原样返回") + private String extraParam; +} diff --git a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/result/pay/PayResult.java b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/result/pay/PayResult.java index 16be4fd6..57762c14 100644 --- a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/result/pay/PayResult.java +++ b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/result/pay/PayResult.java @@ -4,7 +4,6 @@ import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.code.PayStatusEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.experimental.Accessors; /** * 统一下单响应参数 @@ -12,7 +11,6 @@ import lombok.experimental.Accessors; * @since 2023/12/17 */ @Data -@Accessors(chain = true) @Schema(title = "统一下单响应参数") public class PayResult { diff --git a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/result/pay/RefundResult.java b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/result/pay/RefundResult.java index 7a304fbb..5b2660c8 100644 --- a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/result/pay/RefundResult.java +++ b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/result/pay/RefundResult.java @@ -2,7 +2,6 @@ package cn.bootx.platform.daxpay.result.pay; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.experimental.Accessors; /** * 退款响应参数 @@ -10,7 +9,6 @@ import lombok.experimental.Accessors; * @since 2023/12/18 */ @Data -@Accessors(chain = true) @Schema(title = "退款响应参数") public class RefundResult { diff --git a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/serializer/TimestampToLocalDateTimeDeserializer.java b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/serializer/TimestampToLocalDateTimeDeserializer.java new file mode 100644 index 00000000..d7142e00 --- /dev/null +++ b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/serializer/TimestampToLocalDateTimeDeserializer.java @@ -0,0 +1,24 @@ +package cn.bootx.platform.daxpay.serializer; + +import cn.bootx.platform.common.core.util.LocalDateTimeUtil; +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; + +import java.io.IOException; +import java.time.LocalDateTime; + +/** + * 时间戳转LocalDateTime + * @author xxm + * @since 2023/12/25 + */ +public class TimestampToLocalDateTimeDeserializer extends JsonDeserializer { + + @Override + public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException { + long timestamp = p.getLongValue(); + return LocalDateTimeUtil.of(timestamp); + } +} diff --git a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/util/PayUtil.java b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/util/PayUtil.java index a7481188..d4d1b73b 100644 --- a/daxpay-core/src/main/java/cn/bootx/platform/daxpay/util/PayUtil.java +++ b/daxpay-core/src/main/java/cn/bootx/platform/daxpay/util/PayUtil.java @@ -54,8 +54,16 @@ public class PayUtil { if (ClassUtil.isBasicType(field.getType())|| field.getType().equals(String.class)) { String fieldValueString = String.valueOf(fieldValue); map.put(fieldName, fieldValueString); - // 集合类型 - } else if (Collection.class.isAssignableFrom(field.getType())) { + + } + // java8时间类型 转为时间戳 + else if (field.getType().equals(LocalDateTime.class)) { + LocalDateTime localDateTime = (LocalDateTime) fieldValue; + long timestamp = LocalDateTimeUtil.timestamp(localDateTime); + map.put(fieldName, String.valueOf(timestamp)); + } + // 集合类型 + else if (Collection.class.isAssignableFrom(field.getType())) { Collection collection = (Collection) fieldValue; if (!collection.isEmpty()) { List> maps = collection.stream() diff --git a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/DaxPaySingleGatewayApp.java b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/DaxPaySingleAdminApp.java similarity index 83% rename from daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/DaxPaySingleGatewayApp.java rename to daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/DaxPaySingleAdminApp.java index 3066d20c..c7beaa07 100644 --- a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/DaxPaySingleGatewayApp.java +++ b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/DaxPaySingleAdminApp.java @@ -1,4 +1,4 @@ -package cn.bootx.platform.daxpay; +package cn.bootx.platform.daxpay.admin; import org.apache.ibatis.annotations.Mapper; import org.mybatis.spring.annotation.MapperScan; @@ -13,5 +13,5 @@ import org.springframework.context.annotation.ComponentScan; @ConfigurationPropertiesScan @MapperScan(annotationClass = Mapper.class) @ComponentScan -public class DaxPaySingleGatewayApp { +public class DaxPaySingleAdminApp { } diff --git a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/openapi/controller/channel/AlipayConfigController.java b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/channel/AlipayConfigController.java similarity index 80% rename from daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/openapi/controller/channel/AlipayConfigController.java rename to daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/channel/AlipayConfigController.java index b0b2b330..8ddff1df 100644 --- a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/openapi/controller/channel/AlipayConfigController.java +++ b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/channel/AlipayConfigController.java @@ -1,4 +1,4 @@ -package cn.bootx.platform.daxpay.openapi.controller.channel; +package cn.bootx.platform.daxpay.admin.controller.channel; import cn.bootx.platform.common.core.rest.Res; import cn.bootx.platform.common.core.rest.ResResult; @@ -22,7 +22,7 @@ import java.util.List; */ @Tag(name = "支付宝配置") @RestController -@RequestMapping("/alipay") +@RequestMapping("/alipay/config") @AllArgsConstructor public class AlipayConfigController { @@ -35,16 +35,16 @@ public class AlipayConfigController { return Res.ok(); } - @Operation(summary = "根据Id查询") - @GetMapping("/findById") - public ResResult findById() { + @Operation(summary = "获取配置") + @GetMapping("/getConfig") + public ResResult getConfig() { return Res.ok(alipayConfigService.getConfig().toDto()); } @Operation(summary = "支付宝支持支付方式") - @GetMapping("/findPayWayList") - public ResResult> findPayWayList() { - return Res.ok(alipayConfigService.findPayWayList()); + @GetMapping("/findPayWays") + public ResResult> findPayWays() { + return Res.ok(alipayConfigService.findPayWays()); } @SneakyThrows diff --git a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/channel/WeChatPayConfigController.java b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/channel/WeChatPayConfigController.java new file mode 100644 index 00000000..85c24207 --- /dev/null +++ b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/channel/WeChatPayConfigController.java @@ -0,0 +1,60 @@ +package cn.bootx.platform.daxpay.admin.controller.channel; + +import cn.bootx.platform.common.core.rest.PageResult; +import cn.bootx.platform.common.core.rest.Res; +import cn.bootx.platform.common.core.rest.ResResult; +import cn.bootx.platform.common.core.rest.dto.LabelValue; +import cn.bootx.platform.common.core.rest.param.PageParam; +import cn.bootx.platform.daxpay.core.channel.wechat.entity.WeChatPayConfig; +import cn.bootx.platform.daxpay.core.channel.wechat.service.WeChatPayConfigService; +import cn.bootx.platform.daxpay.dto.channel.alipay.AlipayConfigDto; +import cn.bootx.platform.daxpay.dto.channel.wechat.WeChatPayConfigDto; +import cn.bootx.platform.daxpay.param.channel.wechat.WeChatPayConfigParam; +import cn.hutool.core.codec.Base64; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import lombok.SneakyThrows; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +/** + * @author xxm + * @since 2021/3/19 + */ +@Tag(name = "微信支付配置") +@RestController +@RequestMapping("/wechat/pay/config") +@AllArgsConstructor +public class WeChatPayConfigController { + + private final WeChatPayConfigService weChatPayConfigService; + + @Operation(summary = "更新") + @PostMapping("/update") + public ResResult update(@RequestBody WeChatPayConfigParam param) { + weChatPayConfigService.update(param); + return Res.ok(); + } + + @Operation(summary = "获取配置") + @GetMapping("/getConfig") + public ResResult getConfig() { + return Res.ok(weChatPayConfigService.getConfig().toDto()); + } + + @Operation(summary = "微信支持支付方式") + @GetMapping("/findPayWays") + public ResResult> findPayWays() { + return Res.ok(weChatPayConfigService.findPayWays()); + } + + @SneakyThrows + @Operation(summary = "将文件转换成base64") + @PostMapping("/toBase64") + public ResResult toBase64(MultipartFile file){ + return Res.ok(Base64.encode(file.getBytes())); + } +} diff --git a/daxpay-single/daxpay-single-admin/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/daxpay-single/daxpay-single-admin/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 88c2aa85..b9b464d2 100644 --- a/daxpay-single/daxpay-single-admin/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/daxpay-single/daxpay-single-admin/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1 @@ -cn.bootx.platform.daxpay.DaxPaySingleGatewayApp +cn.bootx.platform.daxpay.DaxPaySingleAdminApp diff --git a/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/DaxpaySingleGatewayApp.java b/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/DaxpaySingleGatewayApp.java similarity index 90% rename from daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/DaxpaySingleGatewayApp.java rename to daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/DaxpaySingleGatewayApp.java index 61f4e3f3..21c71c7c 100644 --- a/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/DaxpaySingleGatewayApp.java +++ b/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/DaxpaySingleGatewayApp.java @@ -1,4 +1,4 @@ -package cn.bootx.platform.daxpay; +package cn.bootx.platform.daxpay.gateway; import org.apache.ibatis.annotations.Mapper; import org.mybatis.spring.annotation.MapperScan; diff --git a/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/openapi/controller/PayCallbackController.java b/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/PayCallbackController.java similarity index 97% rename from daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/openapi/controller/PayCallbackController.java rename to daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/PayCallbackController.java index 8d0ac07c..a0b695a1 100644 --- a/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/openapi/controller/PayCallbackController.java +++ b/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/PayCallbackController.java @@ -1,4 +1,4 @@ -package cn.bootx.platform.daxpay.openapi.controller; +package cn.bootx.platform.daxpay.gateway.controller; import cn.bootx.platform.common.core.annotation.IgnoreAuth; import cn.bootx.platform.daxpay.core.channel.alipay.service.AliPayCallbackService; diff --git a/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/openapi/controller/UniPayController.java b/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniPayController.java similarity index 85% rename from daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/openapi/controller/UniPayController.java rename to daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniPayController.java index b1a47bf6..9af28383 100644 --- a/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/openapi/controller/UniPayController.java +++ b/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/UniPayController.java @@ -1,8 +1,9 @@ -package cn.bootx.platform.daxpay.openapi.controller; +package cn.bootx.platform.daxpay.gateway.controller; import cn.bootx.platform.common.core.annotation.IgnoreAuth; import cn.bootx.platform.daxpay.annotation.PaymentApi; import cn.bootx.platform.daxpay.core.payment.pay.service.PayService; +import cn.bootx.platform.daxpay.core.payment.refund.service.PayRefundService; import cn.bootx.platform.daxpay.param.pay.*; import cn.bootx.platform.daxpay.result.DaxResult; import cn.bootx.platform.daxpay.result.pay.PayResult; @@ -28,20 +29,20 @@ import org.springframework.web.bind.annotation.RestController; @RequiredArgsConstructor public class UniPayController { private final PayService payService; + private final PayRefundService payRefundService; @PaymentApi("pay") @Operation(summary = "统一下单") @PostMapping("/pay") public DaxResult pay(@RequestBody PayParam payParam){ - payService.pay(payParam); - return DaxRes.ok(); + return DaxRes.ok(payService.pay(payParam)); } @PaymentApi("simplePay") @Operation(summary = "简单下单") @PostMapping("/simplePay") - public DaxResult simplePay(){ - return DaxRes.ok(); + public DaxResult simplePay(@RequestBody SimplePayParam payParam){ + return DaxRes.ok(payService.simplePay(payParam)); } @PaymentApi("cancel") @@ -62,7 +63,7 @@ public class UniPayController { @Operation(summary = "统一退款") @PostMapping("/refund") public DaxResult refund(@RequestBody RefundParam param){ - return DaxRes.ok(); + return DaxRes.ok(payRefundService.refund(param)); } @PaymentApi("simpleRefund") diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/common/context/PaymentContext.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/common/context/PaymentContext.java index cbaa4679..cd9948dc 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/common/context/PaymentContext.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/common/context/PaymentContext.java @@ -1,6 +1,6 @@ package cn.bootx.platform.daxpay.common.context; -import lombok.Data; +import lombok.Getter; import lombok.experimental.Accessors; /** @@ -8,7 +8,7 @@ import lombok.experimental.Accessors; * @author xxm * @since 2023/12/22 */ -@Data +@Getter @Accessors(chain = true) public class PaymentContext { @@ -27,4 +27,7 @@ public class PaymentContext { /** 消息通知相关信息 */ private final NoticeLocal noticeInfo = new NoticeLocal(); + /** 支付请求相关信息 */ + private final RequestLocal request = new RequestLocal(); + } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/common/context/RequestLocal.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/common/context/RequestLocal.java new file mode 100644 index 00000000..60ebd270 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/common/context/RequestLocal.java @@ -0,0 +1,34 @@ +package cn.bootx.platform.daxpay.common.context; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; + +/** + * 支付请求相关信息 + * @author xxm + * @since 2023/12/25 + */ +@Data +@Accessors(chain = true) +public class RequestLocal { + + /** 客户端ip */ + private String clientIp; + + /** 商户扩展参数,回调时会原样返回 */ + private String extraParam; + + /** 签名 */ + private String sign; + + /** API版本号 */ + private String version; + + /** 请求时间,时间戳转时间 */ + private LocalDateTime reqTime; + + /** 请求链路id */ + private String reqId; +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/entity/PayOrderRefundableInfo.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/common/entity/OrderRefundableInfo.java similarity index 81% rename from daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/entity/PayOrderRefundableInfo.java rename to daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/common/entity/OrderRefundableInfo.java index c9ca8bff..3f038983 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/entity/PayOrderRefundableInfo.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/common/entity/OrderRefundableInfo.java @@ -1,4 +1,4 @@ -package cn.bootx.platform.daxpay.core.order.pay.entity; +package cn.bootx.platform.daxpay.common.entity; import cn.bootx.platform.daxpay.code.PayChannelEnum; import lombok.Data; @@ -11,7 +11,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class PayOrderRefundableInfo { +public class OrderRefundableInfo { /** * @see PayChannelEnum#getCode() */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/callback/entity/CallbackNotify.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/callback/entity/CallbackNotify.java index 905073d7..9f933202 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/callback/entity/CallbackNotify.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/callback/entity/CallbackNotify.java @@ -38,10 +38,17 @@ public class CallbackNotify extends MpCreateEntity { private String notifyInfo; /** - * 处理状态 + * 支付状态 * @see PayStatusEnum */ - @DbComment("处理状态") + @DbComment("支付状态") + private String payStatus; + + /** + * 回调处理状态 + * @see + */ + @DbComment("回调处理状态") private String status; /** 提示信息 */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AliPayCallbackService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AliPayCallbackService.java index d0e5431a..b68d444c 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AliPayCallbackService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AliPayCallbackService.java @@ -6,7 +6,6 @@ import cn.bootx.platform.daxpay.code.AliPayCode; import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.code.PayStatusEnum; import cn.bootx.platform.daxpay.core.callback.dao.CallbackNotifyManager; -import cn.bootx.platform.daxpay.core.channel.alipay.dao.AlipayConfigManager; import cn.bootx.platform.daxpay.core.channel.alipay.entity.AlipayConfig; import cn.bootx.platform.daxpay.core.payment.callback.service.PayCallbackService; import cn.bootx.platform.daxpay.func.AbsPayCallbackStrategy; @@ -33,12 +32,12 @@ import java.util.Objects; @Service public class AliPayCallbackService extends AbsPayCallbackStrategy { - private final AlipayConfigManager alipayConfigManager; + private final AlipayConfigService aliasConfigService; public AliPayCallbackService(RedisClient redisClient, CallbackNotifyManager callbackNotifyManager, - PayCallbackService payCallbackService, AlipayConfigManager alipayConfigManager) { + PayCallbackService payCallbackService, AlipayConfigService aliasConfigService) { super(redisClient, callbackNotifyManager, payCallbackService); - this.alipayConfigManager = alipayConfigManager; + this.aliasConfigService = aliasConfigService; } @Override @@ -69,7 +68,7 @@ public class AliPayCallbackService extends AbsPayCallbackStrategy { log.error("支付宝回调报文 appId 为空 {}", callReq); return false; } - AlipayConfig alipayConfig = null; + AlipayConfig alipayConfig = aliasConfigService.getConfig(); if (Objects.isNull(alipayConfig)) { log.error("支付宝支付配置不存在: {}", callReq); return false; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AliPayOrderService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AliPayOrderService.java index 51bb19e6..29c86388 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AliPayOrderService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AliPayOrderService.java @@ -6,10 +6,11 @@ import cn.bootx.platform.daxpay.common.context.AsyncPayLocal; import cn.bootx.platform.daxpay.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.core.channel.alipay.dao.AliPayOrderManager; import cn.bootx.platform.daxpay.core.channel.alipay.entity.AliPayOrder; +import cn.bootx.platform.daxpay.core.order.pay.dao.PayOrderChannelManager; import cn.bootx.platform.daxpay.core.order.pay.dao.PayOrderManager; import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrder; import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrderChannel; -import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrderRefundableInfo; +import cn.bootx.platform.daxpay.common.entity.OrderRefundableInfo; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.param.pay.PayWayParam; import lombok.RequiredArgsConstructor; @@ -17,7 +18,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -40,30 +40,43 @@ public class AliPayOrderService { private final PayOrderManager payOrderManager; + private final PayOrderChannelManager payOrderChannelManager; + /** * 支付调起成功 更新payment中异步支付类型信息, 如果支付完成, 创建支付宝支付单 */ public void updatePaySuccess(PayOrder payOrder, PayWayParam payWayParam) { AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo(); - payOrder.setAsyncPayMode(true).setAsyncPayChannel(PayChannelEnum.ALI.getCode()); + payOrder.setAsyncPayMode(true) + .setAsyncPayChannel(PayChannelEnum.ALI.getCode()); + + // 更新支付宝异步支付类型信息 + Optional payOrderChannelOpt = payOrderChannelManager.findByPaymentIdAndChannel(payOrder.getId(), PayChannelEnum.ALI.getCode()); + if (!payOrderChannelOpt.isPresent()){ + payOrderChannelManager.deleteByPaymentIdAndAsync(payOrder.getId()); + payOrderChannelManager.save(new PayOrderChannel() + .setPaymentId(payOrder.getId()) + .setChannel(PayChannelEnum.ALI.getCode()) + .setAmount(payWayParam.getAmount()) + .setPayWay(payWayParam.getWay()) + .setChannelExtra(payWayParam.getChannelExtra()) + .setAsync(true) + ); + } else { + payOrderChannelOpt.get() + .setChannelExtra(payWayParam.getChannelExtra()) + .setPayWay(payWayParam.getWay()); + payOrderChannelManager.updateById(payOrderChannelOpt.get()); + } + - // TODO 支付 - List payChannelInfo = new ArrayList<>(); - List refundableInfos = new ArrayList<>(); - // 清除已有的异步支付类型信息 - payChannelInfo.removeIf(payTypeInfo -> PayChannelEnum.ASYNC_TYPE_CODE.contains(payTypeInfo.getChannel())); - refundableInfos.removeIf(payTypeInfo -> PayChannelEnum.ASYNC_TYPE_CODE.contains(payTypeInfo.getChannel())); - // 更新支付宝支付类型信息 - payChannelInfo.add(new PayOrderChannel().setChannel(PayChannelEnum.ALI.getCode()) - .setPayWay(payWayParam.getWay()) - .setAmount(payWayParam.getAmount()) - .setChannelExtra(payWayParam.getChannelExtra())); - // TODO 更新支付关联信息 -// payOrder.setPayChannelInfo(payChannelInfo); // 更新支付宝可退款类型信息 - refundableInfos - .add(new PayOrderRefundableInfo().setChannel(PayChannelEnum.ALI.getCode()) - .setAmount(payWayParam.getAmount())); + List refundableInfos = payOrder.getRefundableInfos(); + refundableInfos.removeIf(payTypeInfo -> PayChannelEnum.ASYNC_TYPE_CODE.contains(payTypeInfo.getChannel())); + refundableInfos.add(new OrderRefundableInfo() + .setChannel(PayChannelEnum.ALI.getCode()) + .setAmount(payWayParam.getAmount()) + ); payOrder.setRefundableInfos(refundableInfos); // 如果支付完成(付款码情况) 调用 updateSyncSuccess 创建支付宝支付记录 if (Objects.equals(payOrder.getStatus(), PayStatusEnum.SUCCESS.getCode())) { @@ -91,7 +104,7 @@ public class AliPayOrderService { .setAmount(payWayParam.getAmount()) .setRefundableBalance(payWayParam.getAmount()) .setBusinessNo(payOrder.getBusinessNo()) - .setStatus(PayStatusEnum.PROGRESS.getCode()) + .setStatus(PayStatusEnum.SUCCESS.getCode()) .setPayTime(LocalDateTime.now()); aliPayOrderManager.save(aliPayOrder); } @@ -102,7 +115,7 @@ public class AliPayOrderService { public void updateClose(Long paymentId) { Optional aliPaymentOptional = aliPayOrderManager.findByPaymentId(paymentId); aliPaymentOptional.ifPresent(aliPayOrder -> { - aliPayOrder.setStatus(PayStatusEnum.CANCEL.getCode()); + aliPayOrder.setStatus(PayStatusEnum.CLOSE.getCode()); aliPayOrderManager.updateById(aliPayOrder); }); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AlipayConfigService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AlipayConfigService.java index 1d3e3871..6848c7f5 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AlipayConfigService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AlipayConfigService.java @@ -33,7 +33,7 @@ import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class AlipayConfigService { - /** 默认支付包配置的主键ID */ + /** 默认支付宝配置的主键ID */ private final static Long ID = 0L; private final AlipayConfigManager alipayConfigManager; @@ -50,7 +50,7 @@ public class AlipayConfigService { /** * 支付宝支持支付方式 */ - public List findPayWayList() { + public List findPayWays() { return AliPayWay.getPayWays() .stream() .map(e -> new LabelValue(e.getName(),e.getCode())) diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/voucher/service/VoucherPayService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/voucher/service/VoucherPayService.java index ded86aa0..47ee569b 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/voucher/service/VoucherPayService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/voucher/service/VoucherPayService.java @@ -20,7 +20,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.math.BigDecimal; import java.util.List; import java.util.Objects; @@ -192,7 +191,7 @@ public class VoucherPayService { * 部分退款, 会退到指定的一张卡上, 如果不指定, 则自动退到有效期最久的卡上 */ @Transactional(rollbackFor = Exception.class) - public void refund(Long paymentId, BigDecimal amount) { + public void refund(Long paymentId, Integer amount) { VoucherPayment voucherPayment = voucherPaymentManager.findByPaymentId(paymentId) .orElseThrow(() -> new PayFailureException("储值卡支付记录不存在")); // 全部退款还是部分退款 diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayCallbackService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayCallbackService.java index f38c063d..1f7a5778 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayCallbackService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayCallbackService.java @@ -5,7 +5,6 @@ import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.code.PayStatusEnum; import cn.bootx.platform.daxpay.code.WeChatPayCode; import cn.bootx.platform.daxpay.core.callback.dao.CallbackNotifyManager; -import cn.bootx.platform.daxpay.core.channel.wechat.dao.WeChatPayConfigManager; import cn.bootx.platform.daxpay.core.channel.wechat.entity.WeChatPayConfig; import cn.bootx.platform.daxpay.core.payment.callback.service.PayCallbackService; import cn.bootx.platform.daxpay.func.AbsPayCallbackStrategy; @@ -18,6 +17,7 @@ import org.springframework.stereotype.Service; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import static cn.bootx.platform.daxpay.code.WeChatPayCode.APPID; @@ -31,13 +31,12 @@ import static cn.bootx.platform.daxpay.code.WeChatPayCode.APPID; @Slf4j @Service public class WeChatPayCallbackService extends AbsPayCallbackStrategy { - - private final WeChatPayConfigManager weChatPayConfigManager; + private final WeChatPayConfigService weChatPayConfigService; public WeChatPayCallbackService(RedisClient redisClient, CallbackNotifyManager callbackNotifyManager, - PayCallbackService payCallbackService, WeChatPayConfigManager weChatPayConfigManager) { + PayCallbackService payCallbackService, WeChatPayConfigService weChatPayConfigService) { super(redisClient, callbackNotifyManager, payCallbackService); - this.weChatPayConfigManager = weChatPayConfigManager; + this.weChatPayConfigService = weChatPayConfigService; } @Override @@ -84,8 +83,8 @@ public class WeChatPayCallbackService extends AbsPayCallbackStrategy { return false; } - WeChatPayConfig weChatPayConfig = null; - if (weChatPayConfig == null) { + WeChatPayConfig weChatPayConfig = weChatPayConfigService.getConfig(); + if (Objects.isNull(weChatPayConfig)) { log.warn("微信支付配置不存在: {}", callReq); return false; } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayCloseService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayCloseService.java index acb1da5a..c40500e7 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayCloseService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayCloseService.java @@ -1,32 +1,23 @@ package cn.bootx.platform.daxpay.core.channel.wechat.service; import cn.bootx.platform.common.spring.exception.RetryableException; -import cn.bootx.platform.daxpay.code.PayChannelEnum; -import cn.bootx.platform.daxpay.code.PayRefundStatusEnum; import cn.bootx.platform.daxpay.code.WeChatPayCode; import cn.bootx.platform.daxpay.common.context.AsyncRefundLocal; import cn.bootx.platform.daxpay.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.core.channel.wechat.entity.WeChatPayConfig; import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrder; -import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrderRefundableInfo; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; -import cn.hutool.core.codec.Base64; -import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import com.ijpay.core.enums.SignType; import com.ijpay.core.kit.WxPayKit; import com.ijpay.wxpay.WxPayApi; import com.ijpay.wxpay.model.CloseOrderModel; -import com.ijpay.wxpay.model.RefundModel; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Service; -import java.io.ByteArrayInputStream; -import java.math.BigDecimal; import java.util.Map; -import java.util.Objects; import java.util.Optional; /** @@ -59,45 +50,6 @@ public class WeChatPayCloseService { this.verifyErrorMsg(result); } - /** - * 退款 - */ - public void refund(PayOrder payOrder, BigDecimal amount, - WeChatPayConfig weChatPayConfig) { - PayOrderRefundableInfo refundableInfo = payOrder.getRefundableInfos().stream() - .filter(o -> Objects.equals(o.getChannel(), PayChannelEnum.WECHAT.getCode())) - .findFirst() - .orElseThrow(() -> new PayFailureException("未找到微信支付的详细信息")); - String refundFee = amount.multiply(BigDecimal.valueOf(100)).toBigInteger().toString(); - String totalFee = refundableInfo.getAmount().toString(); - // 设置退款信息 - AsyncRefundLocal refundInfo = PaymentContextLocal.get().getRefundInfo(); - refundInfo.setRefundNo(IdUtil.getSnowflakeNextIdStr()); - Map params = RefundModel.builder() - .appid(weChatPayConfig.getWxAppId()) - .mch_id(weChatPayConfig.getWxMchId()) - .out_trade_no(String.valueOf(payOrder.getId())) - .out_refund_no(refundInfo.getRefundNo()) - .total_fee(totalFee) - .refund_fee(refundFee) - .nonce_str(WxPayKit.generateStr()) - .build() - .createSign(weChatPayConfig.getApiKeyV2(), SignType.HMACSHA256); - // 获取证书文件 - if (StrUtil.isBlank(weChatPayConfig.getP12())){ - String errorMsg = "微信p.12证书未配置,无法进行退款"; - refundInfo.setErrorMsg(errorMsg); - refundInfo.setErrorCode(PayRefundStatusEnum.SUCCESS.getCode()); - throw new PayFailureException(errorMsg); - } - byte[] fileBytes = Base64.decode(weChatPayConfig.getP12()); - ByteArrayInputStream inputStream = new ByteArrayInputStream(fileBytes); - // 证书密码为 微信商户号 - String xmlResult = WxPayApi.orderRefund(false, params, inputStream, weChatPayConfig.getWxMchId()); - Map result = WxPayKit.xmlToMap(xmlResult); - this.verifyErrorMsg(result); - } - /** * 验证错误信息 */ @@ -109,7 +61,7 @@ public class WeChatPayCloseService { if (StrUtil.isBlank(errorMsg)) { errorMsg = result.get(WeChatPayCode.RETURN_MSG); } - log.error("订单退款/关闭失败 {}", errorMsg); + log.error("订单关闭失败 {}", errorMsg); AsyncRefundLocal refundInfo = PaymentContextLocal.get().getRefundInfo(); refundInfo.setErrorMsg(errorMsg); refundInfo.setErrorCode(Optional.ofNullable(resultCode).orElse(returnCode)); diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayConfigService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayConfigService.java index a2eea75a..ef3ff8cf 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayConfigService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayConfigService.java @@ -1,14 +1,10 @@ package cn.bootx.platform.daxpay.core.channel.wechat.service; import cn.bootx.platform.common.core.exception.DataNotExistException; -import cn.bootx.platform.common.core.rest.PageResult; import cn.bootx.platform.common.core.rest.dto.LabelValue; -import cn.bootx.platform.common.core.rest.param.PageParam; -import cn.bootx.platform.common.mybatisplus.util.MpUtil; import cn.bootx.platform.daxpay.code.WeChatPayWay; import cn.bootx.platform.daxpay.core.channel.wechat.dao.WeChatPayConfigManager; import cn.bootx.platform.daxpay.core.channel.wechat.entity.WeChatPayConfig; -import cn.bootx.platform.daxpay.dto.channel.wechat.WeChatPayConfigDto; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.param.channel.wechat.WeChatPayConfigParam; import cn.hutool.core.bean.BeanUtil; @@ -31,49 +27,35 @@ import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class WeChatPayConfigService { - + /** 默认微信支付配置的主键ID */ + private final static Long ID = 0L; private final WeChatPayConfigManager weChatPayConfigManager; - /** - * 添加微信支付配置 - */ - @Transactional(rollbackFor = Exception.class) - public void add(WeChatPayConfigParam param) { - - WeChatPayConfig weChatPayConfig = WeChatPayConfig.init(param); - weChatPayConfigManager.save(weChatPayConfig); - } - /** * 修改 */ @Transactional(rollbackFor = Exception.class) public void update(WeChatPayConfigParam param) { - WeChatPayConfig weChatPayConfig = weChatPayConfigManager.findById(param.getId()) + WeChatPayConfig weChatPayConfig = weChatPayConfigManager.findById(ID) .orElseThrow(() -> new PayFailureException("微信支付配置不存在")); param.setActivity(null); BeanUtil.copyProperties(param, weChatPayConfig, CopyOptions.create().ignoreNullValue()); weChatPayConfigManager.updateById(weChatPayConfig); } - /** - * 分页 - */ - public PageResult page(PageParam pageParam, WeChatPayConfigParam param) { - return MpUtil.convert2DtoPageResult(weChatPayConfigManager.page(pageParam, param)); - } /** - * 获取 + * 获取支付配置 */ - public WeChatPayConfigDto findById(Long id) { - return weChatPayConfigManager.findById(id).map(WeChatPayConfig::toDto).orElseThrow(DataNotExistException::new); + public WeChatPayConfig getConfig(){ + return weChatPayConfigManager.findById(ID).orElseThrow(() -> new DataNotExistException("微信支付配置不存在")); } + /** * 微信支持支付方式 */ - public List findPayWayList() { + public List findPayWays() { return WeChatPayWay.getPayWays() .stream() .map(e -> new LabelValue(e.getName(),e.getCode())) diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayOrderService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayOrderService.java index 78fa6769..7dfd2cc6 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayOrderService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayOrderService.java @@ -10,7 +10,7 @@ import cn.bootx.platform.daxpay.core.channel.wechat.entity.WeChatPayment; import cn.bootx.platform.daxpay.core.order.pay.dao.PayOrderManager; import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrder; import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrderChannel; -import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrderRefundableInfo; +import cn.bootx.platform.daxpay.common.entity.OrderRefundableInfo; import cn.bootx.platform.daxpay.param.pay.PayWayParam; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -45,7 +45,7 @@ public class WeChatPayOrderService { payOrder.setAsyncPayMode(true).setAsyncPayChannel(PayChannelEnum.WECHAT.getCode()); List payTypeInfos = new ArrayList<>(); - List refundableInfos = new ArrayList<>(); + List refundableInfos = new ArrayList<>(); // 清除已有的异步支付类型信息 payTypeInfos.removeIf(payTypeInfo -> PayChannelEnum.ASYNC_TYPE_CODE.contains(payTypeInfo.getChannel())); refundableInfos.removeIf(payTypeInfo -> PayChannelEnum.ASYNC_TYPE_CODE.contains(payTypeInfo.getChannel())); @@ -57,7 +57,7 @@ public class WeChatPayOrderService { // TODO 更新支付方式列表 // 更新微信可退款类型信息 refundableInfos.add( - new PayOrderRefundableInfo().setChannel(PayChannelEnum.WECHAT.getCode()) + new OrderRefundableInfo().setChannel(PayChannelEnum.WECHAT.getCode()) .setAmount(payWayParam.getAmount())); payOrder.setRefundableInfos(refundableInfos); // 如果支付完成(付款码情况) 调用 updateSyncSuccess 创建微信支付记录 diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayService.java index 69866644..8fba2a97 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayService.java @@ -78,9 +78,9 @@ public class WeChatPayService { /** * 支付 */ - public void pay(int amount, PayOrder payOrder, WeChatPayParam weChatPayParam, PayWayParam payWayParam, - WeChatPayConfig weChatPayConfig) { - // 微信传入的是分, 将元转换为分 + public void pay(PayOrder payOrder, WeChatPayParam weChatPayParam, PayWayParam payWayParam, WeChatPayConfig weChatPayConfig) { + + Integer amount = payWayParam.getAmount(); String totalFee = String.valueOf(amount); AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo();; String payBody = null; @@ -105,7 +105,7 @@ public class WeChatPayService { // 付款码支付 else if (payWayEnum == PayWayEnum.BARCODE) { String tradeNo = this.barCode(totalFee, payOrder, weChatPayParam.getAuthCode(), weChatPayConfig); - asyncPayInfo.setTradeNo(tradeNo).setExpiredTime(false); + asyncPayInfo.setTradeNo(tradeNo); } asyncPayInfo.setPayBody(payBody); } @@ -232,6 +232,7 @@ public class WeChatPayService { * 构建参数 */ private UnifiedOrderModelBuilder buildParams(String amount, PayOrder payment, WeChatPayConfig weChatPayConfig, String tradeType) { + LocalDateTime expiredTime = PaymentContextLocal.get() .getAsyncPayInfo() .getExpiredTime(); diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WechatRefundService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WechatRefundService.java new file mode 100644 index 00000000..15706c85 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WechatRefundService.java @@ -0,0 +1,96 @@ +package cn.bootx.platform.daxpay.core.channel.wechat.service; + +import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.code.PayRefundStatusEnum; +import cn.bootx.platform.daxpay.code.WeChatPayCode; +import cn.bootx.platform.daxpay.common.context.AsyncRefundLocal; +import cn.bootx.platform.daxpay.common.entity.OrderRefundableInfo; +import cn.bootx.platform.daxpay.common.local.PaymentContextLocal; +import cn.bootx.platform.daxpay.core.channel.wechat.entity.WeChatPayConfig; +import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrder; +import cn.bootx.platform.daxpay.exception.pay.PayFailureException; +import cn.hutool.core.codec.Base64; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import com.ijpay.core.enums.SignType; +import com.ijpay.core.kit.WxPayKit; +import com.ijpay.wxpay.WxPayApi; +import com.ijpay.wxpay.model.RefundModel; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.io.ByteArrayInputStream; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +/** + * 微信退款服务 + * @author xxm + * @since 2023/12/25 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class WechatRefundService { + + /** + * 退款 + */ + public void refund(PayOrder payOrder, int amount, + WeChatPayConfig weChatPayConfig) { + OrderRefundableInfo refundableInfo = payOrder.getRefundableInfos().stream() + .filter(o -> Objects.equals(o.getChannel(), PayChannelEnum.WECHAT.getCode())) + .findFirst() + .orElseThrow(() -> new PayFailureException("未找到微信支付的详细信息")); + String refundFee = String.valueOf(amount); + String totalFee = refundableInfo.getAmount().toString(); + // 设置退款信息 + AsyncRefundLocal refundInfo = PaymentContextLocal.get().getRefundInfo(); + refundInfo.setRefundNo(IdUtil.getSnowflakeNextIdStr()); + Map params = RefundModel.builder() + .appid(weChatPayConfig.getWxAppId()) + .mch_id(weChatPayConfig.getWxMchId()) + .out_trade_no(String.valueOf(payOrder.getId())) + .out_refund_no(refundInfo.getRefundNo()) + .total_fee(totalFee) + .refund_fee(refundFee) + .nonce_str(WxPayKit.generateStr()) + .build() + .createSign(weChatPayConfig.getApiKeyV2(), SignType.HMACSHA256); + // 获取证书文件 + if (StrUtil.isBlank(weChatPayConfig.getP12())){ + String errorMsg = "微信p.12证书未配置,无法进行退款"; + refundInfo.setErrorMsg(errorMsg); + refundInfo.setErrorCode(PayRefundStatusEnum.SUCCESS.getCode()); + throw new PayFailureException(errorMsg); + } + byte[] fileBytes = Base64.decode(weChatPayConfig.getP12()); + ByteArrayInputStream inputStream = new ByteArrayInputStream(fileBytes); + // 证书密码为 微信商户号 + String xmlResult = WxPayApi.orderRefund(false, params, inputStream, weChatPayConfig.getWxMchId()); + Map result = WxPayKit.xmlToMap(xmlResult); + this.verifyErrorMsg(result); + } + + /** + * 验证错误信息 + */ + private void verifyErrorMsg(Map result) { + String returnCode = result.get(WeChatPayCode.RETURN_CODE); + String resultCode = result.get(WeChatPayCode.RESULT_CODE); + if (!WxPayKit.codeIsOk(returnCode) || !WxPayKit.codeIsOk(resultCode)) { + String errorMsg = result.get(WeChatPayCode.ERR_CODE_DES); + if (StrUtil.isBlank(errorMsg)) { + errorMsg = result.get(WeChatPayCode.RETURN_MSG); + } + log.error("订单退款失败 {}", errorMsg); + AsyncRefundLocal refundInfo = PaymentContextLocal.get().getRefundInfo(); + refundInfo.setErrorMsg(errorMsg); + refundInfo.setErrorCode(Optional.ofNullable(resultCode).orElse(returnCode)); + throw new PayFailureException(errorMsg); + } + } + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/builder/PaymentBuilder.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/builder/PaymentBuilder.java index 571fca50..2ffad39c 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/builder/PaymentBuilder.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/builder/PaymentBuilder.java @@ -3,11 +3,13 @@ package cn.bootx.platform.daxpay.core.order.pay.builder; import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.code.PayStatusEnum; import cn.bootx.platform.daxpay.common.context.AsyncPayLocal; +import cn.bootx.platform.daxpay.common.context.NoticeLocal; +import cn.bootx.platform.daxpay.common.context.PlatformLocal; import cn.bootx.platform.daxpay.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrder; import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrderChannel; import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrderExtra; -import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrderRefundableInfo; +import cn.bootx.platform.daxpay.common.entity.OrderRefundableInfo; import cn.bootx.platform.daxpay.param.pay.PayParam; import cn.bootx.platform.daxpay.param.pay.PayWayParam; import cn.bootx.platform.daxpay.result.pay.PayResult; @@ -35,7 +37,7 @@ public class PaymentBuilder { */ public PayOrder buildPayOrder(PayParam payParam) { // 可退款信息 - List refundableInfos = buildRefundableInfo(payParam.getPayWays()); + List refundableInfos = buildRefundableInfo(payParam.getPayWays()); // 计算总价 int sumAmount = payParam.getPayWays().stream() .map(PayWayParam::getAmount) @@ -66,16 +68,15 @@ public class PaymentBuilder { * @param paymentId 支付订单id */ public PayOrderExtra buildPayOrderExtra(PayParam payParam, Long paymentId) { + PlatformLocal platform = PaymentContextLocal.get().getPlatform(); + NoticeLocal noticeInfo = PaymentContextLocal.get().getNoticeInfo(); PayOrderExtra payOrderExtra = new PayOrderExtra() .setClientIp(payParam.getClientIp()) .setDescription(payParam.getDescription()) - .setNotReturn(payParam.isNotReturn()) - .setReturnUrl(payParam.getReturnUrl()) .setNotNotify(payParam.isNotNotify()) - .setNotifyUrl(payParam.getNotifyUrl()) + .setNotifyUrl(noticeInfo.getNotifyUrl()) .setSign(payParam.getSign()) - .setSignType(payParam.getSignType()) - .setSignType(payParam.getSign()) + .setSignType(platform.getSignType()) .setApiVersion(payParam.getVersion()) .setReqTime(payParam.getReqTime()); payOrderExtra.setId(paymentId); @@ -101,12 +102,12 @@ public class PaymentBuilder { /** * 构建支付订单的可退款信息列表 */ - private List buildRefundableInfo(List payWayParamList) { + private List buildRefundableInfo(List payWayParamList) { if (CollectionUtil.isEmpty(payWayParamList)) { return Collections.emptyList(); } return payWayParamList.stream() - .map(o-> new PayOrderRefundableInfo() + .map(o-> new OrderRefundableInfo() .setChannel(o.getChannel()) .setAmount(o.getAmount())) .collect(Collectors.toList()); @@ -120,11 +121,11 @@ public class PaymentBuilder { */ public PayResult buildPayResultByPayOrder(PayOrder payOrder) { PayResult paymentResult; - paymentResult = new PayResult() - .setPaymentId(payOrder.getId()) - .setAsyncPayMode(payOrder.isAsyncPayMode()) - .setAsyncPayChannel(payOrder.getAsyncPayChannel()) - .setStatus(payOrder.getStatus()); + paymentResult = new PayResult(); + paymentResult.setPaymentId(payOrder.getId()); + paymentResult.setAsyncPayMode(payOrder.isAsyncPayMode()); + paymentResult.setAsyncPayChannel(payOrder.getAsyncPayChannel()); + paymentResult.setStatus(payOrder.getStatus()); // 设置异步支付参数 AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo();; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/dao/PayOrderChannelManager.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/dao/PayOrderChannelManager.java index bf25470d..5262f3ce 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/dao/PayOrderChannelManager.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/dao/PayOrderChannelManager.java @@ -20,10 +20,21 @@ public class PayOrderChannelManager extends BaseManager findByOderIdAndChannel(Long paymentId, String channel) { + public Optional findByPaymentIdAndChannel(Long paymentId, String channel) { return lambdaQuery() .eq(PayOrderChannel::getPaymentId,paymentId) .eq(PayOrderChannel::getChannel,channel) .oneOpt(); } + + /** + * 根据订单id删除异步支付记录 + */ + public void deleteByPaymentIdAndAsync(Long paymentId){ + lambdaUpdate() + .eq(PayOrderChannel::getPaymentId,paymentId) + .eq(PayOrderChannel::isAsync,true) + .remove(); + + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/entity/PayOrder.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/entity/PayOrder.java index c166a1c5..cf4fa8bb 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/entity/PayOrder.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/entity/PayOrder.java @@ -5,6 +5,7 @@ import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity; import cn.bootx.platform.common.mybatisplus.handler.JacksonRawTypeHandler; import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.code.PayStatusEnum; +import cn.bootx.platform.daxpay.common.entity.OrderRefundableInfo; import cn.bootx.table.modify.annotation.DbColumn; import cn.bootx.table.modify.mysql.annotation.DbMySqlFieldType; import cn.bootx.table.modify.mysql.annotation.DbMySqlIndex; @@ -64,13 +65,13 @@ public class PayOrder extends MpBaseEntity { /** * 退款信息列表 - * @see PayOrderRefundableInfo + * @see OrderRefundableInfo */ @TableField(typeHandler = JacksonRawTypeHandler.class) @BigField @DbMySqlFieldType(MySqlFieldTypeEnum.LONGTEXT) @DbColumn(comment = "退款信息列表") - private List refundableInfos; + private List refundableInfos; /** * 支付状态 diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/entity/PayOrderChannel.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/entity/PayOrderChannel.java index 6b38d41a..e3fff1f2 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/entity/PayOrderChannel.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/entity/PayOrderChannel.java @@ -1,6 +1,6 @@ package cn.bootx.platform.daxpay.core.order.pay.entity; -import cn.bootx.platform.common.mybatisplus.base.MpDelEntity; +import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity; import cn.bootx.platform.daxpay.param.channel.AliPayParam; import cn.bootx.platform.daxpay.param.channel.VoucherPayParam; import cn.bootx.platform.daxpay.param.channel.WalletPayParam; @@ -22,7 +22,7 @@ import lombok.experimental.Accessors; @Accessors(chain = true) @DbTable(comment = "支付订单关联支付时通道信息") @TableName("pay_order_channel") -public class PayOrderChannel extends MpDelEntity { +public class PayOrderChannel extends MpCreateEntity { @DbColumn(comment = "支付id") private Long paymentId; @@ -33,6 +33,9 @@ public class PayOrderChannel extends MpDelEntity { @DbColumn(comment = "支付方式") private String payWay; + @DbColumn(comment = "异步支付方式") + private boolean async; + @DbColumn(comment = "金额") private Integer amount; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/entity/PayOrderExtra.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/entity/PayOrderExtra.java index bc4b86b0..10864ba7 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/entity/PayOrderExtra.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/entity/PayOrderExtra.java @@ -3,6 +3,8 @@ package cn.bootx.platform.daxpay.core.order.pay.entity; import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity; import cn.bootx.table.modify.annotation.DbColumn; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; @@ -21,27 +23,21 @@ import java.time.LocalDateTime; @TableName("pay_order_extra") public class PayOrderExtra extends MpBaseEntity { - /** 支付终端ip */ - @DbColumn(comment = "支付终端ip") - private String clientIp; - /** 描述 */ @DbColumn(comment = "描述") private String description; - @DbColumn(comment = "是否不进行同步通知的跳转") - private boolean notReturn; - - /** 同步通知URL */ - @DbColumn(comment = "同步通知URL") - private String returnUrl; + /** 支付终端ip */ + @DbColumn(comment = "支付终端ip") + private String clientIp; /** 是否不启用异步通知 */ - @DbColumn(comment = "是否不启用异步通知") + @DbColumn(comment = "是否不启用异步通知,以最后一次为准") private boolean notNotify; /** 异步通知地址 */ - @DbColumn(comment = "异步通知地址") + @DbColumn(comment = "异步通知地址,以最后一次为准") + @TableField(updateStrategy = FieldStrategy.ALWAYS) private String notifyUrl; /** 签名类型 */ @@ -49,15 +45,15 @@ public class PayOrderExtra extends MpBaseEntity { private String signType; /** 签名 */ - @DbColumn(comment = "签名") + @DbColumn(comment = "签名,以最后一次为准") private String sign; /** API版本号 */ @DbColumn(comment = "API版本号") private String apiVersion; - /** 请求时间,时间戳转时间 */ - @DbColumn(comment = "请求时间,传输时间戳") + /** 请求时间,时间戳转时间, 以最后一次为准 */ + @DbColumn(comment = "请求时间,传输时间戳,以最后一次为准") private LocalDateTime reqTime; /** 错误码 */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/service/PayOrderService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/service/PayOrderService.java index 4fa9c715..e173c238 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/service/PayOrderService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/pay/service/PayOrderService.java @@ -10,7 +10,7 @@ import cn.bootx.platform.daxpay.core.order.pay.dao.PayOrderExtraManager; import cn.bootx.platform.daxpay.core.order.pay.dao.PayOrderManager; import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrder; import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrderChannel; -import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrderRefundableInfo; +import cn.bootx.platform.daxpay.common.entity.OrderRefundableInfo; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -86,8 +86,8 @@ public class PayOrderService { */ public void updateRefundSuccess(PayOrder payment, int amount, PayChannelEnum payChannelEnum) { // 删除旧有的退款记录, 替换退款完的新的 - List refundableInfos = payment.getRefundableInfos(); - PayOrderRefundableInfo refundableInfo = refundableInfos.stream() + List refundableInfos = payment.getRefundableInfos(); + OrderRefundableInfo refundableInfo = refundableInfos.stream() .filter(o -> Objects.equals(o.getChannel(), payChannelEnum.getCode())) .findFirst() .orElseThrow(() -> new PayFailureException("退款数据不存在")); diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/refund/convert/RefundConvert.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/refund/convert/RefundConvert.java new file mode 100644 index 00000000..21aa96d7 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/refund/convert/RefundConvert.java @@ -0,0 +1,19 @@ +package cn.bootx.platform.daxpay.core.order.refund.convert; + +import cn.bootx.platform.daxpay.core.order.refund.entity.PayRefundOrder; +import cn.bootx.platform.daxpay.dto.order.refund.PayRefundOrderDto; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * @author xxm + * @since 2022/3/2 + */ +@Mapper +public interface RefundConvert { + + RefundConvert CONVERT = Mappers.getMapper(RefundConvert.class); + + PayRefundOrderDto convert(PayRefundOrder in); + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/refund/dao/PayRefundOrderManager.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/refund/dao/PayRefundOrderManager.java new file mode 100644 index 00000000..9b0f1893 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/refund/dao/PayRefundOrderManager.java @@ -0,0 +1,34 @@ +package cn.bootx.platform.daxpay.core.order.refund.dao; + +import cn.bootx.platform.common.core.rest.param.PageParam; +import cn.bootx.platform.common.mybatisplus.base.MpIdEntity; +import cn.bootx.platform.common.mybatisplus.impl.BaseManager; +import cn.bootx.platform.common.mybatisplus.util.MpUtil; +import cn.bootx.platform.daxpay.core.order.refund.entity.PayRefundOrder; +import cn.bootx.platform.daxpay.dto.order.refund.PayRefundOrderDto; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Repository; + +import java.util.Objects; + +/** + * @author xxm + * @since 2022/3/2 + */ +@Slf4j +@Repository +@RequiredArgsConstructor +public class PayRefundOrderManager extends BaseManager { + + public Page page(PageParam pageParam, PayRefundOrderDto param) { + Page mpPage = MpUtil.getMpPage(pageParam, PayRefundOrder.class); + return lambdaQuery().orderByDesc(MpIdEntity::getId) + .like(Objects.nonNull(param.getPaymentId()), PayRefundOrder::getPaymentId, param.getPaymentId()) + .like(Objects.nonNull(param.getBusinessNo()), PayRefundOrder::getBusinessNo, param.getBusinessNo()) + .like(Objects.nonNull(param.getTitle()), PayRefundOrder::getTitle, param.getTitle()) + .page(mpPage); + } + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/refund/dao/PayRefundOrderMapper.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/refund/dao/PayRefundOrderMapper.java new file mode 100644 index 00000000..720c89ae --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/refund/dao/PayRefundOrderMapper.java @@ -0,0 +1,14 @@ +package cn.bootx.platform.daxpay.core.order.refund.dao; + +import cn.bootx.platform.daxpay.core.order.refund.entity.PayRefundOrder; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author xxm + * @since 2022/3/2 + */ +@Mapper +public interface PayRefundOrderMapper extends BaseMapper { + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/refund/entity/PayRefundOrder.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/refund/entity/PayRefundOrder.java new file mode 100644 index 00000000..403d1659 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/refund/entity/PayRefundOrder.java @@ -0,0 +1,77 @@ +package cn.bootx.platform.daxpay.core.order.refund.entity; + +import cn.bootx.platform.common.core.function.EntityBaseFunction; +import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity; +import cn.bootx.platform.common.mybatisplus.handler.JacksonRawTypeHandler; +import cn.bootx.platform.daxpay.common.entity.OrderRefundableInfo; +import cn.bootx.platform.daxpay.core.order.refund.convert.RefundConvert; +import cn.bootx.platform.daxpay.dto.order.refund.PayRefundOrderDto; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 退款记录 + * + * @author xxm + * @since 2022/3/2 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Accessors(chain = true) +@TableName(value = "pay_refund_order", autoResultMap = true) +public class PayRefundOrder extends MpBaseEntity implements EntityBaseFunction { + + /** 支付单号 */ + private Long paymentId; + + /** 关联的业务号 */ + private String businessNo; + + /** 异步方式关联退款请求号(部分退款情况) */ + private String refundRequestNo; + + /** 标题 */ + private String title; + + /** 退款金额 */ + private Integer amount; + + /** 剩余可退 */ + private Integer refundableBalance; + + /** 退款终端ip */ + private String clientIp; + + /** 退款时间 */ + private LocalDateTime refundTime; + + /** + * 退款信息列表 + */ + @TableField(typeHandler = JacksonRawTypeHandler.class) + private List refundableInfo; + + /** + * 退款状态 + * @see PayStatus#REFUND_PROCESS_FAIL + */ + private String refundStatus; + + /** 错误码 */ + private String errorCode; + + /** 错误信息 */ + private String errorMsg; + + @Override + public PayRefundOrderDto toDto() { + return RefundConvert.CONVERT.convert(this); + } + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/refund/service/PayRefundRecordService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/refund/service/PayRefundRecordService.java new file mode 100644 index 00000000..b955782b --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/order/refund/service/PayRefundRecordService.java @@ -0,0 +1,43 @@ +package cn.bootx.platform.daxpay.core.order.refund.service; + +import cn.bootx.platform.common.core.exception.DataNotExistException; +import cn.bootx.platform.common.core.rest.PageResult; +import cn.bootx.platform.common.core.rest.param.PageParam; +import cn.bootx.platform.common.mybatisplus.util.MpUtil; +import cn.bootx.platform.daxpay.core.order.refund.dao.PayRefundOrderManager; +import cn.bootx.platform.daxpay.core.order.refund.entity.PayRefundOrder; +import cn.bootx.platform.daxpay.dto.order.refund.PayRefundOrderDto; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * 退款 + * + * @author xxm + * @since 2022/3/2 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class PayRefundRecordService { + + private final PayRefundOrderManager refundRecordManager; + + /** + * 分页查询 + */ + public PageResult page(PageParam pageParam, PayRefundOrderDto param) { + Page page = refundRecordManager.page(pageParam, param); + return MpUtil.convert2DtoPageResult(page); + } + + /** + * 根据id查询 + */ + public PayRefundOrderDto findById(Long id) { + return refundRecordManager.findById(id).map(PayRefundOrder::toDto).orElseThrow(DataNotExistException::new); + } + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/callback/result/PayCallbackResult.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/callback/result/PayCallbackResult.java index a44d516d..2cd7be82 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/callback/result/PayCallbackResult.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/callback/result/PayCallbackResult.java @@ -18,7 +18,7 @@ public class PayCallbackResult { * 处理状态 * @see PayStatusEnum */ - private String code; + private String status; /** 提示信息 */ private String msg; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/callback/service/PayCallbackService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/callback/service/PayCallbackService.java index 57371d7b..1b1c76a6 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/callback/service/PayCallbackService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/callback/service/PayCallbackService.java @@ -42,22 +42,22 @@ public class PayCallbackService { */ public PayCallbackResult callback(Long paymentId, String tradeStatus, Map map) { - // 获取payment和paymentParam数据 + // 获取支付单 PayOrder payOrder = payOrderService.findById(paymentId).orElse(null); // 支付单不存在,记录回调记录 if (Objects.isNull(payOrder)) { - return new PayCallbackResult().setCode(PayNotifyStatusEnum.FAIL.getCode()).setMsg("支付单不存在,记录回调记录"); + return new PayCallbackResult().setStatus(PayNotifyStatusEnum.FAIL.getCode()).setMsg("支付单不存在,记录回调记录"); } - // 回调时间超出了支付单超时时间, 记录一下, 不做处理 + // 回调时间超出了支付单超时时间, 记录一下, 不做处理 TODO 这块应该吧订单给正常处理了, if (Objects.nonNull(payOrder.getExpiredTime()) && LocalDateTimeUtil.ge(LocalDateTime.now(), payOrder.getExpiredTime())) { - return new PayCallbackResult().setCode(PayNotifyStatusEnum.FAIL.getCode()).setMsg("回调时间超出了支付单支付有效时间"); + return new PayCallbackResult().setStatus(PayNotifyStatusEnum.FAIL.getCode()).setMsg("回调时间超出了支付单支付有效时间"); } // 成功状态 - if (Objects.equals(PayNotifyStatusEnum.SUCCESS, tradeStatus)) { + if (Objects.equals(PayNotifyStatusEnum.SUCCESS.getCode(), tradeStatus)) { return this.success(payOrder, map); } else { @@ -70,16 +70,16 @@ public class PayCallbackService { * 成功处理 */ private PayCallbackResult success(PayOrder payOrder, Map map) { - PayCallbackResult result = new PayCallbackResult().setCode(PayNotifyStatusEnum.SUCCESS.getCode()); + PayCallbackResult result = new PayCallbackResult().setStatus(PayNotifyStatusEnum.SUCCESS.getCode()); // payment已经被支付,不需要重复处理 if (Objects.equals(payOrder.getStatus(), PayStatusEnum.SUCCESS.getCode())) { - return result.setCode(PayNotifyStatusEnum.IGNORE.getCode()).setMsg("支付单已经是支付成功状态,不进行处理"); + return result.setStatus(PayNotifyStatusEnum.IGNORE.getCode()).setMsg("支付单已经是支付成功状态,不进行处理"); } // payment已被取消,记录回调记录 if (!Objects.equals(payOrder.getStatus(), PayStatusEnum.PROGRESS.getCode())) { - return result.setCode(PayNotifyStatusEnum.FAIL.getCode()).setMsg("支付单不是待支付状态,记录回调记录"); + return result.setStatus(PayNotifyStatusEnum.FAIL.getCode()).setMsg("支付单不是待支付状态,记录回调记录"); } // 2.通过工厂生成对应的策略组 @@ -87,7 +87,7 @@ public class PayCallbackService { List paymentStrategyList = PayStrategyFactory.create(payParam.getPayWays()); if (CollectionUtil.isEmpty(paymentStrategyList)) { - return result.setCode(PayStatusEnum.FAIL.getCode()).setMsg("支付单数据非法,未找到对应的支付方式"); + return result.setStatus(PayStatusEnum.FAIL.getCode()).setMsg("支付单数据非法,未找到对应的支付方式"); } // 3.初始化支付的参数 @@ -110,7 +110,7 @@ public class PayCallbackService { // eventSender.sendPayComplete(PayEventBuilder.buildPayComplete(payOrder)); } else { - return result.setCode(PayStatusEnum.FAIL.getCode()).setMsg("回调处理过程报错"); + return result.setStatus(PayStatusEnum.FAIL.getCode()).setMsg("回调处理过程报错"); } return result; } @@ -119,23 +119,23 @@ public class PayCallbackService { * 失败处理, 关闭并退款 按说这块不会发生 */ private PayCallbackResult fail(PayOrder payOrder, Map map) { - PayCallbackResult result = new PayCallbackResult().setCode(PayStatusEnum.SUCCESS.getCode()); + PayCallbackResult result = new PayCallbackResult().setStatus(PayStatusEnum.SUCCESS.getCode()); // payment已被取消,记录回调记录,后期处理 if (!Objects.equals(payOrder.getStatus(), PayStatusEnum.PROGRESS.getCode())) { - return result.setCode(PayNotifyStatusEnum.IGNORE.getCode()).setMsg("支付单已经取消,记录回调记录"); + return result.setStatus(PayNotifyStatusEnum.IGNORE.getCode()).setMsg("支付单已经取消,记录回调记录"); } // payment支付成功, 状态非法 if (!Objects.equals(payOrder.getStatus(), PayStatusEnum.SUCCESS.getCode())) { - return result.setCode(PayNotifyStatusEnum.FAIL.getCode()).setMsg("支付单状态非法,支付网关状态为失败,但支付单状态为已完成"); + return result.setStatus(PayNotifyStatusEnum.FAIL.getCode()).setMsg("支付单状态非法,支付网关状态为失败,但支付单状态为已完成"); } // 2.通过工厂生成对应的策略组 PayParam payParam = null; List paymentStrategyList = PayStrategyFactory.create(payParam.getPayWays()); if (CollectionUtil.isEmpty(paymentStrategyList)) { - return result.setCode(PayNotifyStatusEnum.FAIL.getCode()).setMsg("支付单数据非法,未找到对应的支付方式"); + return result.setStatus(PayNotifyStatusEnum.FAIL.getCode()).setMsg("支付单数据非法,未找到对应的支付方式"); } // 3.初始化支付关闭的参数 for (AbsPayStrategy paymentStrategy : paymentStrategyList) { @@ -156,7 +156,7 @@ public class PayCallbackService { // eventSender.sendPayRefund(PayEventBuilder.buildPayRefund(payOrder)); } else { - return result.setCode(PayNotifyStatusEnum.FAIL.getCode()).setMsg("回调处理过程报错"); + return result.setStatus(PayNotifyStatusEnum.FAIL.getCode()).setMsg("回调处理过程报错"); } return result; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/common/aop/PaymentSignAop.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/common/aop/PaymentVerifySignAop.java similarity index 84% rename from daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/common/aop/PaymentSignAop.java rename to daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/common/aop/PaymentVerifySignAop.java index 4a5bc408..7ac878b9 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/common/aop/PaymentSignAop.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/common/aop/PaymentVerifySignAop.java @@ -1,5 +1,6 @@ package cn.bootx.platform.daxpay.core.payment.common.aop; +import cn.bootx.platform.common.core.util.ValidationUtil; import cn.bootx.platform.daxpay.annotation.PaymentApi; import cn.bootx.platform.daxpay.core.payment.common.service.PaymentSignService; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; @@ -12,7 +13,7 @@ import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; /** - * 支付签名切面, 用于对支付参数进行签名 + * 支付签名切面, 用于对支付参数进行校验和签名 * 执行顺序: 过滤器 -> 拦截器 -> 切面 -> 方法 * @author xxm * @since 2023/12/24 @@ -21,7 +22,7 @@ import org.springframework.stereotype.Component; @Slf4j @Component @RequiredArgsConstructor -public class PaymentSignAop { +public class PaymentVerifySignAop { private final PaymentSignService paymentSignService; @Before("@annotation(paymentApi)") @@ -32,6 +33,9 @@ public class PaymentSignAop { } Object param = args[0]; if (param instanceof PayCommonParam){ + // 参数校验 + ValidationUtil.validateParam(param); + // 验签 paymentSignService.verifySign((PayCommonParam) param); } else { throw new PayFailureException("支付参数需要继承PayCommonParam"); diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/common/service/PaymentSignService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/common/service/PaymentSignService.java index d551d2a4..7caf9224 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/common/service/PaymentSignService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/common/service/PaymentSignService.java @@ -2,9 +2,9 @@ package cn.bootx.platform.daxpay.core.payment.common.service; import cn.bootx.platform.daxpay.code.PaySignTypeEnum; import cn.bootx.platform.daxpay.common.context.ApiInfoLocal; +import cn.bootx.platform.daxpay.common.context.PlatformLocal; import cn.bootx.platform.daxpay.common.local.PaymentContextLocal; -import cn.bootx.platform.daxpay.core.system.entity.PlatformConfig; -import cn.bootx.platform.daxpay.core.system.service.PlatformConfigService; +import cn.bootx.platform.daxpay.core.payment.pay.service.PayAssistService; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.param.pay.PayCommonParam; import cn.hutool.core.util.StrUtil; @@ -28,13 +28,16 @@ public class PaymentSignService { private static final String FIELD_SIGN = "sign"; - private final PlatformConfigService platformConfigService; + private final PayAssistService payAssistService;; /** * 签名 */ public void verifySign(PayCommonParam param) { + // 先触发一下平台配置上下文的初始化 + payAssistService.initPlatform(); ApiInfoLocal apiInfo = PaymentContextLocal.get().getApiInfo(); + PlatformLocal platform = PaymentContextLocal.get().getPlatform(); // 判断当前接口是否不需要签名 if (!apiInfo.isReqSign()){ @@ -42,20 +45,19 @@ public class PaymentSignService { } // 参数转换为Map对象 Map params = param.toMap(); - PlatformConfig config = platformConfigService.getConfig(); - String signType = config.getSignType(); + String signType = platform.getSignType(); // 生成签名前先去除sign params.remove(FIELD_SIGN); String data = PayKit.createLinkString(params); if (Objects.equals(PaySignTypeEnum.HMAC_SHA256.getCode(), signType)){ // 签名验证 - data += "&key=" + config.getSignSecret(); - String sha256 = PayKit.hmacSha256(data, config.getSignSecret()); + data += "&key=" + platform.getSignSecret(); + String sha256 = PayKit.hmacSha256(data, platform.getSignSecret()); if (!Objects.equals(sha256, params.get(FIELD_SIGN))){ throw new PayFailureException("签名验证未通过"); } } else if (Objects.equals(PaySignTypeEnum.MD5.getCode(), signType)){ - data += "&key=" + config.getSignSecret(); + data += "&key=" + platform.getSignSecret(); String md5 = PayKit.md5(data.toUpperCase()); String sign = StrUtil.toString(params.get(FIELD_SIGN)); // 签名验证 diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/pay/service/PayAssistService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/pay/service/PayAssistService.java index 9f8e2a4d..95eae84b 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/pay/service/PayAssistService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/pay/service/PayAssistService.java @@ -1,16 +1,23 @@ package cn.bootx.platform.daxpay.core.payment.pay.service; +import cn.bootx.platform.common.core.code.CommonCode; import cn.bootx.platform.daxpay.common.context.AsyncPayLocal; +import cn.bootx.platform.daxpay.common.context.NoticeLocal; +import cn.bootx.platform.daxpay.common.context.PlatformLocal; +import cn.bootx.platform.daxpay.common.context.RequestLocal; import cn.bootx.platform.daxpay.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrder; import cn.bootx.platform.daxpay.core.system.entity.PlatformConfig; import cn.bootx.platform.daxpay.core.system.service.PlatformConfigService; import cn.bootx.platform.daxpay.param.pay.PayParam; import cn.bootx.platform.daxpay.util.PayUtil; +import cn.hutool.core.util.StrUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.slf4j.MDC; import org.springframework.stereotype.Service; +import java.time.LocalDateTime; import java.util.Objects; /** @@ -23,6 +30,32 @@ import java.util.Objects; @RequiredArgsConstructor public class PayAssistService { private final PlatformConfigService platformConfigService; + /** + * 初始化平台配置上下文 + */ + public void initPlatform(){ + PlatformConfig config = platformConfigService.getConfig(); + PlatformLocal platform = PaymentContextLocal.get().getPlatform(); + platform.setSignType(config.getSignType()); + platform.setSignSecret(config.getSignSecret()); + platform.setNotifyUrl(config.getNotifyUrl()); + platform.setOrderTimeout(config.getOrderTimeout()); + platform.setWebsiteUrl(config.getWebsiteUrl()); + } + + /** + * 初始化支付相关上下文 + */ + public void initPayContext(PayOrder order, PayParam payParam){ + // 初始化支付订单超时时间 + this.initExpiredTime(order,payParam); + // 初始化通知相关上下文 + this.initNotice(payParam); + // 初始化请求相关上下文 + this.initRequest(payParam); + } + + /** * 初始化支付订单超时时间 * 1. 如果支付记录为空, 超时时间读取顺序 PayParam -> 平台设置 @@ -34,6 +67,7 @@ public class PayAssistService { return; } AsyncPayLocal asyncPayInfo = PaymentContextLocal.get().getAsyncPayInfo(); + PlatformLocal platform = PaymentContextLocal.get().getPlatform(); // 支付订单是非为空 if (Objects.nonNull(order)){ asyncPayInfo.setExpiredTime(order.getExpiredTime()); @@ -44,7 +78,41 @@ public class PayAssistService { asyncPayInfo.setExpiredTime(payParam.getExpiredTime()); return; } - PlatformConfig config = platformConfigService.getConfig(); - PayUtil.getPaymentExpiredTime(config.getOrderTimeout()); + LocalDateTime paymentExpiredTime = PayUtil.getPaymentExpiredTime(platform.getOrderTimeout()); + asyncPayInfo.setExpiredTime(paymentExpiredTime); + } + + /** + * 初始化通知相关上下文 + */ + private void initNotice(PayParam payParam){ + NoticeLocal noticeInfo = PaymentContextLocal.get().getNoticeInfo(); + PlatformLocal platform = PaymentContextLocal.get().getPlatform(); + // 异步回调 + if (!payParam.isNotNotify()){ + noticeInfo.setNotifyUrl(payParam.getReturnUrl()); + if (StrUtil.isNotBlank(payParam.getNotifyUrl())){ + noticeInfo.setNotifyUrl(platform.getNotifyUrl()); + } + } + // 同步回调 + if (!payParam.isNotReturn()){ + noticeInfo.setReturnUrl(payParam.getReturnUrl()); + } + // 退出回调地址 + noticeInfo.setQuitUrl(payParam.getQuitUrl()); + } + + /** + * 初始化支付请求相关信息 + */ + public void initRequest(PayParam payParam){ + RequestLocal request = PaymentContextLocal.get().getRequest(); + request.setClientIp(payParam.getClientIp()) + .setExtraParam(payParam.getExtraParam()) + .setSign(payParam.getSign()) + .setVersion(payParam.getVersion()) + .setReqTime(payParam.getReqTime()) + .setReqId(MDC.get(CommonCode.TRACE_ID)); } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/pay/service/PayService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/pay/service/PayService.java index f85ab51b..3834ecc7 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/pay/service/PayService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/pay/service/PayService.java @@ -1,16 +1,16 @@ package cn.bootx.platform.daxpay.core.payment.pay.service; +import cn.bootx.platform.common.core.exception.DataNotExistException; import cn.bootx.platform.common.core.util.LocalDateTimeUtil; -import cn.bootx.platform.common.core.util.ValidationUtil; import cn.bootx.platform.daxpay.code.PayChannelEnum; import cn.bootx.platform.daxpay.code.PayStatusEnum; import cn.bootx.platform.daxpay.core.order.pay.builder.PaymentBuilder; import cn.bootx.platform.daxpay.core.order.pay.dao.PayOrderChannelManager; import cn.bootx.platform.daxpay.core.order.pay.dao.PayOrderExtraManager; +import cn.bootx.platform.daxpay.core.order.pay.dao.PayOrderManager; import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrder; import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrderChannel; import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrderExtra; -import cn.bootx.platform.daxpay.core.order.pay.service.PayOrderService; import cn.bootx.platform.daxpay.core.payment.pay.factory.PayStrategyFactory; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.exception.pay.PayUnsupportedMethodException; @@ -18,8 +18,11 @@ import cn.bootx.platform.daxpay.func.AbsPayStrategy; import cn.bootx.platform.daxpay.func.PayStrategyConsumer; import cn.bootx.platform.daxpay.param.pay.PayParam; import cn.bootx.platform.daxpay.param.pay.PayWayParam; +import cn.bootx.platform.daxpay.param.pay.SimplePayParam; import cn.bootx.platform.daxpay.result.pay.PayResult; import cn.bootx.platform.daxpay.util.PayUtil; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.collection.CollectionUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -43,7 +46,7 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class PayService { - private final PayOrderService payOrderService; + private final PayOrderManager payOrderManager; private final PayAssistService payAssistService;; @@ -51,41 +54,57 @@ public class PayService { private final PayOrderChannelManager payOrderChannelManager; - /** - * 支付方法(同步/异步/组合支付) 同步支付:都只会在第一次执行中就完成支付,例如钱包、积分都是调用完就进行了扣减,完成了支付记录 - * 异步支付:例如支付宝、微信,发起支付后还需要跳转第三方平台进行支付,支付后通常需要进行回调,之后才完成支付记录 - * 组合支付:主要是混合了同步支付和异步支付,同时异步支付只能有一个,在支付时先对同步支付进行扣减,然后异步支付回调结束后完成整个支付单 - * 组合支付在非第一次支付的时候,只对新传入的异步支付PayMode进行处理,PayMode的价格使用第一次发起的价格,旧的同步支付如果传入后也不做处理, - * Payment中PayModeList将会为 旧有的同步支付+新传入的异步支付方式(在具体支付实现中处理) + * 支付下单接口(同步/异步/组合支付) + * 1. 同步支付:都只会在第一次执行中就完成支付,例如钱包、储值卡都是调用完就进行了扣减,完成了支付记录 + * 2. 异步支付:例如支付宝、微信,发起支付后还需要跳转第三方平台进行支付,支付后通常需要进行回调,之后才完成支付记录 + * 3. 组合支付:主要是混合了同步支付和异步支付,同时异步支付只能有一个,在支付时先对同步支付进行扣减,然后异步支付回调结束后完成整个支付单 + * 注意: + * 组合支付在非第一次支付的时候,只对新传入的异步支付通道进行处理,该通道的价格使用第一次发起的价格,旧的同步支付如果传入后也不做处理, + * 支付单中支付通道列表将会为 旧有的同步支付+新传入的异步支付方式(在具体支付实现中处理) */ @Transactional(rollbackFor = Exception.class) public PayResult pay(PayParam payParam) { - // 检验参数 - ValidationUtil.validateParam(payParam); - // 异步支付方式检查 PayUtil.validationAsyncPayMode(payParam); - // 获取并校验支付状态 - PayOrder payOrder = this.getAndCheckByBusinessId(payParam.getBusinessNo()); + // 获取并校验支付订单状态 + PayOrder payOrder = this.getAndCheckByBusinessNo(payParam.getBusinessNo()); // 初始化上下文 - payAssistService.initExpiredTime(payOrder, payParam); + payAssistService.initPayContext(payOrder, payParam); // 异步支付且非第一次支付 if (Objects.nonNull(payOrder) && payOrder.isAsyncPayMode()) { return this.paySyncNotFirst(payParam, payOrder); } else { // 第一次发起支付或同步支付 - return this.payFirst(payParam, payOrder); + return this.firstPay(payParam, payOrder); } } + /** + * 简单下单, 可以视为不支持组合支付的下单接口 + */ + @Transactional(rollbackFor = Exception.class) + public PayResult simplePay(SimplePayParam simplePayParam) { + // 组装支付参数 + PayParam payParam = new PayParam(); + PayWayParam payWayParam = new PayWayParam(); + payWayParam.setChannel(simplePayParam.getPayChannel()); + payWayParam.setWay(simplePayParam.getPayWay()); + payWayParam.setAmount(simplePayParam.getAmount()); + payWayParam.setChannelExtra(simplePayParam.getChannelExtra()); + BeanUtil.copyProperties(simplePayParam,payWayParam, CopyOptions.create().ignoreNullValue()); + payParam.setPayWays(Collections.singletonList(payWayParam)); + // 复用支付下单接口 + return this.pay(payParam); + } + /** * 发起的第一次支付请求(同步/异步) */ - private PayResult payFirst(PayParam payParam, PayOrder payOrder) { + private PayResult firstPay(PayParam payParam, PayOrder payOrder) { // 1. 已经发起过支付情况直接返回支付结果 if (Objects.nonNull(payOrder)) { return PaymentBuilder.buildPayResultByPayOrder(payOrder); @@ -98,18 +117,16 @@ public class PayService { payOrder = this.createPayOrder(payParam); // 4. 调用支付方法进行发起支付 - this.payFirstMethod(payParam, payOrder); + this.firstPayHandler(payParam, payOrder); // 5. 返回支付结果 return PaymentBuilder.buildPayResultByPayOrder(payOrder); } /** - * 执行支付方法 (第一次支付) - * @param payParam 支付参数 - * @param payOrder 支付订单 + * 执行第一次支付的方法 */ - private void payFirstMethod(PayParam payParam, PayOrder payOrder) { + private void firstPayHandler(PayParam payParam, PayOrder payOrder) { // 1.获取支付方式,通过工厂生成对应的策略组 List paymentStrategyList = PayStrategyFactory.create(payParam.getPayWays()); @@ -135,7 +152,7 @@ public class PayService { payOrderObj.setStatus(PayStatusEnum.SUCCESS.getCode()); payOrderObj.setPayTime(LocalDateTime.now()); } - payOrderService.updateById(payOrderObj); + payOrderManager.updateById(payOrderObj); }); } @@ -144,32 +161,35 @@ public class PayService { */ private PayResult paySyncNotFirst(PayParam payParam, PayOrder payOrder) { - // 0. 处理支付完成情况(完成/退款) - List trades = Arrays.asList(PayStatusEnum.SUCCESS.getCode(), PayStatusEnum.CANCEL.getCode(), + // 1. 处理支付完成情况(完成/退款) + List trades = Arrays.asList(PayStatusEnum.SUCCESS.getCode(), PayStatusEnum.CANCEL.getCode(),PayStatusEnum.CLOSE.getCode(), PayStatusEnum.PARTIAL_REFUND.getCode(), PayStatusEnum.REFUNDED.getCode()); if (trades.contains(payOrder.getStatus())) { return PaymentBuilder.buildPayResultByPayOrder(payOrder); } - // 1.获取 异步支付 通道道,通过工厂生成对应的策略组(只包含异步支付的策略, 同步支付不再进行执行) + // 2.获取 异步支付通道,通过工厂生成对应的策略组(只包含异步支付的策略, 同步支付相关逻辑不再进行执行) PayWayParam payWayParam = this.getAsyncPayParam(payParam, payOrder); List asyncStrategyList = PayStrategyFactory.create(Collections.singletonList(payWayParam)); - // 2.初始化支付的参数 + // 3.初始化支付的参数 for (AbsPayStrategy paymentStrategy : asyncStrategyList) { paymentStrategy.initPayParam(payOrder, payParam); } - // 3.支付前准备 + // 4.支付前准备 this.doHandler(payOrder, asyncStrategyList, AbsPayStrategy::doBeforePayHandler, null); - // 4. 发起支付 + // 5. 发起支付 this.doHandler(payOrder, asyncStrategyList, AbsPayStrategy::doPayHandler, (strategyList, paymentObj) -> { // 发起支付成功进行的执行方法 strategyList.forEach(AbsPayStrategy::doSuccessHandler); - payOrderService.updateById(paymentObj); + payOrderManager.updateById(paymentObj); }); - // 5. 组装返回参数 + // 6. 更新支付订单扩展参数 + updatePayOrderExtra(payParam,payOrder.getId()); + + // 7. 组装返回参数 return PaymentBuilder.buildPayResultByPayOrder(payOrder); } @@ -196,7 +216,7 @@ public class PayService { private PayWayParam getAsyncPayParam(PayParam payParam, PayOrder payOrder) { // 查询之前的支付方式 String asyncPayChannel = payOrder.getAsyncPayChannel(); - PayOrderChannel payOrderChannel = payOrderChannelManager.findByOderIdAndChannel(payOrder.getId(), asyncPayChannel) + PayOrderChannel payOrderChannel = payOrderChannelManager.findByPaymentIdAndChannel(payOrder.getId(), asyncPayChannel) .orElseThrow(() -> new PayFailureException("支付方式数据异常")); // 新的异步支付方式 @@ -218,7 +238,7 @@ public class PayService { private PayOrder createPayOrder(PayParam payParam) { // 构建支付订单并保存 PayOrder payOrder = PaymentBuilder.buildPayOrder(payParam); - payOrderService.saveOder(payOrder); + payOrderManager.save(payOrder); // 构建支付订单扩展表并保存 PayOrderExtra payOrderExtra = PaymentBuilder.buildPayOrderExtra(payParam, payOrder.getId()); payOrderExtraManager.save(payOrderExtra); @@ -231,12 +251,28 @@ public class PayService { return payOrder; } + /** + * 更新支付订单扩展参数 + * @param payParam 支付参数 + * @param paymentId 支付订单id + */ + private void updatePayOrderExtra(PayParam payParam,Long paymentId){ + PayOrderExtra payOrderExtra = payOrderExtraManager.findById(paymentId) + .orElseThrow(() -> new DataNotExistException("支付订单不存在")); + payOrderExtra.setReqTime(payParam.getReqTime()) + .setSign(payParam.getSign()) + .setNotNotify(payParam.isNotNotify()) + .setNotifyUrl(payParam.getNotifyUrl()) + .setClientIp(payParam.getClientIp()); + payOrderExtraManager.updateById(payOrderExtra); + } + /** * 校验支付状态,支付成功则返回,支付失败则抛出对应的异常 */ - private PayOrder getAndCheckByBusinessId(String businessId) { + private PayOrder getAndCheckByBusinessNo(String businessNo) { // 根据订单查询支付记录 - PayOrder payment = payOrderService.findByBusinessId(businessId).orElse(null); + PayOrder payment = payOrderManager.findByBusinessNo(businessNo).orElse(null); if (Objects.nonNull(payment)) { // 支付失败类型状态 List tradesStatus = Arrays.asList(PayStatusEnum.FAIL.getCode(), PayStatusEnum.CANCEL.getCode(), diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/pay/strategy/WeChatPayStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/pay/strategy/WeChatPayStrategy.java index d4d1c189..d36f7d20 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/pay/strategy/WeChatPayStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/pay/strategy/WeChatPayStrategy.java @@ -93,8 +93,7 @@ public class WeChatPayStrategy extends AbsPayStrategy { */ @Override public void doPayHandler() { - weChatPayService.pay(this.getPayWayParam().getAmount(), this.getOrder(), this.weChatPayParam, - this.getPayWayParam(), this.weChatPayConfig); + weChatPayService.pay(this.getOrder(), this.weChatPayParam, this.getPayWayParam(), this.weChatPayConfig); } /** diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/factory/PayRefundStrategyFactory.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/factory/PayRefundStrategyFactory.java new file mode 100644 index 00000000..447b7683 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/factory/PayRefundStrategyFactory.java @@ -0,0 +1,114 @@ +package cn.bootx.platform.daxpay.core.payment.refund.factory; + +import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.core.payment.refund.func.AbsPayRefundStrategy; +import cn.bootx.platform.daxpay.core.payment.refund.strategy.*; +import cn.bootx.platform.daxpay.exception.pay.PayUnsupportedMethodException; +import cn.bootx.platform.daxpay.param.pay.RefundChannelParam; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.extra.spring.SpringUtil; +import lombok.val; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import static cn.bootx.platform.daxpay.code.PayChannelEnum.ASYNC_TYPE_CODE; + +/** + * 退款策略工厂 + * @author xxm + * @since 2023/7/4 + */ +public class PayRefundStrategyFactory { + + /** + * 根据传入的支付渠道创建策略 + * @return 支付策略 + */ + public static AbsPayRefundStrategy create(RefundChannelParam refundChannelParam) { + + AbsPayRefundStrategy strategy = null; + PayChannelEnum channelEnum = PayChannelEnum.findByCode(refundChannelParam.getPayChannel()); + switch (channelEnum) { + case ALI: + strategy = SpringUtil.getBean(AliPayRefundStrategy.class); + break; + case WECHAT: + strategy = SpringUtil.getBean(WeChatPayRefundStrategy.class); + break; + case UNION_PAY: + strategy = SpringUtil.getBean(UnionPayRefundStrategy.class); + break; + case CASH: + strategy = SpringUtil.getBean(CashPayRefundStrategy.class); + break; + case WALLET: + strategy = SpringUtil.getBean(WalletPayRefundStrategy.class); + break; + case VOUCHER: + strategy = SpringUtil.getBean(VoucherPayRefundStrategy.class); + break; + default: + throw new PayUnsupportedMethodException(); + } + strategy.setChannelParam(refundChannelParam); + return strategy; + } + + /** + * 根据传入的支付类型批量创建策略, 异步支付在后面 + */ + public static List createDesc(List refundChannelParams) { + return create(refundChannelParams, true); + } + + /** + * 根据传入的支付类型批量创建策略, 默认异步支付在前面 + */ + public static List create(List refundChannelParams) { + return create(refundChannelParams, false); + } + + /** + * 根据传入的支付类型批量创建策略 + * @param refundChannelParams 支付类型 + * @return 支付策略 + */ + private static List create(List refundChannelParams, boolean description) { + if (CollectionUtil.isEmpty(refundChannelParams)) { + return Collections.emptyList(); + } + List list = new ArrayList<>(refundChannelParams.size()); + + // 同步支付 + val syncRefundModeParams = refundChannelParams.stream() + .filter(Objects::nonNull) + .filter(payModeParam -> !ASYNC_TYPE_CODE.contains(payModeParam.getPayChannel())) + .collect(Collectors.toList()); + + // 异步支付 + val asyncRefundModeParams = refundChannelParams.stream() + .filter(Objects::nonNull) + .filter(payModeParam -> ASYNC_TYPE_CODE.contains(payModeParam.getPayChannel())) + .collect(Collectors.toList()); + + List sortList = new ArrayList<>(refundChannelParams.size()); + + // 异步在后面 + if (description) { + sortList.addAll(syncRefundModeParams); + sortList.addAll(asyncRefundModeParams); + } + else { + sortList.addAll(asyncRefundModeParams); + sortList.addAll(syncRefundModeParams); + } + + // 此处有一个根据Type的反转排序, + sortList.stream().filter(Objects::nonNull).forEach(payMode -> list.add(create(payMode))); + return list; + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/func/AbsPayRefundStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/func/AbsPayRefundStrategy.java new file mode 100644 index 00000000..9873aa26 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/func/AbsPayRefundStrategy.java @@ -0,0 +1,61 @@ +package cn.bootx.platform.daxpay.core.payment.refund.func; + +import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.common.exception.ExceptionInfo; +import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrder; +import cn.bootx.platform.daxpay.param.pay.RefundChannelParam; +import cn.bootx.platform.daxpay.param.pay.RefundParam; +import lombok.Getter; +import lombok.Setter; + +/** + * 抽象支付退款策略基类 + * + * @author xxm + * @since 2020/12/11 + */ +@Getter +@Setter +public abstract class AbsPayRefundStrategy { + + /** 支付对象 */ + private PayOrder order = null; + + /** 退款参数 */ + private RefundParam refundParam = null; + + /** 当前支付通道退款参数 退款参数中的与这个不一致, 以这个为准 */ + private RefundChannelParam channelParam = null; + + /** + * 策略标识 + * @see PayChannelEnum + */ + public abstract PayChannelEnum getType(); + + /** + * 初始化支付的参数 + */ + public void initPayParam(PayOrder payOrder, RefundParam refundParam) { + this.order = payOrder; + this.refundParam = refundParam; + } + + /** + * 退款前对处理 包含必要的校验以及对Payment对象的创建和保存操作 + */ + public void doBeforeRefundHandler() { + } + + /** + * 退款操作 + */ + public abstract void doRefundHandler(); + + /** + * 退款失败的处理方式 + */ + public void doErrorHandler(ExceptionInfo exceptionInfo) { + } + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/func/PayRefundStrategyConsumer.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/func/PayRefundStrategyConsumer.java new file mode 100644 index 00000000..fa4f3370 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/func/PayRefundStrategyConsumer.java @@ -0,0 +1,17 @@ +package cn.bootx.platform.daxpay.core.payment.refund.func; + +import cn.bootx.platform.daxpay.core.order.pay.entity.PayOrder; + +import java.util.List; + +/** + * 支付退款策略接口 + * @author xxm + * @since 2023/7/5 + */ +@FunctionalInterface +public interface PayRefundStrategyConsumer, S extends PayOrder> { + + void accept(T t, S s); + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/service/PayRefundService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/service/PayRefundService.java index 986f6543..8fdb25b2 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/service/PayRefundService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/service/PayRefundService.java @@ -1,5 +1,7 @@ package cn.bootx.platform.daxpay.core.payment.refund.service; +import cn.bootx.platform.daxpay.param.pay.RefundParam; +import cn.bootx.platform.daxpay.result.pay.RefundResult; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -13,4 +15,14 @@ import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class PayRefundService { + + /** + * 支付退款 + */ + public RefundResult refund(RefundParam param){ + + return null; + } + + } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/AliPayRefundStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/AliPayRefundStrategy.java new file mode 100644 index 00000000..96ebcaaa --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/AliPayRefundStrategy.java @@ -0,0 +1,62 @@ +package cn.bootx.platform.daxpay.core.payment.refund.strategy; + +import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.core.channel.alipay.entity.AlipayConfig; +import cn.bootx.platform.daxpay.core.channel.alipay.service.AliPayOrderService; +import cn.bootx.platform.daxpay.core.channel.alipay.service.AliPayRefundService; +import cn.bootx.platform.daxpay.core.channel.alipay.service.AlipayConfigService; +import cn.bootx.platform.daxpay.core.order.pay.service.PayOrderService; +import cn.bootx.platform.daxpay.core.payment.refund.func.AbsPayRefundStrategy; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; + +/** + * 支付宝退款 + * @author xxm + * @since 2023/7/4 + */ +@Scope(SCOPE_PROTOTYPE) +@Component +@RequiredArgsConstructor +public class AliPayRefundStrategy extends AbsPayRefundStrategy { + + private final AlipayConfigService alipayConfigService; + private final AliPayOrderService aliPayOrderService; + private final AliPayRefundService aliRefundService; + /** + * 策略标识 + * + * @see PayChannelEnum + */ + @Override + public PayChannelEnum getType() { + return PayChannelEnum.ALI; + } + + private final PayOrderService payOrderService; + + + /** + * 退款前前操作 + */ + @Override + public void doBeforeRefundHandler() { + AlipayConfig config = alipayConfigService.getConfig(); + alipayConfigService.initConfig(config); + } + + /** + * 退款 + */ + @Override + public void doRefundHandler() { + aliRefundService.refund(this.getOrder(), this.getChannelParam().getAmount()); + aliPayOrderService.updatePayRefund(this.getOrder().getId(), this.getChannelParam().getAmount()); + payOrderService.updateRefundSuccess(this.getOrder(), this.getChannelParam().getAmount(), PayChannelEnum.ALI); + } + + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/CashPayRefundStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/CashPayRefundStrategy.java new file mode 100644 index 00000000..a00e0695 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/CashPayRefundStrategy.java @@ -0,0 +1,44 @@ +package cn.bootx.platform.daxpay.core.payment.refund.strategy; + +import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.core.channel.cash.service.CashService; +import cn.bootx.platform.daxpay.core.order.pay.service.PayOrderService; +import cn.bootx.platform.daxpay.core.payment.refund.func.AbsPayRefundStrategy; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; + +/** + * 现金支付退款 + * @author xxm + * @since 2023/7/5 + */ +@Scope(SCOPE_PROTOTYPE) +@Component +@RequiredArgsConstructor +public class CashPayRefundStrategy extends AbsPayRefundStrategy { + + private final CashService cashService; + private final PayOrderService paymentService; + + /** + * 策略标识 + * + * @see PayChannelEnum + */ + @Override + public PayChannelEnum getType() { + return PayChannelEnum.CASH; + } + + /** + * 退款 + */ + @Override + public void doRefundHandler() { + cashService.refund(this.getOrder().getId(), this.getChannelParam().getAmount()); + paymentService.updateRefundSuccess(this.getOrder(), this.getChannelParam().getAmount(), PayChannelEnum.CASH); + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/UnionPayRefundStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/UnionPayRefundStrategy.java new file mode 100644 index 00000000..74d28fc5 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/UnionPayRefundStrategy.java @@ -0,0 +1,37 @@ +package cn.bootx.platform.daxpay.core.payment.refund.strategy; + +import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.core.payment.refund.func.AbsPayRefundStrategy; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; + +/** + * 云闪付支付退款 + * @author xxm + * @since 2023/7/5 + */ +@Scope(SCOPE_PROTOTYPE) +@Component +@RequiredArgsConstructor +public class UnionPayRefundStrategy extends AbsPayRefundStrategy { + /** + * 策略标识 + * + * @see PayChannelEnum + */ + @Override + public PayChannelEnum getType() { + return PayChannelEnum.UNION_PAY; + } + + /** + * 退款 + */ + @Override + public void doRefundHandler() { + + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/VoucherPayRefundStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/VoucherPayRefundStrategy.java new file mode 100644 index 00000000..3dc8a06f --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/VoucherPayRefundStrategy.java @@ -0,0 +1,53 @@ +package cn.bootx.platform.daxpay.core.payment.refund.strategy; + +import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.core.channel.voucher.service.VoucherPayService; +import cn.bootx.platform.daxpay.core.channel.voucher.service.VoucherPaymentService; +import cn.bootx.platform.daxpay.core.order.pay.service.PayOrderService; +import cn.bootx.platform.daxpay.core.payment.refund.func.AbsPayRefundStrategy; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; + +/** + * 储值卡支付退款 + * @author xxm + * @since 2023/7/5 + */ +@Scope(SCOPE_PROTOTYPE) +@Component +@RequiredArgsConstructor +public class VoucherPayRefundStrategy extends AbsPayRefundStrategy { + private final VoucherPayService voucherPayService; + private final VoucherPaymentService voucherPaymentService; + private final PayOrderService payOrderService; + + /** + * 策略标识 + * + * @see PayChannelEnum + */ + @Override + public PayChannelEnum getType() { + return PayChannelEnum.VOUCHER; + } + + /** + * 退款前对处理 + */ + @Override + public void doBeforeRefundHandler() { + } + + /** + * 退款 + */ + @Override + public void doRefundHandler() { + voucherPayService.refund(this.getOrder().getId(), this.getChannelParam().getAmount()); + voucherPaymentService.updateRefund(this.getOrder().getId(), this.getChannelParam().getAmount()); + payOrderService.updateRefundSuccess(this.getOrder(), this.getChannelParam().getAmount(), PayChannelEnum.VOUCHER); + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/WalletPayRefundStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/WalletPayRefundStrategy.java new file mode 100644 index 00000000..5ef98a9d --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/WalletPayRefundStrategy.java @@ -0,0 +1,45 @@ +package cn.bootx.platform.daxpay.core.payment.refund.strategy; + +import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.core.channel.wallet.service.WalletPayService; +import cn.bootx.platform.daxpay.core.channel.wallet.service.WalletPaymentService; +import cn.bootx.platform.daxpay.core.order.pay.service.PayOrderService; +import cn.bootx.platform.daxpay.core.payment.refund.func.AbsPayRefundStrategy; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; + +/** + * 钱包支付退款 + * @author xxm + * @since 2023/7/5 + */ +@Scope(SCOPE_PROTOTYPE) +@Component +@RequiredArgsConstructor +public class WalletPayRefundStrategy extends AbsPayRefundStrategy { + private final WalletPayService walletPayService; + private final WalletPaymentService walletPaymentService; + private final PayOrderService payOrderService; + /** + * 策略标识 + * + * @see PayChannelEnum + */ + @Override + public PayChannelEnum getType() { + return PayChannelEnum.WALLET; + } + + /** + * 退款 + */ + @Override + public void doRefundHandler() { + walletPayService.refund(this.getOrder().getId(), this.getChannelParam().getAmount()); + walletPaymentService.updateRefund(this.getOrder().getId(), this.getChannelParam().getAmount()); + payOrderService.updateRefundSuccess(this.getOrder(), this.getChannelParam().getAmount(), PayChannelEnum.WALLET); + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/WeChatPayRefundStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/WeChatPayRefundStrategy.java new file mode 100644 index 00000000..0ec71133 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/refund/strategy/WeChatPayRefundStrategy.java @@ -0,0 +1,63 @@ +package cn.bootx.platform.daxpay.core.payment.refund.strategy; + +import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.core.channel.wechat.entity.WeChatPayConfig; +import cn.bootx.platform.daxpay.core.channel.wechat.service.WeChatPayConfigService; +import cn.bootx.platform.daxpay.core.channel.wechat.service.WeChatPayOrderService; +import cn.bootx.platform.daxpay.core.channel.wechat.service.WechatRefundService; +import cn.bootx.platform.daxpay.core.order.pay.service.PayOrderService; +import cn.bootx.platform.daxpay.core.payment.refund.func.AbsPayRefundStrategy; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; + +/** + * 微信支付退款 + * @author xxm + * @since 2023/7/5 + */ +@Scope(SCOPE_PROTOTYPE) +@Component +@RequiredArgsConstructor +public class WeChatPayRefundStrategy extends AbsPayRefundStrategy { + + private final WeChatPayConfigService weChatPayConfigService; + + private final WechatRefundService wechatRefundService; + private final WeChatPayOrderService weChatPayOrderService; + private final PayOrderService payOrderService; + + private WeChatPayConfig weChatPayConfig; + + /** + * 策略标识 + * + * @see PayChannelEnum + */ + @Override + public PayChannelEnum getType() { + return PayChannelEnum.WECHAT; + } + + /** + * 退款前对处理, 初始化微信支付配置 + */ + @Override + public void doBeforeRefundHandler() { + this.weChatPayConfig = weChatPayConfigService.getConfig(); + } + + /** + * 退款 + */ + @Override + public void doRefundHandler() { + wechatRefundService.refund(this.getOrder(), this.getChannelParam().getAmount(), this.weChatPayConfig); + weChatPayOrderService.updatePayRefund(this.getOrder().getId(), this.getChannelParam().getAmount()); + payOrderService.updateRefundSuccess(this.getOrder(), this.getChannelParam().getAmount(), PayChannelEnum.WECHAT); + + } + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/sync/strategy/AliPaySyncStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/sync/strategy/AliPaySyncStrategy.java index 0aa4100a..a33d264f 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/sync/strategy/AliPaySyncStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/core/payment/sync/strategy/AliPaySyncStrategy.java @@ -1,7 +1,8 @@ package cn.bootx.platform.daxpay.core.payment.sync.strategy; -import cn.bootx.platform.daxpay.core.channel.alipay.dao.AlipayConfigManager; +import cn.bootx.platform.daxpay.core.channel.alipay.entity.AlipayConfig; +import cn.bootx.platform.daxpay.core.channel.alipay.service.AlipayConfigService; import cn.bootx.platform.daxpay.core.channel.alipay.service.AlipaySyncService; import cn.bootx.platform.daxpay.core.payment.sync.func.AbsPaySyncStrategy; import cn.bootx.platform.daxpay.core.payment.sync.result.PaySyncResult; @@ -21,7 +22,7 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT @RequiredArgsConstructor public class AliPaySyncStrategy extends AbsPaySyncStrategy { - private final AlipayConfigManager alipayConfigManager; + private final AlipayConfigService alipayConfigService; private final AlipaySyncService alipaySyncService; @@ -39,5 +40,7 @@ public class AliPaySyncStrategy extends AbsPaySyncStrategy { */ private void initAlipayConfig() { // 检查并获取支付宝支付配置 + AlipayConfig config = alipayConfigService.getConfig(); + alipayConfigService.initConfig(config); } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/alipay/AliPaymentDto.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/alipay/AliPaymentDto.java index 9315f006..c86fcc2d 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/alipay/AliPaymentDto.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/alipay/AliPaymentDto.java @@ -1,6 +1,6 @@ package cn.bootx.platform.daxpay.dto.channel.alipay; -import cn.bootx.platform.daxpay.dto.pay.order.BasePayOrderDto; +import cn.bootx.platform.daxpay.dto.order.pay.PayOrderDto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -16,7 +16,7 @@ import java.io.Serializable; @Data @Accessors(chain = true) @Schema(title = "支付宝支付记录") -public class AliPaymentDto extends BasePayOrderDto implements Serializable { +public class AliPaymentDto extends PayOrderDto implements Serializable { private static final long serialVersionUID = 6883103229754466130L; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/voucher/VoucherPayOrderDto.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/voucher/VoucherPayOrderDto.java index bb256a69..9edb4186 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/voucher/VoucherPayOrderDto.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/voucher/VoucherPayOrderDto.java @@ -1,6 +1,6 @@ package cn.bootx.platform.daxpay.dto.channel.voucher; -import cn.bootx.platform.daxpay.dto.pay.order.BasePayOrderDto; +import cn.bootx.platform.daxpay.dto.order.pay.PayOrderDto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -14,6 +14,6 @@ import lombok.experimental.Accessors; @Data @Accessors(chain = true) @Schema(title = "储值卡支付记录") -public class VoucherPayOrderDto extends BasePayOrderDto { +public class VoucherPayOrderDto extends PayOrderDto { } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/wallet/WalletPayOrderDto.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/wallet/WalletPayOrderDto.java index ff7fe8f9..5a62980e 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/wallet/WalletPayOrderDto.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/wallet/WalletPayOrderDto.java @@ -1,6 +1,6 @@ package cn.bootx.platform.daxpay.dto.channel.wallet; -import cn.bootx.platform.daxpay.dto.pay.order.BasePayOrderDto; +import cn.bootx.platform.daxpay.dto.order.pay.PayOrderDto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -16,7 +16,7 @@ import java.io.Serializable; @Data @Accessors(chain = true) @Schema(title = "钱包支付记录") -public class WalletPayOrderDto extends BasePayOrderDto implements Serializable { +public class WalletPayOrderDto extends PayOrderDto implements Serializable { private static final long serialVersionUID = 8238920331255597223L; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/wechat/WeChatPayOrderDto.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/wechat/WeChatPayOrderDto.java index 912bbf62..a62dd21c 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/wechat/WeChatPayOrderDto.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/channel/wechat/WeChatPayOrderDto.java @@ -1,6 +1,6 @@ package cn.bootx.platform.daxpay.dto.channel.wechat; -import cn.bootx.platform.daxpay.dto.pay.order.BasePayOrderDto; +import cn.bootx.platform.daxpay.dto.order.pay.PayOrderDto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -16,7 +16,7 @@ import java.io.Serializable; @Data @Accessors(chain = true) @Schema(title = "微信支付记录") -public class WeChatPayOrderDto extends BasePayOrderDto implements Serializable { +public class WeChatPayOrderDto extends PayOrderDto implements Serializable { private static final long serialVersionUID = -2400358210732595795L; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/pay/order/BasePayOrderDto.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/order/pay/PayOrderDto.java similarity index 91% rename from daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/pay/order/BasePayOrderDto.java rename to daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/order/pay/PayOrderDto.java index 0a28b433..583b62c0 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/pay/order/BasePayOrderDto.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/order/pay/PayOrderDto.java @@ -1,4 +1,4 @@ -package cn.bootx.platform.daxpay.dto.pay.order; +package cn.bootx.platform.daxpay.dto.order.pay; import cn.bootx.platform.common.core.rest.dto.BaseDto; import cn.bootx.platform.daxpay.code.PayStatusEnum; @@ -18,7 +18,7 @@ import java.time.LocalDateTime; @Data @Accessors(chain = true) @Schema(title = "具体支付日志基类") -public class BasePayOrderDto extends BaseDto { +public class PayOrderDto extends BaseDto { @Schema(description = "支付id") private Long paymentId; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/order/refund/PayRefundOrderDto.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/order/refund/PayRefundOrderDto.java new file mode 100644 index 00000000..4d9dc5b4 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/dto/order/refund/PayRefundOrderDto.java @@ -0,0 +1,65 @@ +package cn.bootx.platform.daxpay.dto.order.refund; + +import cn.bootx.platform.common.core.rest.dto.BaseDto; +import cn.bootx.platform.daxpay.common.entity.OrderRefundableInfo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 退款记录 + * + * @author xxm + * @since 2022/3/2 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Accessors(chain = true) +@Schema(title = "退款记录") +public class PayRefundOrderDto extends BaseDto { + + @Schema(description = "关联的业务id") + private String businessNo; + + @Schema(description = "付款付单号") + private Long paymentId; + + @Schema(description = "异步方式关联退款请求号(部分退款情况)") + private String refundRequestNo; + + @Schema(description = "标题") + private String title; + + @Schema(description = "退款金额") + private BigDecimal amount; + + @Schema(description = "剩余可退") + private BigDecimal refundableBalance; + + @Schema(description = "退款终端ip") + private String clientIp; + + @Schema(description = "退款时间") + private LocalDateTime refundTime; + + @Schema(description = "退款信息列表") + private List refundableInfo; + + /** + * @see PayStatusCode#REFUND_PROCESS_FAIL + */ + @Schema(description = "退款状态") + private String refundStatus; + + @Schema(description = "错误码") + private String errorCode; + + @Schema(description = "错误信息") + private String errorMsg; + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/func/AbsPayCallbackStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/func/AbsPayCallbackStrategy.java index d2c21833..7bbc7d7e 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/func/AbsPayCallbackStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/func/AbsPayCallbackStrategy.java @@ -104,7 +104,7 @@ public abstract class AbsPayCallbackStrategy { .setNotifyTime(LocalDateTime.now()) .setPaymentId(this.getPaymentId()) .setPayChannel(this.getPayChannel().getCode()) - .setStatus(result.getCode()) + .setPayStatus(result.getStatus()) .setMsg(result.getMsg()); callbackNotifyManager.save(payNotifyRecord); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/param/channel/wechat/WeChatPayConfigParam.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/param/channel/wechat/WeChatPayConfigParam.java index 828db801..705f18a7 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/param/channel/wechat/WeChatPayConfigParam.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/param/channel/wechat/WeChatPayConfigParam.java @@ -20,9 +20,6 @@ import java.util.List; @Schema(title = "微信支付配置参数") public class WeChatPayConfigParam { - @Schema(description = "主键") - private Long id; - @Schema(description = "名称") private String name; diff --git a/daxpay-single/daxpay-single-service/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/daxpay-single/daxpay-single-service/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 88c2aa85..da3a0c28 100644 --- a/daxpay-single/daxpay-single-service/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/daxpay-single/daxpay-single-service/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1 @@ -cn.bootx.platform.daxpay.DaxPaySingleGatewayApp +cn.bootx.platform.daxpay.DaxpaySingleServiceApp diff --git a/daxpay-single/daxpay-single-service/src/test/java/cn/bootx/platform/daxpay/core/payment/common/service/PaymentSignServiceTest.java b/daxpay-single/daxpay-single-service/src/test/java/cn/bootx/platform/daxpay/core/payment/common/service/PaymentSignServiceTest.java index b0c5e0f2..bb530986 100644 --- a/daxpay-single/daxpay-single-service/src/test/java/cn/bootx/platform/daxpay/core/payment/common/service/PaymentSignServiceTest.java +++ b/daxpay-single/daxpay-single-service/src/test/java/cn/bootx/platform/daxpay/core/payment/common/service/PaymentSignServiceTest.java @@ -9,6 +9,7 @@ import com.ijpay.core.kit.PayKit; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; +import java.time.LocalDateTime; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -30,8 +31,9 @@ class PaymentSignServiceTest { payParam.setNotReturn(true); payParam.setNotifyUrl("http://127.0.0.1:8080/pay/notify"); payParam.setReturnUrl("http://127.0.0.1:8080/pay/return"); - payParam.setSignType("MD5"); payParam.setVersion("1.0"); + // 传入的话需要传输时间戳 + payParam.setReqTime(LocalDateTime.now()); PayWayParam p1 = new PayWayParam(); p1.setAmount(100); diff --git a/daxpay-single/daxpay-single-start/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/daxpay-single/daxpay-single-start/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 88c2aa85..b9b464d2 100644 --- a/daxpay-single/daxpay-single-start/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/daxpay-single/daxpay-single-start/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1 @@ -cn.bootx.platform.daxpay.DaxPaySingleGatewayApp +cn.bootx.platform.daxpay.DaxPaySingleAdminApp