尝试精简
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 限流异常类(需自定义)
|
||||
|
||||
Reference in New Issue
Block a user