项目介绍
业务需要调用企查查接口,本文章基于封装企查查接口调用过程中所遇到的问题及其解决方案,以供后续参考。
特点
- 基于Spring框架:开箱即用的设计,简化开发流程。
- 状态码转换:将企查查API的多种状态码转换为六个主要的业务状态码,降低对接难度。
- 成功:正常响应。
- 参数异常:输入参数不符合预期。
- 权限异常:访问权限受限。
- 服务异常:服务器端出现问题。
- 服务量不足:超出服务配额。
- 预警机制:对特定API状态码进行实时监控,提前预警潜在问题。
- 重试机制:针对网络问题和服务器错误自动重试,提高请求成功率。
项目代码介绍
代码下载
使用IDEA 导入本项目,选择Maven项目
代码环境与相关技术栈
- Spring Boot
- JDK1.8
- 设计模式:如建造者模式、多态、工厂方法等。
- 重试机制:使用Spring Retry模块处理网络问题和服务器错误。
- 预警机制:通过预警接口处理特定状态码。
数据准备
账号注册
410接口申请
接口申请
- 选择套餐,点击立即购买,按照流程购买即可 410接口申请
接口申请结果
- 数据中心、我的接口获取 Key获取
- 接口列表中存在 410接口
配置参数修改
- 修改类配置:QccApiServiceConfig
ApiClientConfigurationBuilder configuration = ApiClientConfiguration.builder()
.key("********") // 对应Key
.secretKey("********") // 对应SecretKey
.tokeAlgorithm(EncryptionAlgorithm.MD5) // Token 加密方式 支持自定义
.domain("https://api.qichacha.com") // 域名
// 状态码转化器设置,支持自定义
.apiStatusCodeConfig(new ApiStatusCodeConfig(new DefaultErrorCodeLoader("msg/qcc_errors_convert.config")));
- Token 加密规则说明
- 加密规则 MD5请求加密
状态码转义
- API接口返回的状态码比较多,通过统一配置文件转化为业务状态码,方便状态码管理。
- 支持自定义配置,当企查查API状态码新增时,只需要对应修改配置文件即可
- 状态码配置文件
单元测试
QccApiServiceImplTest.java
执行单元测试,选择 testGetEciv4BasicDetailsByNameApiResponse 方法
关键实现介绍
AbstractIQccApiService
类
此抽象类提供了基本的API调用框架,包括HTTP请求的构造和处理,以及状态码的转换。它还包括了重试机制,用于处理常见的HTTP服务器错误和资源访问异常。
// 接口调用
@Retryable(value = {HttpServerErrorException.class, ResourceAccessException.class}, backoff = @Backoff(delay = 2000))
@Override
public ApiResponse<DetailsByNameApiResponse> getBasicDetailsByName(DetailsByNameApiRequest request) {
Assert.notNull(request, "DetailsByNameApiRequest Is Null");
Map<String, Object> requestParams = convertToRequestMap(request);
String url = "/ECIV4/GetBasicDetailsByName";
return get(url, requestParams);
}
protected <T> ApiResponse<T> get(String url, Map<String, Object> requestParams) {
try {
HttpHeaders httpHeaders = builderHeaders();
String requestUri = convertToUri(getRequestUrl(url), requestParams);
HttpEntity<Map<String, Object>> headerEntity = new HttpEntity<>(httpHeaders);
ResponseEntity<BaseApiResponse<T>> response = restTemplate.exchange(requestUri, HttpMethod.GET, headerEntity,
new ParameterizedTypeReference<BaseApiResponse<T>>() {
});
logger.debug("Request URI: {}", requestUri);
logger.debug("Response Body: {}", response.getBody());
// 处理API响应
BaseApiResponse<T> apiResponse = handleResponse(response);
// 处理API响应的状态码
return handleApiResponseStatus(apiResponse);
} catch (HttpClientErrorException e) {
logger.error("客户端错误", e);
throw new CustomApiException(e.getStatusCode().value(), "客户端错误");
} catch (HttpServerErrorException e) {
throw new CustomApiException(e.getStatusCode().value(), "服务器错误");
}
}
方法
get(String url, Map<String, Object> requestParams)
:带有重试机制的GET请求方法。handleResponse(ResponseEntity<BaseApiResponse<T>> response)
:处理HTTP响应的方法。handleApiResponseStatus(BaseApiResponse<T> response)
:处理API响应状态码,并转换为业务状态码。
# 错误码统一管理
# Y是有效请求,N是无效请求
# (有效请求|无效请求)=业务状态码=业务状态码描述=企查查API状态码=企查查API状态码描述
Y=200=成功=200=【有效请求】查询成功
Y=200=成功=201=【有效请求】查询无结果
Y=200=成功=205=【有效请求】等待处理中
N=400=参数异常=223=【无效请求】查询参数模糊,无法获取结果
Y=400=参数异常=202=【有效请求】查询参数错误,请检查
Y=400=参数异常=213=【有效请求】参数长度不能小于2
Y=400=参数异常=215=【有效请求】不支持的查询关键字
Y=400=参数异常=218=【有效请求】该企业暂不支持空壳扫描
Y=400=参数异常=219=【有效请求】该企业暂不支持准入尽调
状态码转换
在handleApiResponseStatus
方法中,通过配置对象apiStatusCodeConfig
查找并转换API状态码为业务状态码,使得状态码管理更加集中和一致。
预警机制
引入了预警处理接口AlertHandler
,并在处理API响应状态码时检查是否需要触发预警。预警信息通过AlertInfo
对象传递给预警处理器。
private <T> ApiResponse<T> handleApiResponseStatus(BaseApiResponse<T> response) {
int statusCode = response.getStatus();
// 检查是否有预配置的状态码转换规则
if (Objects.nonNull(apiStatusCodeConfig)) {
ApiStatusCode code = apiStatusCodeConfig.getCode(String.valueOf(response.getStatus()));
if (Objects.nonNull(code)) {
// 检查是否需要发送预警
if (code.isNeedAlert()) {
if (Objects.nonNull(alertHandler)) {
alertHandler
.handleAlert(new AlertInfo<>(code.getCode(), code.getMessage(), "API状态码预警", response.getResult()));
}
}
return ApiResponse.of(code.getCode(), code.getMessage(), code.getSubCode(), code.getSubMsg(), code.getSubCodeStatus(), response.getResult());
} else {
// 对未知状态码进行预警处理
if (Objects.nonNull(alertHandler)) {
alertHandler
.handleAlert(new AlertInfo<>(String.valueOf(statusCode), response.getMessage(), 1000, "API新增状态码预警", response.getResult()));
}
}
}
return ApiResponse.of(String.valueOf(statusCode), response.getMessage(),
String.valueOf(statusCode), response.getMessage(), null,
response.getResult());
}
public interface AlertHandler
{
void handleAlert(AlertInfo alertInfo);
}
实现预警处理器
实现AlertHandler
接口,根据实际需要处理预警逻辑,例如记录日志、发送邮件通知等。
public class LogAlertHandler implements AlertHandler {
@Override
public void handleAlert(AlertInfo alertInfo) {
System.out.println("Alert: " + alertInfo);
// 这里可以记录日志、发送邮件等操作
}
}
其他说明
- 默认使用UTF-8编码,如有需要,请自行修改编码格式
- 本版本是初始化版本还有很多功能未完善,后续会不断完善,仅供使用参考