|
@@ -0,0 +1,377 @@
|
|
|
|
|
+package com.sckw.transport.service;
|
|
|
|
|
+
|
|
|
|
|
+import com.alibaba.fastjson2.JSON;
|
|
|
|
|
+import com.sckw.core.common.enums.enums.ErrorCodeEnum;
|
|
|
|
|
+import com.sckw.core.exception.BusinessPlatfromException;
|
|
|
|
|
+import com.sckw.core.utils.OkHttpUtils;
|
|
|
|
|
+import com.sckw.core.utils.TruckNoUtils;
|
|
|
|
|
+import com.sckw.transport.model.enuma.ParkingCarTypeEnum;
|
|
|
|
|
+import com.sckw.transport.model.enuma.ParkingChargeTypeEnum;
|
|
|
|
|
+import com.sckw.transport.model.enuma.ParkingDeductStatusEnum;
|
|
|
|
|
+import com.sckw.transport.model.param.ChargeInfoItemResp;
|
|
|
|
|
+import com.sckw.transport.model.param.ChargeInfoQueryParam;
|
|
|
|
|
+import com.sckw.transport.model.param.EntryNotificationParam;
|
|
|
|
|
+import com.sckw.transport.model.param.ExitNotificationParam;
|
|
|
|
|
+import com.sckw.transport.model.param.ExitNotificationResp;
|
|
|
|
|
+import com.sckw.transport.model.param.ParkingPlatformReportResult;
|
|
|
|
|
+import com.sckw.transport.model.param.ParkingPlatformResult;
|
|
|
|
|
+import com.sckw.transport.model.param.PlateInfoQueryParam;
|
|
|
|
|
+import com.sckw.transport.model.param.PlateInfoResp;
|
|
|
|
|
+import com.sckw.transport.util.ParkingPlatformResponseParser;
|
|
|
|
|
+import com.sckw.transport.util.ParkingPlatformSignUtil;
|
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.HashMap;
|
|
|
|
|
+import java.util.Map;
|
|
|
|
|
+import java.util.Objects;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 停车平台对接服务
|
|
|
|
|
+ */
|
|
|
|
|
+@Slf4j
|
|
|
|
|
+@Service
|
|
|
|
|
+public class ParkingPlateInfoService {
|
|
|
|
|
+
|
|
|
|
|
+ private static final String LIST_PLATE_INFO_PATH = "/list-plate-info";
|
|
|
|
|
+
|
|
|
|
|
+ private static final String ENTRY_NOTIFICATION_PATH = "/entry-notification";
|
|
|
|
|
+
|
|
|
|
|
+ private static final String EXIT_NOTIFICATION_PATH = "/exit-notification";
|
|
|
|
|
+
|
|
|
|
|
+ private static final String LIST_CHARGE_INFO_PATH = "/list-charge-info";
|
|
|
|
|
+
|
|
|
|
|
+ private static final int DEDUCT_STATUS_SUCCESS = 1;
|
|
|
|
|
+
|
|
|
|
|
+ @Value("${parking.platform.base-url:}")
|
|
|
|
|
+ private String baseUrl;
|
|
|
|
|
+
|
|
|
|
|
+ @Value("${parking.platform.park-id:}")
|
|
|
|
|
+ private String defaultParkId;
|
|
|
|
|
+
|
|
|
|
|
+ @Value("${parking.platform.sign-key:665@EOPqkl%hel}")
|
|
|
|
|
+ private String signKey;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 查询车辆信息
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 调用停车平台接口查询指定车牌号的车辆信息,包括车辆类型、入场时间等
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param param 查询参数,包含车牌号和车场ID
|
|
|
|
|
+ * @return 停车平台返回的车辆信息结果
|
|
|
|
|
+ * @throws BusinessPlatfromException 当车牌号格式不正确、车场ID为空或接口调用失败时抛出异常
|
|
|
|
|
+ */
|
|
|
|
|
+ public ParkingPlatformResult<PlateInfoResp> queryPlateInfo(PlateInfoQueryParam param) {
|
|
|
|
|
+ // 1. 参数校验与标准化:车牌号格式校验并转换为标准格式
|
|
|
|
|
+ String carLicense = normalizeCarLicense(param.getCarLicense());
|
|
|
|
|
+ log.debug("车牌号标准化完成,原始值={}, 标准化后={}", param.getCarLicense(), carLicense);
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 解析车场ID:优先使用传入的车场ID,否则使用默认配置的车场ID
|
|
|
|
|
+ String parkId = resolveParkId(param.getParkId());
|
|
|
|
|
+ log.debug("车场ID解析完成,parkId={}", parkId);
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 构建请求参数:包含车场ID、车牌号、时间戳和签名
|
|
|
|
|
+ Map<String, String> params = buildSignedParams(parkId, builder -> builder.put("carLicense", carLicense));
|
|
|
|
|
+ log.debug("请求参数构建完成,params={}", params);
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 调用停车平台接口查询车辆信息
|
|
|
|
|
+ log.info("调用停车平台车辆信息查询,parkId={}, carLicense={}", parkId, carLicense);
|
|
|
|
|
+ String responseBody = postJsonToParkingPlatform(LIST_PLATE_INFO_PATH, params);
|
|
|
|
|
+ log.info("停车平台车辆信息查询返回,carLicense={}, response={}", carLicense, responseBody);
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 解析响应结果
|
|
|
|
|
+ ParkingPlatformResult<PlateInfoResp> result = ParkingPlatformResponseParser.parseGeneral(responseBody, PlateInfoResp.class);
|
|
|
|
|
+
|
|
|
|
|
+ // 6. 数据增强:补充车牌号、车辆类型描述等信息
|
|
|
|
|
+ enrichPlateInfo(result.getData(), carLicense);
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 入场通知
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 向停车平台发送车辆入场通知,告知车辆已通过指定通道进入车场
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param param 入场通知参数,包含车牌号、车场ID、通道ID和业务单号
|
|
|
|
|
+ * @return 停车平台返回的处理结果
|
|
|
|
|
+ * @throws BusinessPlatfromException 当车牌号格式不正确、车场ID/通道ID/业务单号为空或接口调用失败时抛出异常
|
|
|
|
|
+ */
|
|
|
|
|
+ public ParkingPlatformResult<Object> entryNotification(EntryNotificationParam param) {
|
|
|
|
|
+ log.info("调用停车平台入场通知,入参={}", JSON.toJSONString( param));
|
|
|
|
|
+ // 1. 参数校验与标准化:车牌号格式校验并转换为标准格式
|
|
|
|
|
+ String carLicense = normalizeCarLicense(param.getCarLicense());
|
|
|
|
|
+ log.debug("车牌号标准化完成,原始值={}, 标准化后={}", param.getCarLicense(), carLicense);
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 解析车场ID:优先使用传入的车场ID,否则使用默认配置的车场ID
|
|
|
|
|
+ String parkId = resolveParkId(param.getParkId());
|
|
|
|
|
+ log.debug("车场ID解析完成,parkId={}", parkId);
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 必填参数校验:通道ID和业务单号不能为空
|
|
|
|
|
+ String gateId = requireText(param.getGateId(), "通道ID不能为空");
|
|
|
|
|
+ String businessId = requireText(param.getBusinessId(), "业务单号不能为空");
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 构建请求参数:包含车场ID、车牌号、通道ID、业务单号、时间戳和签名
|
|
|
|
|
+ Map<String, String> params = buildSignedParams(parkId, builder -> {
|
|
|
|
|
+ builder.put("carLicense", carLicense);
|
|
|
|
|
+ builder.put("gateId", gateId);
|
|
|
|
|
+ builder.put("businessId", businessId);
|
|
|
|
|
+ });
|
|
|
|
|
+ log.debug("请求参数构建完成,params={}", params);
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 调用停车平台接口发送入场通知
|
|
|
|
|
+ log.info("调用停车平台入场通知,parkId={}, carLicense={}, gateId={}, businessId={}",
|
|
|
|
|
+ parkId, carLicense, gateId, businessId);
|
|
|
|
|
+ String responseBody = postJsonToParkingPlatform(ENTRY_NOTIFICATION_PATH, params);
|
|
|
|
|
+ log.info("停车平台入场通知返回,businessId={}, response={}", businessId, responseBody);
|
|
|
|
|
+
|
|
|
|
|
+ // 6. 解析响应结果
|
|
|
|
|
+ ParkingPlatformResult<Object> result = ParkingPlatformResponseParser.parseGeneral(responseBody, Object.class);
|
|
|
|
|
+ log.debug("响应解析完成,success={}", result.isSuccess());
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 出场扣费通知
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 向停车平台发送车辆出场通知,告知车辆已通过指定通道离开车场,并可选择是否进行扣费
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param param 出场通知参数,包含车牌号、车场ID、通道ID、业务单号和是否需要扣费标识
|
|
|
|
|
+ * @return 停车平台返回的出场扣费结果,包含扣费状态和扣费金额等信息
|
|
|
|
|
+ * @throws BusinessPlatfromException 当车牌号格式不正确、车场ID/通道ID/业务单号为空、接口调用失败或扣费失败时抛出异常
|
|
|
|
|
+ */
|
|
|
|
|
+ public ParkingPlatformResult<ExitNotificationResp> exitNotification(ExitNotificationParam param) {
|
|
|
|
|
+ log.info("调用停车平台出场扣费通知,入参={}", JSON.toJSONString(param));
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 参数校验与标准化:车牌号格式校验并转换为标准格式
|
|
|
|
|
+ String carLicense = normalizeCarLicense(param.getCarLicense());
|
|
|
|
|
+ log.debug("车牌号标准化完成,原始值={}, 标准化后={}", param.getCarLicense(), carLicense);
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 解析车场ID:优先使用传入的车场ID,否则使用默认配置的车场ID
|
|
|
|
|
+ String parkId = resolveParkId(param.getParkId());
|
|
|
|
|
+ log.debug("车场ID解析完成,parkId={}", parkId);
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 必填参数校验:通道ID和业务单号不能为空
|
|
|
|
|
+ String gateId = requireText(param.getGateId(), "通道ID不能为空");
|
|
|
|
|
+ String businessId = requireText(param.getBusinessId(), "业务单号不能为空");
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 构建请求参数:包含车场ID、车牌号、通道ID、业务单号、是否扣费、时间戳和签名
|
|
|
|
|
+ Map<String, String> params = buildSignedParams(parkId, builder -> {
|
|
|
|
|
+ builder.put("carLicense", carLicense);
|
|
|
|
|
+ builder.put("gateId", gateId);
|
|
|
|
|
+ builder.put("businessId", businessId);
|
|
|
|
|
+ if (param.getNeedDeduct() != null) {
|
|
|
|
|
+ builder.put("needDeduct", String.valueOf(param.getNeedDeduct()));
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ log.debug("请求参数构建完成,params={}", params);
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 调用停车平台接口发送出场扣费通知
|
|
|
|
|
+ log.info("调用停车平台出场扣费通知,parkId={}, carLicense={}, gateId={}, businessId={}, needDeduct={}",
|
|
|
|
|
+ parkId, carLicense, gateId, businessId, param.getNeedDeduct());
|
|
|
|
|
+ String responseBody = postJsonToParkingPlatform(EXIT_NOTIFICATION_PATH, params);
|
|
|
|
|
+ log.info("停车平台出场扣费通知返回,businessId={}, response={}", businessId, responseBody);
|
|
|
|
|
+
|
|
|
|
|
+ // 6. 解析响应结果
|
|
|
|
|
+ ParkingPlatformResult<ExitNotificationResp> result =
|
|
|
|
|
+ ParkingPlatformResponseParser.parseGeneral(responseBody, ExitNotificationResp.class);
|
|
|
|
|
+ log.debug("响应解析完成,success={}", result.isSuccess());
|
|
|
|
|
+
|
|
|
|
|
+ // 7. 数据增强:补充车牌号、业务单号、车辆类型描述、扣费状态描述等信息,并校验扣费状态
|
|
|
|
|
+ enrichExitNotification(result.getData(), carLicense, businessId);
|
|
|
|
|
+ log.debug("数据增强完成,最终结果={}", result.getData());
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 充值扣费明细查询
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 查询指定时间范围内的充值扣费明细记录,支持按车牌号和业务单号筛选
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param param 查询参数,包含车场ID、车牌号(可选)、业务单号(可选)、开始时间、结束时间、分页参数
|
|
|
|
|
+ * @return 停车平台返回的充值扣费明细列表,包含分页信息和每条明细的详细信息
|
|
|
|
|
+ * @throws BusinessPlatfromException 当车场ID为空、开始/结束时间为空或接口调用失败时抛出异常
|
|
|
|
|
+ */
|
|
|
|
|
+ public ParkingPlatformReportResult<ChargeInfoItemResp> listChargeInfo(ChargeInfoQueryParam param) {
|
|
|
|
|
+ log.info("调用停车平台充值扣费明细查询,入参={}", JSON.toJSONString(param));
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 解析车场ID:优先使用传入的车场ID,否则使用默认配置的车场ID
|
|
|
|
|
+ String parkId = resolveParkId(param.getParkId());
|
|
|
|
|
+ log.debug("车场ID解析完成,parkId={}", parkId);
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 必填参数校验:开始时间和结束时间不能为空
|
|
|
|
|
+ String startTime = requireText(param.getStartTime(), "开始时间不能为空");
|
|
|
|
|
+ String endTime = requireText(param.getEndTime(), "结束时间不能为空");
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 构建请求参数:包含车场ID、车牌号(可选)、业务单号(可选)、时间范围、分页参数、时间戳和签名
|
|
|
|
|
+ Map<String, String> params = buildSignedParams(parkId, builder -> {
|
|
|
|
|
+ putIfNotBlank(builder, "carLicense", normalizeCarLicenseIfPresent(param.getCarLicense()));
|
|
|
|
|
+ putIfNotBlank(builder, "businessId", param.getBusinessId());
|
|
|
|
|
+ builder.put("startTime", startTime);
|
|
|
|
|
+ builder.put("endTime", endTime);
|
|
|
|
|
+ builder.put("start", String.valueOf(param.getStart()));
|
|
|
|
|
+ builder.put("limit", String.valueOf(param.getLimit()));
|
|
|
|
|
+ });
|
|
|
|
|
+ log.debug("请求参数构建完成,params={}", params);
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 调用停车平台接口查询充值扣费明细
|
|
|
|
|
+ log.info("调用停车平台充值扣费明细查询,parkId={}, carLicense={}, businessId={}, startTime={}, endTime={}",
|
|
|
|
|
+ parkId, param.getCarLicense(), param.getBusinessId(), startTime, endTime);
|
|
|
|
|
+ String responseBody = postJsonToParkingPlatform(LIST_CHARGE_INFO_PATH, params);
|
|
|
|
|
+ log.info("停车平台充值扣费明细查询返回,parkId={}, response={}", parkId, responseBody);
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 解析响应结果
|
|
|
|
|
+ ParkingPlatformReportResult<ChargeInfoItemResp> result =
|
|
|
|
|
+ ParkingPlatformResponseParser.parseReport(responseBody, ChargeInfoItemResp.class);
|
|
|
|
|
+ log.debug("响应解析完成,success={}", result.isSuccess());
|
|
|
|
|
+
|
|
|
|
|
+ // 6. 数据增强:为每条明细记录补充扣费类型描述
|
|
|
|
|
+ if (result.getData() != null) {
|
|
|
|
|
+ result.getData().forEach(this::enrichChargeInfoItem);
|
|
|
|
|
+ log.debug("数据增强完成,明细记录数={}", result.getData().size());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 向停车平台发送POST请求
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 构建完整的请求URL,将参数转换为JSON格式,通过OkHttp发送POST请求到停车平台
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param path 接口路径,如 /list-plate-info
|
|
|
|
|
+ * @param params 请求参数Map,已包含签名信息
|
|
|
|
|
+ * @return 停车平台返回的响应体字符串
|
|
|
|
|
+ * @throws BusinessPlatfromException 当请求失败或响应为空时抛出异常
|
|
|
|
|
+ */
|
|
|
|
|
+ private String postJsonToParkingPlatform(String path, Map<String, String> params) {
|
|
|
|
|
+ // 1. 构建完整的请求URL
|
|
|
|
|
+ String requestUrl = buildRequestUrl(path);
|
|
|
|
|
+ log.debug("请求URL构建完成,requestUrl={}", requestUrl);
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 将参数Map转换为JSON字符串
|
|
|
|
|
+ String requestBody = JSON.toJSONString(params);
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 记录请求信息(包含敏感参数,生产环境需注意脱敏)
|
|
|
|
|
+ log.info("停车平台JSON请求,url={}, body={}", requestUrl, requestBody);
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 发送HTTP POST请求
|
|
|
|
|
+ String responseBody = OkHttpUtils.builder()
|
|
|
|
|
+ .url(requestUrl)
|
|
|
|
|
+ .addHeader("Content-Type", "application/json;charset=UTF-8")
|
|
|
|
|
+ .addHeader("Accept", "application/json;charset=UTF-8")
|
|
|
|
|
+ .addBodyJsonStr(requestBody)
|
|
|
|
|
+ .post(true)
|
|
|
|
|
+ .sync();
|
|
|
|
|
+ log.debug("HTTP请求发送完成,responseBody={}", responseBody);
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 校验响应结果
|
|
|
|
|
+ if (StringUtils.isBlank(responseBody) || responseBody.startsWith("请求失败")) {
|
|
|
|
|
+ log.error("停车平台接口调用失败,url={}, response={}", requestUrl, responseBody);
|
|
|
|
|
+ throw new BusinessPlatfromException(ErrorCodeEnum.INTERFACE_PARAM_MISMATCH, "停车平台接口调用失败");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ log.debug("停车平台接口调用成功,responseLength={}", responseBody.length());
|
|
|
|
|
+ return responseBody;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Map<String, String> buildSignedParams(String parkId, java.util.function.Consumer<Map<String, String>> consumer) {
|
|
|
|
|
+ Map<String, String> params = new HashMap<>(8);
|
|
|
|
|
+ params.put("parkId", parkId);
|
|
|
|
|
+ consumer.accept(params);
|
|
|
|
|
+ params.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
|
|
|
|
+ params.put("sign", ParkingPlatformSignUtil.createSign(params, signKey));
|
|
|
|
|
+ return params;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void enrichPlateInfo(PlateInfoResp plateInfo, String carLicense) {
|
|
|
|
|
+ if (plateInfo == null) {
|
|
|
|
|
+ throw new BusinessPlatfromException(ErrorCodeEnum.RESOURCE_NOT_FOUND, "停车平台未返回车辆信息");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (StringUtils.isBlank(plateInfo.getCarLicense())) {
|
|
|
|
|
+ plateInfo.setCarLicense(carLicense);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (plateInfo.getCarType() != null) {
|
|
|
|
|
+ plateInfo.setCarTypeDesc(ParkingCarTypeEnum.getDescByCode(plateInfo.getCarType()));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void enrichExitNotification(ExitNotificationResp resp, String carLicense, String businessId) {
|
|
|
|
|
+ if (resp == null) {
|
|
|
|
|
+ throw new BusinessPlatfromException(ErrorCodeEnum.RESOURCE_NOT_FOUND, "停车平台未返回出场扣费结果");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (StringUtils.isBlank(resp.getCarLicense())) {
|
|
|
|
|
+ resp.setCarLicense(carLicense);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (StringUtils.isBlank(resp.getBusinessId())) {
|
|
|
|
|
+ resp.setBusinessId(businessId);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (resp.getCarType() != null) {
|
|
|
|
|
+ resp.setCarTypeDesc(ParkingCarTypeEnum.getDescByCode(resp.getCarType()));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (resp.getDeductStatus() != null) {
|
|
|
|
|
+ resp.setDeductStatusDesc(ParkingDeductStatusEnum.getDescByCode(resp.getDeductStatus()));
|
|
|
|
|
+ if (!Objects.equals(resp.getDeductStatus(), DEDUCT_STATUS_SUCCESS)) {
|
|
|
|
|
+ throw new BusinessPlatfromException(ErrorCodeEnum.INTERFACE_PARAM_MISMATCH,
|
|
|
|
|
+ StringUtils.defaultIfBlank(resp.getDeductStatusDesc(), "停车平台出场扣费失败"));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void enrichChargeInfoItem(ChargeInfoItemResp item) {
|
|
|
|
|
+ if (item != null && item.getChargeType() != null) {
|
|
|
|
|
+ item.setChargeTypeDesc(ParkingChargeTypeEnum.getDescByCode(item.getChargeType()));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void putIfNotBlank(Map<String, String> params, String key, String value) {
|
|
|
|
|
+ if (StringUtils.isNotBlank(value)) {
|
|
|
|
|
+ params.put(key, value.trim());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private String normalizeCarLicenseIfPresent(String carLicense) {
|
|
|
|
|
+ if (StringUtils.isBlank(carLicense)) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ return normalizeCarLicense(carLicense);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private String normalizeCarLicense(String carLicense) {
|
|
|
|
|
+ if (StringUtils.isBlank(carLicense)) {
|
|
|
|
|
+ throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "车牌号码不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+ String cleaned = carLicense.trim().toUpperCase();
|
|
|
|
|
+ if (!TruckNoUtils.isValidTruckNo(cleaned)) {
|
|
|
|
|
+ throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "车牌号格式不正确");
|
|
|
|
|
+ }
|
|
|
|
|
+ return TruckNoUtils.formatTruckNo(cleaned);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private String requireText(String value, String message) {
|
|
|
|
|
+ if (StringUtils.isBlank(value)) {
|
|
|
|
|
+ throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, message);
|
|
|
|
|
+ }
|
|
|
|
|
+ return value.trim();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private String resolveParkId(String requestParkId) {
|
|
|
|
|
+ String parkId = StringUtils.isNotBlank(requestParkId) ? requestParkId.trim() : defaultParkId;
|
|
|
|
|
+ if (StringUtils.isBlank(parkId)) {
|
|
|
|
|
+ throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "车场ID不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+ return parkId;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private String buildRequestUrl(String path) {
|
|
|
|
|
+ if (StringUtils.isBlank(baseUrl)) {
|
|
|
|
|
+ throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "停车平台服务地址未配置");
|
|
|
|
|
+ }
|
|
|
|
|
+ String normalizedBaseUrl = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl;
|
|
|
|
|
+ return normalizedBaseUrl + path;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|