Bladeren bron

Merge remote-tracking branch 'origin/master'

yjwang 3 weken geleden
bovenliggende
commit
2e20e3a3d7
29 gewijzigde bestanden met toevoegingen van 881 en 171 verwijderingen
  1. 20 12
      fs-admin/src/main/java/com/fs/task/CrmCustomerAiProcessingTask.java
  2. 16 1
      fs-company/src/main/java/com/fs/company/controller/crm/CrmCustomerAnalyzeController.java
  3. 10 1
      fs-company/src/main/java/com/fs/company/controller/live/LiveController.java
  4. 1 1
      fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java
  5. 1 1
      fs-service/src/main/java/com/fs/core/config/WxMaConfiguration.java
  6. 2 0
      fs-service/src/main/java/com/fs/course/domain/FsCourseLink.java
  7. 1 1
      fs-service/src/main/java/com/fs/crm/mapper/CrmCustomerAnalyzeMapper.java
  8. 35 0
      fs-service/src/main/java/com/fs/crm/param/PolishingScriptParam.java
  9. 16 1
      fs-service/src/main/java/com/fs/crm/service/ICrmCustomerAnalyzeService.java
  10. 319 14
      fs-service/src/main/java/com/fs/crm/service/impl/CrmCustomerAnalyzeServiceImpl.java
  11. 16 7
      fs-service/src/main/java/com/fs/crm/utils/CrmCustomerAiTagUtil.java
  12. 25 1
      fs-service/src/main/java/com/fs/erp/utils/WeizouApiClient.java
  13. 11 0
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreAfterSalesServiceImpl.java
  14. 59 57
      fs-service/src/main/java/com/fs/his/utils/LinkUtil.java
  15. 10 0
      fs-service/src/main/java/com/fs/hisStore/domain/FsStoreScrm.java
  16. 1 1
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreOrderScrmMapper.java
  17. 3 0
      fs-service/src/main/java/com/fs/hisStore/service/IFsStoreOrderScrmService.java
  18. 165 21
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java
  19. 4 1
      fs-service/src/main/java/com/fs/live/service/ILiveService.java
  20. 116 3
      fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java
  21. 1 1
      fs-service/src/main/resources/application-config-druid-jsbk.yml
  22. 14 1
      fs-service/src/main/resources/mapper/crm/CrmCustomerAnalyzeMapper.xml
  23. 3 1
      fs-service/src/main/resources/mapper/crm/CrmCustomerMapper.xml
  24. 4 1
      fs-service/src/main/resources/mapper/hisStore/FsStoreScrmMapper.xml
  25. 7 2
      fs-service/src/main/resources/mapper/qw/QwExternalContactMapper.xml
  26. 8 21
      fs-user-app/src/main/java/com/fs/app/controller/InquiryOrderController.java
  27. 3 1
      fs-user-app/src/main/java/com/fs/app/controller/live/LiveController.java
  28. 0 20
      fs-user-app/src/main/java/com/fs/app/controller/store/CompanyUserScrmController.java
  29. 10 0
      fs-user-app/src/main/java/com/fs/app/controller/store/StoreOrderScrmController.java

+ 20 - 12
fs-admin/src/main/java/com/fs/task/CrmCustomerAiProcessingTask.java

@@ -94,21 +94,29 @@ public class CrmCustomerAiProcessingTask {
         String threadName = Thread.currentThread().getName();
         long batchStartTime = System.currentTimeMillis();
 
-        try {
+//        try {
             log.info("线程 {} 开始处理批次, 数据量: {}", threadName, batch.size());
 
             // 示例:处理每条数据
             for (Map<String, String> data : batch) {
                 // 获取数据
-                String customerId = data.get("customerId");
+                Long customerId = Long.valueOf(data.get("customerId"));
                 String dataJson = data.get("data");
-                String logId = data.get("logId");
-                //todo 业务!!!!!!1.ai沟通总结2.流失风险等级3.沟通摘要4.客户画像8.客户关注点9.客户意向度 //都要异步处理
+                Long logId = Long.valueOf(data.get("logId"));
+                //todo 业务!!!!!!2.流失风险等级8.9.客户意向度 //都要异步处理
+                //客户画像
                 crmCustomerAnalyzeService.aiGeneratedCustomerPortrait(customerId,dataJson,logId);
+                //沟通总结
+                crmCustomerAnalyzeService.aiCommunicationSummary(customerId,dataJson,logId);
+                //沟通摘要
+                crmCustomerAnalyzeService.aiCommunicationAbstract(customerId,dataJson,logId);
+//                //流失风险等级 //ai暂时未提供,等ai提供
+                crmCustomerAnalyzeService.aiAttritionLevel(customerId,dataJson,logId);
+                //客户关注点
+                crmCustomerAnalyzeService.aiCustomerFocus(customerId,dataJson,logId);
+                //客户意向度
+                crmCustomerAnalyzeService.aiIntentionDegree(customerId,dataJson,logId);
 
-
-                // 模拟业务处理
-                Thread.sleep(10);
             }
 
             long costTime = System.currentTimeMillis() - batchStartTime;
@@ -116,11 +124,11 @@ public class CrmCustomerAiProcessingTask {
             log.info("线程 {} 批次处理完成, 数据量: {}, 耗时: {}ms",
                     threadName, batch.size(), costTime);
 
-        } catch (Exception e) {
-            failCount.addAndGet(batch.size());
-            log.error("线程 {} 批次处理失败, 数据量: {}", threadName, batch.size(), e);
-            throw new RuntimeException("批次处理失败", e);
-        }
+//        } catch (Exception e) {
+//            failCount.addAndGet(batch.size());
+//            log.error("线程 {} 批次处理失败, 数据量: {}", threadName, batch.size(), e);
+//            throw new RuntimeException("批次处理失败", e);
+//        }
     }
     /**
      * 处理失败的数据

+ 16 - 1
fs-company/src/main/java/com/fs/company/controller/crm/CrmCustomerAnalyzeController.java

@@ -1,6 +1,9 @@
 package com.fs.company.controller.crm;
 
 import java.util.List;
+
+import com.fs.common.core.domain.R;
+import com.fs.crm.param.PolishingScriptParam;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -22,7 +25,7 @@ import com.fs.common.core.page.TableDataInfo;
 
 /**
  * 客户聊天记录分析Controller
- * 
+ *
  * @author fs
  * @date 2026-03-24
  */
@@ -112,4 +115,16 @@ public class CrmCustomerAnalyzeController extends BaseController
     {
         return toAjax(crmCustomerAnalyzeService.deleteCrmCustomerAnalyzeByIds(ids));
     }
+
+    /**
+     * 话术润色
+     */
+    @PreAuthorize("@ss.hasPermi('crm:analyze:polishingScript')")
+    @Log(title = "话术润色", businessType = BusinessType.INSERT)
+    @PostMapping("/polishingScript")
+    public R polishingScript(@RequestBody PolishingScriptParam param)
+    {
+        return R.ok().put("data",crmCustomerAnalyzeService.polishingScript(param));
+    }
+
 }

+ 10 - 1
fs-company/src/main/java/com/fs/company/controller/live/LiveController.java

@@ -5,6 +5,7 @@ import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
+import com.fs.common.core.domain.model.LoginUser;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.DateUtils;
@@ -12,7 +13,6 @@ import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.http.HttpUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.domain.CompanyUser;
-import com.fs.framework.security.LoginUser;
 import com.fs.framework.security.SecurityUtils;
 import com.fs.framework.service.TokenService;
 import com.fs.his.domain.FsPayConfig;
@@ -402,4 +402,13 @@ public class LiveController extends BaseController
 
         return R.ok().put("data", exist);
     }
+
+    @ApiOperation("创建App跳转通用链接")
+    @GetMapping("/createAppLink")
+    @PreAuthorize("@ss.hasPermi('live:live:createAppLink')")
+    public R createAppLink(@RequestParam("liveId") Long liveId,@RequestParam("corpId")String corpId) {
+        CompanyUser user = SecurityUtils.getLoginUser().getUser();
+        return liveService.createAppLink(user,liveId,corpId);
+    }
+
 }

+ 1 - 1
fs-ipad-task/src/main/java/com/fs/app/service/IpadSendServer.java

@@ -774,7 +774,7 @@ public class IpadSendServer {
         }
         sendShortLink = sendShortLink.replace(".html","");
         String InvitationCode = LinkUtil.encryptLink(sendShortLink);
-        TxtVo txtVo = TxtVo.builder().content(InvitationCode).build();
+        TxtVo txtVo = TxtVo.builder().content("康好健康"+InvitationCode).build();
         txtVo.setBase(vo);
         WxWorkResponseDTO<WxWorkSendTextMsgRespDTO> resp = ipadSendUtils.sendTxt(txtVo);
         if (resp.getErrcode() != 0) {

+ 1 - 1
fs-service/src/main/java/com/fs/core/config/WxMaConfiguration.java

@@ -111,7 +111,7 @@ public class WxMaConfiguration {
             // 查询数据库
             FsCoursePlaySourceConfigMapper configMapper = SpringUtils.getBean(FsCoursePlaySourceConfigMapper.class);
             Wrapper<FsCoursePlaySourceConfig> queryWrapper = Wrappers.<FsCoursePlaySourceConfig>lambdaQuery()
-                    .eq(FsCoursePlaySourceConfig::getAppid, appid)
+                    .eq(FsCoursePlaySourceConfig::getAppid, appid.trim())
                     .eq(FsCoursePlaySourceConfig::getIsDel, 0);
             FsCoursePlaySourceConfig config = configMapper.selectOne(queryWrapper);
             if (config == null) {

+ 2 - 0
fs-service/src/main/java/com/fs/course/domain/FsCourseLink.java

@@ -72,4 +72,6 @@ public class FsCourseLink extends BaseEntity
     //@ApiModelProperty(value = "直播id")
     private Long liveId;
 
+    private Long userId;
+
 }

+ 1 - 1
fs-service/src/main/java/com/fs/crm/mapper/CrmCustomerAnalyzeMapper.java

@@ -62,7 +62,7 @@ public interface CrmCustomerAnalyzeMapper extends BaseMapper<CrmCustomerAnalyze>
 
     CrmCustomerAnalyze selectLatestOne(@Param("customerId") Long customerId);
 
-    int updateCustomerPortrait(@Param("customerId") Long customerId,@Param("customerPortrait") String customerPortrait);
+    int updateCustomerPortrait(CrmCustomerAnalyze crmCustomerAnalyze);
 
     List<CrmCustomerAnalyze> selectCrmCustomerAnalyzeListAll(CrmCustomerAnalyze crmCustomerAnalyze);
 }

+ 35 - 0
fs-service/src/main/java/com/fs/crm/param/PolishingScriptParam.java

@@ -0,0 +1,35 @@
+package com.fs.crm.param;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.util.Map;
+
+@Data
+@Accessors(chain = true)
+@AllArgsConstructor
+@NoArgsConstructor
+@Api(value = "话术润色参数")
+public class PolishingScriptParam {
+    /**
+     * 聊天内容
+     */
+    @ApiModelProperty(value = "聊天内容")
+    private String content;
+
+    /**
+     * 客户画像
+     */
+    @ApiModelProperty(value = "客户画像")
+    private Map<String,String> portrait;
+
+    /**
+     * 聊天id,时间戳
+     */
+    @ApiModelProperty(value = "聊天id,时间戳")
+    private String chatId;
+}

+ 16 - 1
fs-service/src/main/java/com/fs/crm/service/ICrmCustomerAnalyzeService.java

@@ -3,6 +3,7 @@ package com.fs.crm.service;
 import java.util.List;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.crm.domain.CrmCustomerAnalyze;
+import com.fs.crm.param.PolishingScriptParam;
 
 /**
  * 客户聊天记录分析Service接口
@@ -59,7 +60,21 @@ public interface ICrmCustomerAnalyzeService extends IService<CrmCustomerAnalyze>
      */
     int deleteCrmCustomerAnalyzeById(Long id);
 
-    void aiGeneratedCustomerPortrait(String customerId, String dataJson,String logId);
+    void aiGeneratedCustomerPortrait(Long customerId, String dataJson,Long logId);
+
+    void aiCommunicationSummary(Long customerId, String dataJson, Long logId);
+
+    void aiCommunicationAbstract(Long customerId, String dataJson, Long logId);
+
+    void aiAttritionLevel(Long customerId, String dataJson, Long logId);
+
+    void aiCustomerFocus(Long customerId, String dataJson, Long logId);
+
+    String polishingScript(PolishingScriptParam param);
+
+    void aiIntentionDegree(Long customerId, String dataJson, Long logId);
 
     List<CrmCustomerAnalyze> selectCrmCustomerAnalyzeListAll(CrmCustomerAnalyze crmCustomerAnalyze);
+
+    String aiIntentionDegree(String content , Long chatId);
 }

+ 319 - 14
fs-service/src/main/java/com/fs/crm/service/impl/CrmCustomerAnalyzeServiceImpl.java

@@ -7,23 +7,24 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.entity.SysDictData;
 import com.fs.common.utils.DateUtils;
 import com.fs.crm.domain.CrmCustomerAnalyze;
 import com.fs.crm.mapper.CrmCustomerAnalyzeMapper;
+import com.fs.crm.param.PolishingScriptParam;
 import com.fs.crm.service.ICrmCustomerAnalyzeService;
 import com.fs.crm.utils.CrmCustomerAiTagUtil;
 import com.fs.system.mapper.SysDictDataMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -35,6 +36,7 @@ import java.util.stream.Collectors;
 @Service
 public class CrmCustomerAnalyzeServiceImpl extends ServiceImpl<CrmCustomerAnalyzeMapper, CrmCustomerAnalyze> implements ICrmCustomerAnalyzeService {
 
+    private static final Logger log = LoggerFactory.getLogger(CrmCustomerAnalyzeServiceImpl.class);
     @Autowired
     private SysDictDataMapper sysDictDataMapper;
     /**
@@ -114,9 +116,11 @@ public class CrmCustomerAnalyzeServiceImpl extends ServiceImpl<CrmCustomerAnalyz
     //ai获取客户画像
     @Override
     @Async
-    public void aiGeneratedCustomerPortrait(String customerId, String dataJson,String logId) {
-        Map<String, Object> stringObjectMap = buildRequestParam(Long.valueOf(customerId), dataJson);
-        R aiResponse = CrmCustomerAiTagUtil.callAiService(stringObjectMap, Long.valueOf(logId));
+    public void aiGeneratedCustomerPortrait(Long customerId, String dataJson,Long logId) {
+        Map<String, Object> stringObjectMap = buildRequestParam(customerId, dataJson);
+        stringObjectMap.put("modelType","客户画像");
+        log.info("请求参数:{}", stringObjectMap);
+        R aiResponse = CrmCustomerAiTagUtil.callAiService(stringObjectMap, logId);
 
         JSONObject root = JSON.parseObject(JSONUtil.toJsonStr(aiResponse));
 
@@ -147,7 +151,247 @@ public class CrmCustomerAnalyzeServiceImpl extends ServiceImpl<CrmCustomerAnalyz
         }
 
         if (userInfo != null) {
-            baseMapper.updateCustomerPortrait(Long.valueOf(customerId),userInfo.toString());
+            CrmCustomerAnalyze crmCustomerAnalyze = new CrmCustomerAnalyze();
+            crmCustomerAnalyze.setCustomerId(customerId);
+            crmCustomerAnalyze.setCustomerPortraitJson(userInfo.toString());
+            baseMapper.updateCustomerPortrait(crmCustomerAnalyze);
+        }
+    }
+
+    @Override
+    @Async
+    public void aiCommunicationSummary(Long customerId, String dataJson, Long logId) {
+        Map<String, Object> stringObjectMap = buildRequestParam(customerId, dataJson);
+        stringObjectMap.put("modelType","沟通总结");
+        log.info("请求参数:{}", stringObjectMap);
+        R aiResponse = CrmCustomerAiTagUtil.callAiService(stringObjectMap, logId);
+        JSONObject root = JSON.parseObject(JSONUtil.toJsonStr(aiResponse));
+        System.out.println(aiResponse);
+// 获取 data.responseData
+        JSONArray responseData = root.getJSONObject("data").getJSONArray("responseData");
+
+        JSONArray summary = null;
+
+// 遍历 responseData
+        for (int i = 0; i < responseData.size(); i++) {
+            JSONObject node = responseData.getJSONObject(i);
+            JSONArray historyPreview = node.getJSONArray("historyPreview");
+
+            if (historyPreview != null) {
+                for (int j = 0; j < historyPreview.size(); j++) {
+                    JSONObject historyItem = historyPreview.getJSONObject(j);
+
+                    // 找到 obj 为 "AI" 的项
+                    if ("AI".equals(historyItem.getString("obj"))) {
+                        String valueStr = historyItem.getString("value");
+                        JSONObject valueObj = JSON.parseObject(valueStr);
+                        summary = valueObj.getJSONArray("tagInfos");
+                        break;
+                    }
+                }
+            }
+            if (summary != null) break;
+        }
+        StringBuilder summaryText = new StringBuilder();
+        if (summary!= null && !summary.isEmpty()) {
+            for (int i = 0; i < summary.size(); i++) {
+                summaryText.append(summary.get(i)).append(",");
+            }
+            summaryText.delete(summaryText.length()-1,summaryText.length());
+            CrmCustomerAnalyze crmCustomerAnalyze = new CrmCustomerAnalyze();
+            crmCustomerAnalyze.setCustomerId(customerId);
+            crmCustomerAnalyze.setCommunicationSummary(summaryText.toString());
+            baseMapper.updateCustomerPortrait(crmCustomerAnalyze);
+        }
+    }
+
+    @Override
+    @Async
+    public void aiCommunicationAbstract(Long customerId, String dataJson, Long logId) {
+        Map<String, Object> stringObjectMap = buildRequestParam(customerId, dataJson);
+        stringObjectMap.put("modelType","沟通摘要");
+        log.info("请求参数:{}", stringObjectMap);
+
+        R aiResponse = CrmCustomerAiTagUtil.callAiService(stringObjectMap, logId);
+        JSONObject root = JSON.parseObject(JSONUtil.toJsonStr(aiResponse));
+
+// 获取 data.responseData
+        JSONArray responseData = root.getJSONObject("data").getJSONArray("responseData");
+
+        String summary = null;
+
+// 遍历 responseData
+        for (int i = 0; i < responseData.size(); i++) {
+            JSONObject node = responseData.getJSONObject(i);
+            JSONArray historyPreview = node.getJSONArray("historyPreview");
+
+            if (historyPreview != null) {
+                for (int j = 0; j < historyPreview.size(); j++) {
+                    JSONObject historyItem = historyPreview.getJSONObject(j);
+
+                    // 找到 obj 为 "AI" 的项
+                    if ("AI".equals(historyItem.getString("obj"))) {
+                        String valueStr = historyItem.getString("value");
+                        JSONObject valueObj = JSON.parseObject(valueStr);
+                        summary = valueObj.getString("userContent");
+                        break;
+                    }
+                }
+            }
+            if (summary != null) break;
+        }
+        if (summary != null){
+            CrmCustomerAnalyze c = new CrmCustomerAnalyze();
+            c.setCustomerId(customerId);
+            c.setCommunicationAbstract(summary);
+            baseMapper.updateCustomerPortrait(c);
+        }
+    }
+
+    @Override
+    @Async
+    public void aiAttritionLevel(Long customerId, String dataJson, Long logId) {
+        Map<String, Object> stringObjectMap = buildRequestParam(customerId, dataJson);
+        stringObjectMap.put("modelType","流失风险等级");
+        log.info("请求参数:{}", stringObjectMap);
+
+        R aiResponse = CrmCustomerAiTagUtil.callAiService(stringObjectMap, logId);
+        JSONObject root = JSON.parseObject(JSONUtil.toJsonStr(aiResponse));
+
+// 获取 data.responseData
+        JSONArray responseData = root.getJSONObject("data").getJSONArray("responseData");
+
+        String summary = null;
+
+// 遍历 responseData
+        for (int i = 0; i < responseData.size(); i++) {
+            JSONObject node = responseData.getJSONObject(i);
+            JSONArray historyPreview = node.getJSONArray("historyPreview");
+
+            if (historyPreview != null) {
+                for (int j = 0; j < historyPreview.size(); j++) {
+                    JSONObject historyItem = historyPreview.getJSONObject(j);
+
+                    // 找到 obj 为 "AI" 的项
+                    if ("AI".equals(historyItem.getString("obj"))) {
+                        String valueStr = historyItem.getString("value");
+                        JSONObject valueObj = JSON.parseObject(valueStr);
+                        summary = valueObj.getString("tagInfos");
+                        break;
+                    }
+                }
+            }
+            if (summary != null) break;
+        }
+        if (summary != null){
+            //todo 响应处理
+        }
+    }
+
+    @Override
+    @Async
+    public void aiCustomerFocus(Long customerId, String dataJson, Long logId) {
+        Map<String, Object> stringObjectMap = buildRequestParam(customerId, dataJson);
+        stringObjectMap.put("modelType","客户关注点");
+        log.info("请求参数:{}", stringObjectMap);
+
+        R aiResponse = CrmCustomerAiTagUtil.callAiService(stringObjectMap, logId);
+        System.out.println(aiResponse);
+        JSONObject root = JSON.parseObject(JSONUtil.toJsonStr(aiResponse));
+
+// 获取 data.responseData
+        JSONArray responseData = root.getJSONObject("data").getJSONArray("responseData");
+
+        JSONArray summary = null;
+
+// 遍历 responseData
+        for (int i = 0; i < responseData.size(); i++) {
+            JSONObject node = responseData.getJSONObject(i);
+            JSONArray historyPreview = node.getJSONArray("historyPreview");
+
+            if (historyPreview != null) {
+                for (int j = 0; j < historyPreview.size(); j++) {
+                    JSONObject historyItem = historyPreview.getJSONObject(j);
+
+                    // 找到 obj 为 "AI" 的项
+                    if ("AI".equals(historyItem.getString("obj"))) {
+                        String valueStr = historyItem.getString("value");
+                        JSONObject valueObj = JSON.parseObject(valueStr);
+                        summary = valueObj.getJSONArray("userContent");
+                        break;
+                    }
+                }
+            }
+            if (summary != null) break;
+        }
+        if (summary != null){
+            List<String> list = new ArrayList<String>();
+            summary.forEach(o->{
+                JSONObject jsonObject = (JSONObject) o;
+                list.add(jsonObject.getString("tagName"));
+            });
+            CrmCustomerAnalyze crmCustomerAnalyze = new CrmCustomerAnalyze();
+            crmCustomerAnalyze.setCustomerId(customerId);
+            crmCustomerAnalyze.setCustomerFocusJson(list.toString());
+            baseMapper.updateCustomerPortrait(crmCustomerAnalyze);
+        }
+    }
+
+    @Override
+    public String polishingScript(PolishingScriptParam param) {
+        Map<String, Object> requestParam = new HashMap<>();
+        requestParam.put("history", param.getContent());
+        requestParam.put("modelType","话术润色");
+        requestParam.putAll(param.getPortrait());
+
+        // 设置其他参数
+        requestParam.put("tagInfos", Collections.emptyList());
+        requestParam.put("isRepository", "");
+        requestParam.put("userContent", "");
+        requestParam.put("aiContent", "");
+        requestParam.put("likeRatio", "");
+        R aiResponse = CrmCustomerAiTagUtil.callAiService(requestParam, Long.valueOf(param.getChatId()));
+        System.out.println(aiResponse);
+        return "";
+    }
+
+    @Override
+    public void aiIntentionDegree(Long customerId, String dataJson, Long logId) {
+        Map<String, Object> stringObjectMap = buildRequestParam(customerId, dataJson);
+        stringObjectMap.put("modelType","客户意向度");
+        log.info("请求参数:{}", stringObjectMap);
+
+        R aiResponse = CrmCustomerAiTagUtil.callAiService(stringObjectMap, logId);
+        System.out.println(aiResponse);
+        JSONObject root = JSON.parseObject(JSONUtil.toJsonStr(aiResponse));
+
+// 获取 data.responseData
+        JSONArray responseData = root.getJSONObject("data").getJSONArray("responseData");
+
+        JSONArray summary = null;
+
+// 遍历 responseData
+        for (int i = 0; i < responseData.size(); i++) {
+            JSONObject node = responseData.getJSONObject(i);
+            JSONArray historyPreview = node.getJSONArray("historyPreview");
+
+            if (historyPreview != null) {
+                for (int j = 0; j < historyPreview.size(); j++) {
+                    JSONObject historyItem = historyPreview.getJSONObject(j);
+
+                    // 找到 obj 为 "AI" 的项
+                    if ("AI".equals(historyItem.getString("obj"))) {
+                        String valueStr = historyItem.getString("value");
+                        JSONObject valueObj = JSON.parseObject(valueStr);
+                        summary = valueObj.getJSONArray("userContent");
+                        break;
+                    }
+                }
+            }
+            if (summary != null) break;
+        }
+        if (summary != null) {
+            //todo 响应处理
         }
     }
 
@@ -156,6 +400,70 @@ public class CrmCustomerAnalyzeServiceImpl extends ServiceImpl<CrmCustomerAnalyz
         return baseMapper.selectCrmCustomerAnalyzeListAll(crmCustomerAnalyze);
     }
 
+    @Override
+    public String aiIntentionDegree(String content, Long chatId) throws JsonProcessingException {
+        Map<String, Object> requestParam = new HashMap<>();
+
+        List<Map<String, Object>> maps = mapper.readValue(content,
+                new com.fasterxml.jackson.core.type.TypeReference<List<Map<String, Object>>>() {
+                });
+        maps.remove(0);//去除提示词
+        StringBuilder history = new StringBuilder();
+        history.append("{");
+        for (Map<String, Object> o :
+                maps) {
+            String role = (String) o.get("role");
+            String contentResult = (String) o.get("content");
+            String roleTag = "user".equals(role) ? "user" : "ai";
+            history.append(String.format("\"%s\":\"%s\",", roleTag, contentResult));
+        }
+        history.deleteCharAt(history.length() - 1).append("}");
+        requestParam.put("history", history);
+
+        // 设置其他参数
+        requestParam.put("tagInfos", Collections.emptyList());
+        requestParam.put("isRepository", "");
+        requestParam.put("userContent", "");
+        requestParam.put("aiContent", "");
+        requestParam.put("likeRatio", "");
+        requestParam.put("modelType","客户意向度");
+        log.info("请求参数:{}", requestParam);
+
+        R aiResponse = CrmCustomerAiTagUtil.callAiService(requestParam, chatId);
+        System.out.println(aiResponse);
+        JSONObject root = JSON.parseObject(JSONUtil.toJsonStr(aiResponse));
+
+// 获取 data.responseData
+        JSONArray responseData = root.getJSONObject("data").getJSONArray("responseData");
+
+        JSONArray summary = null;
+
+// 遍历 responseData
+        for (int i = 0; i < responseData.size(); i++) {
+            JSONObject node = responseData.getJSONObject(i);
+            JSONArray historyPreview = node.getJSONArray("historyPreview");
+
+            if (historyPreview != null) {
+                for (int j = 0; j < historyPreview.size(); j++) {
+                    JSONObject historyItem = historyPreview.getJSONObject(j);
+
+                    // 找到 obj 为 "AI" 的项
+                    if ("AI".equals(historyItem.getString("obj"))) {
+                        String valueStr = historyItem.getString("value");
+                        JSONObject valueObj = JSON.parseObject(valueStr);
+                        summary = valueObj.getJSONArray("userContent");
+                        break;
+                    }
+                }
+            }
+            if (summary != null) break;
+        }
+        if (summary != null) {
+            //todo 响应处理
+        }
+        return null;
+    }
+
     private Map<String, Object> buildRequestParam(Long customerId,
                                                          String communication) {
         Map<String, Object> requestParam = new HashMap<>();
@@ -169,7 +477,7 @@ public class CrmCustomerAnalyzeServiceImpl extends ServiceImpl<CrmCustomerAnalyz
             likeRatio = (String) userInfo.remove("likeRatio");
         }
         // 合并数据
-        requestParam.putAll(history);
+        requestParam.put("history",communication);
         requestParam.putAll(userInfo);
 
         // 设置其他参数
@@ -178,7 +486,6 @@ public class CrmCustomerAnalyzeServiceImpl extends ServiceImpl<CrmCustomerAnalyz
         requestParam.put("userContent", "");
         requestParam.put("aiContent", "");
         requestParam.put("likeRatio", likeRatio);
-        requestParam.put("modelType","客户画像");
 
         return requestParam;
     }
@@ -189,16 +496,14 @@ public class CrmCustomerAnalyzeServiceImpl extends ServiceImpl<CrmCustomerAnalyz
 //        userInfo.put("name", crmCustomerAnalyze.getCustomerName()==null?"" : crmCustomerAnalyze.getCustomerName());
         List<SysDictData> portraits = sysDictDataMapper.selectDictDataByType(AI_PORTRAIT);
         List<String> dictValue = portraits.stream().map(SysDictData::getDictValue).collect(Collectors.toList());
-        Map<String, String> portraitMap = portraits.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
+//        Map<String, String> portraitMap = portraits.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
 
         if (crmCustomerAnalyze.getCustomerPortraitJson() != null){
             Map<String, String> portraitList = JSON.parseObject(
                     crmCustomerAnalyze.getCustomerPortraitJson(),
                     new TypeReference<Map<String, String>>() {}
             );
-            portraitList.forEach((k, v)->{
-                if(ObjectUtil.isNotEmpty(portraitMap.get(k)))userInfo.put(portraitMap.get(k),v);
-            });
+            userInfo.putAll(portraitList);
 
         }else {
             dictValue.forEach(o->{

+ 16 - 7
fs-service/src/main/java/com/fs/crm/utils/CrmCustomerAiTagUtil.java

@@ -31,6 +31,8 @@ import com.fs.fastgptApi.param.ChatParam;
 import com.fs.fastgptApi.service.ChatService;
 import com.fs.hisapi.util.MapUtil;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
@@ -54,9 +56,17 @@ public class CrmCustomerAiTagUtil {
 
     private static String APP_KEY;
 
+    // 1. 声明静态变量
+    private static RedisTemplate redisTemplate;
+
+    // 2. 注入实例到非静态变量
+    @Autowired
+    @Qualifier("redisTemplate")
+    private RedisTemplate redisTemplateInstance;
     @PostConstruct
     public void initStatic() {
         APP_KEY = this.appKey;
+        redisTemplate = this.redisTemplateInstance;
     }
 
     public static List<CrmCustomerAiTagVo> getCrmCustomerAiTag(CrmCustomerAiTagParam content) throws JsonProcessingException {
@@ -77,7 +87,7 @@ public class CrmCustomerAiTagUtil {
         List<CrmCustomerAiTagVo> results = parseAiResponse(aiResponse, customerId);
 
         // 5. 异步保存到Redis,后续调用ai分析其他数据 //暂时只传聊天记录
-        saveToRedisAsync(customerId, (String) requestParam.get("history"),logId);
+        saveToRedisAsync(customerId,  requestParam.get("history").toString(),logId);
         return results;
     }
     private static void saveToRedisAsync(Long customerId, String aiResponse, Long logId) {
@@ -90,8 +100,6 @@ public class CrmCustomerAiTagUtil {
                 dataMap.put("logId", logId);
                 dataMap.put("timestamp", System.currentTimeMillis());
 
-                RedisTemplate<String, Object> redisTemplate = SpringUtils.getBean(RedisTemplate.class);
-
                 // 存储队列索引
                 redisTemplate.opsForList().rightPush(CRM_AI_REDIS_KEY, dataMap);
 
@@ -382,10 +390,11 @@ public class CrmCustomerAiTagUtil {
             }
         });
         if (!maps.isEmpty()){
-            CrmCustomerAnalyze crmCustomerInfo = new CrmCustomerAnalyze();
-            crmCustomerInfo.setCustomerId(Long.valueOf(customerId));
-            crmCustomerInfo.setAiChatRecord(JSONUtil.toJsonStr(maps));
-            SpringUtils.getBean(CrmCustomerAnalyzeMapper.class).insertCrmCustomerAnalyze(crmCustomerInfo);
+            CrmCustomerAnalyzeMapper bean = SpringUtils.getBean(CrmCustomerAnalyzeMapper.class);
+            CrmCustomerAnalyze crmCustomerAnalyze = bean.selectLatestOne(Long.valueOf(customerId));
+            crmCustomerAnalyze.setAiChatRecord(JSONUtil.toJsonStr(maps));
+            crmCustomerAnalyze.setCreateTime(new Date());
+            bean.insertCrmCustomerAnalyze(crmCustomerAnalyze);
         }
 
         return result;

+ 25 - 1
fs-service/src/main/java/com/fs/erp/utils/WeizouApiClient.java

@@ -1,6 +1,7 @@
 package com.fs.erp.utils;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fs.common.utils.CloudHostUtils;
 import com.fs.erp.domain.WeizouApiPushOrderParam;
 import lombok.extern.slf4j.Slf4j;
 import okhttp3.*;
@@ -48,6 +49,8 @@ public class WeizouApiClient {
 
     @Value("${weizou.appSecret:a6cd645383a3405d842ce00da106ded0}")
     private String appSecretInstance;
+    @Value("${weizou.createName:wz_5dd9126f39b84ae096a0e18ea313559a}")
+    private String createName;
     // 3. @PostConstruct 将实例赋值给静态变量
     @PostConstruct
     public void initStatic() {
@@ -56,6 +59,7 @@ public class WeizouApiClient {
         BASE_URL = this.baseUrlInstance;
         APP_ID = this.appIdInstance;
         APP_SECRET = this.appSecretInstance;
+        CREATE_NAME = this.createName;
         log.info("配置加载完成:BASE_URL={}, APP_ID={}", BASE_URL, APP_ID);
     }
 
@@ -63,6 +67,7 @@ public class WeizouApiClient {
     // TODO: 替换为平台提供的实际应用ID和密钥
     private static  String APP_ID ;
     private static  String APP_SECRET;
+    private static String CREATE_NAME;
 
     private static final String WEIZOU_API_CLIENT_KEY = "weizou:api:client:key";
 
@@ -156,7 +161,7 @@ public class WeizouApiClient {
      */
     public static String pushOrder(WeizouApiPushOrderParam orderData) throws IOException {
         String token = getAccessToken();
-
+        orderData.setCreateName(CREATE_NAME);
         String orderJson = objectMapper.writeValueAsString(orderData);
 
         Request request = new Request.Builder()
@@ -176,6 +181,25 @@ public class WeizouApiClient {
         }
     }
 
+    public static String cancelOrder(Map<String, Object> orderData) throws IOException {
+        String token = getAccessToken();
+        String orderJson = objectMapper.writeValueAsString(orderData);
+
+        Request request = new Request.Builder()
+                .url(BASE_URL + "/cs/api/storeOrder/thirdParty/cancel")
+                .post(RequestBody.create(MediaType.parse("application/json; charset=utf-8"), orderJson))
+                .addHeader("Content-Type", "application/json")
+                .addHeader("token", token) // 假设使用Bearer Token
+                // TODO: 根据文档添加其他必要的Headers
+                .build();
+        try (Response response = httpClient.newCall(request).execute()) {
+            if (!response.isSuccessful()) {
+                log.error("取消失败:"+response.code()+response.message());
+                throw new IOException("订单推送失败,HTTP状态码: " + response.code());
+            }
+            return response.body().string();
+        }
+    }
     // ========== 内部辅助类 ==========
 
     /**

+ 11 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsStoreAfterSalesServiceImpl.java

@@ -1,5 +1,6 @@
 package com.fs.his.service.impl;
 
+import java.io.IOException;
 import java.lang.reflect.Field;
 import java.math.BigDecimal;
 import java.sql.Timestamp;
@@ -33,6 +34,7 @@ import com.fs.core.config.WxPayProperties;
 import com.fs.core.utils.OrderCodeUtils;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
+import com.fs.erp.utils.WeizouApiClient;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.config.StoreConfig;
 import com.fs.erp.dto.BaseResponse;
@@ -644,6 +646,15 @@ public class FsStoreAfterSalesServiceImpl implements IFsStoreAfterSalesService {
                     }
                 }
             }
+            if (CloudHostUtils.hasCloudHostName("今正科技")) {
+                try {//今正订单取消调用微走
+                    HashMap<String, Object> objectObjectHashMap = new HashMap<>();
+                    objectObjectHashMap.put("extendOrderId", order.getOrderId());
+                    WeizouApiClient.cancelOrder(objectObjectHashMap);
+                } catch (IOException e) {
+                    logger.error("微走取消订单失败{}", order.getOrderId() + e.getMessage());
+                }
+            }
         } else {
             if (order.getRefundAmount().compareTo(BigDecimal.ZERO) == 0) {
 

+ 59 - 57
fs-service/src/main/java/com/fs/his/utils/LinkUtil.java

@@ -8,76 +8,78 @@ import javax.crypto.spec.SecretKeySpec;
 import java.nio.charset.StandardCharsets;
 
 public class LinkUtil {
-    private static final String KEY = "AESAabCdeREssREA";
-    private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding";
 
+    // 保持密钥不变(16位 AES 密钥)
+    private static final String AES_KEY = "abcedfghijklmnop";
+    // 改用 CBC 模式(比 ECB 安全),搭配 PKCS5Padding
+    private static final String AES_ALGORITHM = "AES/CBC/PKCS5Padding";
+    // CBC 模式需要初始化向量(IV),固定 16 位(和 AES 分组长度一致)
+    private static final byte[] IV = AES_KEY.getBytes(StandardCharsets.UTF_8);
 
-    public static String encryptLink(String text) {
-        String encryptedText=null;
+    // 优化后:仅 AES + Base64URL 编码(去掉 GZIP,适配短字符串)
+    public static String encryptLink(String plainText){
         try {
-            SecretKeySpec secretKey = new SecretKeySpec(KEY.getBytes(), "AES");
-            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
-            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
-            byte[] encryptedBytes = cipher.doFinal(text.getBytes());
-            encryptedText = Base62Utils.bytesToBase62(encryptedBytes);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return encryptedText;
-    }
+            if (plainText == null || plainText.isEmpty()) {
+                return plainText;
+            }
+            // 1. 初始化 AES CBC 模式(比 ECB 安全,长度和 ECB 一致)
+            SecretKeySpec keySpec = new SecretKeySpec(AES_KEY.getBytes(StandardCharsets.UTF_8), "AES");
+            javax.crypto.spec.IvParameterSpec ivSpec = new javax.crypto.spec.IvParameterSpec(IV);
+            Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
+            cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
 
-    public static String decryptLink(String encryptedText) {
-        String text=null;
-        try {
-            SecretKeySpec secretKey = new SecretKeySpec(KEY.getBytes(), "AES");
-            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
-            cipher.init(Cipher.DECRYPT_MODE, secretKey);
-            byte[] decryptedBytes = cipher.doFinal(Base62Utils.base62ToBytes(encryptedText));
-            text = new String(decryptedBytes);
+            // 2. AES 加密
+            byte[] plainBytes = plainText.getBytes(StandardCharsets.UTF_8);
+            byte[] encryptBytes = cipher.doFinal(plainBytes);
+
+            // 3. Base64URL 编码(优化:替换 +/ 为 -_,去掉 =,比标准 Base64 短)
+            String base64Str = Base64Utils.encodeToString(encryptBytes);
+            return base64Str.replace("+", "-").replace("/", "_").replace("=", "");
         } catch (Exception e) {
-            e.printStackTrace();
+            return null;
         }
-        return text;
     }
 
-    public static String decryptPhoneMk(String encryptedText) {
-        String text=null;
+    // 解密方法(可逆)
+    public static String decryptLink(String cipherText){
         try {
-            SecretKeySpec secretKey = new SecretKeySpec(KEY.getBytes(), "AES");
-            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
-            cipher.init(Cipher.DECRYPT_MODE, secretKey);
-            byte[] decryptedBytes = cipher.doFinal(Base62Utils.base62ToBytes(encryptedText));
-            text = new String(decryptedBytes);
-            text =text.replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
+            if (cipherText == null || cipherText.isEmpty()) {
+                return cipherText;
+            }
+            // 1. 还原 Base64URL 为标准 Base64
+            String base64Str = cipherText.replace("-", "+").replace("_", "/");
+            int padding = 4 - (base64Str.length() % 4);
+            if (padding != 4) {
+                base64Str += "====".substring(0, padding);
+            }
+            byte[] encryptBytes = Base64Utils.decodeFromString(base64Str);
+
+            // 2. AES CBC 解密
+            SecretKeySpec keySpec = new SecretKeySpec(AES_KEY.getBytes(StandardCharsets.UTF_8), "AES");
+            javax.crypto.spec.IvParameterSpec ivSpec = new javax.crypto.spec.IvParameterSpec(IV);
+            Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
+            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
+            byte[] plainBytes = cipher.doFinal(encryptBytes);
+
+            return new String(plainBytes, StandardCharsets.UTF_8);
         } catch (Exception e) {
-            e.printStackTrace();
+            return null;
         }
-        return text;
     }
 
-    public static String decryptAutoPhoneMk(String encryptedText) {
-        String text=null;
-        if (encryptedText!=null&&encryptedText!="") {
-            if (encryptedText.length()>11){
-                try {
-                    SecretKeySpec secretKey = new SecretKeySpec(KEY.getBytes(), "AES");
-                    Cipher cipher = Cipher.getInstance(TRANSFORMATION);
-                    cipher.init(Cipher.DECRYPT_MODE, secretKey);
-                    byte[] decryptedBytes = cipher.doFinal(Base62Utils.base62ToBytes(encryptedText));
-                    text = new String(decryptedBytes);
-                    text =text.replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            }else {
-                text =  ParseUtils.parsePhone(encryptedText);
-            }
-        }
+    // 测试:你的原字符串加密后长度对比
+    /*public static void main(String[] args) throws Exception {
+        String original = "/pages_live/livingList?link=2034103257541902336";
+        System.out.println("原字符串长度:" + original.length()); // 约 40 字符
 
-        return text;
-    }
+        // 优化后加密
+        String encrypted = encryptShortStr(original);
+        System.out.println("优化后加密长度:" + encrypted.length()); // 约 50 字符(从 150 大幅缩短)
+        System.out.println("加密后内容:" + encrypted);
+
+        // 解密验证可逆性
+        String decrypted = decryptShortStr(encrypted);
+        System.out.println("解密后是否一致:" + original.equals(decrypted)); // true
+    }*/
 
-    public static void main(String[] args) {
-        System.out.println(decryptLink("43fP1nkB0dzuoa8nyqZ45nbgqeXHtgOeOYbfSS53fsCDaR0Y1F4ySPuMzi8UNrY0VBL21XdcWAY232W9UOkjTTL3O"));
-    }
 }

+ 10 - 0
fs-service/src/main/java/com/fs/hisStore/domain/FsStoreScrm.java

@@ -194,4 +194,14 @@ public class FsStoreScrm extends BaseEntity
     /** 医疗机构执业许可证有效期结束 */
     private LocalDate medicalLicenseExpiryEnd;
 
+
+    /** 其他特殊资格 */
+    private String otherSpecialQualification;
+
+    /** 其他特殊资格有效期开始 */
+    private LocalDate otherSpecialQualificationStart;
+
+    /** 其他特殊资格有效期结束 */
+    private LocalDate otherSpecialQualificationEnd;
+
 }

+ 1 - 1
fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreOrderScrmMapper.java

@@ -37,7 +37,7 @@ public interface FsStoreOrderScrmMapper
      * @param id 订单ID
      * @return 订单
      */
-    public FsStoreOrderScrm selectFsStoreOrderById(Long id);
+    public FsStoreOrderScrm selectFsStoreOrderById(@Param("id") Long id);
 
     /**
      * 根据订单ID列表批量查询订单

+ 3 - 0
fs-service/src/main/java/com/fs/hisStore/service/IFsStoreOrderScrmService.java

@@ -15,6 +15,7 @@ import com.fs.erp.domain.ErpOrder;
 import com.fs.his.dto.FsStoreOrderAmountScrmStatsQueryDto;
 import com.fs.his.enums.PaymentMethodEnum;
 import com.fs.his.param.FsIntegralOrderDoPayParam;
+import com.fs.his.param.FsStoreOrderDoPayParam;
 import com.fs.his.param.FsStoreOrderSalesParam;
 import com.fs.his.vo.FsStoreOrderAmountScrmStatsVo;
 import com.fs.his.vo.FsStoreOrderExcelVO;
@@ -391,4 +392,6 @@ public interface IFsStoreOrderScrmService
     R editOrderMoneyBySidebar(FsStoreOrderScrmSidebarVO param);
 
     R payment(FsIntegralOrderDoPayParam param, PaymentMethodEnum paymentMethodEnum);
+
+    R zfbPayment(FsStoreOrderDoPayParam param);
 }

+ 165 - 21
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java

@@ -57,30 +57,35 @@ import com.fs.erp.service.IErpOrderService;
 import com.fs.his.config.AppConfig;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.domain.*;
-import com.fs.his.dto.FsPrescribeUsageDTO;
-import com.fs.his.dto.FsProdItemDTO;
-import com.fs.his.dto.FsStoreOrderAmountScrmStatsQueryDto;
-import com.fs.his.dto.FsStoreOrderItemDTO;
+import com.fs.his.dto.*;
 import com.fs.his.enums.*;
 import com.fs.his.mapper.*;
-import com.fs.his.param.FsIntegralOrderDoPayParam;
-import com.fs.his.param.FsStoreOrderSalesParam;
-import com.fs.his.param.FsUserAddIntegralTemplateParam;
-import com.fs.his.param.PayOrderParam;
+import com.fs.his.param.*;
 import com.fs.his.service.IFsPrescribeService;
+import com.fs.his.service.IFsStoreOrderService;
 import com.fs.his.service.IFsUserIntegralLogsService;
 import com.fs.his.service.IFsUserWatchService;
 import com.fs.his.utils.ConfigUtil;
-import com.fs.his.vo.FsInquiryOrderVO;
-import com.fs.his.vo.FsStoreOrderAmountScrmStatsVo;
-import com.fs.his.vo.FsStoreOrderExcelVO;
+import com.fs.his.vo.*;
 import com.fs.his.vo.FsPrescribeVO;
 import com.fs.hisStore.config.FsErpConfig;
 import com.fs.hisStore.constants.ErpTypeEnum;
 import com.fs.hisStore.dto.*;
+import com.fs.hisStore.dto.ErpRemarkDTO;
+import com.fs.hisStore.dto.ExpressDataDTO;
+import com.fs.hisStore.dto.ExpressInfoDTO;
+import com.fs.hisStore.dto.ExpressNotifyDTO;
+import com.fs.hisStore.dto.ExpressResultDTO;
+import com.fs.hisStore.dto.FsStoreCartDTO;
+import com.fs.hisStore.dto.StoreOrderExpressExportDTO;
+import com.fs.hisStore.dto.StorePackageProductDTO;
+import com.fs.hisStore.dto.StoreProductGroupDTO;
 import com.fs.hisStore.enums.ShipperCodeEnum;
 import com.fs.hisStore.mapper.*;
 import com.fs.hisStore.param.*;
+import com.fs.hisStore.param.FsStoreAfterSalesParam;
+import com.fs.hisStore.param.FsStoreOrderParam;
+import com.fs.hisStore.param.FsStoreOrderPayParam;
 import com.fs.hisStore.vo.*;
 import com.fs.hisStore.vo.FsStoreOrderErpExportVO;
 import com.fs.hisStore.vo.FsStoreOrderItemVO;
@@ -111,6 +116,11 @@ import com.fs.hisStore.service.*;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.service.ISysConfigService;
 import com.fs.system.service.ISysDictTypeService;
+import com.fs.tzBankPay.TzBankService.TzBankService;
+import com.fs.tzBankPay.doman.PayCreateOrder;
+import com.fs.tzBankPay.doman.PayCreateOrderResult;
+import com.fs.tzBankPay.doman.PayType;
+import com.fs.tzBankPay.doman.TzBankResult;
 import com.fs.wx.miniapp.config.WxMaProperties;
 import com.fs.wx.order.domain.FsWxExpressTask;
 import com.fs.wx.order.dto.*;
@@ -153,6 +163,8 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport;
 import org.redisson.api.RLock;
 import org.redisson.api.RedissonClient;
 
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import javax.annotation.PostConstruct;
 import java.lang.reflect.Field;
 import java.math.BigDecimal;
@@ -253,6 +265,12 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     @Lazy
     private IFsPrescribeService fsPrescribeService;
 
+    @Autowired
+    private TzBankService tzBankService;
+
+    @Autowired
+    private FsUserWxMapper fsUserWxMapper;
+
     @Autowired
     private IPayService payService;
     @Autowired
@@ -5889,19 +5907,26 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             if (config.getServiceFee() != null) {
                 storeOrder.setServiceFee(config.getServiceFee());
             }
-
-            //后台制单处理
-            if (param.getPayPrice() != null && param.getPayPrice().compareTo(BigDecimal.ZERO) > 0) {
-                if (param.getPayPrice().compareTo(dto.getTotalPrice()) > 0) {
-                    return R.error("改价价格不能大于商品总价");
+            BigDecimal money = redisCache.getCacheObject("createOrderMoney:" + param.getOrderKey());
+            if(money != null && money.compareTo(BigDecimal.ZERO) >= 0 && money.compareTo(param.getPayPrice()) <= 0){
+                storeOrder.setPayPrice(money);
+                storeOrder.setPayMoney(money);
+            }else{
+                //后台制单处理
+                if (param.getPayPrice() != null && param.getPayPrice().compareTo(BigDecimal.ZERO) > 0) {
+                    if (param.getPayPrice().compareTo(dto.getTotalPrice()) > 0) {
+                        return R.error("改价价格不能大于商品总价");
+                    }
+                    storeOrder.setPayPrice(param.getPayPrice());
+                    storeOrder.setPayMoney(param.getPayPrice());
+                } else {
+                    storeOrder.setPayPrice(dto.getPayPrice());
+                    storeOrder.setPayMoney(dto.getPayPrice());
                 }
-                storeOrder.setPayPrice(param.getPayPrice());
-                storeOrder.setPayMoney(param.getPayPrice());
-            } else {
-                storeOrder.setPayPrice(dto.getPayPrice());
-                storeOrder.setPayMoney(dto.getPayPrice());
             }
 
+
+
             storeOrder.setStatus(1);
             storeOrder.setPaid(1);
             storeOrder.setPayTime(new Date());
@@ -6081,6 +6106,125 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         return storePaymentService.processPaymentScrm(payOrderParam);
     }
 
+    @Override
+    public R zfbPayment(FsStoreOrderDoPayParam param) {
+        FsStoreOrderScrm order = fsStoreOrderMapper.selectFsStoreOrderById(param.getOrderId());
+
+        FSUserVO user=userService.selectFsUserByUserId(param.getUserId());
+
+        String json = configService.selectConfigByKey("his.pay");
+        PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
+
+        String openId = null;
+        String appId = param.getAppId();
+        if (StringUtils.isNotBlank(appId)) {
+            //查询fs_user_wx的openId
+            Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                    .eq(FsUserWx::getFsUserId, param.getUserId())
+                    .eq(FsUserWx::getAppId, appId);
+            FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+            if (fsUserWx != null) {
+                openId = fsUserWx.getOpenId();
+            }
+        } else {
+            appId = payConfigDTO.getAppId();
+            openId = Objects.isNull(user) ? "" : user.getMaOpenId();
+            if (StringUtils.isBlank(openId)){
+                Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                        .eq(FsUserWx::getFsUserId, param.getUserId())
+                        .eq(FsUserWx::getAppId, appId);
+                FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+                if (Objects.nonNull(fsUserWx)){
+                    openId = fsUserWx.getOpenId();
+                }
+            }
+        }
+
+        if(order.getPayMoney().compareTo(new BigDecimal(0))==0){
+            /*this.payConfirm(order.getOrderCode(),"","","",2,null,null);
+            return R.ok().put("isPay",1);*/
+        }
+        else{
+            String payCode =  OrderCodeUtils.getOrderSn();
+            if(StringUtils.isEmpty(payCode)){
+                return R.error("订单生成失败,请重试");
+            }
+//            String json = configService.selectConfigByKey("his.pay");
+//            PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
+            FsStorePaymentScrm storePayment=new FsStorePaymentScrm();
+            storePayment.setStatus(0);
+            storePayment.setPayMode(payConfigDTO.getType());
+            storePayment.setPayCode(payCode);
+            storePayment.setCompanyId(order.getCompanyId());
+            storePayment.setCompanyUserId(order.getCompanyUserId());
+            storePayment.setBusinessCode(order.getOrderCode());
+            storePayment.setPayMoney(order.getPayMoney());
+            storePayment.setCreateTime(new Date());
+            storePayment.setPayTypeCode("支付宝");
+            storePayment.setBusinessType(1);
+            storePayment.setRemark("商城订单支付");
+            storePayment.setOpenId(openId);
+            storePayment.setOrderId(order.getId());
+            storePayment.setUserId(user.getUserId());
+            storePayment.setBusinessOrderId(order.getId().toString());
+            if(storePaymentService.insertFsStorePayment(storePayment)>0){
+                if (payConfigDTO.getType().equals("yb")) {
+                    return R.error("支付暂不可用!");
+                } else if (payConfigDTO.getType().equals("tz")) {
+                    PayCreateOrder o = new PayCreateOrder();
+                    o.setOrderNo("store" + storePayment.getPayCode()); // 业务系统订单号
+                    o.setTrxAmt(storePayment.getPayMoney().doubleValue()); // 交易金额
+                    o.setBusinessCstNo(order.getUserId().toString()); // 业务平台客户号
+                    String phone="";
+                    if (user.getPhone()!=null&&user.getPhone().length()>4){
+                        phone=user.getPhone().substring(user.getPhone().length()-4);
+                    }
+                    o.setPayerName("微信用户"+phone);
+                    o.setGoodsInfo("商城订单支付"); // 订单信息
+                    o.setOrderType(2);
+                    o.setOrderId(order.getOrderCode());
+                    o.setPayType(Arrays.asList(PayType.ALIPAY_BARCODE_PAYMENT.getCode()));
+                    TzBankResult<PayCreateOrderResult> result = tzBankService.createOrder(o);
+                    FsStorePaymentScrm mt=new FsStorePaymentScrm();
+                    mt.setPaymentId(storePayment.getPaymentId());
+                    mt.setTradeNo(result.getBody().getOrderFlowNo());
+                    storePaymentService.updateFsStorePayment(mt);
+                    return R.ok().put("isPay", 0).put("data", result).put("type", "tz");
+                }else if (payConfigDTO.getType().equals("hf")) {
+                    HuiFuCreateOrder o = new HuiFuCreateOrder();
+                    o.setTradeType("A_NATIVE");
+                    o.setOpenid(openId);
+                    o.setReqSeqId("store-"+storePayment.getPayCode());
+                    o.setTransAmt(storePayment.getPayMoney().toString());
+                    o.setGoodsDesc("商城订单支付");
+                    o.setAppId(appId);
+                    if (o.getAppId()!=null&& !o.getAppId().isEmpty()){
+                        Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                                .eq(FsUserWx::getFsUserId, param.getUserId())
+                                .eq(FsUserWx::getAppId, payConfigDTO.getAppId());
+                        FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+                        if (fsUserWx!=null){
+                            o.setOpenid(fsUserWx.getOpenId());
+                        }
+                    }
+                    HuifuCreateOrderResult result = huiFuService.createOrder(o);
+                    FsStorePaymentScrm mt=new FsStorePaymentScrm();
+                    mt.setPaymentId(storePayment.getPaymentId());
+                    mt.setTradeNo(result.getHf_seq_id());
+                    mt.setAppId(appId);
+                    storePaymentService.updateFsStorePayment(mt);
+                    return R.ok().put("isPay",0).put("data",result).put("type","hf");
+                }
+
+            }
+            else{
+                throw new CustomException("支付失败");
+            }
+
+        }
+        return R.error();
+    }
+
 
     /**
      * 综合参数

+ 4 - 1
fs-service/src/main/java/com/fs/live/service/ILiveService.java

@@ -2,6 +2,7 @@ package com.fs.live.service;
 
 
 import com.fs.common.core.page.PageRequest;
+import com.fs.company.domain.CompanyUser;
 import com.fs.company.vo.CompanyVO;
 import com.fs.live.param.LiveNotifyParam;
 import com.fs.live.vo.LiveVo;
@@ -222,9 +223,11 @@ public interface ILiveService
 
     R liveDecryptLink(String url);
 
-    R liveDecryptLinkV2(String url);
+    R liveDecryptLinkV2(String url,String userId);
 
     R getLiveQwUserInfo(Long qwUserId);
 
     List<Live> selectLiveListNew(Live live);
+
+    R createAppLink(CompanyUser user, Long liveId, String corpId);
 }

+ 116 - 3
fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java

@@ -14,15 +14,23 @@ import com.fs.common.core.page.PageRequest;
 import com.fs.common.core.redis.service.StockDeductService;
 import com.fs.common.exception.base.BaseException;
 import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.domain.CompanyUserUser;
 import com.fs.company.mapper.CompanyMapper;
+import com.fs.company.service.ICompanyUserService;
+import com.fs.company.service.ICompanyUserUserService;
 import com.fs.company.vo.CompanyVO;
 import com.fs.core.config.WxMaConfiguration;
 import com.fs.course.config.CourseConfig;
+import com.fs.course.domain.FsCourseLink;
+import com.fs.course.domain.FsCourseRealLink;
+import com.fs.course.mapper.FsCourseLinkMapper;
 import com.fs.his.domain.FsStoreProduct;
 import com.fs.his.domain.FsUser;
 import com.fs.his.domain.FsUserWx;
 import com.fs.his.mapper.FsUserMapper;
 import com.fs.his.mapper.FsUserWxMapper;
+import com.fs.his.service.IFsUserService;
 import com.fs.his.utils.LinkUtil;
 import com.fs.his.utils.PhoneUtil;
 import com.fs.hisStore.domain.FsStoreProductScrm;
@@ -43,10 +51,13 @@ import com.fs.live.param.LiveReplayParam;
 import com.fs.live.service.*;
 import com.fs.live.utils.ProcessManager;
 import com.fs.live.vo.*;
+import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.domain.QwUser;
 import com.fs.qw.mapper.QwUserMapper;
+import com.fs.qw.service.IQwExternalContactService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.service.ISysConfigService;
+import com.fs.voice.utils.StringUtil;
 import com.github.pagehelper.PageInfo;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -80,6 +91,8 @@ import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
+import static com.fs.course.utils.LinkUtil.generateRandomStringWithLock;
+
 /**
  * 直播Service业务层处理
  *
@@ -155,6 +168,17 @@ public class LiveServiceImpl implements ILiveService
 
     private final String liveUrl = "/living/#/?s=";
 
+    @Autowired
+    private ICompanyUserUserService companyUserUserService;
+    @Autowired
+    private ICompanyUserService companyUserService;
+    @Autowired
+    private IQwExternalContactService qwExternalContactService;
+    @Autowired
+    private IFsUserService userService;
+    @Autowired
+    private FsCourseLinkMapper fsCourseLinkMapper;
+
     @Override
     public Live selectLiveDbByLiveId(Long liveId) {
         // 缓存中没有,从数据库查询
@@ -229,11 +253,59 @@ public class LiveServiceImpl implements ILiveService
      * @return
      */
     @Override
-    public R liveDecryptLinkV2(String url) {
+    public R liveDecryptLinkV2(String url,String userId) {
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSON.parseObject(json, CourseConfig.class);
+        Long fsUserId = Long.valueOf(userId);
         String decryptLink = LinkUtil.decryptLink(url);
         Map<String, Object> data = new HashMap<>();
-        data.put("decryptLink", decryptLink);
-        return R.ok().put("data", data);
+        data.put("decryptLink", config.getRealLinkH5LiveName()+decryptLink);
+        String[] split = decryptLink.split("=");
+        if(split[1] != null){
+            FsCourseLink courseLink = fsCourseLinkMapper.selectFsCourseLinkByLink(split[1]);
+            String realLink = courseLink.getRealLink();
+            data.put("realLink", config.getRealLinkH5LiveName() + realLink);
+            String[] split1 = realLink.split("=");
+            if(split1[1] != null){
+                try {
+                    JSONObject jsonObject = JSONObject.parseObject(split1[1]);
+                    Long companyUserId = jsonObject.getLong("companyUserId");
+                    Long qwExternalId = jsonObject.getLong("qwExternalId");
+
+                    if(companyUserId == null){
+                        return R.error("销售不存在,链接无效!");
+                    }
+
+                    CompanyUserUser map = new CompanyUserUser();
+                    map.setCompanyUserId(companyUserId);
+                    map.setUserId(fsUserId);
+                    //将小程序客户和销售做绑定
+                    List<CompanyUserUser> list = companyUserUserService.selectCompanyUserUserList(map);
+                    if (list == null || list.isEmpty()) {
+                        CompanyUser companyUser = companyUserService.selectCompanyUserById(companyUserId);
+                        if (companyUser != null && companyUser.getStatus().equals("0")) {
+                            map.setCompanyId(companyUser.getCompanyId());
+                            companyUserUserService.insertCompanyUserUser(map);
+                        }
+                    }
+
+                    FsUser user=userService.selectFsUserByUserId(fsUserId);
+                    if(user != null && qwExternalId != null){
+                        QwExternalContact qwExternalContact = qwExternalContactService.selectQwExternalContactById(qwExternalId);
+                        if(qwExternalContact != null && qwExternalContact.getFsUserId() == null){
+                            QwExternalContact qwExtContact = new QwExternalContact();
+                            qwExtContact.setId(qwExternalContact.getId());
+                            qwExtContact.setFsUserId(fsUserId);
+                            qwExternalContactService.updateQwExternalContactBindUserId(qwExtContact);
+                        }
+                    }
+                } catch (Exception e) {
+                    return R.error("链接无效,请联系销售重新发送!");
+                }
+            }
+            return R.ok().put("data", data);
+        }
+        return R.error("链接无效,请联系销售重新发送!");
     }
 
     @Override
@@ -263,6 +335,47 @@ public class LiveServiceImpl implements ILiveService
         return baseMapper.selectLiveListNew(live);
     }
 
+    @Override
+    public R createAppLink(CompanyUser user, Long liveId, String corpId) {
+        if(user == null || user.getCompanyId() == null){
+            return R.error("销售账号请绑定销售公司");
+        }
+
+        if(corpId == null){
+            return R.error("请选择企微公司,方便判定客户归属!");
+        }
+
+        // 手动创建 FsCourseLink 对象,避免使用 BeanUtils.copyProperties
+        FsCourseLink link = new FsCourseLink();
+        link.setCompanyId(user.getCompanyId());
+        //link.setQwUserId(Long.valueOf(qwUserId));
+        link.setCompanyUserId(user.getUserId());
+        link.setLiveId(liveId);
+        link.setCorpId(corpId);
+        link.setUNo(UUID.randomUUID().toString());
+        String randomString = generateRandomStringWithLock();
+        if (StringUtil.strIsNullOrEmpty(randomString)) {
+            link.setLink(UUID.randomUUID().toString().replace("-", ""));
+        } else {
+            link.setLink(randomString);
+        }
+        link.setCreateTime(new Date());
+        FsCourseRealLink courseMap = new FsCourseRealLink();
+        org.springframework.beans.BeanUtils.copyProperties(link, courseMap);
+        String courseJson = JSON.toJSONString(link);
+        String realLinkFull = "/pages_live/livingList?link=" + courseJson;
+        link.setRealLink(realLinkFull);
+        //存短链-
+        fsCourseLinkMapper.insertFsCourseLink(link);
+
+        String sendShortLink = "/pages_live/livingList?link=" + link.getLink();
+
+        sendShortLink = sendShortLink.replace(".html","");
+        String InvitationCode = LinkUtil.encryptLink(sendShortLink);
+        log.info("真实链接为:{},发送的短链为:{}",realLinkFull, InvitationCode);
+        return R.ok().put("realLink","康好健康"+InvitationCode);
+    }
+
 
     /**
      * 查询直播

+ 1 - 1
fs-service/src/main/resources/application-config-druid-jsbk.yml

@@ -68,7 +68,7 @@ fs :
   h5CommonApi: http://172.16.16.4:8010
   jwt:
     # 加密秘钥
-    secret: f4y2x52034348j86b67cde581c0f5625
+    secret: f4y2x52034348j86b67cde58fcsf5625
     # token有效时长,7天,单位秒
     expire: 31536000
     header: AppToken

+ 14 - 1
fs-service/src/main/resources/mapper/crm/CrmCustomerAnalyzeMapper.xml

@@ -114,7 +114,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </update>
     <update id="updateCustomerPortrait">
         update crm_customer_analyze
-        set customer_portrait_json = #{customerPortrait}
+        <set>
+            <if test="customerPortraitJson != null and customerPortraitJson != ''">
+                customer_portrait_json = #{customerPortraitJson},
+            </if>
+            <if test="communicationSummary != null and communicationSummary != ''">
+                communication_summary = #{communicationSummary},
+            </if>
+            <if test="communicationAbstract != null and communicationAbstract != ''">
+                communication_abstract = #{communicationAbstract},
+            </if>
+            <if test="customerFocusJson != null and customerFocusJson != ''">
+                customer_focus_json = #{customerFocusJson},
+            </if>
+        </set>
         where customer_id = #{customerId}
         ORDER BY create_time DESC
         LIMIT 1

+ 3 - 1
fs-service/src/main/resources/mapper/crm/CrmCustomerMapper.xml

@@ -554,6 +554,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             id,customer_id,name,sex,age,address,habits,illness_time,body,study,course_status,course,family,family_disease,disease,is_line,
             talk,user_type,is_self,intensify,is_cold,cold_body,sweat,other,toilet,eat,menses,medicine,constitution,recommend_medicine,
             consult_product,is_buy,buy_product,create_time,update_time,reply_time,product_talk,disease_talk,channel_type
-        FROM crm_customer_info;
+        FROM crm_customer_info
+        where
+            customer_id = #{customerId};
     </select>
 </mapper>

+ 4 - 1
fs-service/src/main/resources/mapper/hisStore/FsStoreScrmMapper.xml

@@ -70,7 +70,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                drug_license_expiry_start,drug_license_expiry_end,medical_device1,medical_device1_expiry_start,medical_device1_expiry_end,
                medicalDevice2,medical_device2_expiry_start,medical_device2_expiry_end,medicalDevice3,medical_device3_expiry_start,
                medical_device3_expiry_end,food_license,food_license_expiry_start,food_license_expiry_end,medical_license,
-               medical_license_expiry_start,medical_license_expiry_end
+               medical_license_expiry_start,medical_license_expiry_end,other_special_qualification,other_special_qualification_start,other_special_qualification_end
         from fs_store_scrm
     </sql>
 
@@ -262,6 +262,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="medicalLicense !=null and medicalLicense !=''"> medical_license = #{medicalLicense} ,</if>
             <if test="medicalLicenseExpiryStart !=null "> medical_license_expiry_start = #{medicalLicenseExpiryStart} ,</if>
             <if test="medicalLicenseExpiryEnd !=null "> medical_license_expiry_end = #{medicalLicenseExpiryEnd} ,</if>
+            <if test="otherSpecialQualification !=null and otherSpecialQualification !=''"> other_special_qualification = #{otherSpecialQualification} ,</if>
+            <if test="otherSpecialQualificationStart !=null "> other_special_qualification_start = #{otherSpecialQualificationStart} ,</if>
+            <if test="otherSpecialQualificationEnd !=null "> other_special_qualification_end = #{otherSpecialQualificationEnd} ,</if>
         </trim>
         where store_id = #{storeId}
     </update>

+ 7 - 2
fs-service/src/main/resources/mapper/qw/QwExternalContactMapper.xml

@@ -820,8 +820,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             resultMap="QwExternalContactResult">
         <include refid="selectQwExternalContactVo"/>
         where corp_id = #{param.corpId} and external_user_id = #{param.externalUserId}
-        and company_user_id = #{param.companyUserId}
-        and user_id is not null and company_id is not null
+        <if test="param.companyUserId != null">
+            and company_user_id = #{param.companyUserId}
+        </if>
+        <if test="param.qwUserId != null">
+            and user_id = #{param.qwUserId}
+        </if>
+        and fs_user_id is not null and company_user_id is not null and qw_user_id is not null
         limit 1
     </select>
 </mapper>

+ 8 - 21
fs-user-app/src/main/java/com/fs/app/controller/InquiryOrderController.java

@@ -470,24 +470,11 @@ public class InquiryOrderController extends  AppBaseController {
     @PostMapping("/zfbPayment")
     public R zfbPayment(HttpServletRequest request, @Validated @RequestBody FsInquiryOrderDoPayParam param)
     {
-        param.setUserId(Long.parseLong(getUserId()));
         FsInquiryOrder order=inquiryOrderService.selectFsInquiryOrderByOrderId(param.getOrderId());
         FsUser user=userService.selectFsUserByUserId(Long.parseLong(getUserId()));
 
-        if (StringUtils.isBlank(param.getAppId())) {
-            throw new IllegalArgumentException("appId不能为空");
-        }
-        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigService.selectCoursePlaySourceConfigByAppId(param.getAppId());
-        if (fsCoursePlaySourceConfig == null) {
-            throw new CustomException("未找到appId对应的小程序配置: " + param.getAppId());
-        }
-        Long merchantConfigId = fsCoursePlaySourceConfig.getMerchantConfigId();
-        if (merchantConfigId == null || merchantConfigId <= 0) {
-            throw new CustomException("小程序没有配置商户信息");
-        }
-        MerchantAppConfig merchantAppConfig = merchantAppConfigService.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
-        FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
-//        PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
+        String json = configService.selectConfigByKey("his.pay");
+        PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
 
         String openId = null;
         String appId = param.getAppId();
@@ -501,7 +488,7 @@ public class InquiryOrderController extends  AppBaseController {
                 openId = fsUserWx.getOpenId();
             }
         } else {
-            appId = fsCoursePlaySourceConfig.getAppid();
+            appId = payConfigDTO.getAppId();
             openId = Objects.isNull(user) ? "" : user.getMaOpenId();
             if (StringUtils.isBlank(openId)){
                 Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
@@ -527,7 +514,7 @@ public class InquiryOrderController extends  AppBaseController {
 //            PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
             FsStorePayment storePayment=new FsStorePayment();
             storePayment.setStatus(0);
-            storePayment.setPayMode(merchantAppConfig.getMerchantType());
+            storePayment.setPayMode(payConfigDTO.getType());
             storePayment.setPayCode(payCode);
             storePayment.setCompanyId(order.getCompanyId());
             storePayment.setCompanyUserId(order.getCompanyUserId());
@@ -541,9 +528,9 @@ public class InquiryOrderController extends  AppBaseController {
             storePayment.setUserId(user.getUserId());
             storePayment.setBusinessId(order.getOrderId().toString());
             if(storePaymentService.insertFsStorePayment(storePayment)>0){
-                if (merchantAppConfig.getMerchantType().equals("yb")) {
+                if (payConfigDTO.getType().equals("yb")) {
                     return R.error("支付暂不可用!");
-                } else if (merchantAppConfig.getMerchantType().equals("tz")) {
+                } else if (payConfigDTO.getType().equals("tz")) {
                     PayCreateOrder o = new PayCreateOrder();
                     o.setOrderNo("inquiry" + storePayment.getPayCode()); // 业务系统订单号
                     o.setTrxAmt(storePayment.getPayMoney().doubleValue()); // 交易金额
@@ -563,7 +550,7 @@ public class InquiryOrderController extends  AppBaseController {
                     mt.setTradeNo(result.getBody().getOrderFlowNo());
                     storePaymentService.updateFsStorePayment(mt);
                     return R.ok().put("isPay", 0).put("data", result).put("type", "tz");
-                }else if (merchantAppConfig.getMerchantType().equals("hf")) {
+                }else if (payConfigDTO.getType().equals("hf")) {
                     HuiFuCreateOrder o = new HuiFuCreateOrder();
                     o.setTradeType("A_NATIVE");
                     o.setOpenid(openId);
@@ -574,7 +561,7 @@ public class InquiryOrderController extends  AppBaseController {
                     if (o.getAppId()!=null&& !o.getAppId().isEmpty()){
                         Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
                                 .eq(FsUserWx::getFsUserId, Long.parseLong(getUserId()))
-                                .eq(FsUserWx::getAppId, fsCoursePlaySourceConfig.getAppid());
+                                .eq(FsUserWx::getAppId, payConfigDTO.getAppId());
                         FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
                         if (fsUserWx!=null){
                             o.setOpenid(fsUserWx.getOpenId());

+ 3 - 1
fs-user-app/src/main/java/com/fs/app/controller/live/LiveController.java

@@ -426,10 +426,12 @@ public class LiveController extends AppBaseController {
 		return liveService.liveDecryptLink(param.getUrl());
 	}
 
+	@Login
 	@ApiOperation("解密链接参数")
 	@PostMapping("/decryptLink/v2")
 	public R decryptLinkV2(@RequestBody FsLiveEncryptLinkParam param) {
-		return liveService.liveDecryptLink(param.getUrl());
+		String userId = getUserId();
+		return liveService.liveDecryptLinkV2(param.getUrl(),userId);
 	}
 
 	@ApiOperation("获取微信小程序企微信息")

+ 0 - 20
fs-user-app/src/main/java/com/fs/app/controller/store/CompanyUserScrmController.java

@@ -275,26 +275,6 @@ public class CompanyUserScrmController extends AppBaseController {
         return R.ok().put("data",WxaCode);
     }
 
-    /**
-     * 济世百康功能,将companyUserId加密后发送给客户,后续添加绑定使用
-     * @param companyUserId
-     * @return
-     */
-    @ApiOperation("获取销售邀请码")
-    @GetMapping("/getCompanyUserInvitationCode")
-    public R getCompanyUserInvitationCode(@RequestParam("companyUserId")Long companyUserId){
-        if(companyUserId == null){
-            return R.error("请登陆账号后再试!");
-        }
-        CompanyUser companyUser = companyUserMapper.selectCompanyUserByUserId(companyUserId);
-        if (companyUser == null) {
-            return R.error("销售不存在,邀请码不合法");
-        }
-        String InvitationCode = PhoneUtil.encryptPhone(String.valueOf(companyUserId));
-        Map<String, Object> data = new HashMap<>();
-        data.put("InvitationCode", InvitationCode);
-        return R.ok().put("data",data);
-    }
 
 
     @ApiOperation("上传声纹")

+ 10 - 0
fs-user-app/src/main/java/com/fs/app/controller/store/StoreOrderScrmController.java

@@ -19,6 +19,7 @@ import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.ip.IpUtils;
 import com.fs.core.config.WxMaConfiguration;
 import com.fs.erp.service.IErpOrderService;
+import com.fs.his.param.FsStoreOrderDoPayParam;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.hisStore.config.FsErpConfig;
 import com.fs.hisStore.domain.*;
@@ -216,6 +217,15 @@ public class StoreOrderScrmController extends AppBaseController {
         return orderService.createOrder(Long.parseLong(getUserId()),param);
     }
 
+    @Login
+    @ApiOperation("支付宝支付")
+    @PostMapping("/zfbPayment")
+    public R zfbPayment(HttpServletRequest request, @Validated @RequestBody FsStoreOrderDoPayParam param)
+    {
+        param.setUserId(Long.parseLong(getUserId()));
+        return orderService.zfbPayment(param);
+    }
+
     @Login
     @ApiOperation("支付")
     @PostMapping("/pay")