Browse Source

tulin线上信息同步

Guos 14 hours ago
parent
commit
d983b724f7

+ 27 - 0
fs-admin/src/main/java/com/fs/task/SgTestController.java

@@ -0,0 +1,27 @@
+package com.fs.task;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/10/23 下午2:18
+ */
+@RestController
+@RequestMapping("/sg/test")
+public class SgTestController {
+
+    @Resource
+    private SyncTuLinStudentInfoTask syncTuLinStudentInfoTask;
+
+
+    @RequestMapping("/execute")
+    public void execute(){
+        syncTuLinStudentInfoTask.execute();
+    }
+
+
+}

+ 27 - 0
fs-admin/src/main/java/com/fs/task/SyncTuLinStudentInfoTask.java

@@ -0,0 +1,27 @@
+package com.fs.task;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fs.tulin.service.ITulinInfoSyncLogService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * @description: 同步TuLin学生信息定时任务
+ * @author: Guos
+ * @time: 2025/10/23 上午10:26
+ */
+@AllArgsConstructor
+@Component("syncTuLinStudentInfoTask")
+public class SyncTuLinStudentInfoTask {
+
+
+    @Resource
+    private final ITulinInfoSyncLogService tulinInfoSyncLogService;
+
+    public void execute() {
+        tulinInfoSyncLogService.syncInfo();
+    }
+
+}

+ 77 - 0
fs-service/src/main/java/com/fs/tulin/entity/QwExUserInfo.java

@@ -0,0 +1,77 @@
+package com.fs.tulin.entity;
+
+import lombok.Data;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/10/23 下午3:08
+ */
+@Data
+public class QwExUserInfo {
+
+
+    private Long fs_user_id;
+
+    /**
+     * 必填 union_id
+     * 小程序union_id
+     */
+    private String union_id;
+
+    /**
+     * 必填 open_id
+     * 小程序open_id
+     */
+    private String open_id;
+
+    /**
+     * 必填 appid
+     * 微信小程序appid
+     */
+    private String appid;
+
+    /**
+     * 必填 nickname
+     * 昵称
+     */
+    private String nickname;
+
+    /**
+     * 必填 column_name
+     * 栏目名称
+     */
+    private String column_name;
+
+    /**
+     * 必填 pharmacy_id
+     * 药店ID
+     */
+    private String pharmacy_id;
+
+    /**
+     * 必填 service_phone
+     * 客服手机号
+     */
+    private String service_phone;
+
+    /**
+     * 可选 period_name
+     * 学员所属期名称(可选)
+     */
+    private String period_name;
+
+    /**
+     * 可选 name
+     * 学员名称(可选)
+     */
+    private String name;
+
+    /**
+     * 可选 avatar
+     * 学员头像 (可选)
+     */
+    private String avatar;
+
+
+}

+ 5 - 5
fs-service/src/main/java/com/fs/tulin/StudentInfo.java → fs-service/src/main/java/com/fs/tulin/entity/StudentInfo.java

@@ -1,11 +1,9 @@
-package com.fs.tulin;
+package com.fs.tulin.entity;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.ToString;
+import lombok.*;
 
 /**
  * @description:
@@ -16,6 +14,8 @@ import lombok.ToString;
 @Getter
 @Builder
 @ToString
+@NoArgsConstructor
+@AllArgsConstructor
 @JsonPropertyOrder(alphabetic = true)
 @JsonInclude(JsonInclude.Include.NON_NULL)
 public class StudentInfo {

+ 48 - 0
fs-service/src/main/java/com/fs/tulin/entity/TulinInfoSyncLog.java

@@ -0,0 +1,48 @@
+package com.fs.tulin.entity;
+
+/**
+ * @description: 信息同步实体类
+ * @author: Guos
+ * @time: 2025/10/23 下午1:04
+ */
+import java.util.Date;
+import lombok.Data;
+
+@Data
+public class TulinInfoSyncLog {
+    /**
+     * fs_user表的user_id
+     */
+    private Long fsUserId;
+
+    /**
+     * 请求的url
+     */
+    private String requestUrl;
+
+    /**
+     * 请求体
+     */
+    private String sendBody;
+
+    /**
+     * 请求返回结果体
+     */
+    private String resultBody;
+
+    /**
+     * 是否成功:1成功、0失败
+     */
+    private Integer result;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+}
+

+ 50 - 0
fs-service/src/main/java/com/fs/tulin/mapper/TulinInfoSyncLogMapper.java

@@ -0,0 +1,50 @@
+package com.fs.tulin.mapper;
+
+import com.fs.tulin.entity.QwExUserInfo;
+import com.fs.tulin.entity.StudentInfo;
+import com.fs.tulin.entity.TulinInfoSyncLog;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * @description: 信息同步Mapper
+ * @author: Guos
+ * @time: 2025/10/23 上午11:45
+ */
+@Mapper
+public interface TulinInfoSyncLogMapper {
+
+
+    /**
+     * 插入记录
+     */
+    int insert(TulinInfoSyncLog record);
+
+    /**
+     * 根据主键更新记录
+     */
+    int updateByPrimaryKey(TulinInfoSyncLog record);
+
+    /**
+     * 根据主键删除记录
+     */
+    int deleteByPrimaryKey(@Param("fsUserId") Long fsUserId);
+
+    /**
+     * 根据主键查询记录
+     */
+    TulinInfoSyncLog selectByPrimaryKey(@Param("fsUserId") Long fsUserId);
+
+    /**
+     * 查询所有记录
+     */
+    List<TulinInfoSyncLog> selectAll();
+
+    /**
+     * 查询学生信息
+     */
+    List<QwExUserInfo> selectStudentInfo();
+
+}

+ 20 - 0
fs-service/src/main/java/com/fs/tulin/service/ITulinInfoSyncLogService.java

@@ -0,0 +1,20 @@
+package com.fs.tulin.service;
+
+import com.fs.tulin.entity.TulinInfoSyncLog;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/10/23 上午11:44
+ */
+public interface ITulinInfoSyncLogService {
+
+    /**
+     * 同步信息
+     */
+    void syncInfo();
+
+    Integer insert(TulinInfoSyncLog record);
+
+
+}

+ 95 - 0
fs-service/src/main/java/com/fs/tulin/service/impl/TulinInfoSyncLogServiceImpl.java

@@ -0,0 +1,95 @@
+package com.fs.tulin.service.impl;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fs.tulin.entity.QwExUserInfo;
+import com.fs.tulin.entity.StudentInfo;
+import com.fs.tulin.entity.TulinInfoSyncLog;
+import com.fs.tulin.mapper.TulinInfoSyncLogMapper;
+import com.fs.tulin.service.ITulinInfoSyncLogService;
+import com.fs.tulin.utils.ColumnNameEnum;
+import com.fs.tulin.utils.PharmacyEnum;
+import com.fs.tulin.utils.SyncStudentInfoService;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @description: 信息同步Service
+ * @author: Guos
+ * @time: 2025/10/23 上午11:44
+ */
+@Slf4j
+@Service
+@AllArgsConstructor
+public class TulinInfoSyncLogServiceImpl implements ITulinInfoSyncLogService {
+
+    @Resource
+    private TulinInfoSyncLogMapper tulinInfoSyncLogMapper;
+
+    private final Environment environment;
+
+    @Override
+    public void syncInfo() {
+        // 获取当前激活的profile
+        String activeProfile = "dev";
+        String[] activeProfiles = environment.getActiveProfiles();
+        if (activeProfiles.length > 0) {
+            activeProfile = activeProfiles[0];
+        }
+        log.info("当前环境:{}", activeProfile);
+        List<QwExUserInfo> qwExUserInfos = tulinInfoSyncLogMapper.selectStudentInfo();
+        if(!activeProfile.equals("dev")){
+            log.info("线上开始执行数据同步");
+            for (QwExUserInfo qwExUserInfo : qwExUserInfos) {
+                StudentInfo studentInfo = new StudentInfo();
+                BeanUtils.copyProperties(qwExUserInfo, studentInfo);
+                studentInfo.setAppid("wx6688e6b9b6fb8700");
+                studentInfo.setColumn_name(ColumnNameEnum.GYBNX.getName());
+                studentInfo.setPharmacy_id(PharmacyEnum.YJKYSY.getPharmacyId());
+                try {
+                    TulinInfoSyncLog tulinInfoSyncLog = SyncStudentInfoService.send("PNBnO6MajM0tAd8t", studentInfo);
+                    tulinInfoSyncLog.setFsUserId(qwExUserInfo.getFs_user_id());
+                    insert(tulinInfoSyncLog);
+                } catch (JsonProcessingException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+//        if(activeProfile.equals("dev")) {
+//            log.info("线下开始执行数据同步");
+//            for (QwExUserInfo qwExUserInfo : qwExUserInfos) {
+//                StudentInfo studentInfo = new StudentInfo();
+//                BeanUtils.copyProperties(qwExUserInfo, studentInfo);
+//                studentInfo.setAppid("wx6688e6b9b6fb8700");
+//                studentInfo.setColumn_name(ColumnNameEnum.GYBNX.getName());
+//                studentInfo.setPharmacy_id(PharmacyEnum.YJKYSY.getPharmacyId());
+//                try {
+//                    TulinInfoSyncLog tulinInfoSyncLog = SyncStudentInfoService.send("PNBnO6MajM0tAd8t", studentInfo);
+//                    tulinInfoSyncLog.setFsUserId(qwExUserInfo.getFs_user_id());
+//                    insert(tulinInfoSyncLog);
+//                } catch (JsonProcessingException e) {
+//                    throw new RuntimeException(e);
+//                }
+//            }
+//        }
+    }
+
+
+    @Override
+    public Integer insert(TulinInfoSyncLog tulinInfoSyncLog) {
+        TulinInfoSyncLog oldObj = tulinInfoSyncLogMapper.selectByPrimaryKey(tulinInfoSyncLog.getFsUserId());
+        if(ObjectUtils.isEmpty(oldObj)){
+            return tulinInfoSyncLogMapper.insert(tulinInfoSyncLog);
+        }else {
+            tulinInfoSyncLog.setUpdateTime(new Date());
+            return tulinInfoSyncLogMapper.updateByPrimaryKey(tulinInfoSyncLog);
+        }
+    }
+}

+ 36 - 0
fs-service/src/main/java/com/fs/tulin/utils/ColumnNameEnum.java

@@ -0,0 +1,36 @@
+package com.fs.tulin.utils;
+
+/**
+ * @description:
+ * @author: Guos
+ * @time: 2025/10/23 上午11:19
+ */
+public enum ColumnNameEnum {
+
+    YYJD("医言九鼎","正式", "prod"),
+    GYBNX("国医伴你行","正式", "prod"),
+    CSLM("测试栏目0921","测试", "dev");
+
+    private String name;
+
+    private String description;
+
+    private String useEnvironment;
+
+    ColumnNameEnum(String name, String description, String useEnvironment){
+        this.name = name;
+        this.description = description;
+        this.useEnvironment = useEnvironment;
+    }
+    public String getName() {
+        return this.name;
+    }
+
+    public String getDescription() {
+        return this.description;
+    }
+
+    public String getUseEnvironment() {
+        return this.useEnvironment;
+    }
+}

+ 1 - 1
fs-service/src/main/java/com/fs/tulin/JsonSortUtils.java → fs-service/src/main/java/com/fs/tulin/utils/JsonSortUtils.java

@@ -1,4 +1,4 @@
-package com.fs.tulin;
+package com.fs.tulin.utils;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 

+ 1 - 1
fs-service/src/main/java/com/fs/tulin/PharmacyEnum.java → fs-service/src/main/java/com/fs/tulin/utils/PharmacyEnum.java

@@ -1,4 +1,4 @@
-package com.fs.tulin;
+package com.fs.tulin.utils;
 
 /**
  * @description: 这个后面要放到数据库去方便动态添加

+ 26 - 59
fs-service/src/main/java/com/fs/tulin/SyncStudentInfoService.java → fs-service/src/main/java/com/fs/tulin/utils/SyncStudentInfoService.java

@@ -1,9 +1,11 @@
-package com.fs.tulin;
+package com.fs.tulin.utils;
 
 import cn.hutool.http.HttpRequest;
 import cn.hutool.http.HttpResponse;
 import cn.hutool.http.HttpUtil;
 import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fs.tulin.entity.StudentInfo;
+import com.fs.tulin.entity.TulinInfoSyncLog;
 
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -12,6 +14,9 @@ import java.util.logging.Logger;
 
 /**
  * @description:
+ * 正确与错误返回结果示例:
+ * {"data":{"status":"ok","err_msg":"","execute_log":[***]}
+ * {"msg":"******","code":*****}
  * @author: Guos
  * @time: 2025/10/21 下午3:40
  */
@@ -34,39 +39,7 @@ public class SyncStudentInfoService {
      */
     private static final String CORP_ID = "PNBnO6MajM0tAd8t";
 
-
-    public static void main(String[] args) throws JsonProcessingException {
-//第一种方式
-//        Map<String, Object> requestBody = new HashMap<>();
-//        requestBody.put("corp_id", "PNBnO6MajM0tAd8t");
-//        List<Map<String, Object>> dataList = new ArrayList<>();
-//        Map<String, Object> dataItem = new HashMap<>();
-//        dataItem.put("union_id", "oLH_O648dcNgoZdQT4CN2Qft8i7k");
-//        dataItem.put("open_id", "ozzk-19AxQC5D3X9Wqpb-I3_Y3EQ");
-//        dataItem.put("appid", "wx6688e6b9b6fb8700");
-//        dataItem.put("nickname", "@冰阔落");
-//        dataItem.put("column_name", "测试栏目0921");
-//        dataItem.put("pharmacy_id", "26ee29ce-35aa-46c8-9650-3fe46014690c");
-//        dataItem.put("service_phone", "13760648472");
-//        dataList.add(dataItem);
-//        String sort = sortRequestBody(dataItem);
-//        requestBody.put("data", dataList);
-//      // 生成签名
-//        long timestamp = generateTimestamp();
-//        String sign = generateSign("PNBnO6MajM0tAd8t", sort, timestamp);
-//        System.out.println("时间戳: " + timestamp);
-//        System.out.println("签名: " + sign);
-//        // 构建完整的请求URL          "https://api.xiangyue.life/api/v1/mp/sync/student
-//        String url = String.format("https://api.xiangyue.life/api/v1/mp/sync/student?sign=%s&t=%d", sign, timestamp);
-//        HttpRequest httpRequest = HttpUtil.createPost(url);
-//        httpRequest.header("Content-Type", "application/json");
-//        System.out.println("url: " + url);
-//        System.out.println("排序后的"+sortRequestBody(requestBody));
-//        httpRequest.body(sortRequestBody(requestBody));
-//        HttpResponse execute = httpRequest.execute();
-//        String body = execute.body();
-//        System.out.println("响应结果: " + body);
-//第二种方式
+//    public static void main(String[] args) throws JsonProcessingException {
 //        StudentInfo student = StudentInfo.builder()
 //                .union_id("oLH_O648dcNgoZdQT4CN2Qft8i7k")
 //                .open_id("ozzk-19AxQC5D3X9Wqpb-I3_Y3EQ")
@@ -74,28 +47,8 @@ public class SyncStudentInfoService {
 //                .nickname("@冰阔落")
 //                .column_name("测试栏目0921")
 //                .pharmacy_id(PHARMACY_ID).service_phone("13760648472").build();
-//        //排序
-//        String sortedJson = JsonSortUtils.toSortedJson(student);
-//        long timestamp = generateTimestamp();
-//        String sign = generateSign(CORP_ID, sortedJson, timestamp);
-//        String url = String.format("https://api.xiangyue.life/api/v1/mp/sync/student?sign=%s&t=%d", sign, timestamp);
-//        Map<String, Object> request = new HashMap<>();
-//        request.put("corp_id", CORP_ID);
-//        request.put("data", Collections.singletonList(student));
-//        String jsonBody = mapper.writeValueAsString(request);
-//        System.out.println("正确JSON:");
-//        System.out.println(jsonBody);
-//        sendHttpPost(url, jsonBody);
-
-        StudentInfo student = StudentInfo.builder()
-                .union_id("oLH_O648dcNgoZdQT4CN2Qft8i7k")
-                .open_id("ozzk-19AxQC5D3X9Wqpb-I3_Y3EQ")
-                .appid("wx6688e6b9b6fb8700")
-                .nickname("@冰阔落")
-                .column_name("测试栏目0921")
-                .pharmacy_id(PHARMACY_ID).service_phone("13760648472").build();
-        String result = send(CORP_ID, student);
-    }
+//        String result = send(CORP_ID, student);
+//    }
 
     /**
      * @param corpId 企业ID
@@ -103,7 +56,7 @@ public class SyncStudentInfoService {
      * @return 请求结果
      * @throws JsonProcessingException
      */
-    public static String send(String corpId, StudentInfo studentInfo) throws JsonProcessingException {
+    public static TulinInfoSyncLog send(String corpId, StudentInfo studentInfo) throws JsonProcessingException {
         String sortedJson = JsonSortUtils.toSortedJson(studentInfo);
         long timestamp = generateTimestamp();
         String sign = generateSign(corpId, sortedJson, timestamp);
@@ -121,7 +74,7 @@ public class SyncStudentInfoService {
      * @param jsonBody 请求体JSON字符串
      * @return 响应结果
      */
-    private static String sendHttpPost(String url, String jsonBody) {
+    private static TulinInfoSyncLog sendHttpPost(String url, String jsonBody) {
         logger.info("云联学生信息同步接口");
         logger.info("请求URL:"+ url);
         logger.info("请求Body:"+ jsonBody);
@@ -131,7 +84,14 @@ public class SyncStudentInfoService {
         HttpResponse execute = httpRequest.execute();
         String result = execute.body();
         logger.info("请求结果:"+ result);
-        return result;
+        TulinInfoSyncLog tulinInfoSyncLog = new TulinInfoSyncLog();
+        tulinInfoSyncLog.setRequestUrl(url);
+        tulinInfoSyncLog.setResultBody(result);
+        tulinInfoSyncLog.setCreateTime(new Date());
+        tulinInfoSyncLog.setUpdateTime(new Date());
+        tulinInfoSyncLog.setSendBody(jsonBody);
+        tulinInfoSyncLog.setResult(containsOk(result));
+        return tulinInfoSyncLog;
     }
 
     /**
@@ -179,4 +139,11 @@ public class SyncStudentInfoService {
         return System.currentTimeMillis() / 1000;
     }
 
+    /**
+     * 判断结果是否成功
+     */
+    private static int containsOk(String resultStr) {
+        return resultStr.contains("ok")? 1 : 0;
+    }
+
 }

+ 82 - 0
fs-service/src/main/resources/mapper/tulin/TulinInfoSyncLogMapper.xml

@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.tulin.mapper.TulinInfoSyncLogMapper">
+
+    <resultMap id="BaseResultMap" type="com.fs.tulin.entity.TulinInfoSyncLog">
+        <id column="fs_user_id" property="fsUserId" />
+        <result column="request_url" property="requestUrl" />
+        <result column="send_body" property="sendBody" />
+        <result column="result_body" property="resultBody" />
+        <result column="result" property="result" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        fs_user_id, request_url, send_body, result_body, result, create_time, update_time
+    </sql>
+
+    <select id="selectByPrimaryKey" parameterType="long" resultMap="BaseResultMap">
+        SELECT <include refid="Base_Column_List" />
+        FROM tulin_info_sync_log
+        WHERE fs_user_id = #{fsUserId}
+    </select>
+
+    <insert id="insert" parameterType="com.fs.tulin.entity.TulinInfoSyncLog">
+        INSERT INTO tulin_info_sync_log
+        (fs_user_id, request_url, send_body, result_body, result, create_time, update_time)
+        VALUES
+            (#{fsUserId}, #{requestUrl}, #{sendBody}, #{resultBody}, #{result}, #{createTime}, #{updateTime})
+    </insert>
+
+    <update id="updateByPrimaryKey" parameterType="com.fs.tulin.entity.TulinInfoSyncLog">
+        UPDATE tulin_info_sync_log
+        SET
+            request_url = #{requestUrl},
+            send_body = #{sendBody},
+            result_body = #{resultBody},
+            result = #{result},
+            update_time = #{updateTime}
+        WHERE fs_user_id = #{fsUserId}
+    </update>
+
+    <delete id="deleteByPrimaryKey" parameterType="long">
+        DELETE FROM tulin_info_sync_log
+        WHERE fs_user_id = #{fsUserId}
+    </delete>
+
+    <select id="selectAll" resultMap="BaseResultMap">
+        SELECT <include refid="Base_Column_List" />
+        FROM tulin_info_sync_log
+    </select>
+
+    <resultMap id="selectStudentInfoMap" type="com.fs.tulin.entity.QwExUserInfo">
+        <id column="fs_user_id" property="fs_user_id" />
+        <result column="nickname" property="nickname" />
+        <result column="service_phone" property="service_phone" />
+        <result column="union_id" property="union_id" />
+        <result column="open_id" property="open_id" />
+        <result column="avatar" property="avatar" />
+        <result column="name" property="name" />
+    </resultMap>
+
+    <select id="selectStudentInfo" resultMap="selectStudentInfoMap">
+        SELECT
+            fu.user_id as fs_user_id,
+            fu.nick_name as nickname,
+            fu.phone as service_phone,
+            fu.union_id as union_id,
+            fu.ma_open_id as open_id,
+            fu.avatar as avatar,
+            qec.name as name
+        FROM qw_user AS qu
+        INNER JOIN qw_external_contact AS qec ON qu.id = qec.qw_user_id
+        inner join fs_user as fu on fu.qw_ext_id = qec.id
+        left join tulin_info_sync_log as tisl on tisl.fs_user_id = fu.user_id
+        where fu.union_id is not null and fu.ma_open_id is not null
+        and tisl.result = 0
+    </select>
+
+</mapper>

+ 8 - 0
fs-service/src/test/java/com/fs/his/service/impl/FsUserServiceImplTest.java

@@ -1,9 +1,17 @@
 package com.fs.his.service.impl;
 
 
+import com.fs.tulin.service.ITulinInfoSyncLogService;
+
+import javax.annotation.Resource;
+
 class FsUserServiceImplTest {
 
+    @Resource
+    private ITulinInfoSyncLogService tulinInfoSyncLogService;
+
 
     void selectFsUserPageListNew() {
+        tulinInfoSyncLogService.syncInfo();
     }
 }