Merge remote-tracking branch 'origin/cc_20250325_select' into cc_20250325_select

# Conflicts:
#	coolstore-partner-web/src/main/java/com/cool/store/controller/webb/PCTestController.java
This commit is contained in:
苏竹红
2025-04-11 16:14:42 +08:00
12 changed files with 249 additions and 17 deletions

View File

@@ -2,8 +2,11 @@ package com.cool.store.service;
import com.cool.store.dto.GetAccessTokenDTO;
import com.cool.store.dto.ModifyPasswordDTO;
import com.cool.store.dto.XgjOrganizationDTO;
import com.cool.store.request.ZxjpApiRequest;
import java.util.List;
/**
* @Author suzhuhong
* @Date 2025/4/9 14:23
@@ -55,6 +58,7 @@ public interface PushService {
*/
String getPosToken(GetAccessTokenDTO dto);
List<XgjOrganizationDTO> getXgjOrganization(String partnerId);

View File

@@ -3,14 +3,20 @@ package com.cool.store.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.cool.store.dto.GetAccessTokenDTO;
import com.cool.store.dto.ModifyPasswordDTO;
import com.cool.store.dto.XgjOrganizationDTO;
import com.cool.store.enums.ErrorCodeEnum;
import com.cool.store.exception.ServiceException;
import com.cool.store.request.ZxjpApiRequest;
import com.cool.store.response.XgjBaseResponse;
import com.cool.store.response.XgjOrganizationResponse;
import com.cool.store.response.huoma.ShopBaseInfoResponse;
import com.cool.store.response.oppty.OpportunityApiResponse;
import com.cool.store.service.PushService;
import com.cool.store.utils.HmacSigner;
import com.cool.store.utils.RedisUtilPool;
import com.cool.store.utils.poi.StringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
@@ -19,7 +25,12 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @Author suzhuhong
@@ -32,6 +43,9 @@ public class PushServiceImpl implements PushService {
// TODO: 2025/4/9 suzhuhong_
@Value("${spring.profiles.active}")
private String active;
@Value("${api.auth.url}")
private String url;
@@ -74,27 +88,39 @@ public class PushServiceImpl implements PushService {
ObjectMapper objectMapper;
@Value("${xgj.open.organization.X-key}")
private String xgjOpenOrganizationXKey;
@Value("${xgj.open.organization.X-Secret}")
private String xgjOpenOrganizationXSecret;
@Value("${xgj.open.organization.url}")
private String xgjOpenOrganizationUrl;
@Resource
private RedisUtilPool redisUtilPool;
@Value("${mybatis.configuration.variables.enterpriseId}")
private String eid;
@Override
public Boolean pushDataToXGJ(ZxjpApiRequest zxjpApiRequest) {
String apiUrl = xgjUrl + "XXX";
return executeApiCall(apiUrl,zxjpApiRequest, Boolean.class,xgjUsername,xgjSecret);
return executeApiCall(apiUrl, zxjpApiRequest, Boolean.class, xgjUsername, xgjSecret);
}
@Override
public Boolean pushDataToPOS(ZxjpApiRequest zxjpApiRequest) {
String apiUrl = url + "/dzgV1/zxcrm/shop/upsert";
return executeApiCall(apiUrl,zxjpApiRequest, Boolean.class,username,secret);
return executeApiCall(apiUrl, zxjpApiRequest, Boolean.class, username, secret);
}
private Boolean modifyXGJPassword(ModifyPasswordDTO dto) {
String apiUrl = xgjUrl + "XXX";
return executeApiCall(apiUrl,dto, Boolean.class,xgjUsername,xgjSecret);
return executeApiCall(apiUrl, dto, Boolean.class, xgjUsername, xgjSecret);
}
private Boolean modifyPosPassword(ModifyPasswordDTO dto) {
private Boolean modifyPosPassword(ModifyPasswordDTO dto) {
String apiUrl = url + "/dzgV1/zxcrm/business_user/modifyPassword";
return executeApiCall(apiUrl,dto, Boolean.class,username,secret);
return executeApiCall(apiUrl, dto, Boolean.class, username, secret);
}
@@ -112,28 +138,56 @@ public class PushServiceImpl implements PushService {
@Override
public String getYlsToken(GetAccessTokenDTO dto) {
String apiUrl = url + "XXX";
return executeApiCall(apiUrl,dto, String.class,ylsUsername,ylsSecret);
return executeApiCall(apiUrl, dto, String.class, ylsUsername, ylsSecret);
}
@Override
public String getXzgToken(GetAccessTokenDTO dto) {
String apiUrl = url + "XXX";
return executeApiCall(apiUrl,dto, String.class,xzgUsername,xzgSecret);
return executeApiCall(apiUrl, dto, String.class, xzgUsername, xzgSecret);
}
@Override
public String getPosToken(GetAccessTokenDTO dto) {
String apiUrl = url + "/dzgV1/zxcrm/business_user/generateToken";
return executeApiCall(apiUrl,dto, String.class,username,secret);
return executeApiCall(apiUrl, dto, String.class, username, secret);
}
@Override
public List<XgjOrganizationDTO> getXgjOrganization(String partnerId) {
String key = active+"_XgjOrganization_" + eid;
String resObject = redisUtilPool.getString(key);
if (StringUtils.isBlank(resObject)) {
String apiUrl = xgjOpenOrganizationUrl + "/open/organization";
resObject = JSONObject.toJSONString(executeApiGetCall(apiUrl, null, Object.class, xgjOpenOrganizationXKey, xgjOpenOrganizationXSecret));
redisUtilPool.setNxExpire(key, resObject, 7200000);
}
List<XgjOrganizationDTO> response = new ArrayList<>();
if (StringUtils.isNotBlank(resObject)) {
// 使用 Jackson 将 Object 转换为目标类型
ObjectMapper objectMapper = new ObjectMapper();
try {
response = objectMapper.readValue(resObject, new TypeReference<List<XgjOrganizationDTO>>() {
});
} catch (JsonProcessingException e) {
throw new ServiceException("数据类型转化异常: " + e.getMessage());
}
}
List<XgjOrganizationDTO> filteredList = response.stream()
.filter(customer -> customer.getParentId().equals(partnerId))
.collect(Collectors.toList());
return filteredList;
}
private <T> T executeApiCall(String url, Object requestBody, Class<T> responseType,String username,String secret) {
private <T> T executeApiCall(String url, Object requestBody, Class<T> responseType, String username, String secret) {
// 1. 打印请求前日志
logRequest(url, requestBody);
try {
Request request = buildRequest(requestBody, url,username,secret);
Request request = buildRequest(requestBody, url, username, secret);
try (Response response = okHttpClient.newCall(request).execute()) {
// 2. 获取原始响应内容
@@ -218,7 +272,7 @@ public class PushServiceImpl implements PushService {
}
private Request buildRequest(Object requestBody, String url,String username,String secret) {
private Request buildRequest(Object requestBody, String url, String username, String secret) {
try {
Map<String, String> authHeaders = HmacSigner.generateHeaders(
@@ -244,8 +298,113 @@ public class PushServiceImpl implements PushService {
}
}
private <T> T executeApiGetCall(String url, Map<String, Object> requestParams, Class<T> responseType, String username, String secret) {
//1.处理请求参数
String buildUrlWithParams = buildUrlWithParams(url, requestParams);
// 2. 打印请求前日志
logRequest(buildUrlWithParams, requestParams);
try {
Request request = buildGetRequest(url, username, secret);
try (Response response = okHttpClient.newCall(request).execute()) {
// 2. 获取原始响应内容
String responseBody = null;
if (response.body() != null) {
responseBody = response.body().string();
}
// 3. 打印响应日志
logResponse(url, response.code(), responseBody);
if (!response.isSuccessful()) {
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,
"HTTP请求失败状态码: " + response.code());
}
// 4. 解析响应
JavaType javaType = objectMapper.getTypeFactory()
.constructParametricType(XgjBaseResponse.class, responseType);
XgjBaseResponse<T> apiResponse = objectMapper.readValue(responseBody, javaType);
if (apiResponse.getRetCode() != 200) {
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,
"业务逻辑错误: " + apiResponse.getRetMsg());
}
return apiResponse.getRetData();
}
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
log.error("API调用异常 - URL: {}, 错误: {}", url, e.getMessage(), e);
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "接口调用异常: " + e.getMessage());
}
}
private Request buildGetRequest(String url, String username, String secret) {
try {
// Map<String, String> authHeaders = HmacSigner.generateHeaders(
// username, secret,null);
// log.debug("签名生成 - 签名结果: {}", JSONObject.toJSONString(authHeaders));
return new Request.Builder()
.url(url)
.get()
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("X-Key", username)
.addHeader("X-Secret", secret)
.build();
} catch (Exception e) {
throw new ServiceException(ErrorCodeEnum.THIRD_API_SIGN_ERROR);
}
}
public String buildUrlWithParams(String baseUrl, Map<String, Object> requestParams) {
if (requestParams == null || requestParams.isEmpty()) {
// 如果没有参数,直接返回基础 URL
return baseUrl;
}
StringBuilder urlBuilder = new StringBuilder(baseUrl);
// 检查是否需要添加 "?" 或 "&"
if (!baseUrl.contains("?")) {
urlBuilder.append("?");
} else if (!baseUrl.endsWith("&")) {
urlBuilder.append("&");
}
try {
// 遍历参数并拼接
for (Map.Entry<String, Object> entry : requestParams.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value != null) {
// 对键和值进行 URL 编码
urlBuilder.append(URLEncoder.encode(key, "UTF-8"))
.append("=")
.append(URLEncoder.encode(value.toString(), "UTF-8"))
.append("&");
}
}
// 删除最后一个多余的 "&"
if (urlBuilder.charAt(urlBuilder.length() - 1) == '&') {
urlBuilder.deleteCharAt(urlBuilder.length() - 1);
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Error encoding URL parameters", e);
}
return urlBuilder.toString();
}
}

View File

@@ -112,6 +112,7 @@ public class SyncDataServiceImpl implements SyncDataService {
request.setCrmAccount(lineInfoDO.getMobile());
request.setDownstreamSystemPassword(hyPartnerUserInfoDO.getDownstreamSystemPassword());
request.setDownstreamSystemSalt(hyPartnerUserInfoDO.getDownstreamSystemSalting());
request.setDownstreamSystemSecondaryPassword(hyPartnerUserInfoDO.getDownstreamSystemSecondaryPassword());
if (StringUtils.isNotBlank(shopInfo.getFranchiseBrand())) {
String[] split = shopInfo.getFranchiseBrand().split(Constants.COMMA);
request.setFranchiseBrand(split[0]);