feat: 新增退单操作接口及相关逻辑
主要修改: 1. 在LinkController中新增退单操作接口,支持用户对指定链接进行退单。 2. 在LinkStatusService中实现退单逻辑,确保用户只能退单自己的链接,并更新链接状态。 3. 在ScriptClient中新增调用退单接口的方法,处理与外部系统的交互。 技术细节: - 通过新增的退单功能,提升了用户对链接的管理能力,确保操作的安全性和有效性。
This commit is contained in:
@@ -253,6 +253,49 @@ public Mono<Boolean> deleteLink(@PathVariable("codeNo") String codeNo, Authentic
|
||||
});
|
||||
}
|
||||
|
||||
@PostMapping("/{codeNo}/refund")
|
||||
@Operation(summary = "退单操作", description = "对指定链接进行退单操作,会调用外部退单接口并更新数据库状态")
|
||||
public Mono<Boolean> refundOrder(@PathVariable("codeNo") String codeNo, Authentication authentication) {
|
||||
log.info("=== 开始退单操作 ===");
|
||||
log.info("链接编号: {}", codeNo);
|
||||
|
||||
if (authentication == null) {
|
||||
log.error("=== 认证失败:Authentication为空 ===");
|
||||
return Mono.error(new IllegalArgumentException("用户未认证:Authentication为空"));
|
||||
}
|
||||
|
||||
// 获取用户ID
|
||||
Claims claims = (Claims) authentication.getDetails();
|
||||
if (claims == null) {
|
||||
log.error("=== 认证失败:Claims为空 ===");
|
||||
log.error("Authentication details: {}", authentication.getDetails());
|
||||
return Mono.error(new IllegalArgumentException("用户未认证:Claims为空"));
|
||||
}
|
||||
|
||||
Long agentId = claims.get("userId", Long.class);
|
||||
String userType = claims.get("userType", String.class);
|
||||
|
||||
log.info("用户信息: agentId={}, userType={}", agentId, userType);
|
||||
|
||||
if (agentId == null) {
|
||||
log.error("=== 无法获取用户ID ===");
|
||||
return Mono.error(new IllegalArgumentException("无法获取用户ID"));
|
||||
}
|
||||
|
||||
return linkStatusService.refundOrder(codeNo, agentId)
|
||||
.doOnSuccess(success -> {
|
||||
if (success) {
|
||||
log.info("退单操作成功: codeNo={}, agentId={}", codeNo, agentId);
|
||||
} else {
|
||||
log.warn("退单操作失败: codeNo={}, agentId={}", codeNo, agentId);
|
||||
}
|
||||
})
|
||||
.doOnError(error -> {
|
||||
log.error("退单操作时发生错误: codeNo={}, agentId={}, error={}",
|
||||
codeNo, agentId, error.getMessage(), error);
|
||||
});
|
||||
}
|
||||
|
||||
@PostMapping("/batch-delete")
|
||||
@Operation(summary = "批量删除链接", description = "批量删除指定的链接,用户只能删除自己创建的链接,最多一次删除100个")
|
||||
public Mono<BatchDeleteResponse> batchDeleteLinks(@RequestBody BatchDeleteRequest request, Authentication authentication) {
|
||||
|
||||
@@ -359,6 +359,29 @@ public class ScriptClient {
|
||||
log.warn("获取设备状态失败: 设备={}, 错误={}", machineId, e.toString());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用退单接口
|
||||
* @param machineId 真实设备编号 (如 f1, ss9)
|
||||
* @return 退单操作结果
|
||||
*/
|
||||
public Mono<String> refundOrder(String machineId) {
|
||||
String url = String.format(apiBaseUrl + "/yijianwan_netfile/saveMsg?文件名=判断退单&cc2=%s", machineId);
|
||||
log.info("调用退单接口: 设备={}, url={}", machineId, url);
|
||||
|
||||
return webClient.get()
|
||||
.uri(url)
|
||||
.accept(MediaType.TEXT_PLAIN)
|
||||
.retrieve()
|
||||
.bodyToMono(String.class)
|
||||
.timeout(Duration.ofSeconds(10))
|
||||
.doOnSuccess(result -> {
|
||||
log.info("退单接口调用成功: 设备={}, 结果={}", machineId, result);
|
||||
})
|
||||
.doOnError(e -> {
|
||||
log.error("退单接口调用失败: 设备={}, 错误={}", machineId, e.toString());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -145,6 +145,93 @@ public class LinkStatusService {
|
||||
.onErrorReturn(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退单操作
|
||||
* @param codeNo 链接编号
|
||||
* @param agentId 代理ID(确保用户只能退单自己的链接)
|
||||
* @return 退单结果
|
||||
*/
|
||||
@Transactional
|
||||
public Mono<Boolean> refundOrder(String codeNo, Long agentId) {
|
||||
return Mono.fromCallable(() -> doRefundOrder(codeNo, agentId))
|
||||
.subscribeOn(Schedulers.boundedElastic());
|
||||
}
|
||||
|
||||
private Boolean doRefundOrder(String codeNo, Long agentId) {
|
||||
log.info("=== 开始处理退单操作 ===");
|
||||
log.info("链接编号: {}, 代理ID: {}", codeNo, agentId);
|
||||
|
||||
try {
|
||||
// 1. 查询链接任务
|
||||
LinkTask linkTask = linkTaskMapper.findByCodeNo(codeNo);
|
||||
if (linkTask == null) {
|
||||
log.error("链接任务不存在: codeNo={}", codeNo);
|
||||
throw new IllegalArgumentException("链接不存在");
|
||||
}
|
||||
|
||||
// 2. 验证代理ID(确保用户只能退单自己的链接)
|
||||
if (!linkTask.getAgentId().equals(agentId)) {
|
||||
log.error("权限不足: 用户{}无权退单链接{}", agentId, codeNo);
|
||||
throw new IllegalArgumentException("权限不足:您无权操作此链接");
|
||||
}
|
||||
|
||||
// 3. 检查链接状态是否允许退单
|
||||
String currentStatus = linkTask.getStatus();
|
||||
if ("REFUNDED".equals(currentStatus)) {
|
||||
log.warn("链接已经退过单: codeNo={}, status={}", codeNo, currentStatus);
|
||||
throw new IllegalStateException("链接已经退过单");
|
||||
}
|
||||
|
||||
if ("EXPIRED".equals(currentStatus)) {
|
||||
log.warn("过期链接不允许退单: codeNo={}, status={}", codeNo, currentStatus);
|
||||
throw new IllegalStateException("过期链接不允许退单");
|
||||
}
|
||||
|
||||
if ("COMPLETED".equals(currentStatus)) {
|
||||
log.warn("已完成链接不允许退单: codeNo={}, status={}", codeNo, currentStatus);
|
||||
throw new IllegalStateException("已完成链接不允许退单");
|
||||
}
|
||||
|
||||
// 4. 如果链接有关联的设备,调用脚本端退单接口
|
||||
String machineId = linkTask.getMachineId();
|
||||
if (machineId != null && !machineId.trim().isEmpty()) {
|
||||
log.info("链接关联设备: {}, 调用脚本端退单接口", machineId);
|
||||
|
||||
try {
|
||||
// 同步调用脚本端退单接口
|
||||
String refundResult = scriptClient.refundOrder(machineId).block();
|
||||
log.info("脚本端退单接口调用成功: 设备={}, 结果={}", machineId, refundResult);
|
||||
} catch (Exception e) {
|
||||
log.error("脚本端退单接口调用失败: 设备={}, 错误={}", machineId, e.getMessage());
|
||||
// 即使脚本端调用失败,我们仍然继续更新数据库状态
|
||||
// 这样可以确保用户能够看到退单状态,避免重复退单
|
||||
}
|
||||
} else {
|
||||
log.info("链接未关联设备,跳过脚本端退单调用");
|
||||
}
|
||||
|
||||
// 5. 更新链接状态为REFUNDED
|
||||
linkTask.setStatus("REFUNDED");
|
||||
linkTask.setRefundAt(LocalDateTime.now());
|
||||
linkTask.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
int updateResult = linkTaskMapper.update(linkTask);
|
||||
if (updateResult <= 0) {
|
||||
log.error("更新链接状态失败: codeNo={}", codeNo);
|
||||
throw new RuntimeException("更新链接状态失败");
|
||||
}
|
||||
|
||||
log.info("退单操作成功: codeNo={}, 设备={}, 状态更新为REFUNDED", codeNo, machineId);
|
||||
log.info("=== 退单操作完成 ===");
|
||||
return true;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("=== 退单操作失败 ===");
|
||||
log.error("codeNo={}, agentId={}, 错误详情: {}", codeNo, agentId, e.getMessage(), e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除链接(确保用户只能删除自己的链接)
|
||||
*/
|
||||
|
||||
@@ -70,7 +70,7 @@ script:
|
||||
|
||||
# 服务器配置
|
||||
app:
|
||||
base-url: "http://192.140.164.137:18080" # 生产环境需要配置为实际域名
|
||||
base-url: "https://2.uzi0.cc" # 生产环境需要配置为实际域名
|
||||
image-save-path: "./images" # 图片保存路径
|
||||
|
||||
link:
|
||||
|
||||
Reference in New Issue
Block a user