You've already forked FrameTour-BE
feat(profit-share): 调整分账与退款消息结构并优化接口
- 修改手动分账接口路径为 /manual 并支持请求体参数 - 更新计算分账结果接口路径为 /calculate - 将退款消息主题从 zt-refund 更改为 zt-profitshare-refund -重构退款消息对象字段,增加退款类型和原订单 ID - 更新退款消息生产者逻辑以适配新字段和主题配置 - 强化退款消息校验规则,确保必要字段完整性
This commit is contained in:
@@ -2,6 +2,7 @@ package com.ycwl.basic.controller.pc;
|
|||||||
|
|
||||||
import com.ycwl.basic.integration.profitshare.dto.CalculateResultVO;
|
import com.ycwl.basic.integration.profitshare.dto.CalculateResultVO;
|
||||||
import com.ycwl.basic.integration.profitshare.dto.CalculateShareRequest;
|
import com.ycwl.basic.integration.profitshare.dto.CalculateShareRequest;
|
||||||
|
import com.ycwl.basic.integration.profitshare.dto.ManualShareRequest;
|
||||||
import com.ycwl.basic.integration.profitshare.dto.TypesVO;
|
import com.ycwl.basic.integration.profitshare.dto.TypesVO;
|
||||||
import com.ycwl.basic.integration.profitshare.dto.record.RecordDetailVO;
|
import com.ycwl.basic.integration.profitshare.dto.record.RecordDetailVO;
|
||||||
import com.ycwl.basic.integration.profitshare.dto.record.RecordVO;
|
import com.ycwl.basic.integration.profitshare.dto.record.RecordVO;
|
||||||
@@ -210,14 +211,14 @@ public class ProfitShareV2Controller {
|
|||||||
/**
|
/**
|
||||||
* 手动触发分账
|
* 手动触发分账
|
||||||
*/
|
*/
|
||||||
@PostMapping("/share/manual/{orderId}")
|
@PostMapping("/manual")
|
||||||
public ApiResponse<String> manualShare(@PathVariable String orderId) {
|
public ApiResponse<String> manualShare(@Valid @RequestBody ManualShareRequest request) {
|
||||||
log.info("手动触发分账, orderId: {}", orderId);
|
log.info("手动触发分账, orderId: {}", request.getOrderId());
|
||||||
try {
|
try {
|
||||||
profitShareIntegrationService.manualShare(orderId);
|
profitShareIntegrationService.manualShare(request.getOrderId());
|
||||||
return ApiResponse.success("手动分账触发成功");
|
return ApiResponse.success("手动分账触发成功");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("手动触发分账失败, orderId: {}", orderId, e);
|
log.error("手动触发分账失败, orderId: {}", request.getOrderId(), e);
|
||||||
return ApiResponse.fail("手动触发分账失败: " + e.getMessage());
|
return ApiResponse.fail("手动触发分账失败: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -225,7 +226,7 @@ public class ProfitShareV2Controller {
|
|||||||
/**
|
/**
|
||||||
* 计算分账结果(不执行)
|
* 计算分账结果(不执行)
|
||||||
*/
|
*/
|
||||||
@PostMapping("/share/calculate")
|
@PostMapping("/calculate")
|
||||||
public ApiResponse<CalculateResultVO> calculateShare(@Valid @RequestBody CalculateShareRequest request) {
|
public ApiResponse<CalculateResultVO> calculateShare(@Valid @RequestBody CalculateShareRequest request) {
|
||||||
log.info("计算分账结果, scenicId: {}, totalAmount: {}", request.getScenicId(), request.getTotalAmount());
|
log.info("计算分账结果, scenicId: {}, totalAmount: {}", request.getScenicId(), request.getTotalAmount());
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class KafkaIntegrationProperties {
|
|||||||
private String bootstrapServers = "100.64.0.12:39092";
|
private String bootstrapServers = "100.64.0.12:39092";
|
||||||
private String ztMessageTopic = "zt-message"; // topic for zt-message microservice
|
private String ztMessageTopic = "zt-message"; // topic for zt-message microservice
|
||||||
private String profitShareTopic = "zt-profitshare"; // topic for profit share messages
|
private String profitShareTopic = "zt-profitshare"; // topic for profit share messages
|
||||||
private String refundTopic = "zt-refund"; // topic for refund messages
|
private String refundTopic = "zt-profitshare-refund"; // topic for refund messages
|
||||||
private Consumer consumer = new Consumer();
|
private Consumer consumer = new Consumer();
|
||||||
private Producer producer = new Producer();
|
private Producer producer = new Producer();
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import lombok.Data;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款消息(发送到 zt-refund topic)
|
* 退款消息(发送到 zt-profitshare-refund topic)
|
||||||
*
|
*
|
||||||
* @author Claude Code
|
* @author Claude Code
|
||||||
* @date 2025-01-11
|
* @date 2025-01-11
|
||||||
@@ -21,16 +21,16 @@ import lombok.NoArgsConstructor;
|
|||||||
public class RefundMessage {
|
public class RefundMessage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单ID
|
* 退款订单ID
|
||||||
*/
|
*/
|
||||||
@JsonProperty("order_id")
|
@JsonProperty("refund_order_id")
|
||||||
private String orderId;
|
private String refundOrderId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 景区ID
|
* 原订单ID
|
||||||
*/
|
*/
|
||||||
@JsonProperty("scenic_id")
|
@JsonProperty("original_order_id")
|
||||||
private Long scenicId;
|
private String originalOrderId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款金额(单位:元)
|
* 退款金额(单位:元)
|
||||||
@@ -38,18 +38,18 @@ public class RefundMessage {
|
|||||||
@JsonProperty("refund_amount")
|
@JsonProperty("refund_amount")
|
||||||
private Double refundAmount;
|
private Double refundAmount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退款类型(full: 全额退款, partial: 部分退款)
|
||||||
|
*/
|
||||||
|
@JsonProperty("refund_type")
|
||||||
|
private String refundType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付系统(alipay, wechat, union)
|
* 支付系统(alipay, wechat, union)
|
||||||
*/
|
*/
|
||||||
@JsonProperty("payment_system")
|
@JsonProperty("payment_system")
|
||||||
private String paymentSystem;
|
private String paymentSystem;
|
||||||
|
|
||||||
/**
|
|
||||||
* 退款订单ID
|
|
||||||
*/
|
|
||||||
@JsonProperty("refund_order_id")
|
|
||||||
private String refundOrderId;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unix 时间戳(秒)
|
* Unix 时间戳(秒)
|
||||||
*/
|
*/
|
||||||
@@ -59,13 +59,13 @@ public class RefundMessage {
|
|||||||
/**
|
/**
|
||||||
* 快速创建退款消息
|
* 快速创建退款消息
|
||||||
*/
|
*/
|
||||||
public static RefundMessage of(String orderId, Long scenicId, Double refundAmount, String paymentSystem, String refundOrderId) {
|
public static RefundMessage of(String refundOrderId, String originalOrderId, Double refundAmount, String refundType, String paymentSystem) {
|
||||||
return RefundMessage.builder()
|
return RefundMessage.builder()
|
||||||
.orderId(orderId)
|
|
||||||
.scenicId(scenicId)
|
|
||||||
.refundAmount(refundAmount)
|
|
||||||
.paymentSystem(paymentSystem)
|
|
||||||
.refundOrderId(refundOrderId)
|
.refundOrderId(refundOrderId)
|
||||||
|
.originalOrderId(originalOrderId)
|
||||||
|
.refundAmount(refundAmount)
|
||||||
|
.refundType(refundType)
|
||||||
|
.paymentSystem(paymentSystem)
|
||||||
.timestamp(System.currentTimeMillis() / 1000)
|
.timestamp(System.currentTimeMillis() / 1000)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import org.springframework.stereotype.Service;
|
|||||||
public class ProfitShareKafkaProducer {
|
public class ProfitShareKafkaProducer {
|
||||||
|
|
||||||
public static final String DEFAULT_PROFITSHARE_TOPIC = "zt-profitshare";
|
public static final String DEFAULT_PROFITSHARE_TOPIC = "zt-profitshare";
|
||||||
public static final String DEFAULT_REFUND_TOPIC = "zt-refund";
|
public static final String DEFAULT_REFUND_TOPIC = "zt-profitshare-refund";
|
||||||
|
|
||||||
private final KafkaTemplate<String, String> kafkaTemplate;
|
private final KafkaTemplate<String, String> kafkaTemplate;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
@@ -63,18 +63,18 @@ public class ProfitShareKafkaProducer {
|
|||||||
String topic = kafkaProps != null && StringUtils.isNotBlank(kafkaProps.getRefundTopic())
|
String topic = kafkaProps != null && StringUtils.isNotBlank(kafkaProps.getRefundTopic())
|
||||||
? kafkaProps.getRefundTopic()
|
? kafkaProps.getRefundTopic()
|
||||||
: DEFAULT_REFUND_TOPIC;
|
: DEFAULT_REFUND_TOPIC;
|
||||||
String key = message.getOrderId();
|
String key = message.getOriginalOrderId();
|
||||||
String payload = toJson(message);
|
String payload = toJson(message);
|
||||||
|
|
||||||
log.info("[REFUND] producing to topic={}, key={}, orderId={}, scenicId={}, amount={}",
|
log.info("[REFUND] producing to topic={}, key={}, refundOrderId={}, originalOrderId={}, amount={}, type={}",
|
||||||
topic, key, message.getOrderId(), message.getScenicId(), message.getRefundAmount());
|
topic, key, message.getRefundOrderId(), message.getOriginalOrderId(), message.getRefundAmount(), message.getRefundType());
|
||||||
|
|
||||||
kafkaTemplate.send(topic, key, payload).whenComplete((metadata, ex) -> {
|
kafkaTemplate.send(topic, key, payload).whenComplete((metadata, ex) -> {
|
||||||
if (ex != null) {
|
if (ex != null) {
|
||||||
log.error("[REFUND] produce failed: orderId={}, error={}", message.getOrderId(), ex.getMessage(), ex);
|
log.error("[REFUND] produce failed: refundOrderId={}, error={}", message.getRefundOrderId(), ex.getMessage(), ex);
|
||||||
} else if (metadata != null) {
|
} else if (metadata != null) {
|
||||||
log.info("[REFUND] produced: orderId={}, partition={}, offset={}",
|
log.info("[REFUND] produced: refundOrderId={}, partition={}, offset={}",
|
||||||
message.getOrderId(), metadata.getRecordMetadata().partition(), metadata.getRecordMetadata().offset());
|
message.getRefundOrderId(), metadata.getRecordMetadata().partition(), metadata.getRecordMetadata().offset());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -104,21 +104,21 @@ public class ProfitShareKafkaProducer {
|
|||||||
if (msg == null) {
|
if (msg == null) {
|
||||||
throw new IllegalArgumentException("RefundMessage is null");
|
throw new IllegalArgumentException("RefundMessage is null");
|
||||||
}
|
}
|
||||||
if (StringUtils.isBlank(msg.getOrderId())) {
|
if (StringUtils.isBlank(msg.getRefundOrderId())) {
|
||||||
throw new IllegalArgumentException("orderId is required");
|
throw new IllegalArgumentException("refundOrderId is required");
|
||||||
}
|
}
|
||||||
if (msg.getScenicId() == null || msg.getScenicId() <= 0) {
|
if (StringUtils.isBlank(msg.getOriginalOrderId())) {
|
||||||
throw new IllegalArgumentException("scenicId is required and must be positive");
|
throw new IllegalArgumentException("originalOrderId is required");
|
||||||
}
|
}
|
||||||
if (msg.getRefundAmount() == null || msg.getRefundAmount() <= 0) {
|
if (msg.getRefundAmount() == null || msg.getRefundAmount() <= 0) {
|
||||||
throw new IllegalArgumentException("refundAmount is required and must be positive");
|
throw new IllegalArgumentException("refundAmount is required and must be positive");
|
||||||
}
|
}
|
||||||
|
if (StringUtils.isBlank(msg.getRefundType())) {
|
||||||
|
throw new IllegalArgumentException("refundType is required");
|
||||||
|
}
|
||||||
if (StringUtils.isBlank(msg.getPaymentSystem())) {
|
if (StringUtils.isBlank(msg.getPaymentSystem())) {
|
||||||
throw new IllegalArgumentException("paymentSystem is required");
|
throw new IllegalArgumentException("paymentSystem is required");
|
||||||
}
|
}
|
||||||
if (StringUtils.isBlank(msg.getRefundOrderId())) {
|
|
||||||
throw new IllegalArgumentException("refundOrderId is required");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String toJson(Object obj) {
|
private String toJson(Object obj) {
|
||||||
|
|||||||
Reference in New Issue
Block a user