Merge remote-tracking branch 'origin/cc_20251112_wallet' into cc_20251112_wallet
This commit is contained in:
@@ -10,7 +10,8 @@ public enum ResponseCodeEnum {
|
|||||||
/**
|
/**
|
||||||
* 成功返回
|
* 成功返回
|
||||||
*/
|
*/
|
||||||
SUCCESS(200000, "SUCCESS");
|
SUCCESS(200000, "SUCCESS"),
|
||||||
|
SUCCESS_WALLET(200, "SUCCESS");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回码
|
* 返回码
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import lombok.Getter;
|
|||||||
public enum PingAnAccountStatusEnum {
|
public enum PingAnAccountStatusEnum {
|
||||||
|
|
||||||
UNCOMMITTED(1, "待提交"),
|
UNCOMMITTED(1, "待提交"),
|
||||||
UNAUTHORIZED(2, "带鉴权"),
|
UNAUTHORIZED(2, "待鉴权"),
|
||||||
AUTHENTICATING(3, "鉴权中"),
|
AUTHENTICATING(3, "鉴权中"),
|
||||||
OPEN(4, "开通"),
|
OPEN(4, "开通"),
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.cool.store.utils;
|
package com.cool.store.utils;
|
||||||
|
|
||||||
import com.sun.deploy.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
|
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
|
||||||
import sun.security.util.DerInputStream;
|
import sun.security.util.DerInputStream;
|
||||||
|
|||||||
@@ -97,8 +97,8 @@ public class ShopInfoDAO {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Long addShopInfo(ShopInfoDO shopInfo){
|
public Long addShopInfo(ShopInfoDO shopInfo){
|
||||||
shopInfoMapper.insertSelective(shopInfo);
|
|
||||||
shopInfo.setStoreId(UUIDUtils.get32UUID());
|
shopInfo.setStoreId(UUIDUtils.get32UUID());
|
||||||
|
shopInfoMapper.insertSelective(shopInfo);
|
||||||
return shopInfo.getId();
|
return shopInfo.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.cool.store.request.wallet;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/11/17 13:49
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AddTagCallbackNoticeRequest {
|
||||||
|
|
||||||
|
@ApiModelProperty(name = "CRM门店编号", required = true)
|
||||||
|
private String outStoreId;
|
||||||
|
@ApiModelProperty(name = "状态1.打标成功 2.打标失败 3.处理中(打标状态)", required = true)
|
||||||
|
private Integer status;
|
||||||
|
@ApiModelProperty(name = "1.法人 2.非法人", required = true)
|
||||||
|
private Integer addTagType;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.cool.store.request.wallet;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/11/17 11:20
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class UpdatePasswordRequest {
|
||||||
|
|
||||||
|
@ApiModelProperty(name = "CRM门店编号", required = true)
|
||||||
|
private String outStoreId;
|
||||||
|
@ApiModelProperty(name = "维护类型 1.设置密码 2.修改密码", required = true)
|
||||||
|
private Integer upholdType;
|
||||||
|
@ApiModelProperty(name = "新支付密码(sm3加密后字符串)", required = true)
|
||||||
|
private String newPayPwd;
|
||||||
|
@ApiModelProperty(name = "确认新支付密码(sm3加密后字符串)", required = true)
|
||||||
|
private String confirmPayPwd;
|
||||||
|
@ApiModelProperty(name = "当前使用的支付密码(sm3加密后字符串),维护类型为修改密码时必填", required = false)
|
||||||
|
private String currentPayPwd;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,9 +3,12 @@ package com.cool.store.response.bigdata;
|
|||||||
import com.cool.store.constants.CommonConstants;
|
import com.cool.store.constants.CommonConstants;
|
||||||
import com.cool.store.enums.ErrorCodeEnum;
|
import com.cool.store.enums.ErrorCodeEnum;
|
||||||
import com.cool.store.enums.ResponseCodeEnum;
|
import com.cool.store.enums.ResponseCodeEnum;
|
||||||
|
import com.cool.store.response.ResponseResult;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.slf4j.MDC;
|
import org.slf4j.MDC;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author suzhuhong
|
* @Author suzhuhong
|
||||||
* @Date 2025/4/1 10:49
|
* @Date 2025/4/1 10:49
|
||||||
@@ -31,7 +34,19 @@ public class ApiResponse<T> {
|
|||||||
return new ApiResponse(ResponseCodeEnum.SUCCESS.getCode(), "ok", data);
|
return new ApiResponse(ResponseCodeEnum.SUCCESS.getCode(), "ok", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static<T> ApiResponse<T> error(ErrorCodeEnum errorCodeEnum) {
|
/**
|
||||||
return new ApiResponse(errorCodeEnum.getCode(), errorCodeEnum.getMessage(), null);
|
* 钱包系统 响应用200
|
||||||
|
* @param data
|
||||||
|
* @param <T>
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static<T> ApiResponse<T> successByWallet(T data) {
|
||||||
|
return new ApiResponse(ResponseCodeEnum.SUCCESS_WALLET.getCode(), "ok", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static ApiResponse fail(ErrorCodeEnum responseEnum, Object... objects){
|
||||||
|
String message = MessageFormat.format(responseEnum.getMessage(), objects);
|
||||||
|
return new ApiResponse(responseEnum.getCode(), message, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,6 +161,14 @@ public class WalletApiService {
|
|||||||
return walletHttpClientRest.postWithSign("https://api.dev.wenmatech.com:443/open/crm/base/v1/findPageBank", request, BankListDTO.class);
|
return walletHttpClientRest.postWithSign("https://api.dev.wenmatech.com:443/open/crm/base/v1/findPageBank", request, BankListDTO.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改密码
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String upholdPwd(UpdatePasswordRequest request){
|
||||||
|
return walletHttpClientRest.postWithSign("https://api.dev.wenmatech.com:443/open/crm/account/v1/upholdPwd", request, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -49,4 +49,11 @@ public interface WalletService {
|
|||||||
* @param storeId 主数据门店id
|
* @param storeId 主数据门店id
|
||||||
*/
|
*/
|
||||||
void addTagIfUploadLicense(Long shopId, String storeId);
|
void addTagIfUploadLicense(Long shopId, String storeId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打标成功回调通知
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean addTagCallback(AddTagCallbackNoticeRequest request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import com.cool.store.vo.wallet.BankVO;
|
|||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -149,6 +150,8 @@ public class WalletServiceImpl implements WalletService {
|
|||||||
// 营业执照已上传,调用打标接口
|
// 营业执照已上传,调用打标接口
|
||||||
if (Objects.nonNull(licenseTransactDO) && StringUtils.isNotBlank(licenseTransactDO.getCreditUrl())) {
|
if (Objects.nonNull(licenseTransactDO) && StringUtils.isNotBlank(licenseTransactDO.getCreditUrl())) {
|
||||||
try {
|
try {
|
||||||
|
// 判断一下账户的开通状态
|
||||||
|
if (enableAddTag(storeId)) {
|
||||||
// 调用 签约人账户打标(升级)接口
|
// 调用 签约人账户打标(升级)接口
|
||||||
log.info("营业执照已上传,账户打标");
|
log.info("营业执照已上传,账户打标");
|
||||||
AccountAddTagRequest tagRequest = AccountAddTagRequest.builder()
|
AccountAddTagRequest tagRequest = AccountAddTagRequest.builder()
|
||||||
@@ -162,12 +165,26 @@ public class WalletServiceImpl implements WalletService {
|
|||||||
.build();
|
.build();
|
||||||
AddTagDTO addTagDTO = walletApiService.addTag(tagRequest);
|
AddTagDTO addTagDTO = walletApiService.addTag(tagRequest);
|
||||||
log.info("打标接口调用成功,response:{}", JSONObject.toJSONString(addTagDTO));
|
log.info("打标接口调用成功,response:{}", JSONObject.toJSONString(addTagDTO));
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("营业执照已上传,打标失败", e);
|
log.error("营业执照已上传,打标失败", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账户存在且未打标
|
||||||
|
*/
|
||||||
|
private boolean enableAddTag(String storeId) {
|
||||||
|
List<AccountInfoDTO> accountInfo = walletApiService.getAccountInfo(new OutStoreIdRequest(storeId));
|
||||||
|
return CollectionUtils.isNotEmpty(accountInfo) && accountInfo.size() == 1 && accountInfo.get(0).getLabelingStatus().equals(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean addTagCallback(AddTagCallbackNoticeRequest request) {
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询并校验门店是否存在以及阶段是否处于平安钱包未开通状态
|
* 查询并校验门店是否存在以及阶段是否处于平安钱包未开通状态
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import com.cool.store.constants.CommonConstants;
|
|||||||
import com.cool.store.enums.ErrorCodeEnum;
|
import com.cool.store.enums.ErrorCodeEnum;
|
||||||
import com.cool.store.exception.ServiceException;
|
import com.cool.store.exception.ServiceException;
|
||||||
import com.cool.store.response.ResponseResult;
|
import com.cool.store.response.ResponseResult;
|
||||||
|
import com.cool.store.response.bigdata.ApiResponse;
|
||||||
import com.cool.store.utils.OpenSignatureUtil;
|
import com.cool.store.utils.OpenSignatureUtil;
|
||||||
|
import com.cool.store.utils.RsaSignUtil;
|
||||||
import com.cool.store.utils.UUIDUtils;
|
import com.cool.store.utils.UUIDUtils;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
@@ -42,6 +44,8 @@ public class OpenApiValidateFilter implements Filter {
|
|||||||
private String coolAppKey;
|
private String coolAppKey;
|
||||||
@Value("${cool.api.secret}")
|
@Value("${cool.api.secret}")
|
||||||
private String coolAppSecret;
|
private String coolAppSecret;
|
||||||
|
@Value("${cool.api.rsa.private.key}")
|
||||||
|
private String coolPrivateKey;
|
||||||
private static final Set<String> WHITELIST_URIS = new HashSet<>(Arrays.asList(
|
private static final Set<String> WHITELIST_URIS = new HashSet<>(Arrays.asList(
|
||||||
"/zxjp/open/v1/statusRefresh",
|
"/zxjp/open/v1/statusRefresh",
|
||||||
"/zxjp/open/v1/getStoreUser",
|
"/zxjp/open/v1/getStoreUser",
|
||||||
@@ -52,6 +56,8 @@ public class OpenApiValidateFilter implements Filter {
|
|||||||
"/zxjp/open/v1/getYlsToken", "/zxjp/open/v1/getStoreList",
|
"/zxjp/open/v1/getYlsToken", "/zxjp/open/v1/getStoreList",
|
||||||
"/zxjp/open/v1/changeReceiptStatus", "/zxjp/open/v1/getStoreUser"));
|
"/zxjp/open/v1/changeReceiptStatus", "/zxjp/open/v1/getStoreUser"));
|
||||||
|
|
||||||
|
// 添加钱包接口路径前缀常量
|
||||||
|
private static final String WALLET_API_PATTERN = "^/zxjp/open/v\\d+/wallet/.*$";
|
||||||
@Override
|
@Override
|
||||||
public void init(FilterConfig filterConfig) throws ServletException {
|
public void init(FilterConfig filterConfig) throws ServletException {
|
||||||
}
|
}
|
||||||
@@ -70,6 +76,11 @@ public class OpenApiValidateFilter implements Filter {
|
|||||||
filterChain.doFilter(servletRequest, response);
|
filterChain.doFilter(servletRequest, response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 针对钱包接口的专用验签处理 所有符合 /zxjp/open/v{版本号}/wallet/ 格式的接口都会走钱包专用的验签流程。
|
||||||
|
if (uri.matches(WALLET_API_PATTERN)) {
|
||||||
|
handleWalletApiValidation(request, response, filterChain);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
HttpServletResponse res = (HttpServletResponse) response;
|
HttpServletResponse res = (HttpServletResponse) response;
|
||||||
// 1. 验证时间戳
|
// 1. 验证时间戳
|
||||||
@@ -186,4 +197,90 @@ public class OpenApiValidateFilter implements Filter {
|
|||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void handleWalletApiValidation(HttpServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
|
||||||
|
HttpServletResponse res = (HttpServletResponse) response;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 读取请求体
|
||||||
|
StringBuilder requestBody = new StringBuilder();
|
||||||
|
try (BufferedReader reader = request.getReader()) {
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
requestBody.append(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String jsonBody = requestBody.toString();
|
||||||
|
|
||||||
|
// 1. 验证时间戳
|
||||||
|
String timestampStr = extractTimestampFromJson(jsonBody);
|
||||||
|
if (timestampStr == null) {
|
||||||
|
writeErrorResponse(res, ErrorCodeEnum.SIGN_FAIL, "缺少timestamp参数");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long timestamp = Long.parseLong(timestampStr) / 1000;
|
||||||
|
long currentTime = System.currentTimeMillis() / 1000;
|
||||||
|
long timeDiff = Math.abs(currentTime - timestamp);
|
||||||
|
|
||||||
|
if (timeDiff > 600) {
|
||||||
|
writeErrorResponse(res, ErrorCodeEnum.SIGN_FAIL, "请求已过期,请保证timestamp时间在10分钟之内");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 钱包接口专用验签逻辑
|
||||||
|
if (!verifyWalletSignatureFromBody(jsonBody)) {
|
||||||
|
writeErrorResponse(res, ErrorCodeEnum.SIGN_FAIL, "签名校验失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("钱包接口验签异常: ", e);
|
||||||
|
writeErrorResponse(res, ErrorCodeEnum.SIGN_FAIL, "验签异常");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从JSON中提取timestamp字段
|
||||||
|
*/
|
||||||
|
private String extractTimestampFromJson(String jsonBody) {
|
||||||
|
try {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
Map<String, Object> params = objectMapper.readValue(jsonBody, new TypeReference<Map<String, Object>>() {});
|
||||||
|
Object timestamp = params.get("timestamp");
|
||||||
|
return timestamp != null ? timestamp.toString() : null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("提取timestamp失败: ", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钱包接口签名验证方法 - 签名在请求体中
|
||||||
|
*/
|
||||||
|
private boolean verifyWalletSignatureFromBody(String jsonBody) {
|
||||||
|
try {
|
||||||
|
// 解析请求参数
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
Map<String, Object> params = objectMapper.readValue(jsonBody, new TypeReference<Map<String, Object>>() {});
|
||||||
|
|
||||||
|
// 使用RsaSignUtil.verifyWalletSign进行验签
|
||||||
|
return RsaSignUtil.verifyWalletSign(params, coolPrivateKey);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("钱包接口签名验证失败: ", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入错误响应
|
||||||
|
*/
|
||||||
|
private void writeErrorResponse(HttpServletResponse response, ErrorCodeEnum errorCode, String message) throws IOException {
|
||||||
|
response.setStatus(HttpStatus.OK.value());
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
response.getWriter().write(JSON.toJSONString(ApiResponse.fail(errorCode, message)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -11,11 +11,13 @@ import com.cool.store.request.StoreCodeDTO;
|
|||||||
import com.cool.store.request.*;
|
import com.cool.store.request.*;
|
||||||
import com.cool.store.request.notice.ThirdHandleMessageRequest;
|
import com.cool.store.request.notice.ThirdHandleMessageRequest;
|
||||||
import com.cool.store.request.notice.ThirdMatterRequest;
|
import com.cool.store.request.notice.ThirdMatterRequest;
|
||||||
|
import com.cool.store.request.wallet.AddTagCallbackNoticeRequest;
|
||||||
import com.cool.store.request.xgj.FranchiseFeeCallBackRequest;
|
import com.cool.store.request.xgj.FranchiseFeeCallBackRequest;
|
||||||
import com.cool.store.request.xgj.ReceiptCallBackRequest;
|
import com.cool.store.request.xgj.ReceiptCallBackRequest;
|
||||||
import com.cool.store.response.ResponseResult;
|
import com.cool.store.response.ResponseResult;
|
||||||
import com.cool.store.response.bigdata.ApiResponse;
|
import com.cool.store.response.bigdata.ApiResponse;
|
||||||
import com.cool.store.service.*;
|
import com.cool.store.service.*;
|
||||||
|
import com.cool.store.service.wallet.WalletService;
|
||||||
import com.cool.store.utils.poi.StringUtils;
|
import com.cool.store.utils.poi.StringUtils;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
@@ -57,6 +59,8 @@ public class OpenApiController {
|
|||||||
WechatMiniAppService wechatMiniAppService;
|
WechatMiniAppService wechatMiniAppService;
|
||||||
@Autowired
|
@Autowired
|
||||||
WeChatHandler weChatHandler;
|
WeChatHandler weChatHandler;
|
||||||
|
@Resource
|
||||||
|
WalletService walletService;
|
||||||
|
|
||||||
@PostMapping("/statusRefresh")
|
@PostMapping("/statusRefresh")
|
||||||
public ApiResponse<Boolean> statusRefresh(@RequestBody StatusRefreshDTO statusRefreshDTO){
|
public ApiResponse<Boolean> statusRefresh(@RequestBody StatusRefreshDTO statusRefreshDTO){
|
||||||
@@ -214,4 +218,10 @@ public class OpenApiController {
|
|||||||
}
|
}
|
||||||
return echostr;
|
return echostr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiOperation("打标回调通知接口")
|
||||||
|
@PostMapping("/wallet/addTagCallback")
|
||||||
|
public ApiResponse<Boolean> addTagCallback(@RequestBody @Validated AddTagCallbackNoticeRequest request) {
|
||||||
|
return ApiResponse.successByWallet(walletService.addTagCallback(request));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user