|
|
@@ -9,21 +9,27 @@ import com.alibaba.fastjson.JSONObject;
|
|
|
import com.alibaba.fastjson.PropertyNamingStrategy;
|
|
|
import com.alibaba.fastjson.TypeReference;
|
|
|
import com.alibaba.fastjson.serializer.SerializeConfig;
|
|
|
+import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.fasterxml.jackson.databind.SerializationFeature;
|
|
|
import com.fs.erp.dto.*;
|
|
|
+import com.fs.erp.dto.tl.TlCreateOrderRequest;
|
|
|
+import com.fs.erp.dto.tl.TlCreateOrderResponse;
|
|
|
import com.fs.erp.service.impl.JstTokenService;
|
|
|
import com.fs.erp.utils.SignUtil;
|
|
|
import com.fs.ybPay.dto.RefundOrderDTO;
|
|
|
import com.hc.openapi.tool.util.ObjectUtils;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
//import org.apache.commons.lang3.ObjectUtils;
|
|
|
+import org.apache.commons.codec.digest.DigestUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.http.*;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.web.client.RestTemplate;
|
|
|
|
|
|
-import java.util.Arrays;
|
|
|
-import java.util.Collections;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.Map;
|
|
|
+import java.time.Instant;
|
|
|
+import java.util.*;
|
|
|
|
|
|
@Slf4j
|
|
|
@Service
|
|
|
@@ -53,12 +59,26 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
|
|
|
// */
|
|
|
// private static final String REFRESH_TOKEN_URL = BASE_URL + "openWebIsv/auth/refreshToken;
|
|
|
|
|
|
+
|
|
|
@Value("${jst.app_key:''}")
|
|
|
private String appKey;
|
|
|
|
|
|
@Value("${jst.app_secret:''}")
|
|
|
private String appSecret;
|
|
|
|
|
|
+
|
|
|
+ // 测试兔灵ERP
|
|
|
+ @Value("${jst.api.url:https://api.xiangyue.life/api}")
|
|
|
+ private String jstApiBaseUrl;
|
|
|
+
|
|
|
+ @Value("${jst.secret.key:xysync_dLsSaheCzK7RU9gd}")
|
|
|
+ private String secretKey;
|
|
|
+
|
|
|
+ private final RestTemplate restTemplate = new RestTemplate();
|
|
|
+ private final ObjectMapper objectMapper = new ObjectMapper()
|
|
|
+ .configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
|
|
|
+
|
|
|
+
|
|
|
@Autowired
|
|
|
private JstTokenService jstTokenService;
|
|
|
|
|
|
@@ -307,4 +327,106 @@ public class JstErpHttpServiceImpl implements JstErpHttpService {
|
|
|
log.info("API请求成功 - 结果: {}", JSON.toJSONString(commonResponse));
|
|
|
return commonResponse;
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public TlCreateOrderResponse syncOrderToJst(TlCreateOrderRequest request) {
|
|
|
+ try {
|
|
|
+ String corpId = request.getCorpId();
|
|
|
+ List<?> rawData = request.getData();
|
|
|
+
|
|
|
+ if (rawData == null || rawData.isEmpty()) {
|
|
|
+ throw new IllegalArgumentException("订单数据不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Map<String, Object>> dataAsMaps = new ArrayList<>();
|
|
|
+ for (Object item : rawData) {
|
|
|
+ Map<String, Object> map = objectMapper.convertValue(item, Map.class);
|
|
|
+ dataAsMaps.add(map);
|
|
|
+ }
|
|
|
+
|
|
|
+ long timestamp = Instant.now().getEpochSecond();
|
|
|
+ String sortedDataJson = sortAndSerializeData(dataAsMaps);
|
|
|
+
|
|
|
+ String signSource = secretKey + corpId + sortedDataJson + timestamp;
|
|
|
+ String sign = DigestUtils.md5Hex(signSource).toLowerCase();
|
|
|
+
|
|
|
+ // 构建 URL
|
|
|
+ String url = jstApiBaseUrl + "/v1/mp/sync/order/jst/create?sign=" + sign + "&t=" + timestamp;
|
|
|
+
|
|
|
+ // 请求体
|
|
|
+ String requestBody = objectMapper.writeValueAsString(request);
|
|
|
+
|
|
|
+ //打印关键调试信息
|
|
|
+ log.info("【聚水潭】请求URL: {}", url);
|
|
|
+ log.info("【聚水潭】请求Body: {}", requestBody);
|
|
|
+ log.info("【聚水潭】sign = MD5({})", signSource);
|
|
|
+ log.info("【聚水潭】最终 sign: {}, t: {}", sign, timestamp);
|
|
|
+
|
|
|
+ // 发起请求
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.setContentType(MediaType.APPLICATION_JSON);
|
|
|
+ HttpEntity<String> entity = new HttpEntity<>(requestBody, headers);
|
|
|
+
|
|
|
+ ResponseEntity<TlCreateOrderResponse> response = restTemplate.exchange(
|
|
|
+ url,
|
|
|
+ HttpMethod.POST,
|
|
|
+ entity,
|
|
|
+ TlCreateOrderResponse.class
|
|
|
+ );
|
|
|
+
|
|
|
+ log.info("【聚水潭】响应状态: {}, body: {}", response.getStatusCode(), response.getBody());
|
|
|
+ if (response.getStatusCode() == HttpStatus.OK) {
|
|
|
+ log.info("订单同步成功");
|
|
|
+ }else {
|
|
|
+ log.error("订单同步失败:{}", response);
|
|
|
+ throw new RuntimeException("订单同步失败");
|
|
|
+ }
|
|
|
+ return response.getBody();
|
|
|
+
|
|
|
+ } catch (JsonProcessingException e) {
|
|
|
+ log.error("JSON 序列化失败", e);
|
|
|
+ throw new RuntimeException("订单数据格式异常", e);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("调用同步聚水潭订单接口失败", e);
|
|
|
+ throw new RuntimeException("同步订单到聚水潭失败: " + e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 递归对 Map 进行按键升序排序(支持嵌套 Map 和 List)
|
|
|
+ */
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ private Object deepSort(Object obj) {
|
|
|
+ if (obj instanceof Map) {
|
|
|
+ Map<String, Object> map = (Map<String, Object>) obj;
|
|
|
+ TreeMap<String, Object> sortedMap = new TreeMap<>();
|
|
|
+ for (Map.Entry<String, Object> entry : map.entrySet()) {
|
|
|
+ sortedMap.put(entry.getKey(), deepSort(entry.getValue()));
|
|
|
+ }
|
|
|
+ return sortedMap;
|
|
|
+ } else if (obj instanceof List) {
|
|
|
+ List<?> list = (List<?>) obj;
|
|
|
+ List<Object> sortedList = new ArrayList<>();
|
|
|
+ for (Object item : list) {
|
|
|
+ sortedList.add(deepSort(item));
|
|
|
+ }
|
|
|
+ return sortedList;
|
|
|
+ } else {
|
|
|
+ return obj; // 基本类型、String、Number 等直接返回
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对 data 列表进行深度排序并序列化为紧凑 JSON(无空格)
|
|
|
+ */
|
|
|
+ private String sortAndSerializeData(List<Map<String, Object>> data) throws JsonProcessingException {
|
|
|
+ if (data == null || data.isEmpty()) {
|
|
|
+ return "[]";
|
|
|
+ }
|
|
|
+ List<Object> sortedList = new ArrayList<>();
|
|
|
+ for (Map<String, Object> item : data) {
|
|
|
+ sortedList.add(deepSort(item));
|
|
|
+ }
|
|
|
+ return objectMapper.writeValueAsString(sortedList);
|
|
|
+ }
|
|
|
}
|