ref 参数修改+联调接口

This commit is contained in:
bootx
2024-04-27 23:08:51 +08:00
parent bf135eec40
commit 54081fd0df
51 changed files with 264 additions and 331 deletions

View File

@@ -39,8 +39,9 @@ import org.springframework.web.bind.annotation.RestController;
public class PayOrderController {
private final PayOrderQueryService queryService;
private final PayOrderExtraService payOrderExtraService;
private final PayCloseService payCloseService;
private final PayCloseService PayCloseService;
private final PaySyncService paySyncService;
private final AllocationService allocationService;
@@ -89,7 +90,7 @@ public class PayOrderController {
public ResResult<Void> close(String orderNo){
PayCloseParam param = new PayCloseParam();
param.setOrderNo(orderNo);
PayCloseService.close(param);
payCloseService.close(param);
return Res.ok();
}

View File

@@ -8,7 +8,6 @@ import cn.bootx.platform.daxpay.param.payment.refund.RefundSyncParam;
import cn.bootx.platform.daxpay.result.pay.SyncResult;
import cn.bootx.platform.daxpay.service.core.order.refund.service.RefundOrderQueryService;
import cn.bootx.platform.daxpay.service.core.order.refund.service.RefundOrderService;
import cn.bootx.platform.daxpay.service.core.payment.refund.service.RefundService;
import cn.bootx.platform.daxpay.service.core.payment.sync.service.RefundSyncService;
import cn.bootx.platform.daxpay.service.dto.order.refund.RefundOrderDto;
import cn.bootx.platform.daxpay.service.dto.order.refund.RefundOrderExtraDto;
@@ -59,8 +58,8 @@ public class RefundOrderController {
}
@Operation(summary = "退款同步")
@PostMapping("/syncById")
public ResResult<SyncResult> syncById(String refundNo){
@PostMapping("/syncByRefundNo")
public ResResult<SyncResult> syncByRefundNo(String refundNo){
RefundSyncParam refundSyncParam = new RefundSyncParam();
refundSyncParam.setRefundNo(refundNo);
return Res.ok(refundSyncService.sync(refundSyncParam));

View File

@@ -34,8 +34,8 @@ public class PayCallbackRecordController {
@Operation(summary = "查询单条")
@GetMapping("/findById")
public ResResult<PayCallbackRecordDto> findById(Long paymentId){
return Res.ok(service.findById(paymentId));
public ResResult<PayCallbackRecordDto> findById(Long id){
return Res.ok(service.findById(id));
}
}

View File

@@ -5,8 +5,6 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
@@ -44,11 +42,4 @@ public enum PayChannelEnum {
.orElseThrow(() -> new PayFailureException("不存在的支付通道"));
}
/** 异步支付通道 */
@Deprecated
public static final List<PayChannelEnum> ASYNC_TYPE = Collections.unmodifiableList(Arrays.asList(ALI, WECHAT, UNION_PAY));
/** 异步支付通道的编码 */
@Deprecated
public static final List<String> ASYNC_TYPE_CODE = Collections.unmodifiableList(Arrays.asList(ALI.code, WECHAT.code, UNION_PAY.code));
}

View File

@@ -20,5 +20,5 @@ public class PayCancelParam extends PaymentCommonParam {
private String orderNo;
@Schema(description = "商户订单号")
private String outTradeNo;
private String bizOrderNo;
}

View File

@@ -16,7 +16,7 @@ import java.time.LocalDateTime;
@Data
@Accessors(chain = true)
@Schema(title = "支付通用返回参数")
public class CommonResult {
public class PaymentCommonResult {
@Schema(description = "响应数据签名值")
private String sign;

View File

@@ -1,6 +1,6 @@
package cn.bootx.platform.daxpay.result.allocation;
import cn.bootx.platform.daxpay.result.CommonResult;
import cn.bootx.platform.daxpay.result.PaymentCommonResult;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -15,7 +15,7 @@ import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@Schema(title = "分账请求结果")
public class AllocationResult extends CommonResult {
public class AllocationResult extends PaymentCommonResult {
@Schema(description = "分账订单ID")
private Long orderId;

View File

@@ -2,7 +2,7 @@ package cn.bootx.platform.daxpay.result.order;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.result.CommonResult;
import cn.bootx.platform.daxpay.result.PaymentCommonResult;
import cn.bootx.platform.daxpay.serializer.LocalDateTimeToTimestampSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -21,7 +21,7 @@ import java.time.LocalDateTime;
@Data
@Accessors(chain = true)
@Schema(title = "支付单响应参数")
public class PayOrderResult extends CommonResult {
public class PayOrderResult extends PaymentCommonResult {
/** 支付订单号 */
@Schema(description = "支付订单号")

View File

@@ -1,6 +1,6 @@
package cn.bootx.platform.daxpay.result.pay;
import cn.bootx.platform.daxpay.result.CommonResult;
import cn.bootx.platform.daxpay.result.PaymentCommonResult;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -15,5 +15,5 @@ import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@Schema(title = "支付关闭响应参数")
public class PayCloseResult extends CommonResult {
public class PayCloseResult extends PaymentCommonResult {
}

View File

@@ -1,6 +1,6 @@
package cn.bootx.platform.daxpay.result.pay;
import cn.bootx.platform.daxpay.result.CommonResult;
import cn.bootx.platform.daxpay.result.PaymentCommonResult;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -15,7 +15,7 @@ import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@Schema(title = "统一下单响应参数")
public class PayResult extends CommonResult {
public class PayResult extends PaymentCommonResult {
/** 商户订单号 */
@Schema(description = "商户订单号")

View File

@@ -1,6 +1,6 @@
package cn.bootx.platform.daxpay.result.pay;
import cn.bootx.platform.daxpay.result.CommonResult;
import cn.bootx.platform.daxpay.result.PaymentCommonResult;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -15,7 +15,7 @@ import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@Schema(title = "退款响应参数")
public class RefundResult extends CommonResult {
public class RefundResult extends PaymentCommonResult {
/** 退款号 */
@Schema(description = "退款号")

View File

@@ -3,7 +3,7 @@ package cn.bootx.platform.daxpay.result.pay;
import cn.bootx.platform.daxpay.code.AllocationOrderStatusEnum;
import cn.bootx.platform.daxpay.code.RefundSyncStatusEnum;
import cn.bootx.platform.daxpay.code.PaySyncStatusEnum;
import cn.bootx.platform.daxpay.result.CommonResult;
import cn.bootx.platform.daxpay.result.PaymentCommonResult;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -20,7 +20,7 @@ import static cn.bootx.platform.daxpay.code.PaySyncStatusEnum.FAIL;
@Data
@Accessors(chain = true)
@Schema(title = "同步结果")
public class SyncResult extends CommonResult {
public class SyncResult extends PaymentCommonResult {
/**
* 支付网关同步状态

View File

@@ -20,6 +20,9 @@ public class OrderNoGenerateUtil {
/** 机器号 */
@Setter
private static String machineNo;
/** 环境前缀 */
@Setter
private static String env;
/**
* 生成支付订单号
@@ -28,7 +31,7 @@ public class OrderNoGenerateUtil {
StringBuilder orderNo = new StringBuilder();
String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmss"));
long id = ATOMIC_LONG.incrementAndGet();
orderNo.append("P").append(dateStr).append(machineNo).append(String.format("%06d", Math.abs(id) % ORDER_MAX_LIMIT));
orderNo.append(env).append("P").append(dateStr).append(machineNo).append(String.format("%06d", Math.abs(id) % ORDER_MAX_LIMIT));
return orderNo.toString();
}
@@ -39,7 +42,7 @@ public class OrderNoGenerateUtil {
StringBuilder orderNo = new StringBuilder();
String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmss"));
long id = ATOMIC_LONG.incrementAndGet();
orderNo.append("R").append(dateStr).append(machineNo).append(String.format("%06d", Math.abs(id) % ORDER_MAX_LIMIT));
orderNo.append(env).append("R").append(dateStr).append(machineNo).append(String.format("%06d", Math.abs(id) % ORDER_MAX_LIMIT));
return orderNo.toString();
}
@@ -50,7 +53,7 @@ public class OrderNoGenerateUtil {
StringBuilder orderNo = new StringBuilder();
String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmss"));
long id = ATOMIC_LONG.incrementAndGet();
orderNo.append("T").append(dateStr).append(machineNo).append(String.format("%06d", Math.abs(id) % ORDER_MAX_LIMIT));
orderNo.append(env).append("T").append(dateStr).append(machineNo).append(String.format("%06d", Math.abs(id) % ORDER_MAX_LIMIT));
return orderNo.toString();
}
@@ -61,7 +64,7 @@ public class OrderNoGenerateUtil {
StringBuilder orderNo = new StringBuilder();
String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmss"));
long id = ATOMIC_LONG.incrementAndGet();
orderNo.append("A").append(dateStr).append(machineNo).append(String.format("%06d", Math.abs(id) % ORDER_MAX_LIMIT));
orderNo.append(env).append("A").append(dateStr).append(machineNo).append(String.format("%06d", Math.abs(id) % ORDER_MAX_LIMIT));
return orderNo.toString();
}
@@ -72,7 +75,7 @@ public class OrderNoGenerateUtil {
StringBuilder orderNo = new StringBuilder();
String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmss"));
long id = ATOMIC_LONG.incrementAndGet();
orderNo.append("C").append(dateStr).append(machineNo).append(String.format("%06d", Math.abs(id) % ORDER_MAX_LIMIT));
orderNo.append(env).append("C").append(dateStr).append(machineNo).append(String.format("%06d", Math.abs(id) % ORDER_MAX_LIMIT));
return orderNo.toString();
}
@@ -83,7 +86,7 @@ public class OrderNoGenerateUtil {
StringBuilder orderNo = new StringBuilder();
String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmss"));
long id = ATOMIC_LONG.incrementAndGet();
orderNo.append("X").append(dateStr).append(machineNo).append(String.format("%06d", Math.abs(id) % ORDER_MAX_LIMIT));
orderNo.append(env).append("X").append(dateStr).append(machineNo).append(String.format("%06d", Math.abs(id) % ORDER_MAX_LIMIT));
return orderNo.toString();
}
}

View File

@@ -3,7 +3,9 @@ package cn.bootx.platform.daxpay.service.annotation;
import java.lang.annotation.*;
/**
* 支付接口标识,支付方法至少有一个参数,并且需要签名支付参数需要放在第一位
* 支付接口标识,
* 支付方法至少有一个参数,并且需要签名支付参数需要放在第一位
* 返回对象必须为 ResResult<T extends PaymentCommonResult> 格式
* @author xxm
* @since 2023/12/22
*/

View File

@@ -26,8 +26,16 @@ public class DaxPayProperties {
/** 机器码, 用于区分不同机器生成的流水号 */
private String machineNo = "56";
/** 当前环境,会影响订单号的生成 */
private String env = "";
public void setMachineNo(String machineNo) {
this.machineNo = machineNo;
OrderNoGenerateUtil.setMachineNo(machineNo);
}
public void setEnv(String env) {
this.env = env;
OrderNoGenerateUtil.setEnv(env);
}
}

View File

@@ -53,7 +53,7 @@ public class AliPaySyncService {
String tradeStatus = response.getTradeStatus();
syncResult.setSyncInfo(JSONUtil.toJsonStr(response));
// 设置网关订单号
syncResult.setOutTradeNo(response.getTradeNo());
syncResult.setOutOrderNo(response.getTradeNo());
// 支付完成 TODO 部分退款也在这个地方, 但无法进行区分, 需要借助对账进行处理
if (Objects.equals(tradeStatus, AliPayCode.NOTIFY_TRADE_SUCCESS) || Objects.equals(tradeStatus, AliPayCode.NOTIFY_TRADE_FINISHED)) {
// 支付完成时间
@@ -101,9 +101,9 @@ public class AliPaySyncService {
try {
AlipayTradeFastpayRefundQueryModel queryModel = new AlipayTradeFastpayRefundQueryModel();
// 退款请求号
queryModel.setOutRequestNo(String.valueOf(refundOrder.getId()));
queryModel.setOutRequestNo(String.valueOf(refundOrder.getRefundNo()));
// 商户订单号
queryModel.setOutTradeNo(String.valueOf(refundOrder.getRefundNo()));
queryModel.setOutTradeNo(String.valueOf(refundOrder.getOrderNo()));
// 设置返回退款完成时间
queryModel.setQueryOptions(Collections.singletonList(GMT_REFUND_PAY));
AlipayTradeFastpayRefundQueryResponse response = AliPayApi.tradeRefundQueryToResponse(queryModel);
@@ -121,7 +121,7 @@ public class AliPaySyncService {
LocalDateTime localDateTime = LocalDateTimeUtil.of(response.getGmtRefundPay());
return syncResult.setRefundTime(localDateTime).setSyncStatus(RefundSyncStatusEnum.SUCCESS);
} else {
return syncResult.setSyncStatus(RefundSyncStatusEnum.FAIL).setErrorMsg("支付宝网关反正退款未成功");
return syncResult.setSyncStatus(RefundSyncStatusEnum.FAIL).setErrorMsg("支付宝网关退款未成功");
}
} catch (AlipayApiException e) {
log.error("退款订单同步失败:", e);

View File

@@ -72,7 +72,7 @@ public class UnionPaySyncService {
String queryId = MapUtil.getStr(result, QUERY_ID);
String timeEnd = MapUtil.getStr(result, TXN_TIME);
LocalDateTime time = LocalDateTimeUtil.parse(timeEnd, DatePattern.PURE_DATETIME_PATTERN);
return syncResult.setOutTradeNo(queryId).setPayTime(time).setSyncStatus(PaySyncStatusEnum.SUCCESS);
return syncResult.setOutOrderNo(queryId).setPayTime(time).setSyncStatus(PaySyncStatusEnum.SUCCESS);
}
// 支付超时 交易不在受理时间范围内
@@ -102,7 +102,7 @@ public class UnionPaySyncService {
RefundSyncResult syncResult = new RefundSyncResult();
AssistOrder query = new AssistOrder();
query.setOutTradeNo(String.valueOf(refundOrder.getId()));
query.setOutTradeNo(String.valueOf(refundOrder.getRefundNo()));
Map<String, Object> result = unionPayKit.query(query);

View File

@@ -190,7 +190,7 @@ public class WeChatPayService {
.profit_sharing(payOrder.getAllocation()?"Y":"N")
.body(payOrder.getTitle())
.auth_code(authCode)
.out_trade_no(String.valueOf(payOrder.getId()))
.out_trade_no(String.valueOf(payOrder.getOrderNo()))
.total_fee(amount)
.spbill_create_ip(NetUtil.getLocalhostStr())
.build()

View File

@@ -47,7 +47,7 @@ public class WeChatPaySyncService {
.appid(weChatPayConfig.getWxAppId())
.mch_id(weChatPayConfig.getWxMchId())
.nonce_str(WxPayKit.generateStr())
.out_trade_no(String.valueOf(order.getId()))
.out_trade_no(String.valueOf(order.getOrderNo()))
.build()
.createSign(weChatPayConfig.getApiKeyV2(), SignType.HMACSHA256);
try {
@@ -67,7 +67,7 @@ public class WeChatPaySyncService {
}
// 设置微信支付网关订单号
syncResult.setOutTradeNo(result.get(TRANSACTION_ID));
syncResult.setOutOrderNo(result.get(TRANSACTION_ID));
// 查询到订单的状态
String tradeStatus = result.get(WeChatPayCode.TRADE_STATE);
// 支付完成
@@ -109,8 +109,8 @@ public class WeChatPaySyncService {
.appid(weChatPayConfig.getWxAppId())
.mch_id(weChatPayConfig.getWxMchId())
.nonce_str(WxPayKit.generateStr())
// 使用退款单号查询, 只返回当前这条, 如果使用支付订单号查询,
.out_refund_no(String.valueOf(refundOrder.getId()))
// 使用退款单号查询, 只返回当前这条, 如果使用支付订单号查询,返回所有相关的
.out_refund_no(String.valueOf(refundOrder.getRefundNo()))
.build()
.createSign(weChatPayConfig.getApiKeyV2(), SignType.HMACSHA256);

View File

@@ -37,7 +37,7 @@ public class WechatPayRefundService {
* 微信需要同时传输订单金额或退款金额
*/
public void refund(RefundOrder refundOrder, WeChatPayConfig weChatPayConfig) {
String refundFee = String.valueOf(refundOrder.getRefundNo());
String refundFee = String.valueOf(refundOrder.getOrderAmount());
String totalFee = String.valueOf(refundOrder.getAmount());
// 设置退款信息
RefundLocal refundInfo = PaymentContextLocal.get().getRefundInfo();
@@ -45,8 +45,8 @@ public class WechatPayRefundService {
.appid(weChatPayConfig.getWxAppId())
.mch_id(weChatPayConfig.getWxMchId())
.notify_url(weChatPayConfig.getNotifyUrl())
.out_trade_no(String.valueOf(refundOrder.getRefundNo()))
.out_refund_no(String.valueOf(refundOrder.getId()))
.out_trade_no(String.valueOf(refundOrder.getOrderNo()))
.out_refund_no(String.valueOf(refundOrder.getRefundNo()))
.total_fee(totalFee)
.refund_fee(refundFee)
.nonce_str(WxPayKit.generateStr())

View File

@@ -44,9 +44,9 @@ public class AllocationOrder extends MpBaseEntity implements EntityBaseFunction<
private String bizAllocationNo;
/**
* 三方系统分账
* 外部分账号
*/
@DbColumn(comment = "网关分账")
@DbColumn(comment = "外部分账号")
private String outAllocationNo;
/** 支付订单ID */
@@ -66,9 +66,9 @@ public class AllocationOrder extends MpBaseEntity implements EntityBaseFunction<
private String bizOrderNo;
/**
* 三方系统支付订单号
* 外部系统支付订单号
*/
@DbColumn(comment = "网关支付订单号")
@DbColumn(comment = "外部支付订单号")
private String outOrderNo;
/**

View File

@@ -41,9 +41,9 @@ public class PayOrder extends MpBaseEntity implements EntityBaseFunction<PayOrde
private String orderNo;
/**
* 三方系统交易号
* 外部系统交易号
*/
@DbColumn(comment = "三方系统交易")
@DbColumn(comment = "外部支付订单")
private String outOrderNo;
/** 标题 */

View File

@@ -58,4 +58,8 @@ public class PayOrderService {
}
payOrderManager.updateById(payOrder);
}
/**
* 关闭
*/
}

View File

@@ -74,11 +74,8 @@ public class RefundOrder extends MpBaseEntity implements EntityBaseFunction<Refu
@DbColumn(comment = "退款原因")
private String reason;
/** 退款发起时间 */
@DbColumn(comment = "退款发起时间")
private LocalDateTime refundTime;
@DbColumn(comment = "退款结束时间")
/** 退款完成时间 */
@DbColumn(comment = "退款完成时间")
private LocalDateTime finishTime;
/**

View File

@@ -36,7 +36,8 @@ public class RefundOrderService {
private final PayApiConfigManager apiConfigManager;
/**
* 手动发起退款
* 手动发起退款
* 退款涉及到回调通知, 索所以需要手动初始化一下上下文
*/
public void refund(PayOrderRefundParam param) {
@@ -46,6 +47,8 @@ public class RefundOrderService {
RefundParam refundParam = new RefundParam();
refundParam.setOrderNo(param.getOrderNo());
refundParam.setBizRefundNo(param.getOrderNo()+"R");
refundParam.setAmount(param.getAmount());
refundParam.setReason(param.getReason());
refundParam.setReqTime(LocalDateTime.now());
refundParam.setClientIp(ip);

View File

@@ -1,13 +1,10 @@
package cn.bootx.platform.daxpay.service.core.payment.close.service;
import cn.bootx.platform.common.core.exception.RepetitiveOperationException;
import cn.bootx.platform.daxpay.code.PaySignTypeEnum;
import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.param.payment.pay.PayCloseParam;
import cn.bootx.platform.daxpay.result.pay.PayCloseResult;
import cn.bootx.platform.daxpay.result.pay.PayResult;
import cn.bootx.platform.daxpay.service.common.context.PlatformLocal;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderQueryService;
@@ -17,7 +14,6 @@ import cn.bootx.platform.daxpay.service.core.payment.notice.service.ClientNotice
import cn.bootx.platform.daxpay.service.core.record.close.entity.PayCloseRecord;
import cn.bootx.platform.daxpay.service.core.record.close.service.PayCloseRecordService;
import cn.bootx.platform.daxpay.service.func.AbsPayCloseStrategy;
import cn.bootx.platform.daxpay.util.PaySignUtil;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import lombok.RequiredArgsConstructor;
@@ -81,15 +77,12 @@ public class PayCloseService {
strategy.doCloseHandler();
// 成功处理
this.successHandler(payOrder);
// 签名
this.sign(result);
// 返回结果
return result;
} catch (Exception e) {
// 记录关闭失败的记录
this.saveRecord(payOrder, false, e.getMessage());
result.setCode("1").setMsg(e.getMessage());
this.sign(result);
return result;
}
}
@@ -123,20 +116,4 @@ public class PayCloseService {
.setClientIp(clientIp);
payCloseRecordService.saveRecord(record);
}
/**
* 对返回结果进行签名
*/
private void sign(PayCloseResult result){
PlatformLocal platformInfo = PaymentContextLocal.get()
.getPlatformInfo();
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("未获取到签名方式,请检查");
}
}
}

View File

@@ -1,15 +1,18 @@
package cn.bootx.platform.daxpay.service.core.payment.common.aop;
import cn.bootx.platform.common.core.rest.Res;
import cn.bootx.platform.common.core.rest.ResResult;
import cn.bootx.platform.common.core.util.ValidationUtil;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.param.PaymentCommonParam;
import cn.bootx.platform.daxpay.result.PaymentCommonResult;
import cn.bootx.platform.daxpay.service.annotation.PaymentApi;
import cn.bootx.platform.daxpay.service.core.payment.common.service.PaymentSignService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
/**
@@ -25,9 +28,9 @@ import org.springframework.stereotype.Component;
public class PaymentVerifySignAop {
private final PaymentSignService paymentSignService;
@Before("@annotation(paymentApi)")
public void beforeMethod(JoinPoint joinPoint, PaymentApi paymentApi) {
Object[] args = joinPoint.getArgs();
@Around("@annotation(paymentApi)")
public Object beforeMethod(ProceedingJoinPoint pjp, PaymentApi paymentApi) throws Throwable {
Object[] args = pjp.getArgs();
if (args.length == 0){
throw new PayFailureException("支付方法至少有一个参数,并且需要签名支付参数需要放在第一位");
}
@@ -35,11 +38,32 @@ public class PaymentVerifySignAop {
if (param instanceof PaymentCommonParam){
// 参数校验
ValidationUtil.validateParam(param);
// 验签
// 参数验签
paymentSignService.verifySign((PaymentCommonParam) param);
} else {
throw new PayFailureException("支付参数需要继承PayCommonParam");
}
Object proceed;
try {
proceed = pjp.proceed();
} catch (PayFailureException ex) {
// 如果抛出支付异常, 包裹异常信息, 进行返回
PaymentCommonResult commonResult = new PaymentCommonResult();
commonResult.setMsg(ex.getMessage());
paymentSignService.sign(commonResult);
return Res.ok(commonResult);
}
// 对返回值进行签名
if (proceed instanceof ResResult){
Object data = ((ResResult<?>) proceed).getData();
if (data instanceof PaymentCommonResult){
paymentSignService.sign((PaymentCommonResult) data);
} else {
throw new PayFailureException("支付方法返回类型需要为 ResResult<T extends PaymentCommonResult> 格式");
}
} else {
throw new PayFailureException("支付方法返回类型需要为 ResResult<T extends PaymentCommonResult> 格式");
}
return proceed;
}
}

View File

@@ -3,6 +3,7 @@ package cn.bootx.platform.daxpay.service.core.payment.common.service;
import cn.bootx.platform.daxpay.code.PaySignTypeEnum;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.param.PaymentCommonParam;
import cn.bootx.platform.daxpay.result.PaymentCommonResult;
import cn.bootx.platform.daxpay.service.common.context.ApiInfoLocal;
import cn.bootx.platform.daxpay.service.common.context.PlatformLocal;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
@@ -55,4 +56,19 @@ public class PaymentSignService {
}
}
/**
* 对对象进行签名
*/
public void sign(PaymentCommonResult result) {
PlatformLocal platformInfo = PaymentContextLocal.get()
.getPlatformInfo();
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("未获取到签名方式,请检查");
}
}
}

View File

@@ -77,7 +77,7 @@ public class ClientNoticeAssistService {
.setRefundNo(order.getRefundNo())
.setChannel(order.getChannel())
.setAmount(order.getAmount())
.setRefundTime(order.getRefundTime())
.setRefundTime(order.getFinishTime())
.setCreateTime(order.getCreateTime())
.setStatus(order.getStatus())
.setAttach(orderExtra.getAttach());

View File

@@ -3,7 +3,6 @@ package cn.bootx.platform.daxpay.service.core.payment.pay.service;
import cn.bootx.platform.common.core.util.CollUtil;
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.PaySignTypeEnum;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.param.payment.pay.PayParam;
import cn.bootx.platform.daxpay.result.pay.PayResult;
@@ -19,7 +18,6 @@ import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrderExtra;
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderQueryService;
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderService;
import cn.bootx.platform.daxpay.service.core.payment.sync.service.PaySyncService;
import cn.bootx.platform.daxpay.util.PaySignUtil;
import cn.bootx.platform.daxpay.util.PayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
@@ -251,23 +249,6 @@ public class PayAssistService {
payResult.setPayBody(asyncPayInfo.getPayBody());
}
// 签名
this.sign(payResult);
return payResult;
}
/**
* 对返回
*/
public void sign(PayResult payResult) {
// 进行签名
PlatformLocal platformInfo = PaymentContextLocal.get()
.getPlatformInfo();
String signType = platformInfo.getSignType();
if (Objects.equals(PaySignTypeEnum.HMAC_SHA256.getCode(), signType)){
payResult.setSign(PaySignUtil.hmacSha256Sign(payResult, platformInfo.getSignSecret()));
} else if (Objects.equals(PaySignTypeEnum.MD5.getCode(), signType)){
payResult.setSign(PaySignUtil.md5Sign(payResult, platformInfo.getSignSecret()));
} else {
throw new PayFailureException("未获取到签名方式,请检查");
}
}
}

View File

@@ -3,7 +3,6 @@ package cn.bootx.platform.daxpay.service.core.payment.reconcile.service;
import cn.bootx.platform.common.core.exception.DataNotExistException;
import cn.bootx.platform.common.core.function.CollectorsFunction;
import cn.bootx.platform.common.core.util.CollUtil;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.ReconcileTradeEnum;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.service.code.AliPayRecordTypeEnum;
@@ -57,12 +56,6 @@ public class ReconcileService {
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public ReconcileOrder create(LocalDate date, String channel) {
// 获取通道枚举
PayChannelEnum channelEnum = PayChannelEnum.findByCode(channel);
// 判断是否为为异步通道
if (!PayChannelEnum.ASYNC_TYPE.contains(channelEnum)){
throw new PayFailureException("不支持对账的通道, 请检查");
}
// 构建对账策略
AbsReconcileStrategy reconcileStrategy = ReconcileStrategyFactory.create(channel);
@@ -173,12 +166,6 @@ public class ReconcileService {
// 查询对账单
List<ReconcileDetail> reconcileDetails = reconcileDetailManager.findAllByOrderId(reconcileOrder.getId());
// 获取通道枚举
if (!PayChannelEnum.ASYNC_TYPE_CODE.contains(reconcileOrder.getChannel())){
log.error("不支持对账的通道, 请检查, 对账订单ID: {}", reconcileOrder.getId());
throw new PayFailureException("不支持对账的通道, 请检查");
}
// 判断是否为为异步通道
// 构建对账策略
AbsReconcileStrategy reconcileStrategy = ReconcileStrategyFactory.create(reconcileOrder.getChannel());
// 初始化参数

View File

@@ -110,6 +110,7 @@ public class RefundAssistService {
.setBizOrderNo(payOrder.getBizOrderNo())
.setRefundNo(OrderNoGenerateUtil.refund())
.setBizRefundNo(refundParam.getBizRefundNo())
.setChannel(payOrder.getChannel())
.setStatus(RefundStatusEnum.PROGRESS.getCode())
.setOrderAmount(payOrder.getAmount())
.setAmount(refundParam.getAmount())
@@ -140,7 +141,7 @@ public class RefundAssistService {
// 退款成功更新退款时间
if (Objects.equals(refundOrder.getStatus(), SUCCESS.getCode())){
// TODO 读取网关返回的退款时间和完成时间
refundOrder.setRefundTime(LocalDateTime.now());
refundOrder.setFinishTime(LocalDateTime.now());
}
refundOrderManager.updateById(refundOrder);
}
@@ -153,6 +154,7 @@ public class RefundAssistService {
RefundLocal refundInfo = PaymentContextLocal.get().getRefundInfo();
refundOrder.setErrorCode(refundInfo.getErrorCode());
refundOrder.setErrorMsg(refundInfo.getErrorMsg());
refundOrder.setStatus(refundInfo.getStatus().getCode());
refundOrderManager.updateById(refundOrder);
}

View File

@@ -1,7 +1,6 @@
package cn.bootx.platform.daxpay.service.core.payment.refund.service;
import cn.bootx.platform.common.core.exception.DataNotExistException;
import cn.bootx.platform.common.core.exception.RepetitiveOperationException;
import cn.bootx.platform.common.core.util.CollUtil;
import cn.bootx.platform.common.core.util.ValidationUtil;
import cn.bootx.platform.daxpay.code.PayStatusEnum;
@@ -107,6 +106,7 @@ public class RefundService {
refundStrategy.doBeforeRefundHandler();
// 退款操作的预处理, 对支付订单进行预扣款, 返回创建成功的退款订单, 成功后才可以进行下一阶段的操作
RefundOrder refundOrder = SpringUtil.getBean(this.getClass()).preRefundMethod(param, payOrder);
refundStrategy.setRefundOrder(refundOrder);
try {
// 执行退款策略
refundStrategy.doRefundHandler();

View File

@@ -109,13 +109,14 @@ public class PayRepairService {
* 回调: 将异步支付状态修改为成功
*/
private void success(PayOrder order) {
// 读取支付网关中的完成时间
LocalDateTime payTime = PaymentContextLocal.get()
.getRepairInfo()
.getFinishTime();
// 修改订单支付状态为成功
order.setStatus(PayStatusEnum.SUCCESS.getCode());
// 读取支付网关中的时间
order.setPayTime(payTime);
order.setStatus(PayStatusEnum.SUCCESS.getCode())
.setPayTime(payTime)
.setCloseTime(null);
payOrderService.updateById(order);
}

View File

@@ -110,7 +110,7 @@ public class RefundRepairService {
}
// 设置退款为完成状态和完成时间
refundOrder.setStatus(RefundStatusEnum.SUCCESS.getCode())
.setRefundTime(repairInfo.getFinishTime());
.setFinishTime(repairInfo.getFinishTime());
payOrder.setStatus(afterPayRefundStatus.getCode());

View File

@@ -25,9 +25,9 @@ public class PaySyncResult {
private PaySyncStatusEnum syncStatus = FAIL;
/**
* 第三方支付网关, 用与记录关联起来
* 外部第三方支付系统的交易号, 用与和本地记录关联起来
*/
private String outTradeNo;
private String outOrderNo;
/** 支付完成时间(通常用于接收异步支付返回的时间) */
private LocalDateTime payTime;

View File

@@ -27,7 +27,7 @@ public class RefundSyncResult {
private String syncInfo;
/**
* 三方支付网关生成的退款交易, 用与将记录关联起来
* 外部三方支付网关生成的退款交易, 用与将记录关联起来
*/
private String outRefundNo;

View File

@@ -4,17 +4,14 @@ import cn.bootx.platform.common.core.exception.BizException;
import cn.bootx.platform.common.core.exception.RepetitiveOperationException;
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.PaySignTypeEnum;
import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.code.PaySyncStatusEnum;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.param.payment.pay.PaySyncParam;
import cn.bootx.platform.daxpay.result.CommonResult;
import cn.bootx.platform.daxpay.result.pay.SyncResult;
import cn.bootx.platform.daxpay.service.code.PayRepairSourceEnum;
import cn.bootx.platform.daxpay.service.code.PayRepairWayEnum;
import cn.bootx.platform.daxpay.service.code.PaymentTypeEnum;
import cn.bootx.platform.daxpay.service.common.context.PlatformLocal;
import cn.bootx.platform.daxpay.service.common.context.RepairLocal;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
@@ -27,7 +24,6 @@ import cn.bootx.platform.daxpay.service.core.payment.sync.result.PaySyncResult;
import cn.bootx.platform.daxpay.service.core.record.sync.entity.PaySyncRecord;
import cn.bootx.platform.daxpay.service.core.record.sync.service.PaySyncRecordService;
import cn.bootx.platform.daxpay.service.func.AbsPaySyncStrategy;
import cn.bootx.platform.daxpay.util.PaySignUtil;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import lombok.RequiredArgsConstructor;
@@ -68,16 +64,14 @@ public class PaySyncService {
*/
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public SyncResult sync(PaySyncParam param) {
SyncResult syncResult = new SyncResult();
PayOrder payOrder = payOrderQueryService.findByBizOrOrderNo(param.getBizOrderNo(), param.getOrderNo())
PayOrder payOrder = payOrderQueryService.findByBizOrOrderNo(param.getOrderNo(), param.getBizOrderNo())
.orElseThrow(() -> new BizException("支付订单不存在"));
// 钱包支付直接返回结果
// 钱包支付钱包不需要
if (PayChannelEnum.WALLET.getCode().equals(payOrder.getChannel())){
throw new PayFailureException("订单没有异步支付方式,不需要同步");
}
// 执行订单同步逻辑
syncResult = this.syncPayOrder(payOrder);
return syncResult;
return this.syncPayOrder(payOrder);
}
/**
* 同步支付状态, 开启一个新的事务, 不受外部抛出异常的影响
@@ -106,8 +100,8 @@ public class PaySyncService {
throw new PayFailureException(syncResult.getErrorMsg());
}
// 支付订单的网关订单号是否一致, 不一致进行更新
if (!Objects.equals(syncResult.getOutTradeNo(), payOrder.getOutOrderNo())){
payOrder.setOutOrderNo(syncResult.getOutTradeNo());
if (!Objects.equals(syncResult.getOutOrderNo(), payOrder.getOutOrderNo())){
payOrder.setOutOrderNo(syncResult.getOutOrderNo());
payOrderService.updateById(payOrder);
}
// 判断网关状态是否和支付单一致, 同时特定情况下更新网关同步状态
@@ -259,20 +253,4 @@ public class PaySyncService {
.setClientIp(PaymentContextLocal.get().getRequestInfo().getClientIp());
paySyncRecordService.saveRecord(paySyncRecord);
}
/**
* 签名
*/
private void sign(CommonResult result){
PlatformLocal platformInfo = PaymentContextLocal.get()
.getPlatformInfo();
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("未获取到签名方式,请检查");
}
}
}

View File

@@ -91,9 +91,9 @@ public class RefundSyncService {
this.saveRecord(refundOrder, syncResult, false, null, syncResult.getErrorMsg());
throw new PayFailureException(syncResult.getErrorMsg());
}
// 支付订单的网关订单号是否一致, 不一致进行更新
// 订单的外部交易号是否一致, 不一致进行更新
if (Objects.nonNull(syncResult.getOutRefundNo()) && !Objects.equals(syncResult.getOutRefundNo(), refundOrder.getOutRefundNo())){
refundOrder.setRefundNo(syncResult.getOutRefundNo());
refundOrder.setOutRefundNo(syncResult.getOutRefundNo());
refundOrderManager.updateById(refundOrder);
}
// 判断网关状态是否和支付单一致

View File

@@ -33,8 +33,8 @@ public class PayCallbackRecord extends MpCreateEntity implements EntityBaseFunct
@DbColumn(comment = "本地交易号")
private String tradeNo;
/** 三方支付交易号 */
@DbColumn(comment = "支付网关订单")
/** 外部交易号 */
@DbColumn(comment = "外部交易")
private String outTradeNo;
/**

View File

@@ -45,17 +45,17 @@ public class TradeFlowRecord extends MpCreateEntity {
/** 本地交易号 */
@DbColumn(comment = "本地订单号")
private String identifyNo;
private String tradeNo;
/** 商户交易号 */
@DbColumn(comment = "商户交易号")
private String bizIdentifyNo;
private String bizTradeNo;
/** 三方系统交易号 */
@DbColumn(comment = "三方系统交易号")
private String outIdentifyNo;
private String outTradeNo;
/** 网关完成时间 */
@DbColumn(comment = "网关完成时间")
private LocalDateTime gatewayTime;
private LocalDateTime finishTime;
}

View File

@@ -37,8 +37,8 @@ public class PaySyncRecord extends MpCreateEntity implements EntityBaseFunction<
@DbColumn(comment = "商户交易号")
private String bizTradeNo;
/** 三方支付交易号 */
@DbColumn(comment = "三方支付交易号")
/** 三方交易号 */
@DbColumn(comment = "三方交易号")
private String outTradeNo;

View File

@@ -1,29 +0,0 @@
package cn.bootx.platform.daxpay.service.core.report.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 支付通道占比饼图
* @author xxm
* @since 2024/3/17
*/
@Data
@Accessors(chain = true)
@Schema(title = "支付通道占比饼图")
public class ChannelProportionPie {
@Schema(description = "通道编码")
private String code;
@Schema(description = "通道名称")
private String name;
@Schema(description = "占比")
private Double proportion;
@Schema(description = "数量")
private Integer count;
}

View File

@@ -2,8 +2,8 @@ package cn.bootx.platform.daxpay.service.dto.order.pay;
import cn.bootx.platform.common.core.rest.dto.BaseDto;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.PayOrderAllocationStatusEnum;
import cn.bootx.platform.daxpay.code.PayStatusEnum;
import cn.bootx.platform.daxpay.code.AllocationOrderStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -21,42 +21,43 @@ import java.time.LocalDateTime;
@Schema(title = "具体支付日志基类")
public class PayOrderDto extends BaseDto {
/** 关联的业务号 */
@Schema(description = "关联的业务")
private String businessNo;
/** 商户订单号 */
@Schema(description = "商户订单")
private String bizOrderNo;
/** 支付网关订单号 */
@Schema(description = "支付网关订单号")
@Schema(description = "支付订单号")
private String orderNo;
/**
* 外部系统交易号
*/
@Schema(description = "外部支付订单号")
private String outOrderNo;
/** 标题 */
@Schema(description = "标题")
private String title;
/** 是否是异步支付 */
@Schema(description = "是否是异步支付")
private boolean asyncPay;
/** 描述 */
@Schema(description = "描述")
private String description;
/** 是否是组合支付 */
@Schema(description = "是否是组合支付")
private boolean combinationPay;
/** 是否需要分账 */
/** 是否支持分账 */
@Schema(description = "是否需要分账")
private Boolean allocation;
/**
* 异步支付通道
* 支付通道
* @see PayChannelEnum
*/
@Schema(description = "异步支付通道")
private String asyncChannel;
private String channel;
/**
* 如果有异步支付的情况下, 用与将记录关联起来
* 支付方式
*/
@Schema(description = "关联网关支付号")
private String gatewayOrderNo;
@Schema(description = "支付方式")
private String method;
/** 金额 */
@Schema(description = "金额")
@@ -75,7 +76,7 @@ public class PayOrderDto extends BaseDto {
/**
* 分账状态
* @see AllocationOrderStatusEnum
* @see PayOrderAllocationStatusEnum
*/
@Schema(description = "分账状态")
private String allocationStatus;
@@ -92,4 +93,13 @@ public class PayOrderDto extends BaseDto {
@Schema(description = "过期时间")
private LocalDateTime expiredTime;
/** 错误码 */
@Schema(description = "错误码")
private String errorCode;
/** 错误信息 */
@Schema(description = "错误信息")
private String errorMsg;
}

View File

@@ -8,7 +8,6 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
@@ -23,57 +22,71 @@ import java.time.LocalDateTime;
@Schema(title = "退款记录")
public class RefundOrderDto extends BaseDto {
/** 支付订单ID */
@Schema(description = "支付订单ID")
private Long orderId;
@Schema(description = "原支付业务号")
private String businessNo;
@Schema(description = "原支付订单号")
/** 支付订单号 */
@Schema(description = "支付订单号")
private String orderNo;
@Schema(description = "原支付标题")
/** 商户支付订单号 */
@Schema(description = "商户支付订单号")
private String bizOrderNo;
/** 支付标题 */
@Schema(description = "支付标题")
private String title;
/** 退款号 */
@Schema(description = "退款号")
private String refundNo;
@Schema(description = "是否含有异步通道")
private boolean asyncPay;
@Schema(description = "商户退款号")
private String bizRefundNo;
/** 三方支付系统退款交易号 */
@Schema(description = "三方支付系统退款交易号")
private String outRefundNo;
/**
* 异步通道
* 退款通道
* @see PayChannelEnum
*/
@Schema(description = "异步通道")
private String asyncChannel;
@Schema(description = "支付通道")
private String channel;
@Schema(description = "支付网关订单号")
private String gatewayOrderNo;
/** 订单金额 */
@Schema(description = "订单金额")
private Integer orderAmount;
/** 退款金额 */
@Schema(description = "退款金额")
private BigDecimal amount;
@Schema(description = "剩余可退")
private BigDecimal refundableBalance;
@Schema(description = "退款终端ip")
private String clientIp;
@Schema(description = "退款时间")
private LocalDateTime refundTime;
private Integer amount;
/** 退款原因 */
@Schema(description = "退款原因")
private String reason;
/** 退款发起时间 */
@Schema(description = "退款发起时间")
private LocalDateTime refundTime;
@Schema(description = "退款结束时间")
private LocalDateTime finishTime;
/**
* 退款状态
* @see RefundStatusEnum
*/
@Schema(description = "退款状态")
private String status;
/** 错误码 */
@Schema(description = "错误码")
private String errorCode;
/** 错误信息 */
@Schema(description = "错误信息")
private String errorMsg;

View File

@@ -20,11 +20,11 @@ import lombok.experimental.Accessors;
@Schema(title = "回调记录")
public class PayCallbackRecordDto extends BaseDto {
@Schema(description = "本地订单ID")
private Long orderId;
@Schema(description = "交易号")
private String tradeNo;
@Schema(description = "支付网关订单")
private String gatewayOrderNo;
@Schema(description = "外部交易")
private String outTradeNo;
/**
* 支付通道
* @see PayChannelEnum#getCode()
@@ -51,7 +51,7 @@ public class PayCallbackRecordDto extends BaseDto {
private String status;
@Schema(description = "修复号")
private String repairOrderNo;
private String repairNo;
/** 提示信息 */
@Schema(description = "提示信息")

View File

@@ -24,7 +24,7 @@ public class PaySyncRecordDto extends BaseDto {
/** 本地订单ID */
@Schema(description = "本地订单ID")
private Long orderId;
private String orderId;
/** 本地业务号 */
@Schema(description = "本地业务号")

View File

@@ -1,36 +0,0 @@
package cn.bootx.platform.daxpay.service.handler.exception;
import cn.bootx.platform.common.core.exception.BizException;
import cn.bootx.platform.common.core.rest.Res;
import cn.bootx.platform.common.core.rest.ResResult;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.result.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 过滤SaTokenException,需要运行在 RestExceptionHandler 之前
*
* @author xxm
* @since 2021/8/5
*/
@Order(Ordered.LOWEST_PRECEDENCE - 2)
@Slf4j
@RestControllerAdvice
public class PaymentExceptionHandler {
/**
* 支付异常
*/
@ExceptionHandler({PayFailureException.class})
public ResResult<CommonResult> handleBusinessException(PayFailureException ex) {
log.info(ex.getMessage(), ex);
CommonResult commonResult = new CommonResult();
commonResult.setMsg(ex.getMessage());
return Res.ok(commonResult);
}
}

View File

@@ -3,6 +3,7 @@ package cn.bootx.platform.daxpay.service.param.order;
import cn.bootx.platform.common.core.annotation.QueryParam;
import cn.bootx.platform.common.core.rest.param.QueryOrder;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.PayOrderAllocationStatusEnum;
import cn.bootx.platform.daxpay.code.PayStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -21,44 +22,64 @@ import lombok.experimental.Accessors;
@Schema(title = "支付订单查询参数")
public class PayOrderQuery extends QueryOrder {
@QueryParam(type = QueryParam.CompareTypeEnum.EQ)
@Schema(description = "支付订单id")
private Long id;
/** 商户订单号 */
@Schema(description = "商户订单号")
private String bizOrderNo;
/** 关联的业务号 */
@QueryParam(type = QueryParam.CompareTypeEnum.LIKE)
@Schema(description = "关联的业务号")
private String businessNo;
@Schema(description = "支付订单号")
private String orderNo;
/**
* 外部系统交易号
*/
@Schema(description = "外部支付订单号")
private String outOrderNo;
/** 标题 */
@QueryParam(type = QueryParam.CompareTypeEnum.LIKE)
@Schema(description = "标题")
private String title;
/** 是否是异步支付 */
@QueryParam(type = QueryParam.CompareTypeEnum.EQ)
@Schema(description = "是否是异步支付")
private Boolean asyncPay;
/** 是否是组合支付 */
@QueryParam(type = QueryParam.CompareTypeEnum.EQ)
@Schema(description = "是否是组合支付")
private Boolean combinationPay;
/** 是否支持分账 */
@Schema(description = "是否需要分账")
private Boolean allocation;
/**
* 异步支付通道
* 支付通道
* @see PayChannelEnum
*/
@QueryParam(type = QueryParam.CompareTypeEnum.EQ)
@Schema(description = "异步支付通道")
private String asyncChannel;
private String channel;
/**
* 支付方式
*/
@Schema(description = "支付方式")
private String method;
/** 金额 */
@Schema(description = "金额")
private Integer amount;
/**
* 支付状态
* @see PayStatusEnum
*/
@QueryParam(type = QueryParam.CompareTypeEnum.EQ)
@Schema(description = "支付状态")
private String status;
/**
* 分账状态
* @see PayOrderAllocationStatusEnum
*/
@Schema(description = "分账状态")
private String allocationStatus;
/** 错误码 */
@Schema(description = "错误码")
private String errorCode;
/** 错误信息 */
@Schema(description = "错误信息")
private String errorMsg;
}

View File

@@ -53,7 +53,7 @@
count(*) as count,
sum(amount) as sum
FROM
pay_channel_order
pay_order
WHERE
create_time BETWEEN #{startTime} AND #{endTime}
AND STATUS IN ( 'success', 'refunding', 'partial_refund', 'refunded' )
@@ -68,33 +68,11 @@
count(*) as count,
sum(amount) as sum
FROM
pay_refund_channel_order
pay_refund_order
WHERE
create_time BETWEEN #{startTime} AND #{endTime}
AND STATUS = 'success'
GROUP BY
channel
</select>
<!-- 支付通道占比饼图 -->
<select id="getPayChannelPie" resultType="cn.bootx.platform.daxpay.service.core.report.entity.ChannelProportionPie">
SELECT
channel,
name,
count(*) as count,
sum(amount) as sum
FROM
pay_channel_order
WHERE
create_time BETWEEN #{startTime} AND #{endTime}
AND STATUS IN ( 'success', 'refunding', 'partial_refund', 'refunded' )
GROUP BY
channel
</select>
<!-- -->
<select id="getRefundChannelPie" resultType="cn.bootx.platform.daxpay.service.core.report.entity.ChannelProportionPie">
</select>
</mapper>

View File

@@ -164,6 +164,8 @@ dax-pay:
front-web-url: http://localhost:9000/#
# 机器号码
machine-no: 63
# 当前环境,会影响订单号的生成
env: DEV
# 演示模块
demo:
# 网关地址