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

@@ -59,6 +59,6 @@ public class HyPartnerUserInfoDO implements Serializable {
private String downstreamSystemPassword;
@ApiModelProperty("下游系统第二密码")
@Column(name = "downstream_system_Secondary_password")
@Column(name = "downstream_system_secondary_password")
private String downstreamSystemSecondaryPassword;
}

View File

@@ -50,6 +50,9 @@ public class ZxjpApiRequest {
@ApiModelProperty(value = "下游系统密码盐值")
private String downstreamSystemSalt;
@ApiModelProperty(value = "第二密码")
private String downstreamSystemSecondaryPassword;
@ApiModelProperty(value = "下游系统店铺名称")
private String downstreamSystemShopName;

View File

@@ -0,0 +1,18 @@
package com.cool.store.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* @Author: WangShuo
* @Date: 2025/04/11/10:57
* @Version 1.0
* @注释:
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class XgjBaseResponse<T> {
private String retMsg;
private int retCode;
private T retData;
}

View File

@@ -0,0 +1,22 @@
package com.cool.store.response;
import com.cool.store.dto.XgjOrganizationDTO;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* @Author: WangShuo
* @Date: 2025/04/11/13:38
* @Version 1.0
* @注释:
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class XgjOrganizationResponse {
List<XgjOrganizationDTO> list;
}

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]);

View File

@@ -59,7 +59,8 @@ public class SignValidateFilter implements Filter {
"/zxjp/mini/program/v1/partnerManage/openArea/areaApplyQuery",
"/zxjp/**/api/audit/result",
"/zxjp/**/api/license",
"/zxjp/mini/line/getRegionPayPic"
"/zxjp/mini/line/getRegionPayPic",
"/zxjp/mini/**"
);

View File

@@ -5,13 +5,11 @@ import com.cool.store.enums.OrderSysTypeEnum;
import com.cool.store.request.OrderSysInfoRequest;
import com.cool.store.response.ResponseResult;
import com.cool.store.service.OrderSysInfoService;
import com.cool.store.service.PushService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@@ -28,6 +26,8 @@ public class PCOrderSysInfoController {
@Resource
private OrderSysInfoService orderSysInfoService;
@Resource
private PushService pushService;
@PostMapping("/submitOrderInfo")
@ApiOperation("物流提交订货信息")
@@ -42,4 +42,11 @@ public class PCOrderSysInfoController {
request.setType(OrderSysTypeEnum.ORDER_SYS_TYPE_2.getType());
return ResponseResult.success(orderSysInfoService.updateByShopId(request, CurrentUserHolder.getUserId()));
}
@GetMapping("/getXgjOrganization")
@ApiOperation("获取新管家组织架构")
public ResponseResult<Object> getXgjOrganization(@RequestParam(value = "partnerId", required = true,defaultValue = "0") String partnerId) {
return ResponseResult.success(pushService.getXgjOrganization(partnerId));
}
}

View File

@@ -35,6 +35,7 @@ import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.apache.ibatis.annotations.Param;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@@ -261,6 +262,13 @@ public class PCTestController {
return ResponseResult.success(shopAccountDAO.initShopAccount(hyPartnerUserInfoDO,Arrays.asList(shopId)));
}
@Resource
private PushService pushService;
@GetMapping("/getXgjOrganization")
@ApiOperation("获取新管家组织架构")
public ResponseResult<Object> getXgjOrganization(@RequestParam(value = "partnerId", required = true,defaultValue = "0") String partnerId) {
return ResponseResult.success(pushService.getXgjOrganization(partnerId));
}
@Resource

View File

@@ -89,6 +89,11 @@ enterprise.dingCorpId=wpayJeDAAAklx_q1jGhyGUd4yEh8vV_g
qywx.task.notice.url2=https://store-h5.coolstore.cn/?corpId=%s&appType=%s#/notice?target=%s&noticeType=zx&corpId=%s&appType=%s&eid=%s
xgj.open.organization.X-key = 2677a58dd9e24fc6b20e835ef5f19e63
xgj.open.organization.X-Secret = 3fe724f9607448728ee3393eff75718a
xgj.open.organization.url = https://masterdata.zhengxinfood.com/dmp/one-id
api.auth.url=https://api.zhengxindzg.cn
api.auth.username=GkqgAhUJ7p9swJo

View File

@@ -121,3 +121,7 @@ xzg.api.auth.secret=****
cool.api.appKey=k8J7fG2qR5tY9vX3
cool.api.secret=wP4sN6dL8zK2xM9c
xgj.open.organization.X-key = 2677a58dd9e24fc6b20e835ef5f19e63
xgj.open.organization.X-Secret = 3fe724f9607448728ee3393eff75718a
xgj.open.organization.url = http://117.139.13.24:11180/dmp/one-id