feat 支付网关对外接口

This commit is contained in:
nws
2023-12-17 22:51:30 +08:00
parent e3702275ac
commit 2026ca0618
25 changed files with 348 additions and 183 deletions

27
dax-pay-sdk/pom.xml Normal file
View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.bootx.cloud</groupId>
<artifactId>dax-pay-sdk</artifactId>
<version>2.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.18</version>
</dependency>
</dependencies>
</project>

View File

@@ -1,22 +0,0 @@
package cn.bootx.platform.daxpay.exception.pay;
import cn.bootx.platform.common.core.exception.FatalException;
import cn.bootx.platform.daxpay.code.DaxPayErrorCode;
/**
* 异常金额
*
* @author xxm
* @since 2020/12/8
*/
public class PayAmountAbnormalException extends FatalException {
public PayAmountAbnormalException(String msg) {
super(DaxPayErrorCode.PAYMENT_AMOUNT_ABNORMAL, msg);
}
public PayAmountAbnormalException() {
super(DaxPayErrorCode.PAYMENT_AMOUNT_ABNORMAL, "异常金额");
}
}

View File

@@ -1,22 +0,0 @@
package cn.bootx.platform.daxpay.exception.pay;
import cn.bootx.platform.common.core.exception.BizException;
import cn.bootx.platform.daxpay.code.DaxPayErrorCode;
/**
* 付款错误
*
* @author xxm
* @since 2020/12/8
*/
public class PayFailureException extends BizException {
public PayFailureException(String message) {
super(DaxPayErrorCode.PAY_FAILURE, message);
}
public PayFailureException() {
super(DaxPayErrorCode.PAY_FAILURE, "支付失败");
}
}

View File

@@ -1,18 +0,0 @@
package cn.bootx.platform.daxpay.exception.pay;
import cn.bootx.platform.common.core.exception.BizException;
import cn.bootx.platform.daxpay.code.DaxPayErrorCode;
/**
* 付款已存在
*
* @author xxm
* @since 2020/12/8
*/
public class PayHasExistedException extends BizException {
public PayHasExistedException() {
super(DaxPayErrorCode.PAYMENT_HAS_EXISTED, "付款已存在");
}
}

View File

@@ -1,18 +0,0 @@
package cn.bootx.platform.daxpay.exception.pay;
import cn.bootx.platform.common.core.exception.BizException;
import cn.bootx.platform.daxpay.code.DaxPayErrorCode;
/**
* 付款正在处理中
*
* @author xxm
* @since 2020/12/8
*/
public class PayIsProcessingException extends BizException {
public PayIsProcessingException() {
super(DaxPayErrorCode.PAYMENT_IS_PROCESSING, "付款正在处理中");
}
}

View File

@@ -1,18 +0,0 @@
package cn.bootx.platform.daxpay.exception.pay;
import cn.bootx.platform.common.core.exception.BizException;
import cn.bootx.platform.daxpay.code.DaxPayErrorCode;
/**
* 付款记录不存在
*
* @author xxm
* @since 2020/12/8
*/
public class PayNotExistedException extends BizException {
public PayNotExistedException() {
super(DaxPayErrorCode.PAYMENT_RECORD_NOT_EXISTED, "付款记录不存在");
}
}

View File

@@ -1,18 +0,0 @@
package cn.bootx.platform.daxpay.exception.pay;
import cn.bootx.platform.common.core.exception.FatalException;
import cn.bootx.platform.daxpay.code.DaxPayErrorCode;
/**
* 付款方式不支持异常
*
* @author xxm
* @since 2020/12/9
*/
public class PayUnsupportedMethodException extends FatalException {
public PayUnsupportedMethodException() {
super(DaxPayErrorCode.PAYMENT_METHOD_UNSUPPORT, "不支持的支付方式");
}
}

View File

@@ -0,0 +1,25 @@
package cn.bootx.platform.daxpay.util;
import cn.bootx.platform.daxpay.result.DaxResult;
import lombok.experimental.UtilityClass;
import static cn.bootx.platform.common.core.code.CommonCode.SUCCESS_CODE;
/**
* 支付相应参数构造工具类
* @author xxm
* @since 2023/12/17
*/
@UtilityClass
public class DaxRes {
private final static String SUCCESS = "success";
public <T> DaxResult<T> ok(T data) {
return new DaxResult<>(SUCCESS_CODE, data, SUCCESS);
}
public static <T> DaxResult<T> ok() {
return new DaxResult<>(SUCCESS_CODE, SUCCESS);
}
}

View File

@@ -53,9 +53,9 @@ public enum PayChannelEnum {
/** 微信 UA */
public static final String UA_WECHAT_PAY = "MicroMessenger";
/** 异步支付道 */
/** 异步支付道 */
public static final List<PayChannelEnum> ASYNC_TYPE = Collections.unmodifiableList(Arrays.asList(ALI, WECHAT, UNION_PAY));
/** 异步支付通道的编码 */
public static final List<String> ASYNC_TYPE_CODE = Collections.unmodifiableList(Arrays.asList(ALI.code, WECHAT.code, UNION_PAY.code));
}

View File

@@ -0,0 +1,31 @@
package cn.bootx.platform.daxpay.code;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* 支付状态
* @author xxm
* @since 2023/12/17
*/
@Getter
@RequiredArgsConstructor
public enum PayStatusEnum {
UNKNOWN("unknown","未知状态"),
PROGRESS("progress","支付中"),
SUCCESS("success","成功"),
FAIL("fail","失败"),
CANCEL("cancel","支付取消"),
CLOSE("close","支付关闭"),
/** 超时取消 */
TIMEOUT("timeout","超时取消"),
PARTIAL_REFUND("partial_refund","部分退款"),
REFUNDED("REFUNDED","已退款");
/** 支付方式字符编码 */
private final String code;
/** 名称 */
private final String name;
}

View File

@@ -17,10 +17,15 @@ import java.util.Objects;
@AllArgsConstructor
public enum PayWayEnum {
NORMAL("NORMAL", "常规支付"), WAP("WAP", "wap支付"), APP("APP", "应用支付"), WEB("WEB", "web支付"), QRCODE("QRCODE", "扫码支付"),
BARCODE("BARCODE", "付款码"), JSAPI("JSAPI", "公众号/小程序支付");
NORMAL("normal", "常规支付"),
WAP("wap", "wap支付"),
APP("app", "应用支付"),
WEB("web", "web支付"),
QRCODE("qrcode", "扫码支付"),
BARCODE("barcode", "付款码"),
JSAPI("jsapi", "公众号/小程序支付");
/** 支付方式字符编码 */
/** 编码 */
private final String code;
/** 名称 */

View File

@@ -0,0 +1,9 @@
package cn.bootx.platform.daxpay.param;
/**
* 通道支付参数标识
* @author xxm
* @since 2023/12/17
*/
public interface ChannelParam {
}

View File

@@ -1,21 +1,16 @@
package cn.bootx.platform.daxpay.param.channel;
import cn.bootx.platform.daxpay.param.ChannelParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @author xxm
* @since 2021/2/27
*/
@Data
@Accessors(chain = true)
@Schema(title = "支付宝支付参数")
public class AliPayParam implements Serializable {
private static final long serialVersionUID = 7467373358780663978L;
public class AliPayParam implements ChannelParam {
@Schema(description = "授权码(主动扫描用户的付款码)")
private String authCode;

View File

@@ -1,8 +1,8 @@
package cn.bootx.platform.daxpay.param.channel;
import cn.bootx.platform.daxpay.param.ChannelParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 储值卡支付参数
@@ -11,9 +11,8 @@ import lombok.experimental.Accessors;
* @since 2022/3/14
*/
@Data
@Accessors(chain = true)
@Schema(title = "储值卡支付参数")
public class VoucherPayParam {
public class VoucherPayParam implements ChannelParam {
@Schema(description = "储值卡号")
private String cardNo;

View File

@@ -1,10 +1,8 @@
package cn.bootx.platform.daxpay.param.channel;
import cn.bootx.platform.daxpay.param.ChannelParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 钱包支付参数
@@ -13,11 +11,8 @@ import java.io.Serializable;
* @since 2020/12/8
*/
@Data
@Accessors(chain = true)
@Schema(title = "钱包支付参数")
public class WalletPayParam implements Serializable {
private static final long serialVersionUID = 3255160458016870367L;
public class WalletPayParam implements ChannelParam {
@Schema(description = "钱包ID")
private Long walletId;

View File

@@ -1,17 +1,16 @@
package cn.bootx.platform.daxpay.param.channel;
import cn.bootx.platform.daxpay.param.ChannelParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* @author xxm
* @since 2021/6/21
*/
@Data
@Accessors(chain = true)
@Schema(title = "微信支付参数")
public class WeChatPayParam {
public class WeChatPayParam implements ChannelParam {
@Schema(description = "微信openId")
private String openId;

View File

@@ -0,0 +1,14 @@
package cn.bootx.platform.daxpay.param.pay;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 支付取消参数
* @author xxm
* @since 2023/12/17
*/
@Data
@Schema(title = "支付取消参数")
public class CancelParam {
}

View File

@@ -0,0 +1,58 @@
package cn.bootx.platform.daxpay.param.pay;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.time.LocalDateTime;
/**
* 支付公共参数
* @author xxm
* @since 2023/12/17
*/
@Data
@Schema(title = "支付公共参数")
public class PayCommonParam {
/** 客户端ip */
@Schema(description = "客户端ip")
private String clientIp;
/** 商户扩展参数,回调时会原样返回 */
@Schema(description = "商户扩展参数,回调时会原样返回")
private String extraParam;
@Schema(description = "是否不进行同步通知的跳转")
private boolean notReturn;
/** 同步通知URL */
@Schema(description = "同步通知URL")
private String returnUrl;
/** 是否不启用异步通知 */
@Schema(description = "是否不启用异步通知")
private boolean notNotify;
/** 异步通知地址 */
@Schema(description = "异步通知地址")
private String notifyUrl;
/** 签名类型 */
@Schema(description = "签名类型")
private String signType;
/** 签名 */
@Schema(description = "签名")
private String sign;
/** API版本号 */
@Schema(description = "API版本号")
@NotBlank()
private String version;
/** 请求时间,时间戳转时间 */
@Schema(description = "请求时间,传输时间戳")
private LocalDateTime reqTime;
}

View File

@@ -2,7 +2,7 @@ package cn.bootx.platform.daxpay.param.pay;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.EqualsAndHashCode;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
@@ -10,28 +10,20 @@ import javax.validation.constraints.NotEmpty;
import java.util.List;
/**
* 支付参数
* 统一下单参数
*
* @author xxm
* @since 2020/12/9
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@Schema(title = "支付参数")
public class PayParam {
public class PayParam extends PayCommonParam{
@Schema(description = "商户编码")
@NotEmpty(message = "商户应用不可为空")
private String mchCode;
@Schema(description = "商户应用编码")
@NotEmpty(message = "商户应用编码不可为空")
private String mchAppCode;
@Schema(description = "业务ID")
@NotBlank(message = "业务ID不可为空")
private String businessId;
@Schema(description = "业务号")
@NotBlank(message = "业务号不可为空")
private String businessNo;
@Schema(description = "支付标题")
@NotBlank(message = "支付标题不可为空")

View File

@@ -8,25 +8,20 @@ import cn.bootx.platform.daxpay.param.channel.WalletPayParam;
import cn.bootx.platform.daxpay.param.channel.WeChatPayParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 不只是支付, 退款发起时也是这个参数
* 同意下单支付方式参数
*
* @author xxm
* @since 2020/12/8
*/
@Data
@Accessors(chain = true)
@Schema(title = "支付方式参数")
public class PayWayParam implements Serializable {
private static final long serialVersionUID = -46959864485463681L;
public class PayWayParam {
/**
* @see PayChannelEnum#getCode()
@@ -52,6 +47,6 @@ public class PayWayParam implements Serializable {
* @see VoucherPayParam
* @see WalletPayParam
*/
@Schema(description = "扩展参数的json字符串")
private String extraParamsJson;
@Schema(description = "附加支付参数")
private String channelExtra;
}

View File

@@ -0,0 +1,64 @@
package cn.bootx.platform.daxpay.param.pay;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.PayWayEnum;
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 io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
* 简单下单参数
* @author xxm
* @since 2023/12/17
*/
@Data
@Schema(title = "简单下单参数")
public class SimplePayParam {
@Schema(description = "业务号")
@NotBlank(message = "业务号不可为空")
private String businessNo;
@Schema(description = "支付标题")
@NotBlank(message = "支付标题不可为空")
private String title;
@Schema(description = "支付描述")
private String description;
/**
* @see PayChannelEnum#getCode()
*/
@Schema(description = "支付渠道编码")
@NotBlank(message = "支付渠道编码不可为空")
private String payChannel;
/**
* @see PayWayEnum#getCode()
*/
@Schema(description = "支付方式编码")
@NotBlank(message = "支付方式编码不可为空")
private String payWay;
@Schema(description = "支付金额")
@NotNull(message = "支付金额不可为空")
private BigDecimal amount;
/**
* @see AliPayParam
* @see WeChatPayParam
* @see VoucherPayParam
* @see WalletPayParam
*/
@Schema(description = "附加支付参数")
private String channelExtra;
}

View File

@@ -0,0 +1,27 @@
package cn.bootx.platform.daxpay.result;
import cn.bootx.platform.common.core.rest.ResResult;
import lombok.*;
/**
* 支付通用响应参数
* @author xxm
* @since 2023/12/17
*/
@Getter
@Setter
@ToString
@EqualsAndHashCode(callSuper = true)
public class DaxResult<T> extends ResResult<T> {
/** 数据签名 */
private String sign;
public DaxResult(int successCode, T data, String success) {
super(successCode, data, success);
}
public DaxResult(int successCode, String success) {
super(successCode, success);
}
}

View File

@@ -0,0 +1,42 @@
package cn.bootx.platform.daxpay.result.pay;
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;
/**
* 统一下单响应参数
* @author xxm
* @since 2023/12/17
*/
@Data
@Accessors(chain = true)
@Schema(title = "统一下单响应参数")
public class PayResult {
@Schema(description = "支付ID")
private Long paymentId;
@Schema(description = "是否是异步支付")
private boolean asyncPayMode;
/**
* @see PayChannelEnum#ASYNC_TYPE_CODE
*/
@Schema(description = "异步支付渠道")
private String asyncPayChannel;
/** 支付参数体(通常用于发起异步支付的参数) */
@Schema(description = "支付参数体")
private String payBody;
/**
* @see PayStatusEnum
*/
@Schema(description = "支付状态")
private String payStatus;
}

View File

@@ -1,12 +1,15 @@
package cn.bootx.platform.daxpay.openapi.controller;
import cn.bootx.platform.common.core.annotation.IgnoreAuth;
import cn.bootx.platform.common.core.rest.Res;
import cn.bootx.platform.common.core.rest.ResResult;
import cn.bootx.platform.daxpay.param.pay.PayParam;
import cn.bootx.platform.daxpay.result.DaxResult;
import cn.bootx.platform.daxpay.result.pay.PayResult;
import cn.bootx.platform.daxpay.util.DaxRes;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -24,42 +27,42 @@ public class UniPayController {
@Operation(summary = "统一下单")
@PostMapping("/pay")
public ResResult<Void> pay(){
return Res.ok();
public DaxResult<PayResult> pay(@RequestBody PayParam payParam){
return DaxRes.ok();
}
@Operation(summary = "简单下单")
@PostMapping("/simplePay")
public ResResult<Void> simplePay(){
return Res.ok();
public DaxResult<PayResult> simplePay(){
return DaxRes.ok();
}
@Operation(summary = "订单撤销")
@PostMapping("/cancel")
public ResResult<Void> cancel(){
return Res.ok();
public DaxResult<Void> cancel(){
return DaxRes.ok();
}
@Operation(summary = "订单关闭")
@PostMapping("/close")
public ResResult<Void> close(){
return Res.ok();
public DaxResult<Void> close(){
return DaxRes.ok();
}
@Operation(summary = "统一退款")
@PostMapping("/refund")
public ResResult<Void> refund(){
return Res.ok();
public DaxResult<Void> refund(){
return DaxRes.ok();
}
@Operation(summary = "简单退款")
@PostMapping("/simpleRefund")
public ResResult<Void> simpleRefund(){
return Res.ok();
public DaxResult<Void> simpleRefund(){
return DaxRes.ok();
}
@Operation(summary = "支付状态同步")
@PostMapping("/syncPay")
public ResResult<Void> syncPay(){
return Res.ok();
public DaxResult<Void> syncPay(){
return DaxRes.ok();
}
@Operation(summary = "退款状态同步")
@PostMapping("/syncRefund")
public ResResult<Void> syncRefund(){
return Res.ok();
public DaxResult<Void> syncRefund(){
return DaxRes.ok();
}
}

View File

@@ -21,6 +21,7 @@
<module>daxpay-core</module>
<module>daxpay-common</module>
<module>daxpay-single</module>
<module>dax-pay-sdk</module>
</modules>
<properties>