mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-09-03 02:56:20 +00:00
ref 参数修改+联调接口
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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));
|
||||
|
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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));
|
||||
|
||||
}
|
||||
|
@@ -20,5 +20,5 @@ public class PayCancelParam extends PaymentCommonParam {
|
||||
private String orderNo;
|
||||
|
||||
@Schema(description = "商户订单号")
|
||||
private String outTradeNo;
|
||||
private String bizOrderNo;
|
||||
}
|
||||
|
@@ -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;
|
@@ -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;
|
||||
|
@@ -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 = "支付订单号")
|
||||
|
@@ -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 {
|
||||
}
|
||||
|
@@ -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 = "商户订单号")
|
||||
|
@@ -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 = "退款号")
|
||||
|
@@ -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 {
|
||||
|
||||
/**
|
||||
* 支付网关同步状态
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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()
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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())
|
||||
|
@@ -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;
|
||||
|
||||
/**
|
||||
|
@@ -41,9 +41,9 @@ public class PayOrder extends MpBaseEntity implements EntityBaseFunction<PayOrde
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 三方系统交易号
|
||||
* 外部系统交易号
|
||||
*/
|
||||
@DbColumn(comment = "三方系统交易号")
|
||||
@DbColumn(comment = "外部支付订单号")
|
||||
private String outOrderNo;
|
||||
|
||||
/** 标题 */
|
||||
|
@@ -58,4 +58,8 @@ public class PayOrderService {
|
||||
}
|
||||
payOrderManager.updateById(payOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭
|
||||
*/
|
||||
}
|
||||
|
@@ -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;
|
||||
|
||||
/**
|
||||
|
@@ -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);
|
||||
|
@@ -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("未获取到签名方式,请检查");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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("未获取到签名方式,请检查");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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());
|
||||
|
@@ -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("未获取到签名方式,请检查");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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());
|
||||
// 初始化参数
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -110,7 +110,7 @@ public class RefundRepairService {
|
||||
}
|
||||
// 设置退款为完成状态和完成时间
|
||||
refundOrder.setStatus(RefundStatusEnum.SUCCESS.getCode())
|
||||
.setRefundTime(repairInfo.getFinishTime());
|
||||
.setFinishTime(repairInfo.getFinishTime());
|
||||
payOrder.setStatus(afterPayRefundStatus.getCode());
|
||||
|
||||
|
||||
|
@@ -25,9 +25,9 @@ public class PaySyncResult {
|
||||
private PaySyncStatusEnum syncStatus = FAIL;
|
||||
|
||||
/**
|
||||
* 第三方支付网关, 用与将记录关联起来
|
||||
* 外部第三方支付系统的交易号, 用与和本地记录关联起来
|
||||
*/
|
||||
private String outTradeNo;
|
||||
private String outOrderNo;
|
||||
|
||||
/** 支付完成时间(通常用于接收异步支付返回的时间) */
|
||||
private LocalDateTime payTime;
|
||||
|
@@ -27,7 +27,7 @@ public class RefundSyncResult {
|
||||
private String syncInfo;
|
||||
|
||||
/**
|
||||
* 第三方支付网关生成的退款交易, 用与将记录关联起来
|
||||
* 外部三方支付网关生成的退款交易, 用与将记录关联起来
|
||||
*/
|
||||
private String outRefundNo;
|
||||
|
||||
|
@@ -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("未获取到签名方式,请检查");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
// 判断网关状态是否和支付单一致
|
||||
|
@@ -33,8 +33,8 @@ public class PayCallbackRecord extends MpCreateEntity implements EntityBaseFunct
|
||||
@DbColumn(comment = "本地交易号")
|
||||
private String tradeNo;
|
||||
|
||||
/** 三方支付交易号 */
|
||||
@DbColumn(comment = "支付网关订单号")
|
||||
/** 外部交易号 */
|
||||
@DbColumn(comment = "外部交易号")
|
||||
private String outTradeNo;
|
||||
|
||||
/**
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -37,8 +37,8 @@ public class PaySyncRecord extends MpCreateEntity implements EntityBaseFunction<
|
||||
@DbColumn(comment = "商户交易号")
|
||||
private String bizTradeNo;
|
||||
|
||||
/** 三方支付交易号 */
|
||||
@DbColumn(comment = "三方支付交易号")
|
||||
/** 三方交易号 */
|
||||
@DbColumn(comment = "三方交易号")
|
||||
private String outTradeNo;
|
||||
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
}
|
@@ -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;
|
||||
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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 = "提示信息")
|
||||
|
@@ -24,7 +24,7 @@ public class PaySyncRecordDto extends BaseDto {
|
||||
|
||||
/** 本地订单ID */
|
||||
@Schema(description = "本地订单ID")
|
||||
private Long orderId;
|
||||
private String orderId;
|
||||
|
||||
/** 本地业务号 */
|
||||
@Schema(description = "本地业务号")
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
||||
}
|
||||
|
@@ -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>
|
||||
|
@@ -164,6 +164,8 @@ dax-pay:
|
||||
front-web-url: http://localhost:9000/#
|
||||
# 机器号码
|
||||
machine-no: 63
|
||||
# 当前环境,会影响订单号的生成
|
||||
env: DEV
|
||||
# 演示模块
|
||||
demo:
|
||||
# 网关地址
|
||||
|
Reference in New Issue
Block a user