mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-09-03 02:56:20 +00:00
ref 校验注解改名, 请求参数增加随机数, 增加请求有效时长参数和校验
This commit is contained in:
15
_doc/Task.md
15
_doc/Task.md
@@ -8,15 +8,19 @@
|
||||
- [ ] DEMO增加获取微信OpenID和支付宝OpenId功能
|
||||
- [ ] 支付宝微信等消息通知地址支持一键生成
|
||||
- [ ] 管理端界面支持扫码绑定对账接收方功能
|
||||
- [ ] 请求IP参数增加正则校验
|
||||
- [ ] 支付接口公共参数添加随机数字段, 预防重放问题
|
||||
- [ ] 请求接口增加有效期校验, 一个请求十分钟后失效
|
||||
- [x] 请求IP参数增加正则校验
|
||||
- [x] 支付接口公共参数添加随机数字段, 预防重放问题
|
||||
- [x] 请求接口增加有效期校验, 超时后失效
|
||||
- [ ] 数据库表进行规则, 字段设置长度, 增加索引
|
||||
- [ ] 订单
|
||||
- [ ] 记录
|
||||
- [ ] 配置
|
||||
- [x] 订单和扩展信息进行合并
|
||||
- [x] 支付通道两个独立的配置进行合并为一个
|
||||
- [X] 去除有效, icon, 颜色等字段
|
||||
- [x] 通道配置设置默认ICON
|
||||
- [ ] 平台配置改版
|
||||
- [ ] 增加接口请求有效时间配置
|
||||
- [x] 平台配置改版
|
||||
- [x] 增加接口请求有效时长配置
|
||||
- [x] 平台配置和接口配置删除回调地址配置
|
||||
- [X] 删除回调地址配置, 更换为消息通知地址和消息通知类型
|
||||
- [X] 接口配置改版
|
||||
@@ -47,7 +51,6 @@
|
||||
- [ ] 微信新增V3版本接口
|
||||
- [ ] 支付宝新增V3版本接口
|
||||
- [ ] 增加各类日志记录,例如钱包的各项操作
|
||||
- [ ] 数据库表进行规则, 字段设置长度, 增加索引
|
||||
- [ ] 针对同步/对账等出现脏数据导致阻塞的问题, 进行优化
|
||||
- [ ] 同步接口
|
||||
- [ ] 对账接口
|
||||
|
@@ -19,7 +19,7 @@ public class LocalDateTimeUtil extends cn.hutool.core.date.LocalDateTimeUtil {
|
||||
/**
|
||||
* 是否在指定的时间范围内
|
||||
*/
|
||||
public boolean between(LocalDateTime now, LocalDateTime start, LocalDateTime end) {
|
||||
public boolean inBetween(LocalDateTime now, LocalDateTime start, LocalDateTime end) {
|
||||
return ge(now, start) && le(now, end);
|
||||
}
|
||||
|
||||
|
@@ -23,6 +23,9 @@ public abstract class DaxPayRequest<T extends DaxPayResponseModel> {
|
||||
/** 请求时间,传输时间戳 */
|
||||
private Long reqTime = DateUtil.currentSeconds();
|
||||
|
||||
/** 随机数 */
|
||||
private String nonceStr;
|
||||
|
||||
/**
|
||||
* 方法请求路径
|
||||
* @return 请求路径
|
||||
|
@@ -23,6 +23,10 @@ public abstract class PaymentCommonParam {
|
||||
@IpAddress
|
||||
private String clientIp;
|
||||
|
||||
/** 随机数 */
|
||||
@Schema(description = "随机数")
|
||||
private String nonceStr;
|
||||
|
||||
/** 签名 */
|
||||
@Schema(description = "签名")
|
||||
private String sign;
|
||||
|
@@ -10,7 +10,7 @@ import cn.daxpay.single.result.DaxResult;
|
||||
import cn.daxpay.single.result.allocation.AllocReceiverAddResult;
|
||||
import cn.daxpay.single.result.allocation.AllocReceiverRemoveResult;
|
||||
import cn.daxpay.single.result.allocation.AllocationResult;
|
||||
import cn.daxpay.single.service.annotation.PaymentSign;
|
||||
import cn.daxpay.single.service.annotation.PaymentVerify;
|
||||
import cn.daxpay.single.service.annotation.InitPaymentContext;
|
||||
import cn.daxpay.single.service.core.payment.allocation.service.AllocationReceiverService;
|
||||
import cn.daxpay.single.service.core.payment.allocation.service.AllocationService;
|
||||
@@ -39,7 +39,7 @@ public class UniAllocationController {
|
||||
|
||||
private final AllocationReceiverService receiverService;
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.ALLOCATION)
|
||||
@Operation(summary = "发起分账接口")
|
||||
@PostMapping("/start")
|
||||
@@ -47,7 +47,7 @@ public class UniAllocationController {
|
||||
return DaxRes.ok(allocationService.allocation(param));
|
||||
}
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.ALLOCATION_FINISH)
|
||||
@Operation(summary = "分账完结接口")
|
||||
@PostMapping("/finish")
|
||||
@@ -55,7 +55,7 @@ public class UniAllocationController {
|
||||
return DaxRes.ok(allocationService.finish(param));
|
||||
}
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.ALLOCATION_RECEIVER_ADD)
|
||||
@Operation(summary = "分账接收方添加接口")
|
||||
@PostMapping("/receiver/add")
|
||||
@@ -63,7 +63,7 @@ public class UniAllocationController {
|
||||
return DaxRes.ok(receiverService.addAndSync(param));
|
||||
}
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.ALLOCATION_RECEIVER_REMOVE)
|
||||
@Operation(summary = "分账接收方删除接口")
|
||||
@PostMapping("/receiver/remove")
|
||||
|
@@ -10,7 +10,7 @@ import cn.daxpay.single.result.DaxResult;
|
||||
import cn.daxpay.single.result.assist.WxAccessTokenResult;
|
||||
import cn.daxpay.single.result.assist.WxAuthUrlResult;
|
||||
import cn.daxpay.single.service.annotation.InitPaymentContext;
|
||||
import cn.daxpay.single.service.annotation.PaymentSign;
|
||||
import cn.daxpay.single.service.annotation.PaymentVerify;
|
||||
import cn.daxpay.single.service.core.payment.assist.service.UniPayAssistService;
|
||||
import cn.daxpay.single.util.DaxRes;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@@ -34,7 +34,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
public class UniPayAssistController {
|
||||
private final UniPayAssistService uniPayAssistService;
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.GET_WX_AUTH_URL)
|
||||
@Operation(summary = "获取微信OAuth2授权链接")
|
||||
@PostMapping("/getWxAuthUrl")
|
||||
@@ -42,7 +42,7 @@ public class UniPayAssistController {
|
||||
return DaxRes.ok(uniPayAssistService.getWxAuthUrl(param));
|
||||
}
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.GET_WX_ACCESS_TOKEN)
|
||||
@Operation(summary = "获取微信AccessToken")
|
||||
@PostMapping("/getWxAccessToken")
|
||||
|
@@ -13,7 +13,7 @@ import cn.daxpay.single.result.pay.PayCloseResult;
|
||||
import cn.daxpay.single.result.pay.PayResult;
|
||||
import cn.daxpay.single.result.pay.RefundResult;
|
||||
import cn.daxpay.single.result.transfer.TransferResult;
|
||||
import cn.daxpay.single.service.annotation.PaymentSign;
|
||||
import cn.daxpay.single.service.annotation.PaymentVerify;
|
||||
import cn.daxpay.single.service.annotation.InitPaymentContext;
|
||||
import cn.daxpay.single.service.core.payment.cancel.service.PayCancelService;
|
||||
import cn.daxpay.single.service.core.payment.close.service.PayCloseService;
|
||||
@@ -46,7 +46,7 @@ public class UniPayController {
|
||||
private final PayCancelService payCancelService;
|
||||
private final TransferService transferService;
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.PAY)
|
||||
@Operation(summary = "统一支付接口")
|
||||
@PostMapping("/pay")
|
||||
@@ -54,7 +54,7 @@ public class UniPayController {
|
||||
return DaxRes.ok(payService.pay(payParam));
|
||||
}
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.CLOSE)
|
||||
@Operation(summary = "支付关闭接口")
|
||||
@PostMapping("/close")
|
||||
@@ -62,7 +62,7 @@ public class UniPayController {
|
||||
return DaxRes.ok(payCloseService.close(param));
|
||||
}
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.CANCEL)
|
||||
@Operation(summary = "支付撤销接口")
|
||||
@PostMapping("/cancel")
|
||||
@@ -70,7 +70,7 @@ public class UniPayController {
|
||||
return DaxRes.ok(payCancelService.cancel(param));
|
||||
}
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.REFUND)
|
||||
@Operation(summary = "统一退款接口")
|
||||
@PostMapping("/refund")
|
||||
@@ -78,7 +78,7 @@ public class UniPayController {
|
||||
return DaxRes.ok(refundService.refund(param));
|
||||
}
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.TRANSFER)
|
||||
@Operation(summary = "统一转账接口")
|
||||
@PostMapping("/transfer")
|
||||
|
@@ -9,7 +9,7 @@ import cn.daxpay.single.result.DaxResult;
|
||||
import cn.daxpay.single.result.sync.AllocSyncResult;
|
||||
import cn.daxpay.single.result.sync.PaySyncResult;
|
||||
import cn.daxpay.single.result.sync.RefundSyncResult;
|
||||
import cn.daxpay.single.service.annotation.PaymentSign;
|
||||
import cn.daxpay.single.service.annotation.PaymentVerify;
|
||||
import cn.daxpay.single.service.annotation.InitPaymentContext;
|
||||
import cn.daxpay.single.service.core.payment.allocation.service.AllocationSyncService;
|
||||
import cn.daxpay.single.service.core.payment.sync.service.PaySyncService;
|
||||
@@ -39,7 +39,7 @@ public class UniPaySyncController {
|
||||
private final RefundSyncService refundSyncService;
|
||||
private final AllocationSyncService allocationSyncService;
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.SYNC_PAY)
|
||||
@Operation(summary = "支付同步接口")
|
||||
@PostMapping("/pay")
|
||||
@@ -47,7 +47,7 @@ public class UniPaySyncController {
|
||||
return DaxRes.ok(paySyncService.sync(param));
|
||||
}
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.SYNC_REFUND)
|
||||
@Operation(summary = "退款同步接口")
|
||||
@PostMapping("/refund")
|
||||
@@ -56,7 +56,7 @@ public class UniPaySyncController {
|
||||
}
|
||||
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.SYNC_ALLOCATION)
|
||||
@Operation(summary = "分账同步接口")
|
||||
@PostMapping("/allocation")
|
||||
@@ -64,7 +64,7 @@ public class UniPaySyncController {
|
||||
return DaxRes.ok(allocationSyncService.sync(param));
|
||||
}
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.SYNC_TRANSFER)
|
||||
@Operation(summary = "转账同步接口")
|
||||
@PostMapping("/transfer")
|
||||
|
@@ -13,7 +13,7 @@ import cn.daxpay.single.result.order.AllocOrderResult;
|
||||
import cn.daxpay.single.result.allocation.AllocReceiversResult;
|
||||
import cn.daxpay.single.result.order.PayOrderResult;
|
||||
import cn.daxpay.single.result.order.RefundOrderResult;
|
||||
import cn.daxpay.single.service.annotation.PaymentSign;
|
||||
import cn.daxpay.single.service.annotation.PaymentVerify;
|
||||
import cn.daxpay.single.service.annotation.InitPaymentContext;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderQueryService;
|
||||
import cn.daxpay.single.service.core.order.refund.service.RefundOrderQueryService;
|
||||
@@ -46,7 +46,7 @@ public class UniQueryController {
|
||||
private final AllocationReceiverService allocationReceiverService;
|
||||
private final AllocationService allocationService;
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.QUERY_PAY_ORDER)
|
||||
@Operation(summary = "支付订单查询接口")
|
||||
@PostMapping("/payOrder")
|
||||
@@ -54,7 +54,7 @@ public class UniQueryController {
|
||||
return DaxRes.ok(payOrderQueryService.queryPayOrder(param));
|
||||
}
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.QUERY_REFUND_ORDER)
|
||||
@Operation(summary = "退款订单查询接口")
|
||||
@PostMapping("/refundOrder")
|
||||
@@ -62,7 +62,7 @@ public class UniQueryController {
|
||||
return DaxRes.ok(refundOrderQueryService.queryRefundOrder(param));
|
||||
}
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.QUERY_ALLOCATION_ORDER)
|
||||
@Operation(summary = "分账订单查询接口")
|
||||
@PostMapping("/allocationOrder")
|
||||
@@ -70,7 +70,7 @@ public class UniQueryController {
|
||||
return DaxRes.ok(allocationService.queryAllocationOrder(param));
|
||||
}
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.QUERY_TRANSFER_ORDER)
|
||||
@Operation(summary = "转账订单查询接口")
|
||||
@PostMapping("/transferOrder")
|
||||
@@ -78,7 +78,7 @@ public class UniQueryController {
|
||||
return DaxRes.ok();
|
||||
}
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.QUERY_ALLOCATION_RECEIVER)
|
||||
@Operation(summary = "分账接收方查询接口")
|
||||
@PostMapping("/allocationReceiver")
|
||||
|
@@ -3,7 +3,7 @@ package cn.daxpay.single.gateway.controller;
|
||||
import cn.bootx.platform.common.core.annotation.IgnoreAuth;
|
||||
import cn.daxpay.single.code.PaymentApiCode;
|
||||
import cn.daxpay.single.result.DaxResult;
|
||||
import cn.daxpay.single.service.annotation.PaymentSign;
|
||||
import cn.daxpay.single.service.annotation.PaymentVerify;
|
||||
import cn.daxpay.single.service.annotation.InitPaymentContext;
|
||||
import cn.daxpay.single.util.DaxRes;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@@ -25,7 +25,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@RequiredArgsConstructor
|
||||
public class UniReconcileController {
|
||||
|
||||
@PaymentSign
|
||||
@PaymentVerify
|
||||
@InitPaymentContext(PaymentApiCode.PAY)
|
||||
@Operation(summary = "下载指定日期的资金流水")
|
||||
@PostMapping("/pay")
|
||||
|
@@ -3,7 +3,7 @@ package cn.daxpay.single.service.annotation;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 支付校验签名标识
|
||||
* 支付校验校验标识
|
||||
* 支付方法至少有一个参数,并且需要签名支付参数需要放在第一位
|
||||
* 返回对象必须为 ResResult<T extends PaymentCommonResult> 格式
|
||||
* @author xxm
|
||||
@@ -13,5 +13,5 @@ import java.lang.annotation.*;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
public @interface PaymentSign {
|
||||
public @interface PaymentVerify {
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
package cn.daxpay.single.service.common.context;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 支付接口信息
|
||||
* @author xxm
|
||||
* @since 2023/12/24
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ApiInfoLocal {
|
||||
|
||||
/** 当前支付接口编码 */
|
||||
private String apiCode;
|
||||
|
||||
/** 回调地址 */
|
||||
private String noticeUrl;
|
||||
|
||||
}
|
@@ -10,7 +10,7 @@ import lombok.experimental.Accessors;
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RequestLocal {
|
||||
public class ClientLocal {
|
||||
|
||||
/** 客户端ip */
|
||||
private String clientIp;
|
@@ -1,15 +0,0 @@
|
||||
package cn.daxpay.single.service.common.context;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 支付同步信息
|
||||
* @author xxm
|
||||
* @since 2024/1/24
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PaySyncLocal {
|
||||
|
||||
}
|
@@ -15,6 +15,9 @@ public class PaymentContext {
|
||||
/** 平台全局配置 */
|
||||
private final PlatformLocal platformInfo = new PlatformLocal();
|
||||
|
||||
/** 请求终端信息 */
|
||||
private final ClientLocal clientInfo = new ClientLocal();
|
||||
|
||||
/** 支付相关信息 */
|
||||
private final PayLocal payInfo = new PayLocal();
|
||||
|
||||
@@ -24,12 +27,6 @@ public class PaymentContext {
|
||||
/** 回调相关信息 */
|
||||
private final CallbackLocal callbackInfo = new CallbackLocal();
|
||||
|
||||
/** 请求相关信息 */
|
||||
private final RequestLocal requestInfo = new RequestLocal();
|
||||
|
||||
/** 支付同步相关信息 */
|
||||
private final PaySyncLocal paySyncInfo = new PaySyncLocal();
|
||||
|
||||
/** 修复相关信息 */
|
||||
private final RepairLocal repairInfo = new RepairLocal();
|
||||
|
||||
|
@@ -28,6 +28,13 @@ public class PlatformLocal {
|
||||
/** 是否对请求进行验签 */
|
||||
private boolean reqSign;
|
||||
|
||||
/**
|
||||
* 请求有效时长(秒)
|
||||
* 如果传输的请求时间早于当前服务时间, 而且差值超过配置的时长, 将会请求失败
|
||||
* 如果传输的请求时间比服务时间大于配置的时长(超过一分钟), 将会请求失败
|
||||
*/
|
||||
private Integer reqTimeout;
|
||||
|
||||
/** 消息通知方式 */
|
||||
private String noticeType;
|
||||
|
||||
|
@@ -1,14 +0,0 @@
|
||||
package cn.daxpay.single.service.common.context;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 退款请求上下文
|
||||
* @author xxm
|
||||
* @since 2023/12/26
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RefundRequestLocal {
|
||||
}
|
@@ -167,7 +167,7 @@ public class AllocationSyncService {
|
||||
.setSyncInfo(syncResult.getSyncInfo())
|
||||
.setErrorCode(errorCode)
|
||||
.setErrorMsg(errorMsg)
|
||||
.setClientIp(PaymentContextLocal.get().getRequestInfo().getClientIp());
|
||||
.setClientIp(PaymentContextLocal.get().getClientInfo().getClientIp());
|
||||
paySyncRecordService.saveRecord(paySyncRecord);
|
||||
}
|
||||
}
|
||||
|
@@ -98,7 +98,7 @@ public class PayCancelService {
|
||||
*/
|
||||
private void saveRecord(PayOrder payOrder, boolean closed, String errMsg){
|
||||
String clientIp = PaymentContextLocal.get()
|
||||
.getRequestInfo()
|
||||
.getClientInfo()
|
||||
.getClientIp();
|
||||
PayCloseRecord record = new PayCloseRecord()
|
||||
.setOrderNo(payOrder.getOrderNo())
|
||||
|
@@ -105,7 +105,7 @@ public class PayCloseService {
|
||||
*/
|
||||
private void saveRecord(PayOrder payOrder, boolean closed, String errMsg){
|
||||
String clientIp = PaymentContextLocal.get()
|
||||
.getRequestInfo()
|
||||
.getClientInfo()
|
||||
.getClientIp();
|
||||
PayCloseRecord record = new PayCloseRecord()
|
||||
.setOrderNo(payOrder.getOrderNo())
|
||||
|
@@ -5,8 +5,8 @@ import cn.bootx.platform.common.core.util.ValidationUtil;
|
||||
import cn.daxpay.single.exception.pay.PayFailureException;
|
||||
import cn.daxpay.single.param.PaymentCommonParam;
|
||||
import cn.daxpay.single.result.PaymentCommonResult;
|
||||
import cn.daxpay.single.service.annotation.PaymentSign;
|
||||
import cn.daxpay.single.service.core.payment.common.service.PaymentSignService;
|
||||
import cn.daxpay.single.service.annotation.PaymentVerify;
|
||||
import cn.daxpay.single.service.core.payment.common.service.PaymentAssistService;
|
||||
import cn.daxpay.single.util.DaxRes;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -27,11 +27,11 @@ import org.springframework.stereotype.Component;
|
||||
@Component
|
||||
@Order()
|
||||
@RequiredArgsConstructor
|
||||
public class PaymentVerifySignAop {
|
||||
private final PaymentSignService paymentSignService;
|
||||
public class PaymentVerifyAop {
|
||||
private final PaymentAssistService paymentAssistService;
|
||||
|
||||
@Around("@annotation(paymentSign)")
|
||||
public Object beforeMethod(ProceedingJoinPoint pjp, @SuppressWarnings("unused") PaymentSign paymentSign) throws Throwable {
|
||||
@Around("@annotation(paymentVerify)")
|
||||
public Object beforeMethod(ProceedingJoinPoint pjp, @SuppressWarnings("unused") PaymentVerify paymentVerify) throws Throwable {
|
||||
Object[] args = pjp.getArgs();
|
||||
if (args.length == 0){
|
||||
throw new PayFailureException("支付方法至少有一个参数,并且需要签名支付参数需要放在第一位");
|
||||
@@ -40,8 +40,14 @@ public class PaymentVerifySignAop {
|
||||
if (param instanceof PaymentCommonParam){
|
||||
// 参数校验
|
||||
ValidationUtil.validateParam(param);
|
||||
// 参数验签
|
||||
paymentSignService.verifySign((PaymentCommonParam) param);
|
||||
|
||||
// 请求上下文初始化
|
||||
paymentAssistService.initRequest((PaymentCommonParam) param);
|
||||
// 参数签名校验
|
||||
paymentAssistService.signVerify((PaymentCommonParam) param);
|
||||
// 参数请求时间校验
|
||||
paymentAssistService.reqTimeoutVerify((PaymentCommonParam) param);
|
||||
|
||||
} else {
|
||||
throw new PayFailureException("支付参数需要继承PayCommonParam");
|
||||
}
|
||||
@@ -54,14 +60,14 @@ public class PaymentVerifySignAop {
|
||||
// todo 后期错误码统一管理后进行更改
|
||||
commonResult.setCode(1);
|
||||
commonResult.setMsg(ex.getMessage());
|
||||
paymentSignService.sign(commonResult);
|
||||
paymentAssistService.sign(commonResult);
|
||||
return DaxRes.ok(commonResult);
|
||||
}
|
||||
// 对返回值进行签名
|
||||
if (proceed instanceof ResResult){
|
||||
Object data = ((ResResult<?>) proceed).getData();
|
||||
if (data instanceof PaymentCommonResult){
|
||||
paymentSignService.sign((PaymentCommonResult) data);
|
||||
paymentAssistService.sign((PaymentCommonResult) data);
|
||||
} else {
|
||||
throw new PayFailureException("支付方法返回类型需要为 ResResult<T extends PaymentCommonResult> 格式");
|
||||
}
|
@@ -1,13 +1,23 @@
|
||||
package cn.daxpay.single.service.core.payment.common.service;
|
||||
|
||||
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
||||
import cn.daxpay.single.code.PaySignTypeEnum;
|
||||
import cn.daxpay.single.exception.pay.PayFailureException;
|
||||
import cn.daxpay.single.param.PaymentCommonParam;
|
||||
import cn.daxpay.single.service.common.context.RequestLocal;
|
||||
import cn.daxpay.single.result.PaymentCommonResult;
|
||||
import cn.daxpay.single.service.common.context.ClientLocal;
|
||||
import cn.daxpay.single.service.common.context.PlatformLocal;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.system.config.service.PlatformConfigService;
|
||||
import cn.daxpay.single.util.PaySignUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 支付、退款等各类操作支持服务
|
||||
* @author xxm
|
||||
@@ -19,18 +29,90 @@ import org.springframework.stereotype.Service;
|
||||
public class PaymentAssistService {
|
||||
private final PlatformConfigService platformConfigService;
|
||||
|
||||
/**
|
||||
* 初始化上下文
|
||||
*/
|
||||
public void initContext(PaymentCommonParam paymentCommonParam){
|
||||
platformConfigService.initPlatform();
|
||||
this.initRequest(paymentCommonParam);
|
||||
}
|
||||
/**
|
||||
* 初始化请求相关信息上下文
|
||||
*/
|
||||
public void initRequest(PaymentCommonParam paymentCommonParam){
|
||||
RequestLocal request = PaymentContextLocal.get().getRequestInfo();
|
||||
ClientLocal request = PaymentContextLocal.get().getClientInfo();
|
||||
request.setClientIp(paymentCommonParam.getClientIp());
|
||||
}
|
||||
|
||||
/**
|
||||
* 入参签名校验
|
||||
*/
|
||||
public void signVerify(PaymentCommonParam param) {
|
||||
PlatformLocal platformInfo = PaymentContextLocal.get().getPlatformInfo();
|
||||
// 如果平台配置所有属性为空, 进行初始化
|
||||
if (BeanUtil.isEmpty(platformInfo)){
|
||||
platformConfigService.initPlatform();
|
||||
}
|
||||
// 判断当前接口是否不需要签名
|
||||
if (!platformInfo.isReqSign()){
|
||||
return;
|
||||
}
|
||||
// 参数转换为Map对象
|
||||
PlatformLocal platform = PaymentContextLocal.get().getPlatformInfo();
|
||||
String signType = platform.getSignType();
|
||||
if (Objects.equals(PaySignTypeEnum.HMAC_SHA256.getCode(), signType)){
|
||||
boolean verified = PaySignUtil.verifyHmacSha256Sign(param, platform.getSignSecret(), param.getSign());
|
||||
if (!verified){
|
||||
throw new PayFailureException("未通过签名验证");
|
||||
}
|
||||
} else if (Objects.equals(PaySignTypeEnum.MD5.getCode(), signType)){
|
||||
boolean verified = PaySignUtil.verifyMd5Sign(param, platform.getSignSecret(), param.getSign());
|
||||
if (!verified){
|
||||
throw new PayFailureException("未通过签名验证");
|
||||
}
|
||||
} else {
|
||||
throw new PayFailureException("签名方式错误");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求有效时间校验
|
||||
*/
|
||||
public void reqTimeoutVerify(PaymentCommonParam param) {
|
||||
PlatformLocal platformInfo = PaymentContextLocal.get().getPlatformInfo();
|
||||
// 如果平台配置所有属性为空, 进行初始化
|
||||
if (BeanUtil.isEmpty(platformInfo)){
|
||||
platformConfigService.initPlatform();
|
||||
}
|
||||
if (Objects.nonNull(platformInfo.getReqTimeout()) ){
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
// 时间差值(秒)
|
||||
long durationSeconds = Math.abs(LocalDateTimeUtil.between(now, param.getReqTime()).getSeconds());
|
||||
// 当前时间是否晚于请求时间
|
||||
if (LocalDateTimeUtil.lt(now, param.getReqTime())){
|
||||
// 请求时间比服务器时间晚, 超过一分钟直接打回
|
||||
if (durationSeconds > 60){
|
||||
throw new PayFailureException("请求时间晚于服务器接收到的时间,请检查");
|
||||
}
|
||||
} else {
|
||||
// 请求时间比服务器时间早, 超过配置时间直接打回
|
||||
if (durationSeconds > platformInfo.getReqTimeout()){
|
||||
throw new PayFailureException("请求已过期,请重新发送!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对对象进行签名
|
||||
*/
|
||||
public void sign(PaymentCommonResult result) {
|
||||
PlatformLocal platformInfo = PaymentContextLocal.get().getPlatformInfo();
|
||||
// 如果平台配置所有属性为空, 进行初始化
|
||||
if (BeanUtil.isEmpty(platformInfo)){
|
||||
platformConfigService.initPlatform();
|
||||
}
|
||||
String signType = platformInfo.getSignType();
|
||||
if (Objects.equals(PaySignTypeEnum.HMAC_SHA256.getCode(), signType)){
|
||||
result.setSign(PaySignUtil.hmacSha256Sign(result, platformInfo.getSignSecret()));
|
||||
} else if (Objects.equals(PaySignTypeEnum.MD5.getCode(), signType)){
|
||||
result.setSign(PaySignUtil.md5Sign(result, platformInfo.getSignSecret()));
|
||||
} else {
|
||||
throw new PayFailureException("未获取到签名方式,请检查");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,80 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.common.service;
|
||||
|
||||
import cn.daxpay.single.code.PaySignTypeEnum;
|
||||
import cn.daxpay.single.exception.pay.PayFailureException;
|
||||
import cn.daxpay.single.param.PaymentCommonParam;
|
||||
import cn.daxpay.single.result.PaymentCommonResult;
|
||||
import cn.daxpay.single.service.common.context.PlatformLocal;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.system.config.service.PlatformConfigService;
|
||||
import cn.daxpay.single.util.PaySignUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 支付签名服务
|
||||
* @author xxm
|
||||
* @since 2023/12/24
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PaymentSignService {
|
||||
|
||||
private final PaymentAssistService paymentAssistService;
|
||||
|
||||
private final PlatformConfigService platformConfigService;
|
||||
|
||||
/**
|
||||
* 入参签名校验
|
||||
*/
|
||||
public void verifySign(PaymentCommonParam param) {
|
||||
// 先触发上下文的初始化
|
||||
paymentAssistService.initContext(param);
|
||||
PlatformLocal platformInfo = PaymentContextLocal.get().getPlatformInfo();
|
||||
|
||||
// 判断当前接口是否不需要签名
|
||||
if (!platformInfo.isReqSign()){
|
||||
return;
|
||||
}
|
||||
// 参数转换为Map对象
|
||||
PlatformLocal platform = PaymentContextLocal.get().getPlatformInfo();
|
||||
String signType = platform.getSignType();
|
||||
if (Objects.equals(PaySignTypeEnum.HMAC_SHA256.getCode(), signType)){
|
||||
boolean verified = PaySignUtil.verifyHmacSha256Sign(param, platform.getSignSecret(), param.getSign());
|
||||
if (!verified){
|
||||
throw new PayFailureException("未通过签名验证");
|
||||
}
|
||||
} else if (Objects.equals(PaySignTypeEnum.MD5.getCode(), signType)){
|
||||
boolean verified = PaySignUtil.verifyMd5Sign(param, platform.getSignSecret(), param.getSign());
|
||||
if (!verified){
|
||||
throw new PayFailureException("未通过签名验证");
|
||||
}
|
||||
} else {
|
||||
throw new PayFailureException("签名方式错误");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对对象进行签名
|
||||
*/
|
||||
public void sign(PaymentCommonResult result) {
|
||||
PlatformLocal platformInfo = PaymentContextLocal.get().getPlatformInfo();
|
||||
// 如果平台配置所有属性为空, 进行初始化
|
||||
if (BeanUtil.isEmpty(platformInfo)){
|
||||
platformConfigService.initPlatform();
|
||||
}
|
||||
String signType = platformInfo.getSignType();
|
||||
if (Objects.equals(PaySignTypeEnum.HMAC_SHA256.getCode(), signType)){
|
||||
result.setSign(PaySignUtil.hmacSha256Sign(result, platformInfo.getSignSecret()));
|
||||
} else if (Objects.equals(PaySignTypeEnum.MD5.getCode(), signType)){
|
||||
result.setSign(PaySignUtil.md5Sign(result, platformInfo.getSignSecret()));
|
||||
} else {
|
||||
throw new PayFailureException("未获取到签名方式,请检查");
|
||||
}
|
||||
}
|
||||
}
|
@@ -10,7 +10,7 @@ import cn.daxpay.single.service.core.order.pay.convert.PayOrderConvert;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import cn.daxpay.single.service.core.order.refund.convert.RefundOrderConvert;
|
||||
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
|
||||
import cn.daxpay.single.service.core.payment.common.service.PaymentSignService;
|
||||
import cn.daxpay.single.service.core.payment.common.service.PaymentAssistService;
|
||||
import cn.daxpay.single.service.core.payment.notice.result.AllocDetailNoticeResult;
|
||||
import cn.daxpay.single.service.core.payment.notice.result.AllocNoticeResult;
|
||||
import cn.daxpay.single.service.core.payment.notice.result.PayNoticeResult;
|
||||
@@ -32,7 +32,7 @@ import java.util.stream.Collectors;
|
||||
@RequiredArgsConstructor
|
||||
public class ClientNoticeAssistService {
|
||||
|
||||
private final PaymentSignService paymentSignService;
|
||||
private final PaymentAssistService paymentAssistService;
|
||||
|
||||
/**
|
||||
* 构建出支付通知任务对象
|
||||
@@ -40,7 +40,7 @@ public class ClientNoticeAssistService {
|
||||
public ClientNoticeTask buildPayTask(PayOrder order){
|
||||
PayNoticeResult payNoticeResult = PayOrderConvert.CONVERT.convertNotice(order);
|
||||
payNoticeResult.setAttach(order.getAttach());
|
||||
paymentSignService.sign(payNoticeResult);
|
||||
paymentAssistService.sign(payNoticeResult);
|
||||
return new ClientNoticeTask()
|
||||
.setUrl(order.getNotifyUrl())
|
||||
// 时间序列化进行了重写, 所以使用Jackson的序列化工具类
|
||||
@@ -60,7 +60,7 @@ public class ClientNoticeAssistService {
|
||||
RefundNoticeResult refundNoticeResult = RefundOrderConvert.CONVERT.convertNotice(order);
|
||||
refundNoticeResult.setAttach(order.getAttach());
|
||||
// 签名
|
||||
paymentSignService.sign(refundNoticeResult);
|
||||
paymentAssistService.sign(refundNoticeResult);
|
||||
return new ClientNoticeTask()
|
||||
.setUrl(order.getNotifyUrl())
|
||||
// 时间序列化进行了重写
|
||||
@@ -86,7 +86,7 @@ public class ClientNoticeAssistService {
|
||||
allocOrderResult.setAttach(order.getAttach())
|
||||
.setDetails(details);
|
||||
// 签名
|
||||
paymentSignService.sign(allocOrderResult);
|
||||
paymentAssistService.sign(allocOrderResult);
|
||||
return new ClientNoticeTask()
|
||||
.setUrl(order.getNotifyUrl())
|
||||
// 时间序列化进行了重写
|
||||
|
@@ -243,7 +243,7 @@ public class PaySyncService {
|
||||
.setRepair(repair)
|
||||
.setRepairNo(repairOrderNo)
|
||||
.setErrorMsg(errorMsg)
|
||||
.setClientIp(PaymentContextLocal.get().getRequestInfo().getClientIp());
|
||||
.setClientIp(PaymentContextLocal.get().getClientInfo().getClientIp());
|
||||
paySyncRecordService.saveRecord(paySyncRecord);
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,6 @@ import cn.bootx.platform.common.core.exception.RepetitiveOperationException;
|
||||
import cn.daxpay.single.code.RefundStatusEnum;
|
||||
import cn.daxpay.single.code.RefundSyncStatusEnum;
|
||||
import cn.daxpay.single.exception.pay.PayFailureException;
|
||||
import cn.daxpay.single.exception.pay.PayUnsupportedMethodException;
|
||||
import cn.daxpay.single.param.payment.refund.RefundSyncParam;
|
||||
import cn.daxpay.single.result.sync.RefundSyncResult;
|
||||
import cn.daxpay.single.service.code.PayRepairSourceEnum;
|
||||
@@ -23,12 +22,10 @@ import cn.daxpay.single.service.core.record.sync.entity.PaySyncRecord;
|
||||
import cn.daxpay.single.service.core.record.sync.service.PaySyncRecordService;
|
||||
import cn.daxpay.single.service.func.AbsRefundSyncStrategy;
|
||||
import cn.daxpay.single.service.util.PayStrategyFactory;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import lombok.val;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -203,7 +200,7 @@ public class RefundSyncService {
|
||||
.setRepair(repair)
|
||||
.setRepairNo(repairOrderNo)
|
||||
.setErrorMsg(errorMsg)
|
||||
.setClientIp(PaymentContextLocal.get().getRequestInfo().getClientIp());
|
||||
.setClientIp(PaymentContextLocal.get().getClientInfo().getClientIp());
|
||||
paySyncRecordService.saveRecord(paySyncRecord);
|
||||
}
|
||||
|
||||
|
@@ -42,6 +42,14 @@ public class PlatformConfig extends MpBaseEntity implements EntityBaseFunction<P
|
||||
@DbColumn(comment = "是否对请求进行验签")
|
||||
private boolean reqSign;
|
||||
|
||||
/**
|
||||
* 请求有效时长(秒)
|
||||
* 如果传输的请求时间早于当前服务时间, 而且差值超过配置的时长, 将会请求失败
|
||||
* 如果传输的请求时间比服务时间大于配置的时长(超过一分钟), 将会请求失败
|
||||
*/
|
||||
@DbColumn(comment = "请求有效时长(秒)")
|
||||
private Integer reqTimeout;
|
||||
|
||||
/**
|
||||
* 消息通知方式, 目前只支持http
|
||||
* @see TradeNotifyTypeEnum
|
||||
|
@@ -47,12 +47,6 @@ public class PlatformConfigService {
|
||||
public void initPlatform(){
|
||||
PlatformConfig config = this.getConfig();
|
||||
PlatformLocal platform = PaymentContextLocal.get().getPlatformInfo();
|
||||
platform.setSignType(config.getSignType());
|
||||
platform.setSignSecret(config.getSignSecret());
|
||||
platform.setOrderTimeout(config.getOrderTimeout());
|
||||
platform.setLimitAmount(config.getLimitAmount());
|
||||
platform.setWebsiteUrl(config.getWebsiteUrl());
|
||||
platform.setNoticeType(config.getNotifyType());
|
||||
platform.setNoticeUrl(config.getNotifyUrl());
|
||||
BeanUtil.copyProperties(config,platform);
|
||||
}
|
||||
}
|
||||
|
@@ -33,6 +33,14 @@ public class PlatformConfigDto {
|
||||
@Schema(description = "是否对请求进行验签")
|
||||
private boolean reqSign;
|
||||
|
||||
/**
|
||||
* 请求有效时长(秒)
|
||||
* 如果传输的请求时间早于当前服务时间, 而且差值超过配置的时长, 将会请求失败
|
||||
* 如果传输的请求时间比服务时间大于配置的时长(超过一分钟), 将会请求失败
|
||||
*/
|
||||
@Schema(description = "请求有效时长(秒)")
|
||||
private Integer reqTimeout;
|
||||
|
||||
/**
|
||||
* 消息通知方式, 目前只支持http
|
||||
* @see TradeNotifyTypeEnum
|
||||
|
@@ -23,6 +23,14 @@ public class PlatformConfigParam {
|
||||
@Schema(description = "是否对请求进行验签")
|
||||
private boolean reqSign;
|
||||
|
||||
/**
|
||||
* 请求有效时长(秒)
|
||||
* 如果传输的请求时间早于当前服务时间, 而且差值超过配置的时长, 将会请求失败
|
||||
* 如果传输的请求时间比服务时间大于配置的时长(超过一分钟), 将会请求失败
|
||||
*/
|
||||
@Schema(description = "请求有效时长(秒)")
|
||||
private Integer reqTimeout;
|
||||
|
||||
/**
|
||||
* @see PaySignTypeEnum
|
||||
*/
|
||||
|
Reference in New Issue
Block a user