|
@@ -0,0 +1,182 @@
|
|
|
+package com.fs.tulin;
|
|
|
+
|
|
|
+import cn.hutool.http.HttpRequest;
|
|
|
+import cn.hutool.http.HttpResponse;
|
|
|
+import cn.hutool.http.HttpUtil;
|
|
|
+import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
+
|
|
|
+import java.security.MessageDigest;
|
|
|
+import java.security.NoSuchAlgorithmException;
|
|
|
+import java.util.*;
|
|
|
+import java.util.logging.Logger;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @description:
|
|
|
+ * @author: Guos
|
|
|
+ * @time: 2025/10/21 下午3:40
|
|
|
+ */
|
|
|
+public class SyncStudentInfoService {
|
|
|
+
|
|
|
+
|
|
|
+ private static final Logger logger = Logger.getLogger(SyncStudentInfoService.class.getName());
|
|
|
+ /**
|
|
|
+ * 密钥
|
|
|
+ */
|
|
|
+ private static final String SECRET_KEY = "xysync_dLsSaheCzK7RU9gd";
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试药店ID
|
|
|
+ */
|
|
|
+ private static final String PHARMACY_ID = "26ee29ce-35aa-46c8-9650-3fe46014690c";
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试企业ID
|
|
|
+ */
|
|
|
+ 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);
|
|
|
+//第二种方式
|
|
|
+// 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 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param corpId 企业ID
|
|
|
+ * @param studentInfo 学生信息对象
|
|
|
+ * @return 请求结果
|
|
|
+ * @throws JsonProcessingException
|
|
|
+ */
|
|
|
+ public static String send(String corpId, StudentInfo studentInfo) throws JsonProcessingException {
|
|
|
+ String sortedJson = JsonSortUtils.toSortedJson(studentInfo);
|
|
|
+ long timestamp = generateTimestamp();
|
|
|
+ String sign = generateSign(corpId, 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", corpId);
|
|
|
+ request.put("data", Collections.singletonList(studentInfo));
|
|
|
+ String jsonBody = JsonSortUtils.toSortedJson(request);
|
|
|
+ return sendHttpPost(url, jsonBody);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送HTTP POST请求
|
|
|
+ * @param url 请求URL
|
|
|
+ * @param jsonBody 请求体JSON字符串
|
|
|
+ * @return 响应结果
|
|
|
+ */
|
|
|
+ private static String sendHttpPost(String url, String jsonBody) {
|
|
|
+ logger.info("云联学生信息同步接口");
|
|
|
+ logger.info("请求URL:"+ url);
|
|
|
+ logger.info("请求Body:"+ jsonBody);
|
|
|
+ HttpRequest httpRequest = HttpUtil.createPost(url);
|
|
|
+ httpRequest.header("Content-Type", "application/json");
|
|
|
+ httpRequest.body(jsonBody);
|
|
|
+ HttpResponse execute = httpRequest.execute();
|
|
|
+ String result = execute.body();
|
|
|
+ logger.info("请求结果:"+ result);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成签名,在这里去组装成数组的样子,然后进行MD5加密
|
|
|
+ * @param corpId 企业ID
|
|
|
+ * @param sortStr 请求体对象
|
|
|
+ * @param timestamp 时间戳(秒级)
|
|
|
+ * @return 32位小写MD5签名
|
|
|
+ */
|
|
|
+ private static String generateSign(String corpId, Object sortStr, long timestamp) {
|
|
|
+ try {
|
|
|
+ String signString = SECRET_KEY + corpId + "["+sortStr+"]" + timestamp;
|
|
|
+ return generateMD5(signString);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("生成签名失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成MD5哈希值
|
|
|
+ */
|
|
|
+ private static String generateMD5(String input) {
|
|
|
+ try {
|
|
|
+ MessageDigest md = MessageDigest.getInstance("MD5");
|
|
|
+ byte[] hash = md.digest(input.getBytes());
|
|
|
+ // 转换为16进制小写字符串
|
|
|
+ StringBuilder hexString = new StringBuilder();
|
|
|
+ for (byte b : hash) {
|
|
|
+ String hex = Integer.toHexString(0xff & b);
|
|
|
+ if (hex.length() == 1) {
|
|
|
+ hexString.append('0');
|
|
|
+ }
|
|
|
+ hexString.append(hex);
|
|
|
+ }
|
|
|
+ return hexString.toString();
|
|
|
+ } catch (NoSuchAlgorithmException e) {
|
|
|
+ throw new RuntimeException("MD5算法不可用", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成当前时间戳(秒级)
|
|
|
+ */
|
|
|
+ private static long generateTimestamp() {
|
|
|
+ return System.currentTimeMillis() / 1000;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|