feat:云流水

This commit is contained in:
苏竹红
2025-04-17 16:02:12 +08:00
parent 1b7e1928cd
commit d54537937a
16 changed files with 124 additions and 29 deletions

View File

@@ -252,6 +252,7 @@ public enum ErrorCodeEnum {
SYSTEM_DATA_ERROR(151004,"平台账号不能为空",null),
CURRENT_STATUS_NOT_OPERATION(151005,"平台账号当前非审核状态!不能提交审核",null),
CURRENT_ENTRY_STATUS_NOT_OPERATION(151006,"进件状态未审核!不能执行该操作",null),
GET_YLS_CODE_FAIL(151006,"系统无云流水编码无法获取TOKEN请先维护该编码",null),
;

View File

@@ -81,10 +81,9 @@ public class ServiceException extends RuntimeException{
}
public ServiceException(ErrorCodeEnum responseEnum, Object... objects) {
super(responseEnum.getMessage());
String message = MessageFormat.format(responseEnum.getMessage(), objects);
super(MessageFormat.format(responseEnum.getMessage(), objects));
this.errorCode = responseEnum.getCode();
this.errorMessage = message;
this.errorMessage = super.getMessage();
}

View File

@@ -68,6 +68,9 @@ public class HmacSigner {
}
private static String hmacSha256(String secret, String data) throws Exception {
if (StringUtil.isEmpty(secret)){
return "";
}
Mac mac = Mac.getInstance(HMAC_ALGORITHM);
mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), HMAC_ALGORITHM));
byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));

View File

@@ -25,7 +25,7 @@ public class OpenSignatureUtil {
// 2. 创建不包含固定参数的临时Map用于排序
Map<String, String> sortedParams = new TreeMap<>(
params.entrySet().stream()
.filter(e -> !"appkey".equals(e.getKey()))
.filter(e -> !"appKey".equals(e.getKey()))
.filter(e -> !"timestamp".equals(e.getKey()))
.filter(e -> !"sign".equals(e.getKey()))
.collect(Collectors.toMap(

View File

@@ -28,4 +28,16 @@ public class OldShopDAO {
example.createCriteria().andEqualTo("mobile", mobile);
return oldShopMapper.selectByExample(example);
}
public OldShopDO getByCode(String code) {
if (StringUtils.isBlank(code)){
return null;
}
Example example = new Example(OldShopDO.class);
example.createCriteria().andEqualTo("ylsShopCode", code);
example.setOrderByClause("id ASC LIMIT 1");
List<OldShopDO> list = oldShopMapper.selectByExample(example);
return list.isEmpty() ? null : list.get(0);
}
}

View File

@@ -0,0 +1,15 @@
package com.cool.store.dto;
import lombok.Data;
/**
* @Author suzhuhong
* @Date 2025/4/17 15:13
* @Version 1.0
*/
@Data
public class AskBotTokenDTO {
private String shopCode;
}

View File

@@ -14,4 +14,12 @@ public class GetAccessTokenDTO {
private String shopCode;
public GetAccessTokenDTO(){
}
public GetAccessTokenDTO(String mobile, String shopCode) {
this.mobile = mobile;
this.shopCode = shopCode;
}
}

View File

@@ -24,6 +24,12 @@ public class OldShopDO {
@Column(name = "shop_code")
private String shopCode;
/**
* 云流水编码
*/
@Column(name = "yls_shop_code")
private String ylsShopCode;
@Column(name = "shop_name")
private String shopName;

View File

@@ -74,7 +74,9 @@ public interface ShopAccountService {
* @param shopId
* @return
*/
String shopCodeToYlsCode(Long shopId);
String shopIdToYlsCode(Long shopId);
String shopCodeToYlsCode(String shopCode);

View File

@@ -78,12 +78,6 @@ public class PushServiceImpl implements PushService {
@Value("${xzg.api.auth.url}")
private String xzgUrl;
@Value("${xzg.api.auth.username}")
private String xzgUsername;
@Value("${xzg.api.auth.secret}")
private String xzgSecret;
@Resource
OkHttpClient okHttpClient;
@Resource
@@ -135,7 +129,8 @@ public class PushServiceImpl implements PushService {
@Override
public String getXzgToken(GetAccessTokenDTO dto) {
String apiUrl = xzgUrl + "/api/supply-chain/get-token-byshopcode";
return executeApiCall(apiUrl, dto, String.class, xzgUsername, xzgSecret);
//不需要验签
return executeApiCall(apiUrl, dto, String.class, "", "");
}
@Override

View File

@@ -1,15 +1,13 @@
package com.cool.store.service.impl;
import com.cool.store.dao.HyPartnerUserInfoDAO;
import com.cool.store.dao.ShopAccountDAO;
import com.cool.store.dao.ShopInfoDAO;
import com.cool.store.dao.ShopStageInfoDAO;
import com.cool.store.dao.*;
import com.cool.store.dto.AccountAuditDTO;
import com.cool.store.dto.AccountEntryStatusAuditDTO;
import com.cool.store.dto.ModifyPasswordDTO;
import com.cool.store.dto.ShopAccount.ShopAccountDTO;
import com.cool.store.dto.AccountEntryStatusChangeDTO;
import com.cool.store.entity.HyPartnerUserInfoDO;
import com.cool.store.entity.OldShopDO;
import com.cool.store.entity.ShopAccountDO;
import com.cool.store.entity.ShopInfoDO;
import com.cool.store.enums.*;
@@ -52,6 +50,8 @@ public class ShopAccountServiceImpl implements ShopAccountService {
ShopStageInfoDAO shopStageInfoDAO;
@Resource
PosAndOrderInfoService posAndOrderInfoService;
@Resource
OldShopDAO oldShopDAO;
@Override
public List<ShopAccountDTO> getShopAccountByShopId(Long shopId) {
@@ -230,7 +230,7 @@ public class ShopAccountServiceImpl implements ShopAccountService {
}
@Override
public String shopCodeToYlsCode(Long shopId) {
public String shopIdToYlsCode(Long shopId) {
ShopInfoDO shopInfo = shopInfoDAO.getShopInfo(shopId);
if (Objects.isNull(shopInfo)){
throw new ServiceException(ErrorCodeEnum.SHOP_NOT_EXIST);
@@ -247,5 +247,19 @@ public class ShopAccountServiceImpl implements ShopAccountService {
return StringUtil.isEmpty(shopAccountDO.getAccount())?shopInfo.getShopCode():shopAccountDO.getAccount();
}
@Override
public String shopCodeToYlsCode(String shopCode) {
ShopInfoDO shopInfoDO = shopInfoDAO.selectByStoreCode(shopCode);
if (!Objects.isNull(shopInfoDO)){
return this.shopIdToYlsCode(shopInfoDO.getId());
}
//查询老店关联表数据
OldShopDO oldShopDO = oldShopDAO.getByCode(shopCode);
if (Objects.isNull(oldShopDO)){
throw new ServiceException(ErrorCodeEnum.GET_YLS_CODE_FAIL);
}
return oldShopDO.getYlsShopCode();
}
}

View File

@@ -3,6 +3,7 @@ import com.cool.store.constants.CommonConstants;
import com.cool.store.enums.ErrorCodeEnum;
import com.cool.store.exception.ServiceException;
import com.cool.store.utils.OpenSignatureUtil;
import com.cool.store.utils.StringUtil;
import com.cool.store.utils.UUIDUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -48,7 +49,7 @@ public class OpenApiValidateFilter implements Filter {
MDC.put(CommonConstants.REQUEST_ID, UUIDUtils.get32UUID());
HttpServletRequest request = (HttpServletRequest) servletRequest;
String uri = request.getRequestURI();
if(!uri.startsWith("/zxjp/open1")){
if(!uri.startsWith("/zxjp/open/v1/getYlsToken")){
filterChain.doFilter(servletRequest, response);
return;
}
@@ -60,15 +61,15 @@ public class OpenApiValidateFilter implements Filter {
log.info("timestampStr is null {}","缺少timestamp参数");
throw new ServiceException(ErrorCodeEnum.SIGN_FAIL);
}
try {
long timestamp = Long.parseLong(timestampStr)/1000;
long currentTime = System.currentTimeMillis()/1000;
long timeDiff = Math.abs(currentTime - timestamp);
try {
if (timeDiff > 600) {
log.info("OpenApiValidateFilter==>{}","请求已过期,服务器时间:" + currentTime + " 请求时间:" + timestamp);
throw new ServiceException(ErrorCodeEnum.SIGN_FAIL);
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,"请求已过期请保证timestamp时间在10分钟之内");
}
} catch (NumberFormatException e) {
log.info("OpenApiValidateFilter==>{}","非法timestamp格式");
@@ -79,12 +80,12 @@ public class OpenApiValidateFilter implements Filter {
String appKey = request.getHeader("appkey");
if (appKey == null || !coolAppKey.equals(appKey)) {
log.info("OpenApiValidateFilter==>{}","无效的appKey");
throw new ServiceException(ErrorCodeEnum.SIGN_FAIL);
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,"无效的appKey");
}
String clientSign = request.getHeader("sign");
if (clientSign == null) {
throw new ServiceException(ErrorCodeEnum.SIGN_FAIL);
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,"签名校验失败");
}
// 1. 读取请求体
StringBuilder requestBody = new StringBuilder();
@@ -103,6 +104,8 @@ public class OpenApiValidateFilter implements Filter {
jsonBody,
new TypeReference<TreeMap<String, String>>() {}
);
params.put("appKey",appKey);
params.put("timestamp", String.valueOf(timestamp));
String serverSign = OpenSignatureUtil.generateSign(params, coolAppSecret);

View File

@@ -1,11 +1,18 @@
package com.cool.store.controller.webb;
import com.alibaba.fastjson.JSONObject;
import com.cool.store.dto.AskBotTokenDTO;
import com.cool.store.dto.GetAccessTokenDTO;
import com.cool.store.dto.StatusRefreshDTO;
import com.cool.store.response.ResponseResult;
import com.cool.store.response.bigdata.ApiResponse;
import com.cool.store.service.OpenApiService;
import com.cool.store.service.PushService;
import com.cool.store.service.ShopAccountService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@@ -23,6 +30,10 @@ public class OpenApiController {
@Resource
OpenApiService openApiService;
@Resource
PushService pushService;
@Resource
ShopAccountService shopAccountService;
@PostMapping("/statusRefresh")
public ApiResponse<Boolean> statusRefresh(@RequestBody StatusRefreshDTO statusRefreshDTO){
@@ -30,4 +41,12 @@ public class OpenApiController {
return ApiResponse.success(openApiService.statusRefresh(statusRefreshDTO));
}
@ApiOperation("获取云流水免登token")
@PostMapping("/getYlsToken")
public ApiResponse<String> getYlsToken(@RequestBody @Validated AskBotTokenDTO dto) {
String ylsCode = shopAccountService.shopCodeToYlsCode(dto.getShopCode());
return ApiResponse.success(pushService.getYlsToken(new GetAccessTokenDTO(ylsCode,ylsCode)));
}
}

View File

@@ -77,7 +77,7 @@ public class MiniShopAccountController {
@ApiOperation("门店编码换云流水编码")
@GetMapping("/shopCodeToYlsCode")
public ResponseResult<String> shopCodeToYlsCode(@RequestParam(value = "shopId",required = true) Long shopId) {
return ResponseResult.success(accountService.shopCodeToYlsCode(shopId));
return ResponseResult.success(accountService.shopIdToYlsCode(shopId));
}
}

View File

@@ -95,15 +95,35 @@ xgj.open.organization.X-Secret = 3fe724f9607448728ee3393eff75718a
xgj.open.organization.url = https://masterdata.zhengxinfood.com/dmp/one-id
#huoma pos
api.auth.url=https://api.zhengxindzg.cn
api.auth.username=GkqgAhUJ7p9swJo
api.auth.secret=NzVrnS3OWiupdDY
#xingguanjia
xgj.api.auth.url=https://masterdata.zhengxinfood.com/dmp/one-id
xgj.api.auth.username=6446346061e043e392dd53c9c8d1af0b
xgj.api.auth.secret=3ba6e4c5632547b8b2b3acefe08667bb
#yunliushui
yls.api.auth.url=http://yuanguiwuliu.com
yls.api.auth.username=096d4009072c927c
yls.api.auth.secret=3b56198f096d4009072c927c96fbc8b6
#机会点地址 已确定
third.party.appKey=IGSAEQoakR2HEaYx
third.party.appSecret=aPsA99K1obFeFm3m
zx.opportunity.url=https://snp.wenmatech.com/
#大数据地址 已确定
zx.big.data.url=https://ds.zhengxinfood.com/
zx.big.data.appKey=ff203b5567744feaaae49fb86f58c5bf
zx.big.data.appSecret=35b8b9a400b4430fa022190be0913cd6
#新掌柜账号
xzg.api.auth.url=http://webapi.zhengxinfood.com
cool.api.appKey=k8J7fG2qR5tY9vX3
cool.api.secret=wP4sN6dL8zK2xM9c

View File

@@ -116,8 +116,6 @@ yls.api.auth.secret=3b56198f096d4009072c927c96fbc8b6
#新掌柜账号
xzg.api.auth.url=http://webapi.zhengxinfood.com
xzg.api.auth.username=****
xzg.api.auth.secret=****
cool.api.appKey=k8J7fG2qR5tY9vX3
cool.api.secret=wP4sN6dL8zK2xM9c