尝试精简

This commit is contained in:
Leo
2025-04-12 14:28:12 +08:00
parent b63d50ab5f
commit c8efd8512e

View File

@@ -9,13 +9,9 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.jd.open.api.sdk.DefaultJdClient;
import com.jd.open.api.sdk.JdClient;
import com.jd.open.api.sdk.domain.kplunion.CouponService.request.get.CreateGiftCouponReq;
import com.jd.open.api.sdk.domain.kplunion.CouponService.request.stop.StopGiftCouponReq;
import com.jd.open.api.sdk.domain.kplunion.GoodsService.request.query.BigFieldGoodsReq;
import com.jd.open.api.sdk.domain.kplunion.GoodsService.request.query.GoodsReq;
import com.jd.open.api.sdk.domain.kplunion.GoodsService.response.query.BigfieldQueryResult;
import com.jd.open.api.sdk.domain.kplunion.GoodsService.response.query.GoodsQueryResult;
import com.jd.open.api.sdk.domain.kplunion.GoodsService.response.query.UrlInfo;
import com.jd.open.api.sdk.domain.kplunion.OrderService.request.query.OrderRowReq;
import com.jd.open.api.sdk.domain.kplunion.promotionbysubunioni.PromotionService.request.get.PromotionCodeReq;
import com.jd.open.api.sdk.request.kplunion.*;
import com.jd.open.api.sdk.response.kplunion.*;
@@ -29,10 +25,6 @@ import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
@@ -140,7 +132,7 @@ public class JDUtil {
public String convertAddress(String input) {
try {
// 正则表达式分解输入内容
Pattern pattern = Pattern.compile("^(.+?)\\[(\\d+)\\]\\s+(\\d+)\\s+(.+)\\[\\d+\\]$");
Pattern pattern = Pattern.compile("^(.+?)\\[(\\d+)\\]\\s+(\\d+)\\s+(.+)\\[\\d+]$");
Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
@@ -461,7 +453,7 @@ public class JDUtil {
return info;
}).collect(Collectors.groupingBy(OrderInfo::getSkuName));
List<Map.Entry<String, Long>> sortedViolationCounts = skuIdViolationCountMap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).collect(Collectors.toList());
List<Map.Entry<String, Long>> sortedViolationCounts = skuIdViolationCountMap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).toList();
Integer num = 0;
for (Map.Entry<String, Long> entry : sortedViolationCounts) {
@@ -576,48 +568,12 @@ public class JDUtil {
}
}
/**
* 获取订单列表
*
* @param start 开始时间
* @param end 结束时间
* @return
* @throws Exception
*/
public UnionOpenOrderRowQueryResponse getUnionOpenOrderRowQueryResponse(LocalDateTime start, LocalDateTime end, Integer pageIndex, String appKey, String secretKey) throws Exception {
String startTime = start.format(DATE_TIME_FORMATTER);
String endTime = end.format(DATE_TIME_FORMATTER);
// 模拟 API 调用
//System.out.println("调用API - 从 " + startTime
// + " 到 " + endTime);
// 实际的 API 调用逻辑应在这里进行
JdClient client = new DefaultJdClient(SERVER_URL, ACCESS_TOKEN, appKey, secretKey);
UnionOpenOrderRowQueryRequest request = new UnionOpenOrderRowQueryRequest();
OrderRowReq orderReq = new OrderRowReq();
orderReq.setPageIndex(pageIndex);
orderReq.setPageSize(200);
orderReq.setStartTime(startTime);
orderReq.setEndTime(endTime);
orderReq.setType(1);
request.setOrderReq(orderReq);
request.setVersion("1.0");
request.setSignmethod("md5");
// 时间戳格式为yyyy-MM-dd HH:mm:ss时区为GMT+8。API服务端允许客户端请求最大时间误差为10分钟
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
request.setTimestamp(simpleDateFormat.format(date));
return client.execute(request);
}
/**
* 接口描述:通过商品链接、领券链接、活动链接获取普通推广链接或优惠券二合一推广链接
* jd.union.open.promotion.bysubunionid.get
*/
String transfer(String url, String giftCouponKey) {
JdClient client = new DefaultJdClient(SERVER_URL, ACCESS_TOKEN, LPF_APP_KEY_WZ, LPF_SECRET_KEY_WZ);
UnionOpenPromotionBysubunionidGetRequest request = new UnionOpenPromotionBysubunionidGetRequest();
@@ -668,22 +624,7 @@ public class JDUtil {
return result;
}
//public UnionOpenGoodsBigfieldQueryResponse getUnionOpenGoodsBigfieldQueryResponse(){
// JdClient client = new DefaultJdClient(SERVER_URL, ACCESS_TOKEN, APP_KEY, SECRET_KEY);
//
// UnionOpenGoodsBigfieldQueryRequest request=new UnionOpenGoodsBigfieldQueryRequest();
// BigFieldGoodsReq goodsReq=new BigFieldGoodsReq();
// goodsReq.setSkuIds();
// request.setGoodsReq(goodsReq);
// request.setVersion("1.0");
// UnionOpenGoodsBigfieldQueryResponse response= null;
// try {
// response = client.execute(request);
// } catch (Exception e) {
// throw new RuntimeException(e);
// }
// return response;
//}
/**
* 消毒柜部分的业务逻辑
@@ -958,155 +899,6 @@ public class JDUtil {
saveState(INTERACTION_STATE_PREFIX + wxid, state);
}
// 在发送提示信息时增加进度指示
private void sendStepPrompt(String wxid, int step, int totalSteps) {
String progress = String.format("[%d/%d] ", step, totalSteps);
String message = progress + "请输入礼金金额示例20.50";
wxUtil.sendTextMessage(wxid, message, 1, wxid, false);
}
private void createPromotionWithGift(String fromWxid, String message) {
String key = INTERACTION_STATE_PREFIX + fromWxid;
UserInteractionState state = userInteractionStates.get(key);
// 修改createPromotionWithGift方法中的校验逻辑
if (!state.validateStep(STEP_CONFIRM_GIFT)) {
logger.warn("状态校验失败,预期步骤:{} 实际步骤:{}", STEP_CONFIRM_GIFT, state.getCurrentStep());
wxUtil.sendTextMessage(fromWxid, "流程顺序异常,请重新开始", 1, fromWxid, false);
return;
}
// 修改点3在createPromotionWithGift方法开始处增加状态校验
if (state == null || state.getCurrentStep() == null) {
logger.warn("非法状态访问: {}", fromWxid);
wxUtil.sendTextMessage(fromWxid, "⚠️ 会话超时,请重新开始流程", 1, fromWxid, false);
return;
} else {
LocalDateTime now = LocalDateTime.now();
LocalDateTime lastInteractionTime = LocalDateTime.parse(state.getLastInteractionTime(), DATE_TIME_FORMATTER);
if (ChronoUnit.MINUTES.between(lastInteractionTime, now) > TIMEOUT_MINUTES) {
userInteractionStates.remove(key);
logger.debug("Deleted timeout state for user: {}", fromWxid);
state = new UserInteractionState();
}
}
state.updateLastInteractionTime();
userInteractionStates.put(key, state); // 确保状态保存
try {
switch (state.getCurrentStep()) {
case STEP_CONFIRM_GIFT:
if ("1".equals(message)) {
state.setCurrentStep(STEP_AMOUNT);
wxUtil.sendTextMessage(fromWxid, "请输入开通金额(元):", 1, fromWxid, false);
} else if ("2".equals(message)) {
// 不开通礼金,直接生成转链
String cachedData = cacheMap.get("productData" + fromWxid);
if (cachedData != null) {
JSONObject jsonObject = JSONObject.parseObject(cachedData);
String skuId = jsonObject.getString("materialUrl");
String transferUrl = transfer(skuId, null);
wxUtil.sendTextMessage(fromWxid, "转链后的链接:\n" + transferUrl, 1, fromWxid, false);
} else {
wxUtil.sendTextMessage(fromWxid, "未找到缓存的商品链接,请重新开始流程", 1, fromWxid, false);
}
state.reset();
userInteractionStates.put(key, state); // 在外部保存
} else {
wxUtil.sendTextMessage(fromWxid, "无效的选择,请重新输入:\n回复 1 - 是\n回复 2 - 否", 1, fromWxid, false);
}
break;
case STEP_AMOUNT:
logger.debug("用户 {} 输入金额:{}", fromWxid, message);
if (message == null || message.trim().isEmpty()) {
wxUtil.sendTextMessage(fromWxid, "金额不能为空请输入数字100.00", 1, fromWxid, false);
return;
}
if (!isValidAmount(message)) {
wxUtil.sendTextMessage(fromWxid, "金额格式错误请输入数字100.00", 1, fromWxid, false);
return;
}
double amount = Double.parseDouble(message);
String formattedAmount = String.format("%.2f", amount);
state.getCollectedFields().put("amount", formattedAmount);
state.setCurrentStep(STEP_QUANTITY);
userInteractionStates.put(key, state); // ▼▼▼ 保存点2 ▼▼▼
wxUtil.sendTextMessage(fromWxid, "请输入数量1-100", 1, fromWxid, false);
sendStepPrompt(fromWxid, 1, 3);
break;
case STEP_QUANTITY:
logger.debug("用户 {} 输入数量:{}", fromWxid, message); // 新增
if (!isValidQuantity(message)) {
wxUtil.sendTextMessage(fromWxid, "数量格式错误,请输入整数", 1, fromWxid, false);
return;
}
int quantity = Integer.parseInt(message);
if (quantity < 1 || quantity > 100) {
wxUtil.sendTextMessage(fromWxid, "数量需在1-100之间", 1, fromWxid, false);
return;
}
// 从缓存中获取 amount
String amountStr = state.getCollectedFields().get("amount");
if (amountStr == null || amountStr.trim().isEmpty()) {
wxUtil.sendTextMessage(fromWxid, "未找到金额,请重新开始流程", 1, fromWxid, false);
state.reset();
userInteractionStates.put(key, state); // 在外部保存
return;
}
amount = Double.parseDouble(amountStr);
logger.debug("礼金参数准备完成:金额={}元,数量={}", amount, quantity); // 新增
String cachedData = cacheMap.get("productData" + fromWxid);
String finalWenAn = cacheMap.get("finalWenAn" + fromWxid);
if (cachedData != null) {
JSONObject jsonObject = JSONObject.parseObject(cachedData);
String skuId = jsonObject.getString("materialUrl");
String owner = jsonObject.getString("owner");
String skuName = jsonObject.getString("skuName");
String giftKey = createGiftCoupon(skuId, amount, quantity, owner, skuName);
if (giftKey == null) {
logger.error("用户 {} 礼金创建失败SKU={}, 金额={}元,数量={}", fromWxid, skuId, amount, quantity); // 新增
wxUtil.sendTextMessage(fromWxid, "❌ 礼金创建失败,请检查商品是否符合要求", 1, fromWxid, false);
state.reset();
userInteractionStates.put(key, state); // 在外部保存
return;
}
logger.info("用户 {} 礼金创建成功批次ID={}, 参数SKU={}, 金额={}元,数量={}", fromWxid, giftKey, skuId, amount, quantity); // 新增关键成功日志
state.getCollectedFields().put("giftKey", giftKey);
// 生成转链
String transferUrl = transfer(skuId, giftKey);
//wxUtil.sendTextMessage(fromWxid, "附带礼金的链接:\n" + transferUrl, 1, fromWxid, false);
wxUtil.sendTextMessage(fromWxid, "附带礼金的方案:\n" + finalWenAn.replaceAll(jsonObject.getString("url"), transferUrl), 1, fromWxid, true);
state.reset();
userInteractionStates.put(key, state); // 在外部保存
} else {
wxUtil.sendTextMessage(fromWxid, "未找到缓存的商品链接,请重新开始流程", 1, fromWxid, false);
state.reset();
userInteractionStates.put(key, state); // 在外部保存
}
break;
default:
state.setCurrentStep(STEP_CONFIRM_GIFT);
wxUtil.sendTextMessage(fromWxid, "是否需要开通礼金?\n回复 1 - 是\n回复 2 - 否", 1, fromWxid, false);
break;
}
} catch (Exception e) {
logger.error("转链和礼金流程异常,用户 {} 当前步骤:{}", fromWxid, state.getCurrentStep(), e);
wxUtil.sendTextMessage(fromWxid, "❌ 系统异常,请稍后重试", 1, fromWxid, false);
state.reset();
userInteractionStates.put(key, state); // 在外部保存
}
}
/**
* 生成转链和方案的方法
*
@@ -1130,7 +922,6 @@ public class JDUtil {
return finallMessage;
}
/**
* {
* "jd_union_open_goods_query_responce": {
@@ -1459,14 +1250,9 @@ public class JDUtil {
/**
* 因为在这里转链返回,没有什么意义,后面走转链不转链,会重新发方案
* */
StringBuilder wenan = new StringBuilder();
// 完成转链后替换链接为u.jd.com链接方案不修改就返回
//for (HashMap<String, String> stringStringHashMap : resultList) {
// String transferUrl = transfer(stringStringHashMap.get("materialUrl"), null);
// wenan = new StringBuilder(message.replace(stringStringHashMap.get("url"), transferUrl));
//}
StringBuilder wenan;
wenan = new StringBuilder().append(FANAN_COMMON).append(message);
//textList.add(String.valueOf(wenan));
finalWenAn.add(String.valueOf(wenan));
@@ -1477,19 +1263,6 @@ public class JDUtil {
}
private String downloadImage(String imageUrl, String destinationFile) {
try (BufferedInputStream in = new BufferedInputStream(new URL(imageUrl).openStream()); FileOutputStream fileOutputStream = new FileOutputStream(destinationFile)) {
byte[] dataBuffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
fileOutputStream.write(dataBuffer, 0, bytesRead);
}
return destinationFile;
} catch (IOException e) {
logger.error("Error downloading image from URL: {}", imageUrl, e);
return null;
}
}
/**
* 提取方案中的所有 u.jd.com 链接
@@ -1552,46 +1325,6 @@ public class JDUtil {
return queryResult;
}
// 在JDUtil类中新增方法实现商品详情查询接口
public UnionOpenGoodsBigfieldQueryResponse getUnionOpenGoodsBigfieldQueryResponse(String skuId) throws Exception {
JdClient client = new DefaultJdClient(SERVER_URL, ACCESS_TOKEN, LPF_APP_KEY_WZ, LPF_SECRET_KEY_WZ);
UnionOpenGoodsBigfieldQueryRequest request = new UnionOpenGoodsBigfieldQueryRequest();
BigFieldGoodsReq goodsReq = new BigFieldGoodsReq();
goodsReq.setSkuIds(List.of(Long.parseLong(skuId)).toArray(new Long[0])); // 传入skuId集合
/**
* 查询域集合不填写则查询全部目目前支持categoryInfo类目信息,imageInfo图片信息,
* baseBigFieldInfo基础大字段信息,bookBigFieldInfo图书大字段信息,
* videoBigFieldInfo影音大字段信息,detailImages商详图*/
//goodsReq.setFields(new String[]{"categoryInfo", "imageInfo", "baseBigFieldInfo"}); // 设置需要查询的字段
goodsReq.setSceneId(2); // 设置场景ID
request.setGoodsReq(goodsReq);
request.setVersion("1.0");
request.setSignmethod("md5");
request.setTimestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
return client.execute(request);
}
// 修改parseSkuFromUrl方法提取SKU
private String parseSkuFromUrl(String url) {
Matcher m = Pattern.compile("item.jd.com/(\\d+).html").matcher(url);
return m.find() ? m.group(1) : null;
}
public BigfieldQueryResult queryProductInfo(String skuId) throws Exception {
UnionOpenGoodsBigfieldQueryResponse response = getUnionOpenGoodsBigfieldQueryResponse(skuId);
if (response == null || response.getQueryResult() == null) {
return null;
}
BigfieldQueryResult queryResult = response.getQueryResult();
if (queryResult.getCode() != 200) {
return null;
}
return queryResult;
}
// 新增礼金创建方法
public String createGiftCoupon(String skuId, double amount, int quantity, String owner, String skuName) throws Exception {
@@ -1662,28 +1395,6 @@ public class JDUtil {
return null;
}
// 修改activateGiftMoney方法调用真实接口
private boolean activateGiftMoney(String skuId, double amount, int quantity, String owner) {
return false;
}
// 新增礼金停止方法(可选)
public boolean stopGiftCoupon(String giftKey) throws Exception {
JdClient client = new DefaultJdClient(SERVER_URL, ACCESS_TOKEN, LPF_APP_KEY_WZ, LPF_SECRET_KEY_WZ);
UnionOpenCouponGiftStopRequest request = new UnionOpenCouponGiftStopRequest();
StopGiftCouponReq couponReq = new StopGiftCouponReq();
couponReq.setGiftCouponKey(giftKey);
request.setCouponReq(couponReq);
request.setVersion("1.0");
request.setSignmethod("md5");
request.setTimestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
UnionOpenCouponGiftStopResponse response = client.execute(request);
return "200".equals(response.getCode());
}
boolean isValidAmount(String input) {
// 新增:直接处理 null 或空字符串
@@ -1795,12 +1506,6 @@ public class JDUtil {
return this.currentStep != null && this.currentStep.getCode() == expectedStep.getCode();
}
// 在UserInteractionState中增加恢复方法
public void restoreState(Map<String, String> backup) {
this.collectedFields.putAll(backup);
this.lastInteractionTime = LocalDateTime.now().format(DATE_TIME_FORMATTER);
}
// 推荐使用枚举管理状态
public enum ProcessState {
INIT, GIFT_MONEY_FLOW, PRODUCT_PROMOTION
@@ -1819,10 +1524,8 @@ public class JDUtil {
return code;
}
}
}
// 限流异常类(需自定义)