package com.ruoyi.cwgl.service.impl; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.ruoyi.cwgl.domain.ApiResponse; import com.ruoyi.cwgl.domain.VehicleDailyData; import com.ruoyi.common.utils.SignUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.*; /** * 车辆数据API客户端服务 * 用于调用外部车辆数据API获取车辆每日数据 * * @author ruoyi */ @Component public class VehicleDataApiClient { private static final Logger logger = LoggerFactory.getLogger(VehicleDataApiClient.class); @Value("${custom.vehicle-api.baseUrl}") private String baseUrl; @Value("${custom.vehicle-api.appid}") private String appid; @Value("${custom.vehicle-api.secret}") private String secret; @Value("${custom.vehicle-api.timeout:30000}") private int timeout; /** * 查询某日车辆数据 * * @param date 查询日期,格式为yyyy-MM-dd * @return API响应结果 */ public ApiResponse> getDailyVehicleData(String date) { logger.info("开始查询日期[{}]的车辆数据", date); // 准备参数 String nonce = SignUtil.generate16CharRandomString(); String timestamp = String.valueOf(System.currentTimeMillis()); Map params = new HashMap<>(); params.put("date", date); // 生成签名 String signature = SignUtil.signParamsSha256(params, appid, nonce, timestamp, secret); logger.debug("生成签名参数: appid={}, nonce={}, timestamp={}", appid, nonce, timestamp); // 构建请求URL String url = baseUrl + "/open/api/v1/dailyData?date=" + date; try { // 使用Hutool发送GET请求 HttpResponse response = HttpRequest.get(url) .header("appid", appid) .header("nonce", nonce) .header("timestamp", timestamp) .header("signature", signature) .header("Content-Type", "application/json") .header("Accept", "application/json") .timeout(timeout) .execute(); logger.debug("请求URL: {}", url); logger.debug("响应状态码: {}", response.getStatus()); if (response.isOk()) { String body = response.body(); logger.info("响应内容: {}", body); // 解析JSON响应 return parseResponse(body); } else { String errorBody = response.body(); logger.error("HTTP请求失败,状态码: {}, 错误响应: {}", response.getStatus(), errorBody); return createErrorResponse("HTTP请求失败: " + response.getStatus() + ", " + errorBody); } } catch (Exception e) { logger.error("API调用异常: {}", e.getMessage(), e); return createErrorResponse("API调用异常: " + e.getMessage()); } } /** * 解析响应内容 * * @param body 响应体JSON字符串 * @return 解析后的API响应对象 */ private ApiResponse> parseResponse(String body) { try { // 使用Hutool的JSONUtil解析响应 JSONObject jsonObject = JSONUtil.parseObj(body); ApiResponse> response = new ApiResponse<>(); response.setCode(jsonObject.getInt("code")); response.setMsg(jsonObject.getStr("msg")); // 解析data数组 if (jsonObject.containsKey("data") && jsonObject.get("data") != null) { String dataJson = JSONUtil.toJsonStr(jsonObject.get("data")); List dataList = JSONUtil.toList(dataJson, VehicleDailyData.class); response.setData(dataList); logger.debug("成功解析到{}条车辆数据", dataList.size()); } else { response.setData(new ArrayList<>()); logger.debug("响应中无数据"); } return response; } catch (Exception e) { logger.error("JSON解析异常: {}", e.getMessage(), e); logger.debug("响应内容: {}", body); return createErrorResponse("JSON解析异常: " + e.getMessage()); } } /** * 创建错误响应 * * @param message 错误消息 * @return 错误响应对象 */ private ApiResponse> createErrorResponse(String message) { ApiResponse> response = new ApiResponse<>(); response.setCode(500); response.setMsg(message); response.setData(new ArrayList<>()); return response; } }