Преглед изворни кода

Merge branch 'sit' into uat-20260202

# Conflicts:
#	alien-lawyer/src/main/java/shop/alien/lawyer/util/AliSms.java
dujian пре 13 часа
родитељ
комит
665af2b1b6
21 измењених фајлова са 430 додато и 151 уклоњено
  1. 111 0
      alien-entity/src/main/java/shop/alien/entity/store/dto/AlipayTradeSettleConfirmDto.java
  2. 1 1
      alien-job/src/main/java/shop/alien/job/second/AiCheckXxlJob.java
  3. 1 1
      alien-job/src/main/java/shop/alien/job/second/AiProductComplaintJob.java
  4. 1 1
      alien-job/src/main/java/shop/alien/job/second/AiUserViolationJob.java
  5. 1 1
      alien-job/src/main/java/shop/alien/job/store/AiTagJob.java
  6. 19 74
      alien-job/src/main/java/shop/alien/job/store/AlipayJob.java
  7. 1 1
      alien-job/src/main/java/shop/alien/job/store/BadReviewAppealJob.java
  8. 2 2
      alien-lawyer/src/main/java/shop/alien/lawyer/util/AliSms.java
  9. 1 1
      alien-lawyer/src/main/java/shop/alien/lawyer/util/ai/AiAuthTokenUtil.java
  10. 6 0
      alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsReportingServiceImpl.java
  11. 1 1
      alien-second/src/main/java/shop/alien/second/util/AiTaskUtils.java
  12. 50 40
      alien-second/src/main/java/shop/alien/second/util/AiUserViolationUtils.java
  13. 1 1
      alien-store-platform/src/main/java/shop/alien/storeplatform/util/AiAuthTokenUtil.java
  14. 1 1
      alien-store/src/main/java/shop/alien/store/controller/AiAuditController.java
  15. 38 0
      alien-store/src/main/java/shop/alien/store/controller/AlipaySettleController.java
  16. 1 1
      alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java
  17. 1 23
      alien-store/src/main/java/shop/alien/store/controller/UserStoreController.java
  18. 16 0
      alien-store/src/main/java/shop/alien/store/service/AlipaySettleService.java
  19. 1 1
      alien-store/src/main/java/shop/alien/store/service/StoreCommentAppealSupplementJobService.java
  20. 175 0
      alien-store/src/main/java/shop/alien/store/service/impl/AlipaySettleServiceImpl.java
  21. 1 1
      alien-store/src/main/java/shop/alien/store/util/AiUserViolationUtils.java

+ 111 - 0
alien-entity/src/main/java/shop/alien/entity/store/dto/AlipayTradeSettleConfirmDto.java

@@ -0,0 +1,111 @@
+package shop.alien.entity.store.dto;
+
+import com.fasterxml.jackson.annotation.JsonAlias;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * alipay.trade.settle.confirm — 统一收单确认结算请求体。
+ *
+ * @see <a href="https://opendocs.alipay.com/open/028xq9">确认结算</a>
+ */
+@Data
+@ApiModel("支付宝确认结算(trade.settle.confirm)")
+public class AlipayTradeSettleConfirmDto implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "确认结算请求流水号(商户侧唯一)", required = true)
+    @JsonProperty("out_request_no")
+    @JsonAlias("outRequestNo")
+    private String outRequestNo;
+
+    @ApiModelProperty(value = "支付宝交易号", required = true)
+    @JsonProperty("trade_no")
+    @JsonAlias("tradeNo")
+    private String tradeNo;
+
+    @ApiModelProperty(value = "结算信息", required = true)
+    @JsonProperty("settle_info")
+    @JsonAlias("settleInfo")
+    private SettleInfo settleInfo;
+
+    @ApiModelProperty("扩展参数(如 royalty_freeze)")
+    @JsonProperty("extend_params")
+    @JsonAlias("extendParams")
+    private ExtendParams extendParams;
+
+    @ApiModelProperty("应用授权令牌 app_auth_token(第三方代调用时选填)")
+    @JsonProperty("app_auth_token")
+    @JsonAlias("appAuthToken")
+    private String appAuthToken;
+
+    @Data
+    @ApiModel("结算信息")
+    public static class SettleInfo implements Serializable {
+
+        private static final long serialVersionUID = 1L;
+
+        @ApiModelProperty(value = "结算明细列表", required = true)
+        @JsonProperty("settle_detail_infos")
+        @JsonAlias("settleDetailInfos")
+        private List<SettleDetailInfo> settleDetailInfos;
+    }
+
+    @Data
+    @ApiModel("结算明细")
+    public static class SettleDetailInfo implements Serializable {
+
+        private static final long serialVersionUID = 1L;
+
+        @ApiModelProperty("结算金额")
+        private String amount;
+
+        @ApiModelProperty("收入方账号")
+        @JsonProperty("trans_in")
+        @JsonAlias("transIn")
+        private String transIn;
+
+        @ApiModelProperty("结算主体类型,如 SecondMerchant")
+        @JsonProperty("settle_entity_type")
+        @JsonAlias("settleEntityType")
+        private String settleEntityType;
+
+        @ApiModelProperty("汇总维度")
+        @JsonProperty("summary_dimension")
+        @JsonAlias("summaryDimension")
+        private String summaryDimension;
+
+        @ApiModelProperty("实际结算金额")
+        @JsonProperty("actual_amount")
+        @JsonAlias("actualAmount")
+        private String actualAmount;
+
+        @ApiModelProperty("结算主体标识")
+        @JsonProperty("settle_entity_id")
+        @JsonAlias("settleEntityId")
+        private String settleEntityId;
+
+        @ApiModelProperty("收入方类型,如 cardAliasNo、defaultSettle")
+        @JsonProperty("trans_in_type")
+        @JsonAlias("transInType")
+        private String transInType;
+    }
+
+    @Data
+    @ApiModel("确认结算扩展参数")
+    public static class ExtendParams implements Serializable {
+
+        private static final long serialVersionUID = 1L;
+
+        @ApiModelProperty("是否冻结分账,如 true / false")
+        @JsonProperty("royalty_freeze")
+        @JsonAlias("royaltyFreeze")
+        private String royaltyFreeze;
+    }
+}

+ 1 - 1
alien-job/src/main/java/shop/alien/job/second/AiCheckXxlJob.java

@@ -69,7 +69,7 @@ public class AiCheckXxlJob {
     private String loginUrl;
 
     //用户名
-    @Value("${third-party-user-name.base-url}")
+    @Value("${third-party-user-name-admin.base-url}")
     private String userName;
 
     //密码

+ 1 - 1
alien-job/src/main/java/shop/alien/job/second/AiProductComplaintJob.java

@@ -45,7 +45,7 @@ public class AiProductComplaintJob {
     private final LifeUserMapper lifeUserMapper;
     private final LifeNoticeMapper lifeNoticeMapper;
 
-    @Value("${third-party-user-name.base-url}")
+    @Value("${third-party-user-name-admin.base-url}")
     private String userName;
 
     @Value("${third-party-pass-word.base-url}")

+ 1 - 1
alien-job/src/main/java/shop/alien/job/second/AiUserViolationJob.java

@@ -46,7 +46,7 @@ public class AiUserViolationJob {
     private final SecondUserCreditMapper secondUserCreditMapper;
     private final SecondUserCreditRecordMapper secondUserCreditRecordMapper;
 
-    @Value("${third-party-user-name.base-url}")
+    @Value("${third-party-user-name-admin.base-url}")
     private String userName;
 
     @Value("${third-party-pass-word.base-url}")

+ 1 - 1
alien-job/src/main/java/shop/alien/job/store/AiTagJob.java

@@ -92,7 +92,7 @@ public class AiTagJob {
     private String aiMerchantOnboardingApplicationsUrl;
 
     //用户名
-    @Value("${third-party-user-name.base-url}")
+    @Value("${third-party-user-name-admin.base-url}")
     private String userName;
 
     //密码

+ 19 - 74
alien-job/src/main/java/shop/alien/job/store/AlipayJob.java

@@ -16,11 +16,8 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Component;
 import shop.alien.entity.store.AlipayZftCreateRecord;
-import shop.alien.entity.store.LawyerUser;
 import shop.alien.entity.store.StoreInfo;
 import shop.alien.mapper.AlipayZftCreateRecordMapper;
-import shop.alien.mapper.LawyerUserMapper;
-import shop.alien.mapper.StoreInfoMapper;
 import shop.alien.store.service.StoreInfoService;
 
 import java.util.List;
@@ -30,16 +27,9 @@ import java.util.List;
 @RequiredArgsConstructor
 public class AlipayJob {
 
-    /** 进件主体:商户 */
-    private static final String PAYMENT_SUBJECT_MERCHANT = "0";
-    /** 进件主体:律师 */
-    private static final String PAYMENT_SUBJECT_LAWYER = "1";
-
     private final AlipayZftCreateRecordMapper alipayZftCreateRecordMapper;
 
-    private final StoreInfoMapper storeInfoMapper;
-
-    private final LawyerUserMapper lawyerUserMapper;
+    private final StoreInfoService storeInfoService;
 
     /**
      * 查询支付宝二级商户进件结果,并从响应中回写门店 smid。
@@ -76,84 +66,38 @@ public class AlipayJob {
             }
 
             String body = response.getBody();
-            JSONObject firstOrder = firstOrderInZftOrderQueryBody(body);
-            String smid = firstOrder == null ? null : firstOrder.getString("smid");
+            String smid = extractSmidFromZftOrderQueryBody(body);
             if (StringUtils.isBlank(smid)) {
                 log.debug("order.query 未解析到 smid orderId={}", orderId);
                 continue;
             }
 
-            String paymentSubject = record.getType() == null ? PAYMENT_SUBJECT_MERCHANT : record.getType();
-            if (PAYMENT_SUBJECT_LAWYER.equals(paymentSubject)) {
-                applySmidToLawyer(record, smid, firstOrder);
-            } else {
-                Integer storeId = record.getStoreId();
-                if (storeId == null) {
-                    log.debug("进件记录无 storeId,跳过回写 orderId={}", orderId);
-                    continue;
-                }
-
-                StoreInfo storeInfo = storeInfoMapper.getStoreInfo(storeId);
-                if (storeInfo == null) {
-                    log.warn("门店不存在 storeId={} orderId={}", storeId, orderId);
-                    continue;
-                }
-
-                if (smid.equals(storeInfo.getAlipaySmid())) {
-                    continue;
-                }
-
-                storeInfo.setAlipaySmid(smid);
-                storeInfoMapper.updateById(storeInfo);
-                log.info("已回写门店 alipay_smid storeId={} orderId={}", storeId, orderId);
+            Integer storeId = record.getStoreId();
+            if (storeId == null) {
+                log.debug("进件记录无 storeId,跳过回写 orderId={}", orderId);
+                continue;
             }
-        }
-    }
 
-    /**
-     * 律师进件:law_firm 与进件 merchant_name 一致,且 zfb_secondary_merchant_account 为空时写入 smid。
-     * 若响应中带 order_id,则与进件记录 order_id 校验一致后再回写。
-     */
-    private void applySmidToLawyer(AlipayZftCreateRecord record, String smid, JSONObject firstOrder) {
-        String orderId = record.getOrderId();
-        String respOrderId = firstOrder != null ? firstOrder.getString("order_id") : null;
-        if (StringUtils.isNotBlank(respOrderId) && StringUtils.isNotBlank(orderId)
-                && !orderId.trim().equals(respOrderId.trim())) {
-            log.warn("order.query 返回 order_id 与进件记录不一致 recordOrderId={} respOrderId={}", orderId, respOrderId);
-            return;
-        }
-
-        String merchantName = record.getMerchantName();
-        if (StringUtils.isBlank(merchantName)) {
-            log.debug("律师进件记录无 merchant_name,跳过回写 orderId={}", orderId);
-            return;
-        }
-
-        LambdaQueryWrapper<LawyerUser> w = new LambdaQueryWrapper<>();
-        w.eq(LawyerUser::getLawFirm, merchantName.trim());
-        List<LawyerUser> lawyers = lawyerUserMapper.selectList(w);
-        if (lawyers == null || lawyers.isEmpty()) {
-            log.warn("未找到 law_firm 与 merchant_name 匹配的律师用户 merchantName={} orderId={}", merchantName, orderId);
-            return;
-        }
-
-        for (LawyerUser lawyer : lawyers) {
-            if (lawyer == null) {
+            StoreInfo storeInfo = storeInfoService.getById(storeId);
+            if (storeInfo == null) {
+                log.warn("门店不存在 storeId={} orderId={}", storeId, orderId);
                 continue;
             }
-            if (StringUtils.isNotBlank(lawyer.getZfbSecondaryMerchantAccount())) {
+
+            if (smid.equals(storeInfo.getAlipaySmid())) {
                 continue;
             }
-            lawyer.setZfbSecondaryMerchantAccount(smid);
-            lawyerUserMapper.updateById(lawyer);
-            log.info("已回写律师 zfb_secondary_merchant_account lawyerUserId={} orderId={}", lawyer.getId(), orderId);
+
+            storeInfo.setAlipaySmid(smid);
+            storeInfoService.updateById(storeInfo);
+            log.info("已回写门店 alipay_smid storeId={} orderId={}", storeId, orderId);
         }
     }
 
     /**
-     * 从 ant.merchant.expand.indirect.zftorder.query 响应 body 中取 orders 首条对象
+     * 从 ant.merchant.expand.indirect.zftorder.query 响应 body 中取 orders 首条的 smid。
      */
-    private static JSONObject firstOrderInZftOrderQueryBody(String body) {
+    private static String extractSmidFromZftOrderQueryBody(String body) {
         if (StringUtils.isBlank(body)) {
             return null;
         }
@@ -167,7 +111,8 @@ public class AlipayJob {
             if (orders == null || orders.isEmpty()) {
                 return null;
             }
-            return orders.getJSONObject(0);
+            JSONObject first = orders.getJSONObject(0);
+            return first == null ? null : first.getString("smid");
         } catch (Exception e) {
             log.warn("解析 zftorder.query 响应 body 失败: {}", e.getMessage());
             return null;

+ 1 - 1
alien-job/src/main/java/shop/alien/job/store/BadReviewAppealJob.java

@@ -71,7 +71,7 @@ public class BadReviewAppealJob {
 //    @Value("${third-party-login.base-url}")
 //    private String loginUrl;
 
-    @Value("${third-party-user-name.base-url}")
+    @Value("${third-party-user-name-admin.base-url}")
     private String userName;
 
     @Value("${third-party-pass-word.base-url}")

+ 2 - 2
alien-lawyer/src/main/java/shop/alien/lawyer/util/AliSms.java

@@ -62,11 +62,11 @@ public class AliSms {
         try {
             // -----------------测试用手机号--------------------------------------------------------------------------------------------
             List<String> phoneList = Arrays.asList("19999990001", "19999990002", "19999990003", "19999990004", "19999990005", "19999990006", "19999990007", "19999990008", "19999990009", "19999990010",
-                    "16666660001", "16666660002", "16666660003", "16666660004", "16666660005", "16666660006", "16666660007", "16666660008", "16666660009", "16666660010",
+                    "16666660001", "16666660002", "16666660003", "16666660004", "16666660005", "16666660006", "16666660007", "16666660008", "16666660009", "16666660010", "16666660011",
                     "18888880001", "18888880002", "18888880003", "18888880004", "18888880005", "18888880006", "18888880007", "18888880008", "18888880009", "18888880010",
                     "17777770001","17777770002","17777770003","17777770004","17777770005","17777770006","17777770007","17777770008","17777770009","17777770010",
                     "17011111112"
-                    );
+            );
             if (phoneList.contains(phone)) {
                 // 验证码发送成功,将验证码保存到redis中 设置60秒过期
                 baseRedisService.setString("verification_lawyer_"+phone,"123456",Long.valueOf(300));

+ 1 - 1
alien-lawyer/src/main/java/shop/alien/lawyer/util/ai/AiAuthTokenUtil.java

@@ -24,7 +24,7 @@ public class AiAuthTokenUtil {
     @Value("${third-party-login.base-url}")
     private String loginUrl;
 
-    @Value("${third-party-user-name.base-url}")
+    @Value("${third-party-user-name-admin.base-url}")
     private String userName;
 
     @Value("${third-party-pass-word.base-url}")

+ 6 - 0
alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsReportingServiceImpl.java

@@ -207,6 +207,12 @@ public class SecondGoodsReportingServiceImpl implements SecondGoodsReportingServ
 //                SecondGoodsRecord goodsRecord = secondGoodsRecordMapper.selectOne(goodsWrapper);
 //                if (null != goodsRecord) lifeuserViolation.setBusinessId(goodsRecord.getId());
 //            }
+            List<String> imgList = lifeuserViolation.getImgUrl();
+            String imgStr = "";
+            if (imgList != null && !imgList.isEmpty()) {
+                imgStr = StringUtils.join(imgList, ",");
+            }
+            lifeuserViolation.setReportEvidenceImg(imgStr);
             int result = lifeUserViolationMapper.insert(lifeuserViolation);
             if (result > 0) {
 

+ 1 - 1
alien-second/src/main/java/shop/alien/second/util/AiTaskUtils.java

@@ -29,7 +29,7 @@ public class AiTaskUtils {
 //    @Value("${third-party-login.base-url:http://192.168.2.250:9000/ai/user-auth-core/api/v1/auth/login}")
 //    private String loginUrl = "http://192.168.2.250:9000/ai/user-auth-core/api/v1/auth/login";
 
-    @Value("${third-party-user-name.base-url:UdUser}")
+    @Value("${third-party-user-name-admin.base-url:UdUser}")
     private String userName;
 
     @Value("${third-party-pass-word.base-url:123456}")

+ 50 - 40
alien-second/src/main/java/shop/alien/second/util/AiUserViolationUtils.java

@@ -43,13 +43,13 @@ public class AiUserViolationUtils {
     @Value("${third-party-login.base-url}")
     private String loginUrl;
 
-    @Value("${third-party-user-name.base-url:UdUser}")
+    @Value("${third-party-user-name-admin.base-url:UdUser}")
     private String userName;
 
     @Value("${third-party-pass-word.base-url:123456}")
     private String passWord;
 
-    @Value("${third-party-ai.report-review.base-url}")
+    @Value("${third-party-ai.reportuser-review.base-url}")
     private String userComplaintRecordUrl;
 
     @Value("${third-party-ai.report-review.base-url}")
@@ -115,36 +115,40 @@ public class AiUserViolationUtils {
         analyzeHeaders.set("Authorization", "Bearer " + accessToken);
 
         Map<String, Object> analyzeRequest = new HashedMap<>();
-//        // 对应参数
-//        if (1 == lifeuserViolation.getDictId()){
-//            analyzeRequest.put("complaint_type", "用户违规");
-//        } else if (2 == lifeuserViolation.getDictId()){
-//            analyzeRequest.put("complaint_type", "色情低俗");
-//        } else if (3 == lifeuserViolation.getDictId()){
-//            analyzeRequest.put("complaint_type", "违法违规");
-//        } else if (4 == lifeuserViolation.getDictId()){
-//            analyzeRequest.put("complaint_type", "谩骂嘲讽、煽动对立");
-//        } else if (5 == lifeuserViolation.getDictId()){
-//            analyzeRequest.put("complaint_type", "涉嫌诈骗");
-//        } else if (6 == lifeuserViolation.getDictId()){
-//            analyzeRequest.put("complaint_type", "人身攻击");
-//        } else if (7 == lifeuserViolation.getDictId()){
-//            analyzeRequest.put("complaint_type", "种族歧视");
-//        } else if (8 == lifeuserViolation.getDictId()){
-//            analyzeRequest.put("complaint_type", "政治敏感");
-//        } else if (9 == lifeuserViolation.getDictId()){
-//            analyzeRequest.put("complaint_type", "虚假、不实内容");
-//        } else if (10 == lifeuserViolation.getDictId()){
-//            analyzeRequest.put("complaint_type", "违反公德秩序");
-//        } else if (11 == lifeuserViolation.getDictId()){
-//            analyzeRequest.put("complaint_type", "危害人身安全");
-//        } else if (12 == lifeuserViolation.getDictId()){
-//            analyzeRequest.put("complaint_type", "网络暴力");
-//        } else {
-//            analyzeRequest.put("complaint_type", "其他");
-//        }
-        analyzeRequest.put("id", lifeuserViolation.getId());
-        analyzeRequest.put("type", lifeuserViolation.getReportContextType());
+        // 对应参数举报类型
+        if (1 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "用户违规");
+        } else if (2 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "色情低俗");
+        } else if (3 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "违法违规");
+        } else if (4 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "谩骂嘲讽、煽动对立");
+        } else if (5 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "涉嫌诈骗");
+        } else if (6 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "人身攻击");
+        } else if (7 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "种族歧视");
+        } else if (8 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "政治敏感");
+        } else if (9 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "虚假、不实内容");
+        } else if (10 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "违反公德秩序");
+        } else if (11 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "危害人身安全");
+        } else if (12 == lifeuserViolation.getDictId()){
+            analyzeRequest.put("complaint_type", "网络暴力");
+        } else {
+            analyzeRequest.put("complaint_type", "其他");
+        }
+        // 设置举报补充
+        analyzeRequest.put("complaint_text",lifeuserViolation.getOtherReasonContent());
+        // 举报凭证
+        analyzeRequest.put("evidence_urls",((SecondUserViolationVo) lifeuserViolation).getImgUrl());
+//        analyzeRequest.put("id", lifeuserViolation.getId());
+//        analyzeRequest.put("type", lifeuserViolation.getReportContextType());
 
         //举报人
         String reporterUserId = lifeuserViolation.getReportingUserId();
@@ -167,8 +171,10 @@ public class AiUserViolationUtils {
         List<LifeMessage> chatMessages = getRecentChatMessages(userReporterUserById, userReportedUserById);
 
         // 将聊天记录转换为文本格式
-        String text = convertMessagesToText(chatMessages);
-        analyzeRequest.put("conversation_context", StringUtils.hasText(text) ? text : "");
+        String text = convertMessagesToText(chatMessages,userReporterUserById);
+        analyzeRequest.put("chat_records", StringUtils.hasText(text) ? text : "");
+        analyzeRequest.put("reporter_user_id", reporterUserId);
+        analyzeRequest.put("reported_user_id", reportedUserId);
 
 //        analyzeRequest.put("text", StringUtils.hasText(text) ? text : "");
 //        analyzeRequest.put("img_urls", img_urls);
@@ -206,7 +212,7 @@ public class AiUserViolationUtils {
                 R.fail("提交用户投诉审核任务返回record_id为空");
                 return  null;
             }
-            // 解析AI审核结果
+          /*  // 解析AI审核结果
             String processingStatus = JSONObject.parseObject(analyzeResp.getBody()).getJSONObject("data").getJSONObject("result").getString("processing_status");
             boolean success = "1".equals(processingStatus);
 
@@ -215,7 +221,7 @@ public class AiUserViolationUtils {
             // 更新举报处理状态
             lifeUserViolation.setProcessingStatus(processingStatus);
             lifeUserViolation.setProcessingTime(new Date());
-            lifeUserViolationMapper.updateById(lifeUserViolation);
+            lifeUserViolationMapper.updateById(lifeUserViolation);*/
             return taskId;
         } else {
             if (analyzeResp != null) {
@@ -409,7 +415,7 @@ public class AiUserViolationUtils {
      * @param messages 聊天消息列表
      * @return 格式化后的文本字符串
      */
-    private String convertMessagesToText(List<LifeMessage> messages) {
+    private String convertMessagesToText(List<LifeMessage> messages, String userReporterUserById) {
         if (messages == null || messages.isEmpty()) {
             return "";
         }
@@ -419,9 +425,13 @@ public class AiUserViolationUtils {
         for (int i = messages.size() - 1; i >= 0; i--) {
             LifeMessage message = messages.get(i);
             // 格式:[时间] 发送者ID: 消息内容
-            sb.append("[").append(formatTime(message.getCreatedTime())).append("] ")
-                    .append(message.getSenderId()).append(": ")
-                    .append(message.getContent()).append("\n");
+            sb.append("[").append(formatTime(message.getCreatedTime())).append("] ");
+            if( message.getSenderId().equals(userReporterUserById) ) {
+                sb.append("0: ");
+            } else {
+                sb.append("1: ");
+            }
+            sb.append(message.getContent()).append("\n");
         }
 
         return sb.toString().trim();

+ 1 - 1
alien-store-platform/src/main/java/shop/alien/storeplatform/util/AiAuthTokenUtil.java

@@ -26,7 +26,7 @@ public class AiAuthTokenUtil {
     @Value("${third-party-login.base-url}")
     private String loginUrl;
 
-    @Value("${third-party-user-name.base-url}")
+    @Value("${third-party-user-name-admin.base-url}")
     private String userName;
 
     @Value("${third-party-pass-word.base-url}")

+ 1 - 1
alien-store/src/main/java/shop/alien/store/controller/AiAuditController.java

@@ -38,7 +38,7 @@ public class AiAuditController {
 
     private final RestTemplate restTemplate;
 
-    @Value("${third-party-user-name.base-url}")
+    @Value("${third-party-user-name-admin.base-url}")
     private String userName;
 
     @Value("${third-party-user-name-admin.base-url}")

+ 38 - 0
alien-store/src/main/java/shop/alien/store/controller/AlipaySettleController.java

@@ -0,0 +1,38 @@
+package shop.alien.store.controller;
+
+import com.alipay.api.AlipayApiException;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiOperationSupport;
+import io.swagger.annotations.ApiSort;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.dto.AlipayTradeSettleConfirmDto;
+import shop.alien.store.service.AlipaySettleService;
+
+/**
+ * 支付宝结算接口 — alipay.trade.settle.confirm 等。
+ */
+@Slf4j
+@Api(tags = {"支付宝-结算"})
+@ApiSort(20)
+@CrossOrigin
+@RestController
+@RequestMapping("/store/alipay/settle")
+@RequiredArgsConstructor
+public class AlipaySettleController {
+
+    private final AlipaySettleService alipaySettleService;
+
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "确认结算", notes = "alipay.trade.settle.confirm;直付通/分账场景在支付成功后调用")
+    @PostMapping("/confirm")
+    public R<String> tradeSettleConfirm(@RequestBody AlipayTradeSettleConfirmDto request) throws AlipayApiException {
+        log.info("AlipaySettleController.tradeSettleConfirm outRequestNo={}, tradeNo={}",
+                request != null ? request.getOutRequestNo() : null,
+                request != null ? request.getTradeNo() : null);
+        return alipaySettleService.tradeSettleConfirm(request);
+    }
+}

+ 1 - 1
alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java

@@ -1134,7 +1134,7 @@ public class StoreInfoController {
                                   @RequestParam(value = "userId", required = false) String userId,
                                   @RequestParam(value = "jingdu", required = false) String jingdu,
                                   @RequestParam(value = "weidu", required = false) String weidu) {
-        log.info("StoreInfoController.getClientStoreDetail?id={},userId={},jingdu={},weidu={}", id, jingdu, weidu);
+        log.info("StoreInfoController.getClientStoreDetail?id={},userId={},jingdu={},weidu={}", id, userId, jingdu, weidu);
         StoreInfoVo storeDetail = storeInfoService.getClientStoreDetail(id, userId, jingdu, weidu);
         return R.data(storeDetail);
     }

+ 1 - 23
alien-store/src/main/java/shop/alien/store/controller/UserStoreController.java

@@ -1,42 +1,20 @@
 package shop.alien.store.controller;
 
-import com.alibaba.fastjson2.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import io.swagger.annotations.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.map.HashedMap;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Component;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
-import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.client.RestTemplate;
 import shop.alien.entity.result.R;
-import shop.alien.entity.store.StoreComment;
-import shop.alien.entity.store.StoreCommentAppeal;
-import shop.alien.entity.store.vo.StoreCommentAppealVo;
 import shop.alien.mapper.StoreCommentAppealMapper;
 import shop.alien.mapper.StoreCommentMapper;
-import shop.alien.store.annotation.TrackEvent;
 import shop.alien.store.service.LifeUserStoreService;
 import shop.alien.util.common.AlipayTradeAppPay;
 import shop.alien.util.common.ListToPage;
 import shop.alien.util.common.UniqueRandomNumGenerator;
 
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -61,7 +39,7 @@ public class UserStoreController {
 
     private String resultUrl = "http://192.168.2.250:9000/ai/auto-review/api/v1/records/{record_id}/completed";
 
-//    @Value("${third-party-user-name.base-url}")
+//    @Value("${third-party-user-name-admin.base-url}")
     private String userName = "UdUser";
 
 //    @Value("${third-party-pass-word.base-url}")

+ 16 - 0
alien-store/src/main/java/shop/alien/store/service/AlipaySettleService.java

@@ -0,0 +1,16 @@
+package shop.alien.store.service;
+
+import com.alipay.api.AlipayApiException;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.dto.AlipayTradeSettleConfirmDto;
+
+/**
+ * 支付宝结算相关接口(如确认结算)。
+ */
+public interface AlipaySettleService {
+
+    /**
+     * alipay.trade.settle.confirm — 统一收单确认结算
+     */
+    R<String> tradeSettleConfirm(AlipayTradeSettleConfirmDto request) throws AlipayApiException;
+}

+ 1 - 1
alien-store/src/main/java/shop/alien/store/service/StoreCommentAppealSupplementJobService.java

@@ -47,7 +47,7 @@ public class StoreCommentAppealSupplementJobService {
     private final StoreInfoMapper storeInfoMapper;
     private final CommonRatingService commonRatingService;
 
-    @Value("${third-party-user-name.base-url}")
+    @Value("${third-party-user-name-admin.base-url}")
     private String userName;
 
     @Value("${third-party-pass-word.base-url}")

+ 175 - 0
alien-store/src/main/java/shop/alien/store/service/impl/AlipaySettleServiceImpl.java

@@ -0,0 +1,175 @@
+package shop.alien.store.service.impl;
+
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.AlipayConfig;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.domain.AlipayTradeSettleConfirmModel;
+import com.alipay.api.domain.SettleConfirmExtendParams;
+import com.alipay.api.domain.SettleDetailInfo;
+import com.alipay.api.domain.SettleInfo;
+import com.alipay.api.request.AlipayTradeSettleConfirmRequest;
+import com.alipay.api.response.AlipayTradeSettleConfirmResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.dto.AlipayTradeSettleConfirmDto;
+import shop.alien.store.service.AlipaySettleService;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+@Service
+public class AlipaySettleServiceImpl implements AlipaySettleService {
+
+    @Override
+    public R<String> tradeSettleConfirm(AlipayTradeSettleConfirmDto request1) throws AlipayApiException {
+        // 初始化SDK
+        AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
+
+        // 构造请求参数以调用接口
+        AlipayTradeSettleConfirmRequest request = new AlipayTradeSettleConfirmRequest();
+        AlipayTradeSettleConfirmModel model = new AlipayTradeSettleConfirmModel();
+
+        // 设置确认结算请求流水号
+        model.setOutRequestNo("3688165032919721921");
+
+        // 设置支付宝交易号
+        model.setTradeNo("2026051423001467461454113691");
+
+        // 设置描述结算信息
+        SettleInfo settleInfo = new SettleInfo();
+        List<SettleDetailInfo> settleDetailInfos = new ArrayList<SettleDetailInfo>();
+        SettleDetailInfo settleDetailInfos0 = new SettleDetailInfo();
+        settleDetailInfos0.setAmount("0.99");
+        settleDetailInfos0.setTransIn("ailien@alienyan.cn");
+//        settleDetailInfos0.setSettleEntityType("SecondMerchant");
+//        settleDetailInfos0.setSummaryDimension("A0001");
+//        settleDetailInfos0.setActualAmount("0.1");
+//        settleDetailInfos0.setSettleEntityId("2088xxxxx;ST_0001");
+        settleDetailInfos0.setTransInType("email");
+        settleDetailInfos.add(settleDetailInfos0);
+        settleInfo.setSettleDetailInfos(settleDetailInfos);
+        model.setSettleInfo(settleInfo);
+
+        // 设置扩展字段信息
+//        SettleConfirmExtendParams extendParams = new SettleConfirmExtendParams();
+//        extendParams.setRoyaltyFreeze("true");
+//        model.setExtendParams(extendParams);
+        // 🔥 核心:直接手动构建 JSON 字符串,amount 是纯数字(无引号)!!!
+        String bizContent = "{"
+                + "\"out_request_no\":\"3688165032919721921\","
+                + "\"trade_no\":\"2026051423001467461454113691\","
+                + "\"settle_info\":{"
+                + "\"settle_detail_infos\":["
+                + "{"
+                + "\"trans_in_type\":\"userId\","
+                + "\"trans_in\":\"2088480335620690\","
+                + "\"settle_dimension_type\":\"USER\","
+                + "\"amount\":1.00" // ✅ 纯数字,无引号!!!
+                + "}"
+                + "]"
+                + "}"
+                + "}";
+        request.setBizContent(bizContent);
+
+//        request.setBizModel(model);
+        // 第三方代调用模式下请设置app_auth_token
+        // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");
+
+        AlipayTradeSettleConfirmResponse response = alipayClient.execute(request);
+        System.out.println(response.getBody());
+
+        if (response == null) {
+            return R.fail("支付宝返回为空");
+        }
+        if (response.isSuccess()) {
+            return R.data("调用成功", response.getBody());
+        }
+        return R.fail("调用失败:" + response.getBody());
+    }
+
+//    public R<String> tradeSettleConfirm(AlipayTradeSettleConfirmDto request) throws AlipayApiException {
+//        if (request == null) {
+//            return R.fail("请求体不能为空");
+//        }
+//        if (StringUtils.isBlank(request.getOutRequestNo())) {
+//            return R.fail("out_request_no 不能为空");
+//        }
+//        if (StringUtils.isBlank(request.getTradeNo())) {
+//            return R.fail("trade_no 不能为空");
+//        }
+//        if (request.getSettleInfo() == null
+//                || request.getSettleInfo().getSettleDetailInfos() == null
+//                || request.getSettleInfo().getSettleDetailInfos().isEmpty()) {
+//            return R.fail("settle_info.settle_detail_infos 不能为空");
+//        }
+//
+//        AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
+//
+//        AlipayTradeSettleConfirmRequest apiRequest = new AlipayTradeSettleConfirmRequest();
+//        apiRequest.setBizModel(toModel(request));
+//        if (StringUtils.isNotBlank(request.getAppAuthToken())) {
+//            apiRequest.putOtherTextParam("app_auth_token", request.getAppAuthToken().trim());
+//        }
+//
+//        log.info("alipay.trade.settle.confirm outRequestNo={}, tradeNo={}",
+//                request.getOutRequestNo(), request.getTradeNo());
+//        AlipayTradeSettleConfirmResponse response = alipayClient.execute(apiRequest);
+//        if (response == null) {
+//            return R.fail("支付宝返回为空");
+//        }
+//        if (response.isSuccess()) {
+//            return R.data("调用成功", response.getBody());
+//        }
+//        return R.fail("调用失败:" + response.getBody());
+//    }
+
+//    private static AlipayTradeSettleConfirmModel toModel(AlipayTradeSettleConfirmDto request) {
+//        AlipayTradeSettleConfirmModel model = new AlipayTradeSettleConfirmModel();
+//        model.setOutRequestNo(request.getOutRequestNo().trim());
+//        model.setTradeNo(request.getTradeNo().trim());
+//
+//        SettleInfo settleInfo = new SettleInfo();
+//        List<SettleDetailInfo> details = new ArrayList<>();
+//        for (AlipayTradeSettleConfirmDto.SettleDetailInfo src : request.getSettleInfo().getSettleDetailInfos()) {
+//            if (src == null) {
+//                continue;
+//            }
+//            SettleDetailInfo detail = new SettleDetailInfo();
+//            detail.setAmount(src.getAmount());
+//            detail.setTransIn(src.getTransIn());
+//            detail.setSettleEntityType(src.getSettleEntityType());
+//            detail.setSummaryDimension(src.getSummaryDimension());
+//            detail.setActualAmount(src.getActualAmount());
+//            detail.setSettleEntityId(src.getSettleEntityId());
+//            detail.setTransInType(src.getTransInType());
+//            details.add(detail);
+//        }
+//        settleInfo.setSettleDetailInfos(details);
+//        model.setSettleInfo(settleInfo);
+//
+//        if (request.getExtendParams() != null) {
+//            SettleConfirmExtendParams extendParams = new SettleConfirmExtendParams();
+//            extendParams.setRoyaltyFreeze(request.getExtendParams().getRoyaltyFreeze());
+//            model.setExtendParams(extendParams);
+//        }
+//        return model;
+//    }
+
+    private static AlipayConfig getAlipayConfig() {
+        String privateKey = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCBTOvScNrk0mw+WbR6Qtx2+HrPxB5IU/V2HSPGZUTDNiCiSU9UZcuXlo0UNwMksFYR43btk4BHW9OsZETdr3uJzbEEko4jQPrY49V6V8d3yFUiexcbLKf9W2X+h7EwdPDahHk6wmM73Lm500xzv8JxdGeo/d2uGTh+qD66HcPW+QYj1YbjRV1JyCOiJ2OiwLcb28arNNLOgj6PktQ69FPSWS4hWrM7nl6DLRr6SdOlyfBT47gwPtW0BQ96/2b9O+qxKBPfrcqdRDH323HvrGFDwa8GoWTdchnKwFjmfIFHMvf+eq3tzilFi8H7vQRtzVRrndwrNa0z+1ss07fcWFDRAgMBAAECggEAItgU0OAizPk7vE22SiBMgy8RAX5rXrhpdIwDwQo3Tpf+kV1KKIdKJy6mFCWDDlcKysVOnlVag2BmmZVnzYnls8wfgQjxjuSK9Pno5JBVK51r+9/J6UPOfYMs6Duu700EPw7mEISj81TXJBGiD6tEfgiNisfm/mzDgbZbORKeXQbaTyrtB+GZn6FNSyyHA1vraARMrgfMEGNzQ4AbtfcUxGO+mejdTFs0PxAq6lovHBY3fYYHI1Nx6kf9iPoom/G4UrcMO67W6QU+1tOCZCXjy4bD2y421z/8XD73+WDyYp+Tjy0hTLqVZc7TpYAOximo1vMIUe23EdJJngdlkdpDFQKBgQDFyETL0knwBSakLfAe2BmFb2x++B4YXUnt4dGbCFBnVooxf5i06GVt/CrfkJhYK6hBSowOScIRf8P6BOSQptRZb2/I1ngQm4vcpAZw6EjUTlgOj/J3XJ+ApUNQnRqE28jDrE4m2RHg4BkQo6yA3DizJAluPCtFoCYDm1a7dV7u7wKBgQCnXEH5sD8VSxURv02/gn80g/uZIP/EOU3ycjBEqZdRGkNINwXT+zqrlZIGYb+bxLvU/R2OqKC5vhcyAL3T1A8ORYqPu5KLnAxg7C+rHuVilUWwCEH7POpCk+ETPXCZwcNvLNa5PIqBH/gdV9Y9PBTef6J4rN6V6TDFgosf5by8PwKBgDpVG71Fk1sAGep4RgbC05wgRc6Y3T9wXDqVzJ098YDY7D83E9HfbPLoWbjAS75Nef1vwCkCpgNFPIbD5KmpGp4aGM0SPC0hwzlbAy9PwxMi3CPHXsrHfZ+SnmzrOQQQUoErk40vnm9FiP74VwtWaD6llUZ25ohNeIi9yvHU5x/vAoGAdU2d1JOq85LHtsO+i9+8pyNnAsJ1YqTDtI5CtK2lqKvewswGIrlxOvi//AchVN3ExZmP0QDyfp31BhAs/T8iOl+Vqf7PzVjX+Eszch5aqwlzadmv3ZepnnamCGVE+hAsmkz0R6tebPjqYC7Ds/HbssQFLc4EyVBD5fwE5ZuR+OMCgYAvGHUYpi0dY9uMHXzL721tIopiwUfKCgLAn3yhSH3p7644NxHBqLLaBLVT2q7JAZQUaZUvXlwiyxU1zvo0xmvcbnB/Vd2qp8KbEUkvHyIYVJkM6Fn+9xBosorcrHv+7B2V1XR9WQcXvppxbN/8farWGuAA0anBD+UGrxd8B0/hHg==";
+        String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnxevClLpYc6c8A9lwmnftPO2BeU+X6aZ/+b/n1Cvq096VJKiHmqcsRgRbrnSlmPDHRrQpDti4en2Ys0L2lx7CObIr/2xP/jJVwjIO1iWHUj/w/NAbjv7dLW/FFY4SeNp8rU+hlgGgviyUxzonfNfr3v+o8grFqQq27/hiZJAofsQRMQu1dEQqoKdJj7eQLkTstiK5miJMyQ+Y3tLztrEUMBz/zRgaCEfGqmFmRZ2diy2X+1dGaX6H4+0QJ2u50eY2QTBkNuvREGbAn6/lttAgvg/+CywPYKGeC4xOfnl5wP8iA1QXYbXrVJRkZjU097nyOmSNhLy9KvJH2BNpojS1QIDAQAB";
+        AlipayConfig alipayConfig = new AlipayConfig();
+        alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
+        alipayConfig.setAppId("2021005196608960");
+        alipayConfig.setPrivateKey(privateKey);
+        alipayConfig.setFormat("json");
+        alipayConfig.setAlipayPublicKey(alipayPublicKey);
+        alipayConfig.setCharset("UTF-8");
+        alipayConfig.setSignType("RSA2");
+        return alipayConfig;
+    }
+}

+ 1 - 1
alien-store/src/main/java/shop/alien/store/util/AiUserViolationUtils.java

@@ -37,7 +37,7 @@ public class AiUserViolationUtils {
     //    @Value("${third-party-login.base-url:http://192.168.2.250:9000/ai/user-auth-core/api/v1/auth/login}")
     private String loginUrl = "http://192.168.2.250:9000/ai/user-auth-core/api/v1/auth/login";
 
-    @Value("${third-party-user-name.base-url:UdUser}")
+    @Value("${third-party-user-name-admin.base-url:UdUser}")
     private String userName;
 
     @Value("${third-party-pass-word.base-url:123456}")