From 3e37608766e57299b12075dbb75d7fbf2d3f28d8 Mon Sep 17 00:00:00 2001 From: huangqizhen <15552608129@163.com> Date: Thu, 18 Dec 2025 09:37:17 +0800 Subject: [PATCH] =?UTF-8?q?12.17=20=E7=BA=A2=E5=8C=85=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/demo/Util/BaseDES3.java | 100 +++++++++++++++ .../demo/controller/Temporary/RedController.java | 10 ++ .../java/com/example/demo/domain/vo/RedList.java | 28 +++++ .../example/demo/domain/vo/coin/ConsumeUser.java | 2 + .../example/demo/service/Temporary/RedService.java | 6 +- .../demo/serviceImpl/Temporary/RedServiceImpl.java | 138 ++++++++++++++++++++- .../demo/serviceImpl/coin/ConsumeServiceImpl.java | 2 +- src/main/resources/application-prod.yml | 1 + src/main/resources/application-test.yml | 1 + 9 files changed, 281 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/example/demo/Util/BaseDES3.java create mode 100644 src/main/java/com/example/demo/domain/vo/RedList.java diff --git a/src/main/java/com/example/demo/Util/BaseDES3.java b/src/main/java/com/example/demo/Util/BaseDES3.java new file mode 100644 index 0000000..4e1e5e8 --- /dev/null +++ b/src/main/java/com/example/demo/Util/BaseDES3.java @@ -0,0 +1,100 @@ +package com.example.demo.Util; + + +import javax.crypto.Cipher; +import java.security.Key; + + +public class BaseDES3 { + private static String strDefaultKey = "98hltleg"; + + private Cipher encryptCipher = null; + + private Cipher decryptCipher = null; + + public static String byteArr2HexStr(byte[] arrB) throws Exception { + int iLen = arrB.length; + + StringBuffer sb = new StringBuffer(iLen * 2); + for (int i = 0; i < iLen; i++) { + int intTmp = arrB[i]; + + while (intTmp < 0) { + intTmp = intTmp + 256; + } + + if (intTmp < 16) { + sb.append("0"); + } + sb.append(Integer.toString(intTmp, 16)); + } + return sb.toString(); + } + + public static byte[] hexStr2ByteArr(String strIn) { + byte[] arrB = strIn.getBytes(); + int iLen = arrB.length; + + byte[] arrOut = new byte[iLen / 2]; + for (int i = 0; i < iLen; i = i + 2) { + String strTmp = new String(arrB, i, 2); + arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16); + } + return arrOut; + } + + public BaseDES3() throws Exception { + this(strDefaultKey); + } + + public BaseDES3(String strKey) throws Exception { + + Key key = getKey(strKey.getBytes()); + + encryptCipher = Cipher.getInstance("DES"); + encryptCipher.init(Cipher.ENCRYPT_MODE, key); + + decryptCipher = Cipher.getInstance("DES"); + decryptCipher.init(Cipher.DECRYPT_MODE, key); + } + + public byte[] encrypt(byte[] arrB) throws Exception { + return encryptCipher.doFinal(arrB); + } + + public String encrypt(String strIn) throws Exception { + return byteArr2HexStr(encrypt(strIn.getBytes())); + } + + public byte[] decrypt(byte[] arrB) throws Exception { + return decryptCipher.doFinal(arrB); + } + + public String decrypt(String strIn) throws Exception { + return new String(decrypt(hexStr2ByteArr(strIn))); + } + + private Key getKey(byte[] arrBTmp) { + + byte[] arrB = new byte[8]; + + for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) { + arrB[i] = arrBTmp[i]; + } + + Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES"); + + return key; + } + + + public static void main(String args[]) { + try { + BaseDES3 d = new BaseDES3(); + String encryptedText = d.encrypt("90035176"); + System.out.println("加密结果:" + encryptedText); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/example/demo/controller/Temporary/RedController.java b/src/main/java/com/example/demo/controller/Temporary/RedController.java index 332c3cc..5cd679c 100644 --- a/src/main/java/com/example/demo/controller/Temporary/RedController.java +++ b/src/main/java/com/example/demo/controller/Temporary/RedController.java @@ -36,4 +36,14 @@ public class RedController { } return Result.success(redService.selectSum(red.getJwcode(),red.getType())); } + @RequestMapping("/RedList") + public Result selectRedList(@RequestBody Red red) { + try { + redService.selectRedList(red.getJwcode()); + } + catch (Exception e) { + return Result.error(e.getMessage()); + } + return Result.success(redService.selectRedList(red.getJwcode())); + } } diff --git a/src/main/java/com/example/demo/domain/vo/RedList.java b/src/main/java/com/example/demo/domain/vo/RedList.java new file mode 100644 index 0000000..71161a6 --- /dev/null +++ b/src/main/java/com/example/demo/domain/vo/RedList.java @@ -0,0 +1,28 @@ +package com.example.demo.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * @program: GOLD + * @ClassName RedList + * @description: + * @author: huangqizhen + * @create: 2025−12-17 14:59 + * @Version 1.0 + **/ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RedList { + private Integer id; + private String title; + private BigDecimal discount; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") + private Date end_time; +} diff --git a/src/main/java/com/example/demo/domain/vo/coin/ConsumeUser.java b/src/main/java/com/example/demo/domain/vo/coin/ConsumeUser.java index 50d76dc..dea46e3 100644 --- a/src/main/java/com/example/demo/domain/vo/coin/ConsumeUser.java +++ b/src/main/java/com/example/demo/domain/vo/coin/ConsumeUser.java @@ -85,5 +85,7 @@ public class ConsumeUser implements Serializable { private BigDecimal price; // 折扣金币 @ExcelIgnore private Integer redMoney; //是否用红包 + @ExcelIgnore + private List redIds; } diff --git a/src/main/java/com/example/demo/service/Temporary/RedService.java b/src/main/java/com/example/demo/service/Temporary/RedService.java index 8d7f250..b95c8b4 100644 --- a/src/main/java/com/example/demo/service/Temporary/RedService.java +++ b/src/main/java/com/example/demo/service/Temporary/RedService.java @@ -1,8 +1,10 @@ package com.example.demo.service.Temporary; import com.example.demo.domain.vo.Red; +import com.example.demo.domain.vo.RedList; import java.math.BigDecimal; +import java.util.List; /** * @program: GOLD @@ -19,5 +21,7 @@ public interface RedService { String sendJwcode(Integer jwcode); BigDecimal selectRedSum(Integer jwcode); - String sendConsumeJwcode(Integer jwcode, BigDecimal price); + String sendConsumeJwcode(Integer jwcode, List redIds ); + + List selectRedList(Integer jwcode); } diff --git a/src/main/java/com/example/demo/serviceImpl/Temporary/RedServiceImpl.java b/src/main/java/com/example/demo/serviceImpl/Temporary/RedServiceImpl.java index 0260142..b88e6d6 100644 --- a/src/main/java/com/example/demo/serviceImpl/Temporary/RedServiceImpl.java +++ b/src/main/java/com/example/demo/serviceImpl/Temporary/RedServiceImpl.java @@ -1,9 +1,11 @@ package com.example.demo.serviceImpl.Temporary; import com.alibaba.fastjson.JSON; +import com.example.demo.Util.BaseDES3; import com.example.demo.Util.BusinessException; import com.example.demo.config.RedTimeRuleConfig; import com.example.demo.domain.vo.Red; +import com.example.demo.domain.vo.RedList; import com.example.demo.exception.SystemException; import com.example.demo.mapper.Temporary.RedMapper; import com.example.demo.service.Temporary.RedService; @@ -18,12 +20,21 @@ import org.springframework.transaction.annotation.Transactional; import java.io.IOException; import java.math.BigDecimal; +import java.net.ConnectException; +import java.net.SocketTimeoutException; import java.net.URI; +import java.net.URLEncoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.time.Duration; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeoutException; /** @@ -38,10 +49,15 @@ import java.time.format.DateTimeFormatter; @Service public class RedServiceImpl implements RedService { @Value("${red.url}") - private String BASE_URLProd ; - private static final String BASE_URLDev = "http://gf977328.natappfree.cc"; + private String BASE_URLProd; + @Value("${red.urllogin}") + private String BASE_URL_LOGIN; + private static final String BASE_URLDev = "http://af9c6249.natappfree.cc"; private static final String PATH = "/api/coupon/IssueRechargeRedPacket"; private static final String PATHRED = "/api/coupon/getTotalDiscount"; + private static final String BASE_URL = "http://localhost:8080"; + private static final String PATHLIST = "/api/coupon/getRedPacket"; + private static final String PATHLOGIN = "/api/user/toujiaoAppLogin"; private static final String CONSUME_PATH = "/api/coupon/updateCostRedPacket"; private static final HttpClient CLIENT = HttpClient.newHttpClient(); @@ -113,11 +129,11 @@ public class RedServiceImpl implements RedService { } } @Override - public String sendConsumeJwcode(Integer jwcode, BigDecimal price) { + public String sendConsumeJwcode(Integer jwcode,List redIds) { try { - String body = JSON.toJSONString(java.util.Map.of("jwcode", jwcode,"discount",price)); + String body = JSON.toJSONString(java.util.Map.of("jwcode", jwcode,"coupon_ids",redIds)); HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(BASE_URLProd + CONSUME_PATH)) //URL记得换 + .uri(URI.create(BASE_URLDev + CONSUME_PATH)) //URL记得换 .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(body)) .build(); @@ -134,6 +150,74 @@ public class RedServiceImpl implements RedService { } } + + @Override + public List selectRedList(Integer jwcode) { + try { + BaseDES3 d = new BaseDES3(); + String encryptedText = d.encrypt(String.valueOf(jwcode)); + String token = loginAndGetToken(encryptedText); + // 构造请求体 + String body = JSON.toJSONString(Map.of( + "type", "1", + "token", token + )); + + log.debug("请求红包列表,用户ID: {}, URL: {}", jwcode, BASE_URLDev + PATHLIST); + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(BASE_URLDev + PATHLIST)) + .timeout(Duration.ofSeconds(10)) // ⭐ 加超时防止线程阻塞 + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(body)) + .build(); + + HttpResponse resp = CLIENT.send(request, HttpResponse.BodyHandlers.ofString()); + + // 检查 HTTP 状态码 + if (resp.statusCode() != 200) { + log.error("红包服务返回非200状态码: {},响应: {}", resp.statusCode(), resp.body()); + throw new BusinessException("红包服务异常,请稍后重试"); + } + + // 解析 JSON + ObjectMapper mapper = new ObjectMapper(); + JsonNode root = mapper.readTree(resp.body()); + + // 检查是否成功(根据你的接口约定,可能 code==200 表示成功) + // 示例:假设 {"code":200, "data": {...}} + if (!root.has("data")) { + String msg = root.has("msg") ? root.get("msg").asText() : "未知错误"; + log.warn("红包服务返回无data字段,响应: {}", resp.body()); + throw new BusinessException("数据格式异常: " + msg); + } + + JsonNode dataNode = root.get("data"); + log.debug("收到红包数据: num={}, total={}, 红包数={}", + dataNode.has("num") ? dataNode.get("num").asInt() : "N/A", + dataNode.has("total") ? dataNode.get("total").asInt() : "N/A", + dataNode.has("red_packet_list") ? dataNode.get("red_packet_list").size() : 0); + + // ✅ 关键:提取 red_packet_list 并映射为 List + JsonNode listNode = dataNode.get("red_packet_list"); + if (listNode == null || listNode.isNull() || !listNode.isArray()) { + log.warn("red_packet_list 字段为空或非数组"); + return Collections.emptyList(); + } + + // 使用 Jackson 的正确方法转换 JSON Array → List + List result = mapper.readValue(mapper.treeAsTokens(listNode), + mapper.getTypeFactory().constructCollectionType(List.class, RedList.class)); + + log.info("成功获取红包列表,用户ID: {}, 数量: {}", jwcode, result.size()); + return result; + + } catch (Exception e) { + log.error("调用红包服务失败", e); + throw new BusinessException("系统异常,请联系管理员"); + } + } + @Override public BigDecimal selectRedSum(Integer jwcode) { try { @@ -205,5 +289,49 @@ public class RedServiceImpl implements RedService { } } } + // 在 RedServiceImpl 或 UserService 中添加 + public String loginAndGetToken(String jwcode) { + try { + // 注意:这个接口是 application/x-www-form-urlencoded,不是 JSON! + String formData = "jwcode=" + URLEncoder.encode(jwcode, StandardCharsets.UTF_8) + + "&token=" + URLEncoder.encode("9ior41AF0xTIbIG2pRnnbZi0+fEeMx8pywnIlrmTwo5FbqJ9lWrSWOxp9MkpKiNtedtUafqvzIwpFKrwuMs", StandardCharsets.UTF_8); + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(BASE_URL_LOGIN+PATHLOGIN)) + .timeout(Duration.ofSeconds(8)) + .header("Content-Type", "application/x-www-form-urlencoded") + .POST(HttpRequest.BodyPublishers.ofString(formData)) + .build(); + + HttpResponse resp = CLIENT.send(request, HttpResponse.BodyHandlers.ofString()); + + if (resp.statusCode() != 200) { + log.error("登录失败,状态码: {},响应: {}", resp.statusCode(), resp.body()); + throw new BusinessException("登录失败,请重试"); + } + + // 假设响应格式:{"code":200,"msg":"success","data":{"token":"xxx","user_id":123}} + ObjectMapper mapper = new ObjectMapper(); + JsonNode root = mapper.readTree(resp.body()); + + if (root.get("code").asInt() != 200) { + String msg = root.has("msg") ? root.get("msg").asText() : "未知错误"; + throw new BusinessException("登录失败: " + msg); + } + + JsonNode data = root.get("data"); + if (data == null || !data.has("token")) { + throw new BusinessException("登录成功但未返回 token"); + } + + String userToken = data.get("token").asText(); + log.debug("用户 {} 登录成功,token: {}", jwcode, userToken.substring(0, 10) + "..."); + return userToken; + + } catch (Exception e) { + log.error("登录异常,jwcode={}", jwcode, e); + throw new BusinessException("登录服务异常"); + } + } } diff --git a/src/main/java/com/example/demo/serviceImpl/coin/ConsumeServiceImpl.java b/src/main/java/com/example/demo/serviceImpl/coin/ConsumeServiceImpl.java index 263eba8..dbbf49e 100644 --- a/src/main/java/com/example/demo/serviceImpl/coin/ConsumeServiceImpl.java +++ b/src/main/java/com/example/demo/serviceImpl/coin/ConsumeServiceImpl.java @@ -205,7 +205,7 @@ public class ConsumeServiceImpl implements ConsumeService { log.warn("消耗累加失败,主流程继续 | jwcode={}", consumeUser.getJwcode(), e); } if(consumeUser.getRedMoney()==1){ - redService.sendConsumeJwcode(consumeUser.getJwcode(),(consumeUser.getPrice().subtract(consumeUser.getSumGold())).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP)); + redService.sendConsumeJwcode(consumeUser.getJwcode(),consumeUser.getRedIds()); } return Result.success(); } diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index fc5e050..849e10b 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -94,6 +94,7 @@ spring: file: upload: url: http://api.homilychart.com/hljw/api/aws/upload + urllogin: https://api.homilychart.com/hljwgo feishu: webhook: url: https://open.feishu.cn/open-apis/bot/v2/hook/1a515b19-b64f-46b7-9486-35842b9539fe diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml index 591474d..c5030ed 100644 --- a/src/main/resources/application-test.yml +++ b/src/main/resources/application-test.yml @@ -103,6 +103,7 @@ bean: red: url: http://39.101.133.168:8828/scms + urllogin: http://39.101.133.168:8828/hljwgo server: port: 8081