ThirdPartyTokenServiceImpl.java 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469
  1. package com.zsElectric.boot.thirdParty.service.impl;
  2. import cn.hutool.core.util.IdUtil;
  3. import cn.hutool.core.util.ObjectUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  6. import com.baomidou.mybatisplus.core.metadata.IPage;
  7. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  8. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  9. import com.fasterxml.jackson.databind.ObjectMapper;
  10. import com.zsElectric.boot.business.mapper.RechargeLevelMapper;
  11. import com.zsElectric.boot.business.mapper.ThirdPartyEquipmentInfoMapper;
  12. import com.zsElectric.boot.business.mapper.ThirdPartyInfoMapper;
  13. import com.zsElectric.boot.business.mapper.ThirdPartyStationInfoMapper;
  14. import com.zsElectric.boot.business.model.vo.applet.AppletConnectorDetailVO;
  15. import com.zsElectric.boot.charging.mapper.ThirdPartyConnectorInfoMapper;
  16. import com.zsElectric.boot.business.mapper.UserAccountMapper;
  17. import com.zsElectric.boot.business.mapper.UserOrderInfoMapper;
  18. import com.zsElectric.boot.business.model.entity.RechargeLevel;
  19. import com.zsElectric.boot.business.model.entity.ThirdPartyInfo;
  20. import com.zsElectric.boot.business.model.entity.UserAccount;
  21. import com.zsElectric.boot.business.model.entity.UserInfo;
  22. import com.zsElectric.boot.business.model.entity.UserOrderInfo;
  23. import com.zsElectric.boot.business.model.query.StationInfoQuery;
  24. import com.zsElectric.boot.business.model.vo.AppletStationDetailVO;
  25. import com.zsElectric.boot.business.model.vo.StationInfoVO;
  26. import com.zsElectric.boot.charging.entity.ThirdPartyConnectorInfo;
  27. import com.zsElectric.boot.charging.entity.ThirdPartyEquipmentInfo;
  28. import com.zsElectric.boot.charging.entity.ThirdPartyStationInfo;
  29. import com.zsElectric.boot.business.service.UserInfoService;
  30. import com.zsElectric.boot.business.service.UserAccountService;
  31. import com.zsElectric.boot.business.service.ChargeOrderInfoService;
  32. import com.zsElectric.boot.business.model.form.applet.AppInvokeChargeForm;
  33. import com.zsElectric.boot.business.model.form.applet.AppStopChargeForm;
  34. import com.zsElectric.boot.business.model.vo.applet.AppChargeVO;
  35. import com.zsElectric.boot.common.constant.SystemConstants;
  36. import com.zsElectric.boot.common.util.AESCryptoUtils;
  37. import com.zsElectric.boot.common.util.HmacMD5Util;
  38. import com.zsElectric.boot.thirdParty.model.*;
  39. import com.zsElectric.boot.thirdParty.service.ThirdPartyTokenService;
  40. import lombok.RequiredArgsConstructor;
  41. import lombok.extern.slf4j.Slf4j;
  42. import org.springframework.data.redis.core.RedisTemplate;
  43. import org.springframework.stereotype.Service;
  44. import org.springframework.transaction.annotation.Transactional;
  45. import java.math.BigDecimal;
  46. import java.time.LocalDateTime;
  47. import java.time.LocalTime;
  48. import java.time.format.DateTimeFormatter;
  49. import java.util.ArrayList;
  50. import java.util.List;
  51. import java.util.Map;
  52. import java.util.concurrent.TimeUnit;
  53. import java.util.stream.Collectors;
  54. /**
  55. * 第三方Token服务实现类
  56. *
  57. * @author wzq
  58. */
  59. @Slf4j
  60. @Service
  61. @RequiredArgsConstructor
  62. public class ThirdPartyTokenServiceImpl implements ThirdPartyTokenService {
  63. private final ThirdPartyInfoMapper thirdPartyInfoMapper;
  64. private final RechargeLevelMapper rechargeLevelMapper;
  65. private final RedisTemplate<String, Object> redisTemplate;
  66. private final UserInfoService userInfoService;
  67. private final UserAccountMapper userAccountMapper;
  68. private final UserAccountService userAccountService;
  69. private final UserOrderInfoMapper userOrderInfoMapper;
  70. private final ThirdPartyStationInfoMapper thirdPartyStationInfoMapper;
  71. private final ThirdPartyEquipmentInfoMapper thirdPartyEquipmentInfoMapper;
  72. private final ThirdPartyConnectorInfoMapper thirdPartyConnectorInfoMapper;
  73. private final ChargeOrderInfoService chargeOrderInfoService;
  74. private final ObjectMapper objectMapper = new ObjectMapper();
  75. /**
  76. * Redis Token Key 前缀
  77. */
  78. private static final String TOKEN_KEY_PREFIX = "third_party_access:token:";
  79. /**
  80. * Redis OperatorId Token映射 Key 前缀
  81. */
  82. private static final String OPERATOR_TOKEN_KEY_PREFIX = "third_party_access:operator:";
  83. /**
  84. * 默认Token有效期(秒)
  85. */
  86. private static final int DEFAULT_TOKEN_EXPIRE_SECONDS = 7200;
  87. @Override
  88. public ThirdPartyResponse queryToken(ThirdPartyRequest request) {
  89. try {
  90. // 1. 参数校验
  91. if (!validateRequestParams(request)) {
  92. return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
  93. }
  94. // 2. 通过operatorId查询第三方配置信息
  95. ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
  96. if (thirdPartyInfo == null) {
  97. log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
  98. return buildErrorResponse(4004, "运营商不存在", null);
  99. }
  100. // 3. 验证签名
  101. String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
  102. if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
  103. log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
  104. return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
  105. }
  106. // 4. 解密并解析业务参数
  107. String decryptedData = AESCryptoUtils.decrypt(
  108. request.getData(),
  109. thirdPartyInfo.getDataSecret(),
  110. thirdPartyInfo.getDataSecretIV()
  111. );
  112. log.info("解密后的请求数据: {}", decryptedData);
  113. QueryTokenRequestData tokenRequest = objectMapper.readValue(decryptedData, QueryTokenRequestData.class);
  114. if (tokenRequest == null || StrUtil.isBlank(tokenRequest.getOperatorId()) || StrUtil.isBlank(tokenRequest.getOperatorSecret())) {
  115. return buildErrorResponse(4004, "请求的业务参数不合法", thirdPartyInfo);
  116. }
  117. // 5. 验证运营商ID和密钥
  118. if (!thirdPartyInfo.getOperatorId().equals(tokenRequest.getOperatorId())
  119. || !thirdPartyInfo.getOperatorSecret().equals(tokenRequest.getOperatorSecret())) {
  120. log.warn("运营商ID或密钥错误, operatorId: {}", tokenRequest.getOperatorId());
  121. // 返回失败响应数据
  122. QueryTokenResponseData failData = QueryTokenResponseData.fail(tokenRequest.getOperatorId(), 1);
  123. return buildSuccessResponse(failData, thirdPartyInfo);
  124. }
  125. // 6. 生成或获取已有Token
  126. String accessToken = getOrGenerateToken(tokenRequest.getOperatorId());
  127. Integer remainingTTL = getRemainingTTL(accessToken);
  128. // 7. 构建成功响应
  129. QueryTokenResponseData responseData = QueryTokenResponseData.success(
  130. tokenRequest.getOperatorId(),
  131. accessToken,
  132. remainingTTL
  133. );
  134. log.info("生成Token成功, operatorId: {}, token有效期: {}秒", tokenRequest.getOperatorId(), remainingTTL);
  135. return buildSuccessResponse(responseData, thirdPartyInfo);
  136. } catch (Exception e) {
  137. log.error("处理query_token请求异常", e);
  138. return buildErrorResponse(500, "系统错误", null);
  139. }
  140. }
  141. @Override
  142. public ThirdPartyResponse queryRechargeLevelPage(ThirdPartyRequest request, String authorization) {
  143. try {
  144. // 1. 参数校验
  145. if (!validateRequestParams(request)) {
  146. return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
  147. }
  148. // 2. 通过operatorId查询第三方配置信息
  149. ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
  150. if (thirdPartyInfo == null) {
  151. log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
  152. return buildErrorResponse(4004, "运营商不存在", null);
  153. }
  154. // 3. 验证签名
  155. String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
  156. if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
  157. log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
  158. return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
  159. }
  160. // 4. 从Header中解析并验证Token
  161. String accessToken = parseAccessToken(authorization);
  162. if (StrUtil.isBlank(accessToken)) {
  163. log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
  164. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  165. }
  166. if (!validateAccessToken(accessToken, request.getOperatorId())) {
  167. log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
  168. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  169. }
  170. // 5. 解密并解析业务参数
  171. String decryptedData = AESCryptoUtils.decrypt(
  172. request.getData(),
  173. thirdPartyInfo.getDataSecret(),
  174. thirdPartyInfo.getDataSecretIV()
  175. );
  176. log.info("解密后的请求数据: {}", decryptedData);
  177. RechargeLevelPageRequestData pageRequest = objectMapper.readValue(decryptedData, RechargeLevelPageRequestData.class);
  178. if (pageRequest == null) {
  179. pageRequest = new RechargeLevelPageRequestData();
  180. }
  181. // 6. 查询充值档位分页数据
  182. IPage<RechargeLevel> pageResult = queryRechargeLevelFromDb(pageRequest);
  183. // 7. 转换为响应数据
  184. List<RechargeLevelPageResponseData.RechargeLevelItem> records = pageResult.getRecords().stream()
  185. .map(this::convertToItem)
  186. .collect(Collectors.toList());
  187. RechargeLevelPageResponseData responseData = RechargeLevelPageResponseData.of(
  188. pageResult.getTotal(),
  189. pageResult.getCurrent(),
  190. pageResult.getSize(),
  191. pageResult.getPages(),
  192. records
  193. );
  194. log.info("查询充值档位成功, operatorId: {}, total: {}", request.getOperatorId(), pageResult.getTotal());
  195. return buildSuccessResponse(responseData, thirdPartyInfo);
  196. } catch (Exception e) {
  197. log.error("处理query_recharge_level_page请求异常", e);
  198. return buildErrorResponse(500, "系统错误", null);
  199. }
  200. }
  201. @Override
  202. public ThirdPartyResponse queryUserInfo(ThirdPartyRequest request, String authorization) {
  203. try {
  204. // 1. 参数校验
  205. if (!validateRequestParams(request)) {
  206. return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
  207. }
  208. // 2. 通过operatorId查询第三方配置信息
  209. ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
  210. if (thirdPartyInfo == null) {
  211. log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
  212. return buildErrorResponse(4004, "运营商不存在", null);
  213. }
  214. // 3. 验证签名
  215. String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
  216. if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
  217. log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
  218. return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
  219. }
  220. // 4. 从Header中解析并验证Token
  221. String accessToken = parseAccessToken(authorization);
  222. if (StrUtil.isBlank(accessToken)) {
  223. log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
  224. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  225. }
  226. if (!validateAccessToken(accessToken, request.getOperatorId())) {
  227. log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
  228. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  229. }
  230. // 5. 解密并解析业务参数
  231. String decryptedData = AESCryptoUtils.decrypt(
  232. request.getData(),
  233. thirdPartyInfo.getDataSecret(),
  234. thirdPartyInfo.getDataSecretIV()
  235. );
  236. log.info("解密后的请求数据: {}", decryptedData);
  237. QueryUserInfoRequestData userInfoRequest = objectMapper.readValue(decryptedData, QueryUserInfoRequestData.class);
  238. if (userInfoRequest == null || StrUtil.isBlank(userInfoRequest.getPhone())) {
  239. log.warn("手机号为空, operatorId: {}", request.getOperatorId());
  240. return buildErrorResponse(4004, "请求的业务参数不合法,手机号不能为空", thirdPartyInfo);
  241. }
  242. String phone = userInfoRequest.getPhone();
  243. // 6. 根据手机号查询用户信息
  244. UserInfo userInfo = userInfoService.getUserInfoByPhone(phone);
  245. Integer isNewUser = 0;
  246. if (userInfo == null) {
  247. // 用户不存在,注册新用户
  248. log.info("用户不存在,注册新用户, phone: {}", phone);
  249. userInfo = userInfoService.registerOrUpdateUserByPhone(phone, null);
  250. if (userInfo == null) {
  251. log.error("注册用户失败, phone: {}", phone);
  252. return buildErrorResponse(500, "注册用户失败", thirdPartyInfo);
  253. }
  254. isNewUser = 1;
  255. }
  256. // 7. 查询用户账户信息
  257. UserAccount userAccount = userAccountMapper.selectOne(
  258. Wrappers.<UserAccount>lambdaQuery()
  259. .eq(UserAccount::getUserId, userInfo.getId())
  260. .eq(UserAccount::getIsDeleted, 0)
  261. );
  262. // 如果账户不存在,创建账户
  263. if (userAccount == null) {
  264. log.info("用户账户不存在,创建账户, userId: {}", userInfo.getId());
  265. userAccount = new UserAccount();
  266. userAccount.setUserId(userInfo.getId());
  267. userAccount.setBalance(BigDecimal.ZERO);
  268. userAccount.setRedeemBalance(BigDecimal.ZERO);
  269. userAccount.setIntegral(BigDecimal.ZERO);
  270. userAccountMapper.insert(userAccount);
  271. }
  272. // 8. 构建响应数据
  273. QueryUserInfoResponseData.UserInfoItem userInfoItem = new QueryUserInfoResponseData.UserInfoItem();
  274. userInfoItem.setUserId(userInfo.getId());
  275. userInfoItem.setNickName(userInfo.getNickName());
  276. userInfoItem.setPhone(userInfo.getPhone());
  277. userInfoItem.setOpenid(userInfo.getOpenid());
  278. QueryUserInfoResponseData.AccountInfoItem accountInfoItem = new QueryUserInfoResponseData.AccountInfoItem();
  279. accountInfoItem.setAccountId(userAccount.getId());
  280. accountInfoItem.setBalance(userAccount.getBalance() != null ? userAccount.getBalance() : BigDecimal.ZERO);
  281. accountInfoItem.setRedeemBalance(userAccount.getRedeemBalance() != null ? userAccount.getRedeemBalance() : BigDecimal.ZERO);
  282. accountInfoItem.setIntegral(userAccount.getIntegral() != null ? userAccount.getIntegral() : BigDecimal.ZERO);
  283. QueryUserInfoResponseData responseData = QueryUserInfoResponseData.of(isNewUser, userInfoItem, accountInfoItem);
  284. log.info("根据手机号查询用户信息成功, operatorId: {}, phone: {}, isNewUser: {}", request.getOperatorId(), phone, isNewUser);
  285. return buildSuccessResponse(responseData, thirdPartyInfo);
  286. } catch (Exception e) {
  287. log.error("处理query_user_info请求异常", e);
  288. return buildErrorResponse(500, "系统错误", null);
  289. }
  290. }
  291. @Override
  292. public ThirdPartyResponse chargeOrderPay(ThirdPartyRequest request, String authorization) {
  293. try {
  294. // 1. 参数校验
  295. if (!validateRequestParams(request)) {
  296. return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
  297. }
  298. // 2. 通过operatorId查询第三方配置信息
  299. ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
  300. if (thirdPartyInfo == null) {
  301. log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
  302. return buildErrorResponse(4004, "运营商不存在", null);
  303. }
  304. // 3. 验证签名
  305. String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
  306. if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
  307. log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
  308. return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
  309. }
  310. // 4. 从Header中解析并验证Token
  311. String accessToken = parseAccessToken(authorization);
  312. if (StrUtil.isBlank(accessToken)) {
  313. log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
  314. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  315. }
  316. if (!validateAccessToken(accessToken, request.getOperatorId())) {
  317. log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
  318. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  319. }
  320. // 5. 解密并解析业务参数
  321. String decryptedData = AESCryptoUtils.decrypt(
  322. request.getData(),
  323. thirdPartyInfo.getDataSecret(),
  324. thirdPartyInfo.getDataSecretIV()
  325. );
  326. log.info("解密后的请求数据: {}", decryptedData);
  327. ChangeOrderPayRequestData payRequest = objectMapper.readValue(decryptedData, ChangeOrderPayRequestData.class);
  328. if (payRequest == null || StrUtil.isBlank(payRequest.getPhone()) || StrUtil.isBlank(payRequest.getOrderNo())) {
  329. log.warn("请求参数不完整, operatorId: {}", request.getOperatorId());
  330. return buildErrorResponse(4004, "请求的业务参数不合法,手机号和订单号不能为空", thirdPartyInfo);
  331. }
  332. Long userId = payRequest.getUserId();
  333. String phone = payRequest.getPhone();
  334. //根据userId和phone校验用户
  335. UserInfo userInfo = userInfoService.getOne(Wrappers.lambdaQuery(UserInfo.class).eq(UserInfo::getPhone, phone).eq(UserInfo::getId, userId).last("limit 1"));
  336. if (ObjectUtil.isNull(userInfo)) {
  337. log.warn("用户不存在, userId: {}, phone: {}", userId, phone);
  338. ChargeOrderPayResponseData failData = ChargeOrderPayResponseData.fail("用户不存在");
  339. return buildSuccessResponse(failData, thirdPartyInfo);
  340. }
  341. String orderNo = payRequest.getOrderNo();
  342. UserAccount userAccount = userAccountService.getOne(Wrappers.lambdaQuery(UserAccount.class).eq(UserAccount::getUserId, userId).last("limit 1"));
  343. // 如果账户不存在,创建账户
  344. if (ObjectUtil.isNull(userAccount)) {
  345. log.info("用户账户不存在,创建账户, userId: {}", userInfo.getId());
  346. userAccount = new UserAccount();
  347. userAccount.setUserId(userInfo.getId());
  348. userAccount.setBalance(BigDecimal.ZERO);
  349. userAccount.setRedeemBalance(BigDecimal.ZERO);
  350. userAccount.setIntegral(BigDecimal.ZERO);
  351. userAccountMapper.insert(userAccount);
  352. }
  353. // 6. 幂等性检查 - 通过Redis检查订单是否已处理
  354. String orderKey = "third_party_pay:order:" + orderNo;
  355. Boolean isProcessed = redisTemplate.hasKey(orderKey);
  356. if (Boolean.TRUE.equals(isProcessed)) {
  357. log.warn("订单已处理,请勿重复提交, orderNo: {}", orderNo);
  358. ChargeOrderPayResponseData failData = ChargeOrderPayResponseData.fail("订单已处理,请勿重复提交");
  359. return buildSuccessResponse(failData, thirdPartyInfo);
  360. }
  361. // 7. 查询充值档位信息(如果有levelId)
  362. BigDecimal rechargeMoney;
  363. if (payRequest.getLevelId() != null) {
  364. RechargeLevel rechargeLevel = rechargeLevelMapper.selectById(payRequest.getLevelId());
  365. if (rechargeLevel == null) {
  366. log.warn("充值档位不存在, levelId: {}", payRequest.getLevelId());
  367. ChargeOrderPayResponseData failData = ChargeOrderPayResponseData.fail("充值档位不存在");
  368. return buildSuccessResponse(failData, thirdPartyInfo);
  369. }
  370. rechargeMoney = rechargeLevel.getMoney();
  371. } else if (StrUtil.isNotBlank(payRequest.getTotalMoney())) {
  372. // 使用传入的金额
  373. rechargeMoney = new BigDecimal(payRequest.getTotalMoney());
  374. } else {
  375. log.warn("充值金额未指定, operatorId: {}", request.getOperatorId());
  376. ChargeOrderPayResponseData failData = ChargeOrderPayResponseData.fail("充值金额未指定");
  377. return buildSuccessResponse(failData, thirdPartyInfo);
  378. }
  379. // 8. 增加充值订单记录到c_user_order_info表
  380. UserOrderInfo orderInfo = new UserOrderInfo();
  381. orderInfo.setUserId(userId);
  382. orderInfo.setOrderNo(orderNo);
  383. orderInfo.setOrderMoney(rechargeMoney);
  384. orderInfo.setPayMoney(rechargeMoney);
  385. orderInfo.setLastMoney(rechargeMoney);
  386. // 解析支付时间
  387. if (StrUtil.isNotBlank(payRequest.getPayTime())) {
  388. try {
  389. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  390. orderInfo.setPayTime(LocalDateTime.parse(payRequest.getPayTime(), formatter));
  391. } catch (Exception e) {
  392. orderInfo.setPayTime(LocalDateTime.now());
  393. }
  394. } else {
  395. orderInfo.setPayTime(LocalDateTime.now());
  396. }
  397. orderInfo.setLevelId(payRequest.getLevelId());
  398. orderInfo.setOutTradeNo(orderNo); // 第三方订单号
  399. orderInfo.setOrderStatus(2); // 已支付
  400. orderInfo.setOrderType(3); // 渠道方
  401. orderInfo.setRemark("第三方渠道充值-" + request.getOperatorId());
  402. userOrderInfoMapper.insert(orderInfo);
  403. log.info("创建充值订单记录成功, orderNo: {}, userId: {}", orderNo, userId);
  404. // 9. 充值账户余额并记录日志
  405. // 使用订单号的Id值作为变更记录ID
  406. Long changeId = orderInfo.getId();
  407. UserAccount updatedAccount = userAccountService.updateAccountBalanceAndLog(
  408. userId,
  409. rechargeMoney,
  410. SystemConstants.CHANGE_TYPE_ADD,
  411. SystemConstants.ACCOUNT_LOG_THIRD_PARTY_PAY_NOTE + "-" + orderNo,
  412. changeId
  413. );
  414. BigDecimal balanceAfter = updatedAccount != null ? updatedAccount.getBalance() : userAccount.getBalance().add(rechargeMoney);
  415. // 10. 构建成功响应
  416. ChargeOrderPayResponseData responseData = ChargeOrderPayResponseData.success(
  417. userId,
  418. rechargeMoney,
  419. balanceAfter,
  420. orderNo
  421. );
  422. log.info("充电券购买成功, operatorId: {}, phone: {}, orderNo: {}, rechargeMoney: {}, balanceAfter: {}",
  423. request.getOperatorId(), phone, orderNo, rechargeMoney, balanceAfter);
  424. return buildSuccessResponse(responseData, thirdPartyInfo);
  425. } catch (Exception e) {
  426. log.error("处理charge_order_pay请求异常", e);
  427. return buildErrorResponse(500, "系统错误", null);
  428. }
  429. }
  430. /**
  431. * 从Authorization Header中解析Token
  432. * 支持格式: "Bearer {token}" 或直接传 "{token}"
  433. */
  434. private String parseAccessToken(String authorization) {
  435. if (StrUtil.isBlank(authorization)) {
  436. return null;
  437. }
  438. // 支持 Bearer Token 格式
  439. if (authorization.startsWith("Bearer ")) {
  440. return authorization.substring(7).trim();
  441. }
  442. // 直接返回Token
  443. return authorization.trim();
  444. }
  445. /**
  446. * 验证访问Token
  447. */
  448. private boolean validateAccessToken(String accessToken, String operatorId) {
  449. String tokenKey = TOKEN_KEY_PREFIX + accessToken;
  450. String storedOperatorId = (String) redisTemplate.opsForValue().get(tokenKey);
  451. return operatorId.equals(storedOperatorId);
  452. }
  453. /**
  454. * 从数据库查询充值档位分页数据
  455. */
  456. private IPage<RechargeLevel> queryRechargeLevelFromDb(RechargeLevelPageRequestData pageRequest) {
  457. Page<RechargeLevel> page = new Page<>(pageRequest.getPageNum(), pageRequest.getPageSize());
  458. LambdaQueryWrapper<RechargeLevel> queryWrapper = new LambdaQueryWrapper<>();
  459. // 按ID排序
  460. queryWrapper.eq(RechargeLevel::getStatus, SystemConstants.STATUS_ONE);
  461. queryWrapper.orderByAsc(RechargeLevel::getId);
  462. return rechargeLevelMapper.selectPage(page, queryWrapper);
  463. }
  464. /**
  465. * 转换为响应项
  466. */
  467. private RechargeLevelPageResponseData.RechargeLevelItem convertToItem(RechargeLevel entity) {
  468. RechargeLevelPageResponseData.RechargeLevelItem item = new RechargeLevelPageResponseData.RechargeLevelItem();
  469. item.setId(entity.getId());
  470. item.setName(entity.getName());
  471. item.setMoney(entity.getMoney());
  472. item.setStatus(entity.getStatus());
  473. item.setTips(entity.getTips());
  474. return item;
  475. }
  476. /**
  477. * 通过operatorId查询第三方配置信息
  478. */
  479. private ThirdPartyInfo getThirdPartyInfoByOperatorId(String operatorId) {
  480. LambdaQueryWrapper<ThirdPartyInfo> queryWrapper = new LambdaQueryWrapper<>();
  481. queryWrapper.eq(ThirdPartyInfo::getOperatorId, operatorId)
  482. .eq(ThirdPartyInfo::getStatus, 0) // 状态正常
  483. .last("LIMIT 1");
  484. return thirdPartyInfoMapper.selectOne(queryWrapper);
  485. }
  486. /**
  487. * 校验请求参数完整性
  488. */
  489. private boolean validateRequestParams(ThirdPartyRequest request) {
  490. return request != null
  491. && StrUtil.isNotBlank(request.getOperatorId())
  492. && StrUtil.isNotBlank(request.getData())
  493. && StrUtil.isNotBlank(request.getTimeStamp())
  494. && StrUtil.isNotBlank(request.getSeq())
  495. && StrUtil.isNotBlank(request.getSig());
  496. }
  497. /**
  498. * 获取或生成Token
  499. * 如果Redis中存在有效Token则返回,否则生成新Token
  500. */
  501. private String getOrGenerateToken(String operatorId) {
  502. // 检查是否有已存在的有效Token
  503. String operatorTokenKey = OPERATOR_TOKEN_KEY_PREFIX + operatorId;
  504. String existingToken = (String) redisTemplate.opsForValue().get(operatorTokenKey);
  505. if (StrUtil.isNotBlank(existingToken)) {
  506. // 验证Token是否仍然有效
  507. String tokenKey = TOKEN_KEY_PREFIX + existingToken;
  508. Boolean hasKey = redisTemplate.hasKey(tokenKey);
  509. if (Boolean.TRUE.equals(hasKey)) {
  510. log.info("返回已存在的有效Token, operatorId: {}", operatorId);
  511. return existingToken;
  512. }
  513. }
  514. // 生成新Token
  515. String newToken = IdUtil.fastSimpleUUID() + IdUtil.fastSimpleUUID();
  516. // 存储Token
  517. String tokenKey = TOKEN_KEY_PREFIX + newToken;
  518. redisTemplate.opsForValue().set(tokenKey, operatorId, DEFAULT_TOKEN_EXPIRE_SECONDS, TimeUnit.SECONDS);
  519. // 存储OperatorId与Token的映射关系
  520. redisTemplate.opsForValue().set(operatorTokenKey, newToken, DEFAULT_TOKEN_EXPIRE_SECONDS, TimeUnit.SECONDS);
  521. log.info("生成新Token, operatorId: {}, expireSeconds: {}", operatorId, DEFAULT_TOKEN_EXPIRE_SECONDS);
  522. return newToken;
  523. }
  524. /**
  525. * 获取Token剩余有效时间(秒)
  526. */
  527. private Integer getRemainingTTL(String token) {
  528. String tokenKey = TOKEN_KEY_PREFIX + token;
  529. Long ttl = redisTemplate.getExpire(tokenKey, TimeUnit.SECONDS);
  530. return ttl != null && ttl > 0 ? ttl.intValue() : 0;
  531. }
  532. /**
  533. * 构建成功响应(通用)
  534. */
  535. private ThirdPartyResponse buildSuccessResponse(Object responseData, ThirdPartyInfo thirdPartyInfo) throws Exception {
  536. String jsonData = objectMapper.writeValueAsString(responseData);
  537. String encryptedData = AESCryptoUtils.encrypt(
  538. jsonData,
  539. thirdPartyInfo.getDataSecret(),
  540. thirdPartyInfo.getDataSecretIV()
  541. );
  542. String sig = HmacMD5Util.genSign(0, "", encryptedData, thirdPartyInfo.getSigSecret());
  543. return ThirdPartyResponse.success(encryptedData, sig);
  544. }
  545. /**
  546. * 构建错误响应
  547. */
  548. private ThirdPartyResponse buildErrorResponse(Integer ret, String msg, ThirdPartyInfo thirdPartyInfo) {
  549. try {
  550. String sigSecret = thirdPartyInfo != null ? thirdPartyInfo.getSigSecret() : "";
  551. String sig = StrUtil.isNotBlank(sigSecret) ? HmacMD5Util.genSign(ret, msg, "", sigSecret) : "";
  552. return ThirdPartyResponse.error(ret, msg, sig);
  553. } catch (Exception e) {
  554. log.error("生成错误响应签名失败", e);
  555. ThirdPartyResponse response = new ThirdPartyResponse();
  556. response.setRet(ret);
  557. response.setMsg(msg);
  558. response.setData("");
  559. response.setSig("");
  560. return response;
  561. }
  562. }
  563. // ==================== 充电站与设备查询接口 ====================
  564. /**
  565. * 时间格式化器 HHmmss
  566. */
  567. private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HHmmss");
  568. @Override
  569. public ThirdPartyResponse queryChargeStationList(ThirdPartyRequest request, String authorization) {
  570. try {
  571. // 1. 参数校验
  572. if (!validateRequestParams(request)) {
  573. return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
  574. }
  575. // 2. 通过operatorId查询第三方配置信息
  576. ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
  577. if (thirdPartyInfo == null) {
  578. log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
  579. return buildErrorResponse(4004, "运营商不存在", null);
  580. }
  581. // 3. 验证签名
  582. String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
  583. if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
  584. log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
  585. return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
  586. }
  587. // 4. 从Header中解析并验证Token
  588. String accessToken = parseAccessToken(authorization);
  589. if (StrUtil.isBlank(accessToken)) {
  590. log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
  591. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  592. }
  593. if (!validateAccessToken(accessToken, request.getOperatorId())) {
  594. log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
  595. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  596. }
  597. // 5. 解密并解析业务参数
  598. String decryptedData = AESCryptoUtils.decrypt(
  599. request.getData(),
  600. thirdPartyInfo.getDataSecret(),
  601. thirdPartyInfo.getDataSecretIV()
  602. );
  603. log.info("解密后的请求数据: {}", decryptedData);
  604. ChargeStationListRequestData listRequest = objectMapper.readValue(decryptedData, ChargeStationListRequestData.class);
  605. if (listRequest == null) {
  606. listRequest = new ChargeStationListRequestData();
  607. }
  608. // 6. 查询充电站分页数据
  609. // 获取当前时间(HHmmss格式)
  610. String currentTime = LocalTime.now().format(TIME_FORMATTER);
  611. // 构建分页对象
  612. Page<StationInfoVO> page = new Page<>(listRequest.getPageNum(), listRequest.getPageSize());
  613. StationInfoQuery stationInfoQuery = new StationInfoQuery().setLatitude(listRequest.getLatitude()).setLongitude(listRequest.getLongitude()).setSortType(listRequest.getSortType());
  614. // 执行查询
  615. IPage<StationInfoVO> pageResult = thirdPartyStationInfoMapper.selectAppletStationInfoPage(
  616. page, stationInfoQuery, currentTime, null
  617. );
  618. // 7. 转换为响应数据
  619. List<ChargeStationListResponseData.StationItem> records = pageResult.getRecords().stream()
  620. .map(this::convertToStationItem)
  621. .collect(Collectors.toList());
  622. ChargeStationListResponseData responseData = ChargeStationListResponseData.of(
  623. pageResult.getTotal(),
  624. pageResult.getCurrent(),
  625. pageResult.getSize(),
  626. pageResult.getPages(),
  627. records
  628. );
  629. log.info("查询充电站列表成功, operatorId: {}, total: {}", request.getOperatorId(), pageResult.getTotal());
  630. return buildSuccessResponse(responseData, thirdPartyInfo);
  631. } catch (Exception e) {
  632. log.error("处理query_charge_station_list请求异常", e);
  633. return buildErrorResponse(500, "系统错误", null);
  634. }
  635. }
  636. @Override
  637. public ThirdPartyResponse queryChargeStationDetail(ThirdPartyRequest request, String authorization) {
  638. try {
  639. // 1. 参数校验
  640. if (!validateRequestParams(request)) {
  641. return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
  642. }
  643. // 2. 通过operatorId查询第三方配置信息
  644. ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
  645. if (thirdPartyInfo == null) {
  646. log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
  647. return buildErrorResponse(4004, "运营商不存在", null);
  648. }
  649. // 3. 验证签名
  650. String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
  651. if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
  652. log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
  653. return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
  654. }
  655. // 4. 从Header中解析并验证Token
  656. String accessToken = parseAccessToken(authorization);
  657. if (StrUtil.isBlank(accessToken)) {
  658. log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
  659. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  660. }
  661. if (!validateAccessToken(accessToken, request.getOperatorId())) {
  662. log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
  663. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  664. }
  665. // 5. 解密并解析业务参数
  666. String decryptedData = AESCryptoUtils.decrypt(
  667. request.getData(),
  668. thirdPartyInfo.getDataSecret(),
  669. thirdPartyInfo.getDataSecretIV()
  670. );
  671. log.info("解密后的请求数据: {}", decryptedData);
  672. ChargeStationDetailRequestData detailRequest = objectMapper.readValue(decryptedData, ChargeStationDetailRequestData.class);
  673. if (detailRequest == null || (detailRequest.getStationId() == null )) {
  674. return buildErrorResponse(4003, "请求的业务参数不合法", thirdPartyInfo);
  675. }
  676. // 6. 查询充电站详情
  677. // 获取当前时间(HHmmss格式)
  678. String currentTime = LocalTime.now().format(TIME_FORMATTER);
  679. // 查询站点详情基本信息
  680. AppletStationDetailVO result = thirdPartyStationInfoMapper.selectStationDetail(
  681. detailRequest.getStationId(), detailRequest.getLongitude(), detailRequest.getLatitude(), currentTime, null
  682. );
  683. if (result == null) {
  684. return buildErrorResponse(4004, "充电站不存在", thirdPartyInfo);
  685. }
  686. // 查询站点对应的stationId
  687. ThirdPartyStationInfo stationInfo = thirdPartyStationInfoMapper.selectById(detailRequest.getStationId());
  688. if (stationInfo == null) {
  689. return buildErrorResponse(4004, "充电站不存在", thirdPartyInfo);
  690. }
  691. // 根据站点stationId查询设备列表(third_party_equipment_info)
  692. List<ThirdPartyEquipmentInfo> equipmentList = thirdPartyEquipmentInfoMapper.selectList(
  693. new LambdaQueryWrapper<ThirdPartyEquipmentInfo>()
  694. .eq(ThirdPartyEquipmentInfo::getStationId, stationInfo.getStationId())
  695. );
  696. // 构建设备ID到设备类型的映射
  697. Map<String, Integer> equipmentTypeMap = equipmentList.stream()
  698. .collect(Collectors.toMap(
  699. ThirdPartyEquipmentInfo::getEquipmentId,
  700. e -> e.getEquipmentType() != null ? e.getEquipmentType() : 0,
  701. (v1, v2) -> v1
  702. ));
  703. // 根据设备列表的equipmentId查询充电接口信息(third_party_connector_info)
  704. List<ThirdPartyConnectorInfo> connectorList = new ArrayList<>();
  705. if (!equipmentList.isEmpty()) {
  706. List<String> equipmentIds = equipmentList.stream()
  707. .map(ThirdPartyEquipmentInfo::getEquipmentId)
  708. .collect(Collectors.toList());
  709. connectorList = thirdPartyConnectorInfoMapper.selectList(
  710. new LambdaQueryWrapper<ThirdPartyConnectorInfo>()
  711. .in(ThirdPartyConnectorInfo::getEquipmentId, equipmentIds)
  712. );
  713. }
  714. // 统计终端状态
  715. int idleCount = 0;
  716. int occupiedCount = 0;
  717. int offlineCount = 0;
  718. List<AppletStationDetailVO.ConnectorInfoVO> connectorVOList = new ArrayList<>();
  719. for (ThirdPartyConnectorInfo connector : connectorList) {
  720. AppletStationDetailVO.ConnectorInfoVO vo = new AppletStationDetailVO.ConnectorInfoVO();
  721. vo.setConnectorId(connector.getId());
  722. vo.setConnectorName(connector.getConnectorName());
  723. vo.setConnectorCode(connector.getConnectorId());
  724. // 设备分类:从设备表获取设备类型(1-直流设备,2-交流设备,3-交直流一体设备,4-无线设备,5-其他)
  725. Integer equipmentType = equipmentTypeMap.get(connector.getEquipmentId());
  726. if (equipmentType != null) {
  727. switch (equipmentType) {
  728. case 1:
  729. vo.setEquipmentType("直流设备");
  730. break;
  731. case 2:
  732. vo.setEquipmentType("交流设备");
  733. break;
  734. case 3:
  735. vo.setEquipmentType("交直流一体设备");
  736. break;
  737. case 4:
  738. vo.setEquipmentType("无线设备");
  739. break;
  740. case 5:
  741. vo.setEquipmentType("其他");
  742. break;
  743. default:
  744. vo.setEquipmentType("未知");
  745. }
  746. }
  747. // 从充电接口表获取实际状态
  748. // 0-离网,1-空闲,2-占用(未充电),3-占用(充电中),4-占用(预约锁定),255-故障
  749. Integer connectorStatus = connector.getStatus();
  750. if (connectorStatus == null) {
  751. // 默认为离网
  752. connectorStatus = 0;
  753. }
  754. vo.setStatus(connectorStatus);
  755. // 设置状态名称并统计
  756. switch (connectorStatus) {
  757. case 0:
  758. vo.setStatusName("离网");
  759. offlineCount++;
  760. break;
  761. case 1:
  762. vo.setStatusName("空闲");
  763. idleCount++;
  764. break;
  765. case 2:
  766. vo.setStatusName("占用(未充电)");
  767. occupiedCount++;
  768. break;
  769. case 3:
  770. vo.setStatusName("占用(充电中)");
  771. occupiedCount++;
  772. break;
  773. case 4:
  774. vo.setStatusName("占用(预约锁定)");
  775. occupiedCount++;
  776. break;
  777. case 255:
  778. vo.setStatusName("故障");
  779. offlineCount++;
  780. break;
  781. default:
  782. vo.setStatusName("未知");
  783. offlineCount++;
  784. }
  785. connectorVOList.add(vo);
  786. }
  787. result.setConnectorList(connectorVOList);
  788. result.setIdleCount(idleCount);
  789. result.setOccupiedCount(occupiedCount);
  790. result.setOfflineCount(offlineCount);
  791. // 7. 转换为响应数据
  792. ChargeStationDetailResponseData responseData = convertToStationDetail(result);
  793. log.info("查询充电站详情成功, operatorId: {}, stationId: {}", request.getOperatorId(), stationInfo.getStationId());
  794. return buildSuccessResponse(responseData, thirdPartyInfo);
  795. } catch (Exception e) {
  796. log.error("处理query_charge_station_detail请求异常", e);
  797. return buildErrorResponse(500, "系统错误", null);
  798. }
  799. }
  800. @Override
  801. public ThirdPartyResponse queryChargeDeviceDetail(ThirdPartyRequest request, String authorization) {
  802. try {
  803. // 1. 参数校验
  804. if (!validateRequestParams(request)) {
  805. return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
  806. }
  807. // 2. 通过operatorId查询第三方配置信息
  808. ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
  809. if (thirdPartyInfo == null) {
  810. log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
  811. return buildErrorResponse(4004, "运营商不存在", null);
  812. }
  813. // 3. 验证签名
  814. String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
  815. if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
  816. log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
  817. return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
  818. }
  819. // 4. 从Header中解析并验证Token
  820. String accessToken = parseAccessToken(authorization);
  821. if (StrUtil.isBlank(accessToken)) {
  822. log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
  823. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  824. }
  825. if (!validateAccessToken(accessToken, request.getOperatorId())) {
  826. log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
  827. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  828. }
  829. // 5. 解密并解析业务参数
  830. String decryptedData = AESCryptoUtils.decrypt(
  831. request.getData(),
  832. thirdPartyInfo.getDataSecret(),
  833. thirdPartyInfo.getDataSecretIV()
  834. );
  835. log.info("解密后的请求数据: {}", decryptedData);
  836. ChargeDeviceDetailRequestData detailRequest = objectMapper.readValue(decryptedData, ChargeDeviceDetailRequestData.class);
  837. if (detailRequest == null || (detailRequest.getId() == null && StrUtil.isBlank(detailRequest.getEquipmentId()))) {
  838. return buildErrorResponse(4003, "请求的业务参数不合法", thirdPartyInfo);
  839. }
  840. // 6. 查询充电设备详情
  841. // 获取当前时间(HHmmss格式)
  842. String currentTime = LocalTime.now().format(TIME_FORMATTER);
  843. AppletConnectorDetailVO result = thirdPartyConnectorInfoMapper.selectConnectorDetailById(
  844. detailRequest.getEquipmentId(), null, currentTime, null, null
  845. );
  846. // 8. 转换为响应数据
  847. ChargeDeviceDetailResponseData responseData = convertToDeviceDetail(result);
  848. log.info("查询充电终端详情成功, operatorId: {}, equipmentId: {}", request.getOperatorId(), result.getConnectorId());
  849. return buildSuccessResponse(responseData, thirdPartyInfo);
  850. } catch (Exception e) {
  851. log.error("处理query_charge_device_detail请求异常", e);
  852. return buildErrorResponse(500, "系统错误", null);
  853. }
  854. }
  855. /**
  856. * 转换充电站信息为详情响应(从AppletStationDetailVO转换)
  857. */
  858. private ChargeStationDetailResponseData convertToStationDetail(AppletStationDetailVO result) {
  859. ChargeStationDetailResponseData detail = new ChargeStationDetailResponseData();
  860. detail.setStationId(result.getStationId());
  861. detail.setStationName(result.getStationName());
  862. detail.setTips(result.getTips());
  863. detail.setDistance(result.getDistance());
  864. detail.setAddress(result.getAddress());
  865. detail.setLongitude(result.getLongitude());
  866. detail.setLatitude(result.getLatitude());
  867. detail.setPictures(result.getPictures());
  868. detail.setCurrentPrice(result.getCurrentPrice());
  869. detail.setCurrentPeriod(result.getCurrentPeriod());
  870. detail.setOriginalPrice(result.getOriginalPrice());
  871. detail.setPeriodFlag(result.getPeriodFlag());
  872. detail.setIdleCount(result.getIdleCount());
  873. detail.setOccupiedCount(result.getOccupiedCount());
  874. detail.setOfflineCount(result.getOfflineCount());
  875. detail.setBusinessHours(result.getBusinessHours());
  876. detail.setServiceProvider(result.getServiceProvider());
  877. detail.setInvoiceProvider(result.getInvoiceProvider());
  878. detail.setCustomerServiceHotline(result.getCustomerServiceHotline());
  879. // 转换充电终端列表
  880. if (result.getConnectorList() != null) {
  881. List<ChargeStationDetailResponseData.ConnectorInfoVO> connectorVOList = result.getConnectorList().stream()
  882. .map(connector -> {
  883. ChargeStationDetailResponseData.ConnectorInfoVO vo = new ChargeStationDetailResponseData.ConnectorInfoVO();
  884. vo.setConnectorId(connector.getConnectorId());
  885. vo.setConnectorName(connector.getConnectorName());
  886. vo.setEquipmentType(connector.getEquipmentType());
  887. vo.setConnectorCode(connector.getConnectorCode());
  888. vo.setStatus(connector.getStatus());
  889. vo.setStatusName(connector.getStatusName());
  890. return vo;
  891. })
  892. .collect(Collectors.toList());
  893. detail.setConnectorList(connectorVOList);
  894. }
  895. return detail;
  896. }
  897. /**
  898. * 转换充电站信息为列表项
  899. */
  900. private ChargeStationListResponseData.StationItem convertToStationItem(StationInfoVO stationInfoVO) {
  901. ChargeStationListResponseData.StationItem item = new ChargeStationListResponseData.StationItem();
  902. item.setStationId(stationInfoVO.getStationId());
  903. item.setStationName(stationInfoVO.getStationName());
  904. item.setTips(stationInfoVO.getTips());
  905. item.setDistance(stationInfoVO.getDistance());
  906. item.setFastCharging(stationInfoVO.getFastCharging());
  907. item.setSlowCharging(stationInfoVO.getSlowCharging());
  908. item.setPeakValue(stationInfoVO.getPeakValue());
  909. item.setPeakTime(stationInfoVO.getPeakTime());
  910. item.setPeriodFlag(stationInfoVO.getPeriodFlag());
  911. item.setPlatformPrice(stationInfoVO.getPlatformPrice());
  912. return item;
  913. }
  914. /**
  915. * 转换充电设备信息为详情响应(从AppletConnectorDetailVO转换)
  916. */
  917. private ChargeDeviceDetailResponseData convertToDeviceDetail(AppletConnectorDetailVO connectorDetail) {
  918. ChargeDeviceDetailResponseData detail = new ChargeDeviceDetailResponseData();
  919. detail.setConnectorId(connectorDetail.getConnectorId());
  920. detail.setConnectorCode(connectorDetail.getConnectorCode());
  921. detail.setConnectorName(connectorDetail.getConnectorName());
  922. detail.setStationId(connectorDetail.getStationId());
  923. detail.setStationName(connectorDetail.getStationName());
  924. detail.setStationAddress(connectorDetail.getStationAddress());
  925. detail.setEquipmentId(connectorDetail.getEquipmentId());
  926. detail.setEquipmentCode(connectorDetail.getEquipmentCode());
  927. detail.setEquipmentName(connectorDetail.getEquipmentName());
  928. detail.setEquipmentType(connectorDetail.getEquipmentType());
  929. detail.setEquipmentTypeName(connectorDetail.getEquipmentTypeName());
  930. detail.setParkNo(connectorDetail.getParkNo());
  931. detail.setStatus(connectorDetail.getStatus());
  932. detail.setStatusName(connectorDetail.getStatusName());
  933. detail.setConnectorType(connectorDetail.getConnectorType());
  934. detail.setConnectorTypeName(connectorDetail.getConnectorTypeName());
  935. detail.setVoltageUpperLimits(connectorDetail.getVoltageUpperLimits());
  936. detail.setVoltageLowerLimits(connectorDetail.getVoltageLowerLimits());
  937. detail.setCurrent(connectorDetail.getCurrent());
  938. detail.setPower(connectorDetail.getPower());
  939. detail.setNationalStandard(connectorDetail.getNationalStandard());
  940. detail.setNationalStandardName(connectorDetail.getNationalStandardName());
  941. detail.setCurrentPrice(connectorDetail.getCurrentPrice());
  942. detail.setPeriodFlag(connectorDetail.getPeriodFlag());
  943. detail.setCurrentPeriodDesc(connectorDetail.getCurrentPeriodDesc());
  944. detail.setParkingTips(connectorDetail.getParkingTips());
  945. return detail;
  946. }
  947. @Override
  948. public ThirdPartyResponse invokeCharge(ThirdPartyRequest request, String authorization) {
  949. try {
  950. // 1. 参数校验
  951. if (!validateRequestParams(request)) {
  952. return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
  953. }
  954. // 2. 通过operatorId查询第三方配置信息
  955. ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
  956. if (thirdPartyInfo == null) {
  957. log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
  958. return buildErrorResponse(4004, "运营商不存在", null);
  959. }
  960. // 3. 验证签名
  961. String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
  962. if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
  963. log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
  964. return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
  965. }
  966. // 4. 从Header中解析并验证Token
  967. String accessToken = parseAccessToken(authorization);
  968. if (StrUtil.isBlank(accessToken)) {
  969. log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
  970. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  971. }
  972. if (!validateAccessToken(accessToken, request.getOperatorId())) {
  973. log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
  974. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  975. }
  976. // 5. 解密并解析业务参数
  977. String decryptedData = AESCryptoUtils.decrypt(
  978. request.getData(),
  979. thirdPartyInfo.getDataSecret(),
  980. thirdPartyInfo.getDataSecretIV()
  981. );
  982. log.info("启动充电-解密后的请求数据: {}", decryptedData);
  983. InvokeChargeRequestData invokeRequest = objectMapper.readValue(decryptedData, InvokeChargeRequestData.class);
  984. if (invokeRequest == null || StrUtil.isBlank(invokeRequest.getEquipmentId())
  985. || StrUtil.isBlank(invokeRequest.getStationId()) || StrUtil.isBlank(invokeRequest.getConnectorId())) {
  986. return buildErrorResponse(4003, "请求的业务参数不合法", thirdPartyInfo);
  987. }
  988. // 6. 构建启动充电表单
  989. AppInvokeChargeForm formData = new AppInvokeChargeForm();
  990. formData.setOrderType(2); // 渠道方订单
  991. formData.setEquipmentId(invokeRequest.getEquipmentId());
  992. formData.setStationId(invokeRequest.getStationId());
  993. formData.setConnectorId(invokeRequest.getConnectorId());
  994. formData.setChannelOrderNo(invokeRequest.getChannelOrderNo());
  995. formData.setChannelUserPhone(invokeRequest.getChannelUserPhone());
  996. formData.setChannelPreAmt(invokeRequest.getChannelPreAmt());
  997. // 7. 调用启动充电服务
  998. AppChargeVO chargeVO = chargeOrderInfoService.invokeCharge(formData);
  999. // 8. 构建响应数据
  1000. InvokeChargeResponseData responseData = InvokeChargeResponseData.success(
  1001. chargeVO.getChargeOrderId(),
  1002. chargeVO.getChargeOrderNo(),
  1003. chargeVO.getStatus()
  1004. );
  1005. log.info("启动充电成功, chargeOrderNo: {}", chargeVO.getChargeOrderNo());
  1006. return buildSuccessResponse(responseData, thirdPartyInfo);
  1007. } catch (Exception e) {
  1008. log.error("处理invoke_charge请求异常", e);
  1009. return buildErrorResponse(500, "系统错误: " + e.getMessage(), null);
  1010. }
  1011. }
  1012. @Override
  1013. public ThirdPartyResponse stopCharge(ThirdPartyRequest request, String authorization) {
  1014. try {
  1015. // 1. 参数校验
  1016. if (!validateRequestParams(request)) {
  1017. return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
  1018. }
  1019. // 2. 通过operatorId查询第三方配置信息
  1020. ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
  1021. if (thirdPartyInfo == null) {
  1022. log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
  1023. return buildErrorResponse(4004, "运营商不存在", null);
  1024. }
  1025. // 3. 验证签名
  1026. String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
  1027. if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
  1028. log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
  1029. return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
  1030. }
  1031. // 4. 从Header中解析并验证Token
  1032. String accessToken = parseAccessToken(authorization);
  1033. if (StrUtil.isBlank(accessToken)) {
  1034. log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
  1035. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  1036. }
  1037. if (!validateAccessToken(accessToken, request.getOperatorId())) {
  1038. log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
  1039. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  1040. }
  1041. // 5. 解密并解析业务参数
  1042. String decryptedData = AESCryptoUtils.decrypt(
  1043. request.getData(),
  1044. thirdPartyInfo.getDataSecret(),
  1045. thirdPartyInfo.getDataSecretIV()
  1046. );
  1047. log.info("停止充电-解密后的请求数据: {}", decryptedData);
  1048. StopChargeRequestData stopRequest = objectMapper.readValue(decryptedData, StopChargeRequestData.class);
  1049. if (stopRequest == null || StrUtil.isBlank(stopRequest.getChargeOrderNo())) {
  1050. return buildErrorResponse(4003, "请求的业务参数不合法", thirdPartyInfo);
  1051. }
  1052. // 6. 构建停止充电表单
  1053. AppStopChargeForm formData = new AppStopChargeForm();
  1054. formData.setChargeOrderNo(stopRequest.getChargeOrderNo());
  1055. // 7. 调用停止充电服务
  1056. AppChargeVO chargeVO = chargeOrderInfoService.stopCharge(formData);
  1057. // 8. 构建响应数据
  1058. StopChargeResponseData responseData = StopChargeResponseData.success(
  1059. chargeVO.getChargeOrderId(),
  1060. chargeVO.getChargeOrderNo(),
  1061. chargeVO.getStatus()
  1062. );
  1063. log.info("停止充电成功, chargeOrderNo: {}", chargeVO.getChargeOrderNo());
  1064. return buildSuccessResponse(responseData, thirdPartyInfo);
  1065. } catch (Exception e) {
  1066. log.error("处理stop_charge请求异常", e);
  1067. return buildErrorResponse(500, "系统错误: " + e.getMessage(), null);
  1068. }
  1069. }
  1070. @Override
  1071. public ThirdPartyResponse queryChargeOrderList(ThirdPartyRequest request, String authorization) {
  1072. try {
  1073. // 1. 参数校验
  1074. if (!validateRequestParams(request)) {
  1075. return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
  1076. }
  1077. // 2. 通过operatorId查询第三方配置信息
  1078. ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
  1079. if (thirdPartyInfo == null) {
  1080. log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
  1081. return buildErrorResponse(4004, "运营商不存在", null);
  1082. }
  1083. // 3. 验证签名
  1084. String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
  1085. if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
  1086. log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
  1087. return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
  1088. }
  1089. // 4. 从Header中解析并验证Token
  1090. String accessToken = parseAccessToken(authorization);
  1091. if (StrUtil.isBlank(accessToken)) {
  1092. log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
  1093. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  1094. }
  1095. if (!validateAccessToken(accessToken, request.getOperatorId())) {
  1096. log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
  1097. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  1098. }
  1099. // 5. 解密并解析业务参数
  1100. String decryptedData = AESCryptoUtils.decrypt(
  1101. request.getData(),
  1102. thirdPartyInfo.getDataSecret(),
  1103. thirdPartyInfo.getDataSecretIV()
  1104. );
  1105. log.info("查询充电订单列表-解密后的请求数据: {}", decryptedData);
  1106. ChargeOrderListRequestData listRequest = objectMapper.readValue(decryptedData, ChargeOrderListRequestData.class);
  1107. if (listRequest == null) {
  1108. listRequest = new ChargeOrderListRequestData();
  1109. }
  1110. // 6. 构建查询条件(只查询渠道类型订单 order_type=2)
  1111. LambdaQueryWrapper<com.zsElectric.boot.business.model.entity.ChargeOrderInfo> queryWrapper = Wrappers.lambdaQuery();
  1112. queryWrapper.eq(com.zsElectric.boot.business.model.entity.ChargeOrderInfo::getOrderType, SystemConstants.CHARGE_ORDER_TYPE_CHANNEL);
  1113. queryWrapper.eq(com.zsElectric.boot.business.model.entity.ChargeOrderInfo::getOperatorId, listRequest.getOperatorId());
  1114. queryWrapper.eq(com.zsElectric.boot.business.model.entity.ChargeOrderInfo::getIsDeleted, 0);
  1115. // 可选条件:userId
  1116. if (listRequest.getUserId() != null) {
  1117. queryWrapper.eq(com.zsElectric.boot.business.model.entity.ChargeOrderInfo::getUserId, listRequest.getUserId());
  1118. }
  1119. // 可选条件:chargeOrderNo
  1120. if (StrUtil.isNotBlank(listRequest.getChargeOrderNo())) {
  1121. queryWrapper.like(com.zsElectric.boot.business.model.entity.ChargeOrderInfo::getChargeOrderNo, listRequest.getChargeOrderNo());
  1122. }
  1123. // 按创建时间倒序
  1124. queryWrapper.orderByDesc(com.zsElectric.boot.business.model.entity.ChargeOrderInfo::getCreateTime);
  1125. // 7. 分页查询
  1126. long pageNo = listRequest.getPageNo() != null && listRequest.getPageNo() > 0 ? listRequest.getPageNo() : 1L;
  1127. long pageSize = listRequest.getPageSize() != null && listRequest.getPageSize() > 0 ? listRequest.getPageSize() : 10L;
  1128. Page<com.zsElectric.boot.business.model.entity.ChargeOrderInfo> page = new Page<>(pageNo, pageSize);
  1129. IPage<com.zsElectric.boot.business.model.entity.ChargeOrderInfo> pageResult = chargeOrderInfoService.page(page, queryWrapper);
  1130. // 8. 转换为响应数据
  1131. List<ChargeOrderListResponseData.ChargeOrderItem> records = pageResult.getRecords().stream()
  1132. .map(this::convertToChargeOrderItem)
  1133. .collect(Collectors.toList());
  1134. ChargeOrderListResponseData responseData = ChargeOrderListResponseData.of(
  1135. pageResult.getTotal(),
  1136. pageResult.getCurrent(),
  1137. pageResult.getSize(),
  1138. pageResult.getPages(),
  1139. records
  1140. );
  1141. log.info("查询充电订单列表成功, operatorId: {}, total: {}", request.getOperatorId(), pageResult.getTotal());
  1142. return buildSuccessResponse(responseData, thirdPartyInfo);
  1143. } catch (Exception e) {
  1144. log.error("处理query_charge_order_list请求异常", e);
  1145. return buildErrorResponse(500, "系统错误: " + e.getMessage(), null);
  1146. }
  1147. }
  1148. /**
  1149. * 将ChargeOrderInfo转换为ChargeOrderItem
  1150. */
  1151. private ChargeOrderListResponseData.ChargeOrderItem convertToChargeOrderItem(com.zsElectric.boot.business.model.entity.ChargeOrderInfo order) {
  1152. ChargeOrderListResponseData.ChargeOrderItem item = new ChargeOrderListResponseData.ChargeOrderItem();
  1153. item.setId(order.getId());
  1154. item.setUserId(order.getUserId());
  1155. item.setChargeOrderNo(order.getChargeOrderNo());
  1156. item.setEquipmentId(order.getEquipmentId());
  1157. item.setConnectorId(order.getConnectorId());
  1158. item.setStartTime(order.getStartTime());
  1159. item.setEndTime(order.getEndTime());
  1160. item.setChargeTime(order.getChargeTime());
  1161. item.setTotalCharge(order.getTotalCharge());
  1162. item.setStatus(order.getStatus());
  1163. item.setPreAmt(order.getPreAmt());
  1164. item.setPhoneNum(order.getPhoneNum());
  1165. item.setPlateNum(order.getPlateNum());
  1166. item.setStopType(order.getStopType());
  1167. item.setStopReason(order.getStopReason());
  1168. item.setCreateTime(order.getCreateTime() != null ? order.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : null);
  1169. // 查询充电站名称
  1170. if (order.getThirdPartyStationId() != null) {
  1171. ThirdPartyStationInfo stationInfo = thirdPartyStationInfoMapper.selectById(order.getThirdPartyStationId());
  1172. if (stationInfo != null) {
  1173. item.setStationName(stationInfo.getStationName());
  1174. }
  1175. }
  1176. // 查询充电设备接口名称
  1177. if (StrUtil.isNotBlank(order.getConnectorId())) {
  1178. ThirdPartyConnectorInfo connectorInfo = thirdPartyConnectorInfoMapper.selectOne(
  1179. Wrappers.<ThirdPartyConnectorInfo>lambdaQuery()
  1180. .eq(ThirdPartyConnectorInfo::getConnectorId, order.getConnectorId())
  1181. .last("LIMIT 1")
  1182. );
  1183. if (connectorInfo != null) {
  1184. item.setConnectorName(connectorInfo.getConnectorName());
  1185. }
  1186. }
  1187. return item;
  1188. }
  1189. @Override
  1190. public ThirdPartyResponse queryChargeOrderInfo(ThirdPartyRequest request, String authorization) {
  1191. try {
  1192. // 1. 参数校验
  1193. if (!validateRequestParams(request)) {
  1194. return buildErrorResponse(4003, "参数不合法,缺少必需的参数", null);
  1195. }
  1196. // 2. 通过operatorId查询第三方配置信息
  1197. ThirdPartyInfo thirdPartyInfo = getThirdPartyInfoByOperatorId(request.getOperatorId());
  1198. if (thirdPartyInfo == null) {
  1199. log.warn("运营商不存在, operatorId: {}", request.getOperatorId());
  1200. return buildErrorResponse(4004, "运营商不存在", null);
  1201. }
  1202. // 3. 验证签名
  1203. String signContent = request.getOperatorId() + request.getData() + request.getTimeStamp() + request.getSeq();
  1204. if (!HmacMD5Util.verify(signContent, thirdPartyInfo.getSigSecret(), request.getSig())) {
  1205. log.warn("签名验证失败, operatorId: {}", request.getOperatorId());
  1206. return buildErrorResponse(4001, "签名错误", thirdPartyInfo);
  1207. }
  1208. // 4. 从Header中解析并验证Token
  1209. String accessToken = parseAccessToken(authorization);
  1210. if (StrUtil.isBlank(accessToken)) {
  1211. log.warn("Token为空或格式错误, operatorId: {}", request.getOperatorId());
  1212. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  1213. }
  1214. if (!validateAccessToken(accessToken, request.getOperatorId())) {
  1215. log.warn("Token验证失败, operatorId: {}", request.getOperatorId());
  1216. return buildErrorResponse(4002, "token错误", thirdPartyInfo);
  1217. }
  1218. // 5. 解密并解析业务参数
  1219. String decryptedData = AESCryptoUtils.decrypt(
  1220. request.getData(),
  1221. thirdPartyInfo.getDataSecret(),
  1222. thirdPartyInfo.getDataSecretIV()
  1223. );
  1224. log.info("查询充电订单详情-解密后的请求数据: {}", decryptedData);
  1225. ChargeOrderDetailRequestData detailRequest = objectMapper.readValue(decryptedData, ChargeOrderDetailRequestData.class);
  1226. if (detailRequest == null || StrUtil.isBlank(detailRequest.getChargeOrderNo())) {
  1227. return buildErrorResponse(4003, "请求的业务参数不合法,chargeOrderNo不能为空", thirdPartyInfo);
  1228. }
  1229. // 6. 查询订单(只查询渠道类型订单 order_type=2)
  1230. com.zsElectric.boot.business.model.entity.ChargeOrderInfo order = chargeOrderInfoService.getOne(
  1231. Wrappers.<com.zsElectric.boot.business.model.entity.ChargeOrderInfo>lambdaQuery()
  1232. .eq(com.zsElectric.boot.business.model.entity.ChargeOrderInfo::getChargeOrderNo, detailRequest.getChargeOrderNo())
  1233. .eq(com.zsElectric.boot.business.model.entity.ChargeOrderInfo::getOrderType, SystemConstants.CHARGE_ORDER_TYPE_CHANNEL)
  1234. .eq(com.zsElectric.boot.business.model.entity.ChargeOrderInfo::getIsDeleted, 0)
  1235. .last("LIMIT 1")
  1236. );
  1237. if (order == null) {
  1238. log.warn("充电订单不存在或不是渠道订单, chargeOrderNo: {}", detailRequest.getChargeOrderNo());
  1239. ChargeOrderDetailResponseData failData = ChargeOrderDetailResponseData.fail("充电订单不存在或不是渠道订单");
  1240. return buildSuccessResponse(failData, thirdPartyInfo);
  1241. }
  1242. // 7. 构建响应数据
  1243. ChargeOrderDetailResponseData responseData = ChargeOrderDetailResponseData.success();
  1244. responseData.setId(order.getId());
  1245. responseData.setUserId(order.getUserId());
  1246. responseData.setChargeOrderNo(order.getChargeOrderNo());
  1247. responseData.setEquipmentId(order.getEquipmentId());
  1248. responseData.setConnectorId(order.getConnectorId());
  1249. responseData.setStartTime(order.getStartTime());
  1250. responseData.setEndTime(order.getEndTime());
  1251. responseData.setChargeTime(order.getChargeTime());
  1252. responseData.setTotalCharge(order.getTotalCharge());
  1253. responseData.setStatus(order.getStatus());
  1254. responseData.setPreAmt(order.getPreAmt());
  1255. responseData.setPhoneNum(order.getPhoneNum());
  1256. responseData.setPlateNum(order.getPlateNum());
  1257. responseData.setStopType(order.getStopType());
  1258. responseData.setStopReason(order.getStopReason());
  1259. responseData.setCreateTime(order.getCreateTime() != null ? order.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : null);
  1260. // 查询充电站名称
  1261. if (order.getThirdPartyStationId() != null) {
  1262. ThirdPartyStationInfo stationInfo = thirdPartyStationInfoMapper.selectById(order.getThirdPartyStationId());
  1263. if (stationInfo != null) {
  1264. responseData.setStationName(stationInfo.getStationName());
  1265. }
  1266. }
  1267. // 查询充电设备接口名称
  1268. if (StrUtil.isNotBlank(order.getConnectorId())) {
  1269. ThirdPartyConnectorInfo connectorInfo = thirdPartyConnectorInfoMapper.selectOne(
  1270. Wrappers.<ThirdPartyConnectorInfo>lambdaQuery()
  1271. .eq(ThirdPartyConnectorInfo::getConnectorId, order.getConnectorId())
  1272. .last("LIMIT 1")
  1273. );
  1274. if (connectorInfo != null) {
  1275. responseData.setConnectorName(connectorInfo.getConnectorName());
  1276. }
  1277. }
  1278. log.info("查询充电订单详情成功, chargeOrderNo: {}", detailRequest.getChargeOrderNo());
  1279. return buildSuccessResponse(responseData, thirdPartyInfo);
  1280. } catch (Exception e) {
  1281. log.error("处理query_charge_order_info请求异常", e);
  1282. return buildErrorResponse(500, "系统错误: " + e.getMessage(), null);
  1283. }
  1284. }
  1285. }