package com.cyksj.server.recharge.impl; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.cyksj.common.constant.Constant; import com.cyksj.common.exception.BusinessRuntimeException; import com.cyksj.common.task.GlobalThreadPoolTaskExecutor; import com.cyksj.mapper.*; import com.cyksj.model.entity.*; import com.cyksj.model.request.GroupsRelationRechargeReq; import com.cyksj.server.recharge.GptProxyRechargeService; import com.cyksj.server.recharge.dto.CardKeyValidationResult; import com.cyksj.server.recharge.dto.TaskResult; import com.cyksj.server.recharge.dto.TaskSubmitResult; import com.cyksj.server.recharge.dto.TokenParseResult; import com.cyksj.service.user.UserBindRelationService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; /** * @author chan * @date 2025/7/30 18:55 */ @Slf4j @Service @RequiredArgsConstructor public class GptProxyRechargeServiceImpl implements GptProxyRechargeService { private static final String BASE_URL = "https://api.ow520.com/api"; private final GptRechargeCardKeyMapper gptRechargeCardKeyMapper; private final GroupsRelationMapper relationMapper; private final UserBindRelationService userBindRelationService; private GroupsMapper groupsMapper; private final GoodsDonSkuMapper skuMapper; private final OrderDonMapper orderDonMapper; private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance(); private HttpRequest createBaseRequest(String uri) { return HttpRequest.get(BASE_URL + uri) .header("accept", "application/json, text/plain, */*") .header("accept-language", "zh-CN,zh;q=0.9,en;q=0.8") .header("origin", "https://www.ow520.com") .header("referer", "https://www.ow520.com/") .header("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"); } public CardKeyValidationResult validateCardKey(String cardKey) { log.info("开始验证卡密: {}", cardKey); try { HttpResponse response = createBaseRequest("/card-keys/" + cardKey) .execute(); String body = response.body(); log.info("卡密验证响应: {}", body); JSONObject jsonResponse = JSONUtil.parseObj(body); CardKeyValidationResult result = new CardKeyValidationResult( jsonResponse.getBool("available") ); //{"available":false,"error":"卡密已被使用"} log.info("卡密验证结果: {}", result); return result; } catch (Exception e) { log.error("验证卡密失败: {}", e.getMessage(), e); throw new RuntimeException("验证卡密失败: " + e.getMessage(), e); } } public TokenParseResult parseToken(String accessToken) { log.info("开始验证凭证: {}", accessToken.substring(0, Math.min(20, accessToken.length())) + "..."); try { String url = BASE_URL + "/parse-token"; JSONObject requestBody = new JSONObject(); requestBody.put("access_token", accessToken); HttpResponse response = HttpRequest.post(url) .header("accept", "application/json, text/plain, */*") .header("accept-language", "zh-CN,zh;q=0.9,en;q=0.8") .header("content-type", "application/json") .header("origin", "https://www.ow520.com") .header("referer", "https://www.ow520.com/") .header("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36") .body(requestBody.toString()) .execute(); String body = response.body(); log.info("凭证验证响应: {}", body); JSONObject jsonResponse = JSONUtil.parseObj(body); TokenParseResult result = new TokenParseResult( jsonResponse.getStr("message"), jsonResponse.getBool("success") ); log.info("凭证验证结果: {}", result); return result; } catch (Exception e) { log.error("验证凭证失败: {}", e.getMessage(), e); throw new RuntimeException("验证凭证失败: " + e.getMessage(), e); } } public TaskSubmitResult submitTask(String cardKey, String accessToken, String idp) { log.info("开始提交任务 - 卡密: {}, idp: {}", cardKey, idp); try { String url = BASE_URL + "/tasks"; JSONObject requestBody = new JSONObject(); requestBody.put("card_key", cardKey); requestBody.put("access_token", accessToken); requestBody.put("idp", idp); HttpResponse response = HttpRequest.post(url) .header("accept", "application/json, text/plain, */*") .header("accept-language", "zh-CN,zh;q=0.9,en;q=0.8") .header("content-type", "application/json") .header("origin", "https://www.ow520.com") .header("referer", "https://www.ow520.com/") .header("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36") .body(requestBody.toString()) .execute(); String body = response.body(); log.info("任务提交响应: {}", body); JSONObject jsonResponse = JSONUtil.parseObj(body); TaskSubmitResult result = new TaskSubmitResult( jsonResponse.getStr("task_id"), jsonResponse.getBool("success") ); log.info("任务提交结果: {}", result); return result; } catch (Exception e) { log.error("提交任务失败: {}", e.getMessage(), e); throw new RuntimeException("提交任务失败: " + e.getMessage(), e); } } public TaskResult getTaskResult(String taskId) { log.info("开始查询任务结果: {}", taskId); try { String uri = "/tasks/" + taskId; HttpResponse response = createBaseRequest(uri) .execute(); String body = response.body(); log.info("任务查询响应: {}", body); JSONObject jsonResponse = JSONUtil.parseObj(body); TaskResult result = new TaskResult( jsonResponse.getStr("status"), jsonResponse.getStr("result") ); log.info("任务查询结果: {}", result); String status = result.getStatus(); //更新代充状态 resetGroupsRelationRechargeStatus(taskId, status); return result; } catch (Exception e) { log.error("获取任务结果失败: {}", e.getMessage(), e); throw new RuntimeException("获取任务结果失败: " + e.getMessage(), e); } } @Override @Transactional(rollbackFor = Throwable.class) public String confirmRecharge(GroupsRelationRechargeReq req) { Long relationId = req.getRelationId(); Long userId = req.getUserId(); List userIdList = userBindRelationService.getRelationUserIdList(userId, null); GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class) .in(GroupsRelation::getUserId, userIdList) .eq(GroupsRelation::getId, relationId) .eq(GroupsRelation::getStatus, GroupsRelation.Status.validity)); if (relation == null) { throw BusinessRuntimeException.getInstance("车票不存在"); } GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId()); GoodsDonSku sku = skuMapper.selectById(groupsTrips.getSkuId()); //GPT 代充 if (sku.getGoodsId() != Constant.GPT_RECHARGE_GOODS_ID) { throw BusinessRuntimeException.getInstance("车票类型错误"); } Integer rechargeRemainNum = relation.getRechargeRemainNum(); if (rechargeRemainNum == null || rechargeRemainNum <= 0) { throw BusinessRuntimeException.getInstance("剩余可代充次数为0"); } if (relation.getRechargeStatus() == GroupsRelation.RechargeStatus.auto_recharge) { throw BusinessRuntimeException.getInstance("自动充值中"); } int updateRemainNum = relationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class) .set(GroupsRelation::getRechargeRemainNum, rechargeRemainNum - 1) .eq(GroupsRelation::getId, relationId) .eq(GroupsRelation::getUserId, relation.getUserId()) .eq(GroupsRelation::getRechargeRemainNum, rechargeRemainNum)); if (updateRemainNum == 0) { throw BusinessRuntimeException.getInstance("代充异常,请重试"); } OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class) .in(OrderDon::getUserId, userIdList) .eq(OrderDon::getRelationId, relation) .notIn(OrderDon::getStatus, Constant.noOrderAllStatus) .orderByDesc(OrderDon::getId) .last("limit 1")); if (orderDon == null) { throw BusinessRuntimeException.getInstance("代充订单不存在或已退款"); } String accessToken = req.getAccessToken(); //验证用户token是否正确 TokenParseResult tokenParseResult = parseToken(accessToken); if (!tokenParseResult.getSuccess()) { throw BusinessRuntimeException.getInstance("您输入的凭证有误,请重新输入"); } String rechargeAccount = tokenParseResult.getMessage(); //获取GPT代充key GptRechargeCardKey gptRechargeCardKey = gptRechargeCardKeyMapper.selectOne(Wrappers.lambdaQuery(GptRechargeCardKey.class) .eq(GptRechargeCardKey::getStatus, Boolean.FALSE) .last("order by rand() limit 1")); if (gptRechargeCardKey != null) { setRechargeRelationStatusAutoError(relation); throw BusinessRuntimeException.getInstance("充值失败,请联系客服开通"); } int update = gptRechargeCardKeyMapper.update(null, Wrappers.lambdaUpdate(GptRechargeCardKey.class) .set(GptRechargeCardKey::getStatus, Boolean.TRUE) .set(GptRechargeCardKey::getOrderId, orderDon.getId()) .set(GptRechargeCardKey::getOrderNo, orderDon.getOrderNo()) .eq(GptRechargeCardKey::getId, gptRechargeCardKey.getId()) .eq(GptRechargeCardKey::getStatus, Boolean.FALSE)); if (update == 0) { setRechargeRelationStatusAutoError(relation); throw BusinessRuntimeException.getInstance("充值失败,请联系客服开通"); } String gptCardKey = gptRechargeCardKey.getCardKey(); //校验卡密是否可用 validateCardKey(gptCardKey); //提交任务 TaskSubmitResult result = submitTask(gptCardKey, accessToken, "auth0"); if (!result.getSuccess()) { setRechargeRelationStatusAutoError(relation); throw BusinessRuntimeException.getInstance("充值失败,请联系客服开通"); } relation.setAccount(rechargeAccount); relation.setGptToken(accessToken); relation.setRechargeStatus(GroupsRelation.RechargeStatus.auto_recharge); relation.setCardKey(gptCardKey); String taskId = result.getTaskId(); relation.setGptTaskId(taskId); relationMapper.updateById(relation); return taskId; } /** * 设置代充自动充值异常 */ public void setRechargeRelationStatusAutoError(GroupsRelation relation) { TASK_EXECUTOR.execute(()->{ relation.setRechargeStatus(GroupsRelation.RechargeStatus.auto_error); relationMapper.updateById(relation); }); } /** * 更新代充状态 */ private void resetGroupsRelationRechargeStatus(String taskId, String status) { if ("completed".equals(status) || !"processing".equals(status)) { GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class) .eq(GroupsRelation::getGptTaskId, taskId) .last("limit 1")); if (relation != null && relation.getRechargeStatus() == GroupsRelation.RechargeStatus.auto_recharge) { Integer rechargeRemainNum = relation.getRechargeRemainNum(); GroupsRelation.RechargeStatus rechargeStatus = "completed".equals(status) ? GroupsRelation.RechargeStatus.complete : GroupsRelation.RechargeStatus.auto_error; if (rechargeStatus == GroupsRelation.RechargeStatus.auto_error) { String cardKey = relation.getCardKey(); GptRechargeCardKey gptRechargeCardKey = gptRechargeCardKeyMapper.selectOne(Wrappers.lambdaQuery(GptRechargeCardKey.class) .eq(GptRechargeCardKey::getCardKey, cardKey) .last("limit 1")); if (gptRechargeCardKey != null) { gptRechargeCardKeyMapper.update(null, Wrappers.lambdaUpdate(GptRechargeCardKey.class) .set(GptRechargeCardKey::getStatus, Boolean.FALSE) .set(GptRechargeCardKey::getOrderId, null) .set(GptRechargeCardKey::getOrderNo, null) .eq(GptRechargeCardKey::getId, gptRechargeCardKey.getId()) .eq(GptRechargeCardKey::getStatus, Boolean.TRUE)); } } relationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class) .set(rechargeStatus == GroupsRelation.RechargeStatus.auto_error, GroupsRelation::getRechargeRemainNum, rechargeRemainNum + 1) .set(GroupsRelation::getRechargeStatus, rechargeStatus) .eq(GroupsRelation::getId, relation.getId()) .eq(GroupsRelation::getRechargeStatus, GroupsRelation.RechargeStatus.auto_recharge)); } } } }