Forráskód Böngészése

Merge remote-tracking branch 'origin/sit' into uat-20260202

dujian 2 napja
szülő
commit
86cb4a594a

+ 7 - 0
alien-entity/src/main/java/shop/alien/entity/store/AlipayZftCreateRecord.java

@@ -56,6 +56,13 @@ public class AlipayZftCreateRecord {
     @TableField("order_id")
     private String orderId;
 
+    /**
+     * 进件主体:0 商户,1 律师(律师进件时按 law_firm 与 merchant_name 匹配回写律师表)。
+     */
+    @ApiModelProperty("类型")
+    @TableField("type")
+    private String type;
+
     @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
     @TableField("delete_flag")
     @TableLogic

+ 82 - 0
alien-entity/src/main/java/shop/alien/entity/store/ContractBundle.java

@@ -0,0 +1,82 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 合同包表 contract_bundle
+ */
+@Data
+@JsonInclude
+@EqualsAndHashCode(callSuper = false)
+@TableName("contract_bundle")
+@ApiModel(value = "ContractBundle对象", description = "合同包表")
+public class ContractBundle extends Model<ContractBundle> {
+
+    @ApiModelProperty(value = "合同包唯一标识")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value = "签约主体类型(store/lawyer)")
+    @TableField("subject_type")
+    private String subjectType;
+
+    @ApiModelProperty(value = "签约主体ID,门店/律师业务主键")
+    @TableField("subject_id")
+    private Long subjectId;
+
+    @ApiModelProperty(value = "签约主体名称")
+    @TableField("subject_name")
+    private String subjectName;
+
+    @ApiModelProperty(value = "业务板块")
+    @TableField("business_segment")
+    private String businessSegment;
+
+    @ApiModelProperty(value = "联系人姓名")
+    @TableField("contact_name")
+    private String contactName;
+
+    @ApiModelProperty(value = "联系人手机号")
+    @TableField("contact_phone")
+    private String contactPhone;
+
+    @ApiModelProperty(value = "组织标识(统一社会信用代码)")
+    @TableField("ord_id")
+    private String ordId;
+
+    @ApiModelProperty(value = "合同包类型(STORE_STANDARD/LAWYER_STANDARD)")
+    @TableField("bundle_type")
+    private String bundleType;
+
+    @ApiModelProperty(value = "整体状态: 未签署/审核中/已签署")
+    @TableField("status")
+    private String status;
+
+    @ApiModelProperty(value = "主合同文档ID")
+    @TableField("primary_document_id")
+    private Long primaryDocumentId;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty(value = "更新时间")
+    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "逻辑删除(0未删/1已删)")
+    @TableField("delete_flag")
+    @TableLogic
+    private Integer deleteFlag;
+}

+ 12 - 0
alien-entity/src/main/java/shop/alien/mapper/ContractBundleMapper.java

@@ -0,0 +1,12 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.store.ContractBundle;
+
+/**
+ * 合同包 Mapper
+ */
+@Mapper
+public interface ContractBundleMapper extends BaseMapper<ContractBundle> {
+}

+ 1 - 0
alien-entity/src/main/java/shop/alien/mapper/StoreInfoMapper.java

@@ -182,6 +182,7 @@ public interface StoreInfoMapper extends BaseMapper<StoreInfo> {
             "left join store_dictionary e on e.type_name = 'storeType' and e.dict_id = a.store_type and e.delete_flag = 0 " +
             "${ew.customSqlSegment} " +
             "and a.store_position is not null and a.store_position != '' " +
+            "and a.head_img_status = 1 " +
             "order by distance3 asc")
     List<StoreInfoVo> getMoreRecommendedStores(@Param(Constants.WRAPPER) QueryWrapper<StoreInfoVo> queryWrapper, @Param("position") String position);
 

+ 72 - 18
alien-job/src/main/java/shop/alien/job/store/AlipayJob.java

@@ -16,8 +16,10 @@ 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.store.service.StoreInfoService;
 
 import java.util.List;
@@ -27,10 +29,17 @@ 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 StoreInfoService storeInfoService;
 
+    private final LawyerUserMapper lawyerUserMapper;
+
     /**
      * 查询支付宝二级商户进件结果,并从响应中回写门店 smid。
      */
@@ -66,38 +75,84 @@ public class AlipayJob {
             }
 
             String body = response.getBody();
-            String smid = extractSmidFromZftOrderQueryBody(body);
+            JSONObject firstOrder = firstOrderInZftOrderQueryBody(body);
+            String smid = firstOrder == null ? null : firstOrder.getString("smid");
             if (StringUtils.isBlank(smid)) {
                 log.debug("order.query 未解析到 smid orderId={}", orderId);
                 continue;
             }
 
-            Integer storeId = record.getStoreId();
-            if (storeId == null) {
-                log.debug("进件记录无 storeId,跳过回写 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 = storeInfoService.getById(storeId);
+                if (storeInfo == null) {
+                    log.warn("门店不存在 storeId={} orderId={}", storeId, orderId);
+                    continue;
+                }
+
+                if (smid.equals(storeInfo.getAlipaySmid())) {
+                    continue;
+                }
+
+                storeInfo.setAlipaySmid(smid);
+                storeInfoService.updateById(storeInfo);
+                log.info("已回写门店 alipay_smid storeId={} orderId={}", storeId, orderId);
             }
+        }
+    }
 
-            StoreInfo storeInfo = storeInfoService.getById(storeId);
-            if (storeInfo == null) {
-                log.warn("门店不存在 storeId={} orderId={}", storeId, orderId);
+    /**
+     * 律师进件: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) {
                 continue;
             }
-
-            if (smid.equals(storeInfo.getAlipaySmid())) {
+            if (StringUtils.isNotBlank(lawyer.getZfbSecondaryMerchantAccount())) {
                 continue;
             }
-
-            storeInfo.setAlipaySmid(smid);
-            storeInfoService.updateById(storeInfo);
-            log.info("已回写门店 alipay_smid storeId={} orderId={}", storeId, orderId);
+            lawyer.setZfbSecondaryMerchantAccount(smid);
+            lawyerUserMapper.updateById(lawyer);
+            log.info("已回写律师 zfb_secondary_merchant_account lawyerUserId={} orderId={}", lawyer.getId(), orderId);
         }
     }
 
     /**
-     * 从 ant.merchant.expand.indirect.zftorder.query 响应 body 中取 orders 首条的 smid。
+     * 从 ant.merchant.expand.indirect.zftorder.query 响应 body 中取 orders 首条对象
      */
-    private static String extractSmidFromZftOrderQueryBody(String body) {
+    private static JSONObject firstOrderInZftOrderQueryBody(String body) {
         if (StringUtils.isBlank(body)) {
             return null;
         }
@@ -111,8 +166,7 @@ public class AlipayJob {
             if (orders == null || orders.isEmpty()) {
                 return null;
             }
-            JSONObject first = orders.getJSONObject(0);
-            return first == null ? null : first.getString("smid");
+            return orders.getJSONObject(0);
         } catch (Exception e) {
             log.warn("解析 zftorder.query 响应 body 失败: {}", e.getMessage());
             return null;

+ 1 - 1
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerConsultationOrderServiceImpl.java

@@ -567,7 +567,7 @@ public class LawyerConsultationOrderServiceImpl extends ServiceImpl<LawyerConsul
         String orderNumber = generateOrderNumber();
         order.setOrderNumber(!StringUtils.isEmpty(lawyerConsultationOrder.getOrderNumber())?lawyerConsultationOrder.getOrderNumber():orderNumber);
         log.info("生成订单编号:orderNumber={}", orderNumber);
-
+        order.setAlipayNo(lawyerConsultationOrder.getOrderNumber());
         // 计算本单收益(平台收益)
         Integer consultationFee = calculateConsultationFee(lawyerUserId, orderAmount);
         order.setConsultationFee(consultationFee);

+ 1 - 1
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StoreContractController.java

@@ -114,7 +114,7 @@ public class StoreContractController {
         return storeContractService.deleteContract(id);
     }
 
-    @ApiOperation("获取合同签署状态")
+    @ApiOperation("获取合同签署状态(contract_bundle:subject_id=店铺ID,subject_type=store,返回 status)")
     @ApiOperationSupport(order = 8)
     @ApiImplicitParams({
             @ApiImplicitParam(name = "store_id", value = "店铺ID", dataType = "int", paramType = "query", required = true)

+ 19 - 32
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StoreContractServiceImpl.java

@@ -9,9 +9,11 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import shop.alien.entity.result.R;
+import shop.alien.entity.store.ContractBundle;
 import shop.alien.entity.store.StoreContract;
 import shop.alien.entity.store.dto.StoreContractQueryDto;
 import shop.alien.entity.store.vo.StoreContractVo;
+import shop.alien.mapper.ContractBundleMapper;
 import shop.alien.mapper.StoreContractMapper;
 import shop.alien.storeplatform.service.StoreContractService;
 
@@ -30,7 +32,11 @@ import java.util.List;
 @Transactional
 public class StoreContractServiceImpl implements StoreContractService {
 
+    /** contract_bundle.subject_type,门店场景固定为 store */
+    private static final String CONTRACT_BUNDLE_SUBJECT_TYPE_STORE = "store";
+
     private final StoreContractMapper storeContractMapper;
+    private final ContractBundleMapper contractBundleMapper;
 
     @Override
     public R<IPage<StoreContractVo>> getContractList(StoreContractQueryDto queryDto) {
@@ -200,41 +206,22 @@ public class StoreContractServiceImpl implements StoreContractService {
             if (storeId == null) {
                 return R.fail("店铺ID不能为空");
             }
-            String contracts = storeContractMapper.selectSigningStatus(storeId);
-
-            // 根据店铺ID查询最新的合同(按创建时间倒序)
-//            List<StoreContract> contracts = storeContractMapper.selectList(
-//                    new LambdaQueryWrapper<StoreContract>()
-//                            .eq(StoreContract::getStoreId, storeId.longValue())
-//                            .eq(StoreContract::getDeleteFlag, 0)
-//                            .orderByDesc(StoreContract::getCreatedTime)
-//                            .last("LIMIT 1")
-//            );
-
-            if (contracts == null || contracts.isEmpty()) {
+
+            // contract_bundle:subject_id=店铺ID,subject_type=store,取最新一条
+            List<ContractBundle> bundles = contractBundleMapper.selectList(
+                    new LambdaQueryWrapper<ContractBundle>()
+                            .eq(ContractBundle::getSubjectId, storeId.longValue())
+                            .eq(ContractBundle::getSubjectType, CONTRACT_BUNDLE_SUBJECT_TYPE_STORE)
+                            .eq(ContractBundle::getDeleteFlag, 0)
+                            .orderByDesc(ContractBundle::getCreatedTime)
+                            .last("LIMIT 1")
+            );
+
+            if (bundles == null || bundles.isEmpty()) {
                 return R.fail("该店铺暂无合同");
             }
 
-//            StoreContract contract = contracts.get(0);
-            String signingStatus = contracts;
-            // 将字符串状态转换为数字:已签署=1, 未签署=0, 已到期=2
-            Integer statusValue = null;
-            if (signingStatus != null) {
-                switch (signingStatus) {
-                    case "已签署":
-                        statusValue = 1;
-                        break;
-                    case "未签署":
-                        statusValue = 0;
-                        break;
-                    case "已到期":
-                        statusValue = 2;
-                        break;
-                    default:
-                        statusValue = 0;
-                }
-            }
-            return R.data(signingStatus);
+            return R.data(bundles.get(0).getStatus());
         } catch (Exception e) {
             log.error("StoreContractServiceImpl.getSigningStatus ERROR: {}", e.getMessage(), e);
             return R.fail("获取签署状态失败: " + e.getMessage());

+ 3 - 2
alien-store/src/main/java/shop/alien/store/controller/AlipayZftOnboardingController.java

@@ -48,9 +48,10 @@ public class AlipayZftOnboardingController {
             + "或顶层 external_id 等与 extraBiz 合并;app_auth_token、notify_url、app_id 等同 curl 公共参数")
     @PostMapping("/create")
     public R<String> create(@RequestBody AntMerchantExpandIndirectZftCreateModel request,
-                            @RequestParam(value = "storeId", required = false) Integer storeId) throws AlipayApiException {
+                            @RequestParam(value = "storeId", required = false) Integer storeId,
+                            @RequestParam(value = "type", required = false) String type) throws AlipayApiException {
         log.info("AlipayZftOnboardingController.create storeId={}", storeId);
-        return alipayZftOnboardingService.zftCreate(request, storeId);
+        return alipayZftOnboardingService.zftCreate(request, storeId, type);
     }
 
     @ApiOperationSupport(order = 3)

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

@@ -21,7 +21,7 @@ public interface AlipayZftOnboardingService {
     /**
      * ant.merchant.expand.indirect.zft.create — 二级商户标准进件(结构化必填:external_id、merchant_type、name、alias_name、mcc、service)
      */
-    R<String> zftCreate(AntMerchantExpandIndirectZftCreateModel request, Integer storeId) throws AlipayApiException;
+    R<String> zftCreate(AntMerchantExpandIndirectZftCreateModel request, Integer storeId, String type) throws AlipayApiException;
 
     /**
      * ant.merchant.expand.indirect.zft.simplecreate — 二级商户免证照进件(SDK setBizModel)

+ 2 - 1
alien-store/src/main/java/shop/alien/store/service/impl/AlipayZftOnboardingServiceImpl.java

@@ -52,7 +52,7 @@ public class AlipayZftOnboardingServiceImpl implements AlipayZftOnboardingServic
     }
 
     @Override
-    public R<String> zftCreate(AntMerchantExpandIndirectZftCreateModel request1, Integer storeId) throws AlipayApiException {
+    public R<String> zftCreate(AntMerchantExpandIndirectZftCreateModel request1, Integer storeId, String type) throws AlipayApiException {
         // 初始化SDK
         AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
 
@@ -250,6 +250,7 @@ public class AlipayZftOnboardingServiceImpl implements AlipayZftOnboardingServic
 
         Date now = new Date();
         AlipayZftCreateRecord record = new AlipayZftCreateRecord();
+        record.setType(type);
         record.setStoreId(storeId);
         record.setExternalId(request1 != null ? request1.getExternalId() : null);
         record.setMerchantName(request1 != null ? request1.getName() : null);

+ 9 - 0
alien-store/src/main/java/shop/alien/store/strategy/payment/impl/AlipayPartnerPaymentStrategyImpl.java

@@ -65,6 +65,15 @@ public class AlipayPartnerPaymentStrategyImpl implements PaymentStrategy {
         // 【关键】设置二级商户信息(直付通必传)
         model.setSubMerchant(subMerchant);
 
+        SettleInfo settleInfo = new SettleInfo();
+        SettleDetailInfo settleDetailInfo = new SettleDetailInfo();
+        settleDetailInfo.setTransIn("defaultSettle");
+        settleDetailInfo.setAmount(total.toString());
+        List<SettleDetailInfo>  settleDetailInfos = new ArrayList<>();
+        settleDetailInfos.add(settleDetailInfo);
+        settleInfo.setSettleDetailInfos(settleDetailInfos);
+        model.setSettleInfo(settleInfo);
+
         // 设置产品码
 //        model.setProductCode("QUICK_MSECURITY_PAY");