|
|
@@ -1,5 +1,7 @@
|
|
|
package shop.alien.lawyer.service.impl;
|
|
|
|
|
|
+import com.alibaba.fastjson2.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
@@ -10,11 +12,19 @@ import org.springframework.http.MediaType;
|
|
|
import org.springframework.http.ResponseEntity;
|
|
|
import org.springframework.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
import org.springframework.web.client.HttpClientErrorException;
|
|
|
import org.springframework.web.client.HttpServerErrorException;
|
|
|
import org.springframework.web.client.RestTemplate;
|
|
|
+import shop.alien.entity.store.LawyerConsultationOrder;
|
|
|
+import shop.alien.entity.store.LawyerUserViolation;
|
|
|
import shop.alien.lawyer.service.AiUserAuditTaskService;
|
|
|
+import shop.alien.lawyer.service.LawyerUserViolationService;
|
|
|
+import shop.alien.lawyer.util.ali.AliApi;
|
|
|
+import shop.alien.mapper.LawyerConsultationOrderMapper;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
import java.util.Map;
|
|
|
|
|
|
/**
|
|
|
@@ -31,12 +41,18 @@ public class AiUserAuditTaskServiceImpl implements AiUserAuditTaskService {
|
|
|
|
|
|
private final RestTemplate restTemplate;
|
|
|
|
|
|
+ private final LawyerUserViolationService lawyerUserViolationService;
|
|
|
+
|
|
|
@Value("${third-party-ai-auto-review.user-complaint-url:http://192.168.2.250:9100/ai/auto-review/api/v1/lawyer_user_complaint_audit_task/submit}")
|
|
|
private String aiUserAuditTaskUrl;
|
|
|
|
|
|
@Value("${third-party-ai-auto-review.lawyer-complaint-url:http://192.168.2.250:9100/ai/auto-review/api/v1/lawyer_complaint_audit_task/submit}")
|
|
|
private String aiAutoReviewUrl;
|
|
|
|
|
|
+ private final LawyerConsultationOrderMapper consultationOrderMapper;
|
|
|
+
|
|
|
+ private final AliApi aliApi;
|
|
|
+
|
|
|
@Override
|
|
|
@Async("lawyerTaskExecutor")
|
|
|
public void asyncCallUserAuditTask(Map<String, Object> requestBody, String accessToken) {
|
|
|
@@ -59,12 +75,25 @@ public class AiUserAuditTaskServiceImpl implements AiUserAuditTaskService {
|
|
|
log.info("异步调用AI用户申诉接口成功,响应状态:{},响应体:{}",
|
|
|
responseEntity.getStatusCode(), responseEntity.getBody());
|
|
|
|
|
|
+ // 解析响应并更新举报记录
|
|
|
+ parseAndUpdateViolation(responseEntity.getBody());
|
|
|
+
|
|
|
} catch (HttpServerErrorException e) {
|
|
|
+ String responseBody = e.getResponseBodyAsString();
|
|
|
log.error("异步调用AI用户申诉接口返回服务器错误,状态码:{},响应体:{},URL:{}",
|
|
|
- e.getStatusCode(), e.getResponseBodyAsString(), aiUserAuditTaskUrl, e);
|
|
|
+ e.getStatusCode(), responseBody, aiUserAuditTaskUrl, e);
|
|
|
+ // 即使返回错误,也尝试解析响应体(可能包含审核结果)
|
|
|
+ if (StringUtils.hasText(responseBody)) {
|
|
|
+ parseAndUpdateViolation(responseBody);
|
|
|
+ }
|
|
|
} catch (HttpClientErrorException e) {
|
|
|
+ String responseBody = e.getResponseBodyAsString();
|
|
|
log.error("异步调用AI用户申诉接口返回客户端错误,状态码:{},响应体:{},URL:{}",
|
|
|
- e.getStatusCode(), e.getResponseBodyAsString(), aiUserAuditTaskUrl, e);
|
|
|
+ e.getStatusCode(), responseBody, aiUserAuditTaskUrl, e);
|
|
|
+ // 即使返回错误,也尝试解析响应体(可能包含审核结果)
|
|
|
+ if (StringUtils.hasText(responseBody)) {
|
|
|
+ parseAndUpdateViolation(responseBody);
|
|
|
+ }
|
|
|
} catch (Exception e) {
|
|
|
log.error("异步调用AI用户申诉接口异常,URL:{},异常信息:{}", aiUserAuditTaskUrl, e.getMessage(), e);
|
|
|
}
|
|
|
@@ -101,5 +130,143 @@ public class AiUserAuditTaskServiceImpl implements AiUserAuditTaskService {
|
|
|
log.error("异步调用AI申诉接口异常,URL:{},异常信息:{}", aiAutoReviewUrl, e.getMessage(), e);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析AI响应并更新举报记录
|
|
|
+ *
|
|
|
+ * @param responseBody 响应体JSON字符串
|
|
|
+ */
|
|
|
+ private void parseAndUpdateViolation(String responseBody) {
|
|
|
+ if (!StringUtils.hasText(responseBody)) {
|
|
|
+ log.warn("AI响应体为空,无法解析");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 解析JSON响应
|
|
|
+ JSONObject responseJson = JSONObject.parseObject(responseBody);
|
|
|
+
|
|
|
+ // 检查响应码
|
|
|
+ Integer code = responseJson.getInteger("code");
|
|
|
+ if (code == null || code != 200) {
|
|
|
+ log.warn("AI响应码异常,code:{},message:{}", code, responseJson.getString("message"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取data对象
|
|
|
+ JSONObject data = responseJson.getJSONObject("data");
|
|
|
+ if (data == null) {
|
|
|
+ log.warn("AI响应data为空,无法获取审核结果");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取订单号
|
|
|
+ String orderNumber = data.getString("order_number");
|
|
|
+ if (!StringUtils.hasText(orderNumber)) {
|
|
|
+ log.warn("AI响应订单号为空,无法更新举报记录");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取result对象
|
|
|
+ JSONObject result = data.getJSONObject("result");
|
|
|
+ if (result == null) {
|
|
|
+ log.warn("AI响应result为空,订单号:{}", orderNumber);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取处理状态和审核结果
|
|
|
+ Integer processingStatus = result.getInteger("processing_status");
|
|
|
+ Boolean isReportValid = result.getBoolean("is_report_valid");
|
|
|
+ String decisionReason = result.getString("decision_reason");
|
|
|
+
|
|
|
+ log.info("解析AI响应成功,订单号:{},processing_status:{},is_report_valid:{},decision_reason:{}",
|
|
|
+ orderNumber, processingStatus, isReportValid, decisionReason);
|
|
|
+
|
|
|
+ if (processingStatus != null) {
|
|
|
+ if (processingStatus == 1 && StringUtils.hasText(orderNumber)) {
|
|
|
+ // processing_status = 1 表示已通过,进行退款操作
|
|
|
+ processRefund(orderNumber);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ log.warn("processing_status为空,订单号:{}", orderNumber);
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("解析AI响应并更新举报记录异常,响应体:{},异常信息:{}", responseBody, e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理订单退款
|
|
|
+ * <p>
|
|
|
+ * 根据订单号查询订单信息,调用支付宝退款接口进行退款
|
|
|
+ * 如果退款失败,会抛出异常以触发事务回滚
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @param orderNumber 订单号
|
|
|
+ * @throws RuntimeException 当退款失败时抛出异常,触发事务回滚
|
|
|
+ */
|
|
|
+ private void processRefund(String orderNumber) {
|
|
|
+ if (org.apache.commons.lang3.StringUtils.isEmpty(orderNumber)) {
|
|
|
+ log.error("处理退款失败:订单号为空");
|
|
|
+ throw new RuntimeException("订单号不能为空,无法处理退款");
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 查询订单信息
|
|
|
+ LambdaQueryWrapper<LawyerConsultationOrder> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
+ queryWrapper.eq(LawyerConsultationOrder::getOrderNumber, orderNumber)
|
|
|
+ .eq(LawyerConsultationOrder::getDeleteFlag, 0)
|
|
|
+ .last("LIMIT 1");
|
|
|
+ LawyerConsultationOrder order = consultationOrderMapper.selectOne(queryWrapper);
|
|
|
+
|
|
|
+ if (order == null) {
|
|
|
+ log.error("处理退款失败:订单不存在,订单号:{}", orderNumber);
|
|
|
+ throw new RuntimeException("订单不存在,无法处理退款,订单号:" + orderNumber);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查订单是否有支付宝交易号
|
|
|
+ if (org.apache.commons.lang3.StringUtils.isEmpty(order.getAlipayNo())) {
|
|
|
+ log.error("处理退款失败:订单无支付宝交易号,订单号:{}", orderNumber);
|
|
|
+ throw new RuntimeException("订单无支付宝交易号,无法处理退款,订单号:" + orderNumber);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查订单金额
|
|
|
+ if (order.getOrderAmount() == null || order.getOrderAmount() <= 0) {
|
|
|
+ log.error("处理退款失败:订单金额无效,订单号:{},订单金额:{}", orderNumber, order.getOrderAmount());
|
|
|
+ throw new RuntimeException("订单金额无效,无法处理退款,订单号:" + orderNumber);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将订单金额从分转换为元
|
|
|
+ BigDecimal refundAmount = new BigDecimal(order.getOrderAmount())
|
|
|
+ .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
|
|
|
+
|
|
|
+ // 退款原因
|
|
|
+ String refundReason = "举报审核通过,订单退款";
|
|
|
+
|
|
|
+ // 调用支付宝退款接口
|
|
|
+ log.info("开始处理订单退款,订单号:{},支付宝交易号:{},退款金额:{}元",
|
|
|
+ orderNumber, order.getAlipayNo(), refundAmount.toString());
|
|
|
+
|
|
|
+ String refundResult = aliApi.processRefund(order.getAlipayNo(), refundAmount.toString(), refundReason, "");
|
|
|
+
|
|
|
+ if ("调用成功".equals(refundResult)) {
|
|
|
+ log.info("订单退款成功,订单号:{},退款金额:{}元", orderNumber, refundAmount.toString());
|
|
|
+ } else {
|
|
|
+ log.error("订单退款失败,订单号:{},退款结果:{}", orderNumber, refundResult);
|
|
|
+ // 退款失败时抛出异常,触发事务回滚
|
|
|
+ throw new RuntimeException("订单退款失败,订单号:" + orderNumber + ",退款结果:" + refundResult);
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (RuntimeException e) {
|
|
|
+ // 重新抛出RuntimeException,触发事务回滚
|
|
|
+ log.error("处理订单退款失败,订单号:{},异常信息:{}", orderNumber, e.getMessage(), e);
|
|
|
+ throw e;
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 其他异常也转换为RuntimeException,触发事务回滚
|
|
|
+ log.error("处理订单退款异常,订单号:{},异常信息:{}", orderNumber, e.getMessage(), e);
|
|
|
+ throw new RuntimeException("处理订单退款时发生异常,订单号:" + orderNumber + ",异常信息:" + e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|