基本完成转链。富贵指日可待!
This commit is contained in:
22
src/main/java/cn/van/business/util/AmountStepHandler.java
Normal file
22
src/main/java/cn/van/business/util/AmountStepHandler.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package cn.van.business.util;
|
||||
|
||||
import static cn.van.business.util.JDUtil.UserInteractionState.GiftMoneyStep.STEP_QUANTITY;
|
||||
|
||||
/**
|
||||
* @author Leo
|
||||
* @version 1.0
|
||||
* @create 2025/4/4 20:46
|
||||
* @description:
|
||||
*/
|
||||
|
||||
// 实现金额处理步骤
|
||||
class AmountStepHandler implements FlowStepHandler {
|
||||
public void handle(JDUtil util, String wxid, String input, JDUtil.UserInteractionState state) {
|
||||
if (!util.isValidAmount(input)) {
|
||||
util.wxUtil.sendTextMessage(wxid, "金额格式错误", 1, wxid);
|
||||
return;
|
||||
}
|
||||
state.getCollectedFields().put("amount", input);
|
||||
state.setCurrentStep(STEP_QUANTITY);
|
||||
}
|
||||
}
|
||||
11
src/main/java/cn/van/business/util/FlowStepHandler.java
Normal file
11
src/main/java/cn/van/business/util/FlowStepHandler.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package cn.van.business.util;
|
||||
|
||||
/**
|
||||
* @author Leo
|
||||
* @version 1.0
|
||||
* @create 2025/4/4 20:45
|
||||
* @description:
|
||||
*/
|
||||
public interface FlowStepHandler {
|
||||
void handle(JDUtil util, String wxid, String input, JDUtil.UserInteractionState state);
|
||||
}
|
||||
@@ -33,6 +33,7 @@ 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;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -41,13 +42,14 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static cn.van.business.util.JDUtil.UserInteractionState.GiftMoneyStep.*;
|
||||
import static cn.van.business.util.JDUtil.UserInteractionState.ProcessState.*;
|
||||
import static cn.van.business.util.JDUtil.UserInteractionState.ProcessState.INIT;
|
||||
import static cn.van.business.util.WXUtil.super_admins;
|
||||
|
||||
/**
|
||||
@@ -78,16 +80,50 @@ public class JDUtil {
|
||||
private static final Logger logger = LoggerFactory.getLogger(JDUtil.class);
|
||||
private static final String INTERACTION_STATE_PREFIX = "interaction_state:";
|
||||
private static final long TIMEOUT_MINUTES = 1;
|
||||
private static final String WENAN_FANAN = "提供方法自己下单\n" +
|
||||
"全程都是自己的账号下单\n" +
|
||||
"标价就是下单的到手价\n" +
|
||||
"(不包含教程费)\n" +
|
||||
"本人有耐心,会一步一步提供教程\n" +
|
||||
"以后有什么质量问题都是用自己的账号走京东售后\n" +
|
||||
"\n" +
|
||||
"更新\n" +
|
||||
"\n" +
|
||||
"用你自己的账号下单\n" +
|
||||
"官方店铺 提供方法自己下单\n" +
|
||||
"不含教程费,价格不对不收费\n" +
|
||||
"教程费用私聊我问价\n" +
|
||||
"——————————————————————————————————————————\n" +
|
||||
"同行可长久合作,可提供神级家电线报\n" +
|
||||
"\n" +
|
||||
"配合家电线报可以自己下单,不用找代购和代下,订单和利润都掌握在自己手中。\n" +
|
||||
"\n" +
|
||||
"一次入会永久使用,包含家电帮,雷神价,韭菜帮,河南&湖南帮,各种暗号帮后返等内部独家家电线报\n" +
|
||||
"\n" +
|
||||
"JD采销采购不定时发放独家优惠券\n" +
|
||||
"\n" +
|
||||
"基本上你能看到的京东家电低价都是从这些渠道里面出来。\n" +
|
||||
"\n" +
|
||||
"2025年家电项目新方向,配合家电线报下单,秒省1K+。";
|
||||
private static final String WENAN_ZCXS = "\n" +
|
||||
"购买后,两小时内出库,物流会电话联系您,同时生成京东官方安装单。送装一体,无需担心。\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"1:全新正品,原包装未拆封(京东商城代购,就近直发)\n" +
|
||||
"2:可提供下单运单号与电子发票(发票在收到货后找我要)。\n" +
|
||||
"3:收货时查看是否有质量或运损问题。可拍照让京东免费申请换新。\n" +
|
||||
"4:下单后非质量问题不支持退款退货,强制退扣100元。\n" +
|
||||
"5:价格有浮动,不支持补差价,谢谢理解。\n" +
|
||||
"6:全国联保,全国统一安装标准。支持官方 400,服务号查询,假一赔十。\n";
|
||||
final WXUtil wxUtil;
|
||||
private final StringRedisTemplate redisTemplate;
|
||||
private final OrderRowRepository orderRowRepository;
|
||||
private final WXUtil wxUtil;
|
||||
private final OrderUtil orderUtil;
|
||||
// 添加ObjectMapper来序列化和反序列化UserInteractionState
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private final ConcurrentHashMap<String, UserInteractionState> userInteractionStates = new ConcurrentHashMap<>();
|
||||
private HashMap<String, String> cacheMap = new HashMap<>();
|
||||
|
||||
|
||||
// 构造函数中注入StringRedisTemplate
|
||||
@Autowired
|
||||
public JDUtil(StringRedisTemplate redisTemplate, OrderRowRepository orderRowRepository, WXUtil wxUtil, OrderUtil orderUtil) {
|
||||
@@ -569,8 +605,7 @@ public class JDUtil {
|
||||
* */
|
||||
String result = "";
|
||||
if (Util.isNotEmpty(response)) {
|
||||
if (response.getCode().equals("0") &&
|
||||
response.getGetResult().getCode() == 200) {
|
||||
if (response.getCode().equals("0") && response.getGetResult().getCode() == 200) {
|
||||
result = response.getGetResult().getData().getShortURL();
|
||||
}
|
||||
} else {
|
||||
@@ -617,249 +652,449 @@ public class JDUtil {
|
||||
// return response;
|
||||
//}
|
||||
|
||||
private void handleUserInteraction(String fromWxid, String message) {
|
||||
String key = INTERACTION_STATE_PREFIX + fromWxid;
|
||||
UserInteractionState state = userInteractionStates.get(key);
|
||||
private void handleUserInteraction(String fromWxid, String message) {
|
||||
String key = INTERACTION_STATE_PREFIX + fromWxid;
|
||||
UserInteractionState state = loadOrCreateState(key);
|
||||
|
||||
if (state == null) {
|
||||
state = new UserInteractionState();
|
||||
logger.debug("New interaction state created for user: {}", fromWxid);
|
||||
} 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);
|
||||
try {
|
||||
switch (state.getCurrentState()) {
|
||||
case INIT:
|
||||
handleInitState(fromWxid, message, state);
|
||||
break;
|
||||
|
||||
case PRODUCT_PROMOTION:
|
||||
handlePromotionState(fromWxid, message, state);
|
||||
break;
|
||||
|
||||
case GIFT_MONEY_FLOW:
|
||||
handleGiftMoneyFlow(fromWxid, message, state);
|
||||
break;
|
||||
|
||||
default:
|
||||
resetState(fromWxid, state);
|
||||
wxUtil.sendTextMessage(fromWxid, "流程异常,请重新开始", 1, fromWxid);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("流程处理异常 - 用户: {}, 状态: {}", fromWxid, state, e);
|
||||
resetState(fromWxid, state);
|
||||
wxUtil.sendTextMessage(fromWxid, "处理异常,请重新开始", 1, fromWxid);
|
||||
} finally {
|
||||
saveState(key, state);
|
||||
}
|
||||
|
||||
userInteractionStates.put(key, state);
|
||||
logger.debug("Updated interaction state for user {}: {}", fromWxid, JSON.toJSONString(state));
|
||||
}
|
||||
|
||||
private UserInteractionState loadOrCreateState(String key) {
|
||||
UserInteractionState state = loadState(key);
|
||||
if (state == null) {
|
||||
state = new UserInteractionState();
|
||||
logger.debug("创建新交互状态: {}", key);
|
||||
} else if (isStateExpired(state)) {
|
||||
redisTemplate.delete(key);
|
||||
state = new UserInteractionState();
|
||||
logger.debug("状态已过期,重置: {}", key);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
private boolean isStateExpired(UserInteractionState state) {
|
||||
LocalDateTime lastTime = LocalDateTime.parse(state.getLastInteractionTime(), DATE_TIME_FORMATTER);
|
||||
return ChronoUnit.MINUTES.between(lastTime, LocalDateTime.now()) > TIMEOUT_MINUTES;
|
||||
}
|
||||
|
||||
private void handleInitState(String wxid, String message, UserInteractionState state) {
|
||||
if ("转".equals(message)) {
|
||||
state.setCurrentState(UserInteractionState.ProcessState.PRODUCT_PROMOTION);
|
||||
state.setCurrentField("content");
|
||||
wxUtil.sendTextMessage(wxid, "请输入推广方案(包含商品链接):", 1, wxid);
|
||||
logger.info("进入转链流程 - 用户: {}", wxid);
|
||||
}
|
||||
}
|
||||
|
||||
state.updateLastInteractionTime();
|
||||
userInteractionStates.put(key, state); // 确保状态保存
|
||||
|
||||
switch (state.getCurrentState()) {
|
||||
case INIT:
|
||||
if ("转链".equals(message)) {
|
||||
state.setCurrentState(UserInteractionState.ProcessState.PRODUCT_PROMOTION);
|
||||
state.setCurrentField("content");
|
||||
wxUtil.sendTextMessage(fromWxid, "请输入推广文案(包含商品链接):", 1, fromWxid);
|
||||
logger.info("进入转链流程 - 文案输入步骤");
|
||||
}
|
||||
break;
|
||||
|
||||
case PRODUCT_PROMOTION:
|
||||
if ("content".equals(state.getCurrentField())) {
|
||||
cacheMap.remove("text" + fromWxid);
|
||||
|
||||
// 第一次输入文案,直接生成内容
|
||||
HashMap<String, List<String>> messagesAll = generatePromotionContent(message);
|
||||
List<String> messages = messagesAll.get("text");// 不需要图片和SKU名称
|
||||
for (String s : messages) {
|
||||
wxUtil.sendTextMessage(fromWxid, s, 1, fromWxid);
|
||||
}
|
||||
try {
|
||||
List<String> images = messagesAll.get("images");
|
||||
if (images != null) {
|
||||
for (String s : images) {
|
||||
if (s != null) {
|
||||
wxUtil.sendImageMessage(fromWxid, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Error generating promotion content: {}", e.getMessage());
|
||||
}
|
||||
cacheMap.put("text" + fromWxid, messagesAll.get("data").get(0));
|
||||
// 直接进入确认开通礼金的步骤
|
||||
state.setCurrentField("confirm");
|
||||
wxUtil.sendTextMessage(fromWxid, "是否需要开通礼金?\n回复 1 - 是\n回复 2 - 否", 1, fromWxid);
|
||||
logger.info("转链流程 - 等待用户确认是否需要开通礼金");
|
||||
} else if ("confirm".equals(state.getCurrentField())) {
|
||||
logger.info("转链流程 - 用户确认是否需要开通礼金:{}", message);
|
||||
if ("1".equals(message)) {
|
||||
// ▼▼▼ 关键修改:明确设置初始步骤 ▼▼▼
|
||||
state.setCurrentState(UserInteractionState.ProcessState.GIFT_MONEY_FLOW);
|
||||
state.setCurrentStep(UserInteractionState.GiftMoneyStep.STEP_AMOUNT);
|
||||
state.getCollectedFields().clear();
|
||||
userInteractionStates.put(key, state); // 立即持久化状态
|
||||
wxUtil.sendTextMessage(fromWxid, "请输入开通金额(元):", 1, fromWxid);
|
||||
} else if ("2".equals(message)) {
|
||||
wxUtil.sendTextMessage(fromWxid, "开通礼金流程已取消", 1, fromWxid);
|
||||
cacheMap.remove("text" + fromWxid);
|
||||
} else {
|
||||
wxUtil.sendTextMessage(fromWxid, "无效的选择,请重新输入:\n回复 1 - 是\n回复 2 - 否", 1, fromWxid);
|
||||
}
|
||||
state.reset(); // 重置状态
|
||||
userInteractionStates.put(key, state); // 在外部保存
|
||||
}
|
||||
break;
|
||||
|
||||
case GIFT_MONEY_FLOW:
|
||||
createPromotionWithGift(fromWxid, message);
|
||||
break;
|
||||
|
||||
default:
|
||||
wxUtil.sendTextMessage(fromWxid, "无效的状态,请重新开始对话", 1, fromWxid);
|
||||
state.setCurrentState(INIT);
|
||||
logger.debug("User {} reset to INIT state due to invalid state", fromWxid);
|
||||
break;
|
||||
}
|
||||
|
||||
userInteractionStates.put(key, state);
|
||||
logger.debug("Updated interaction state for user {}: {}", fromWxid, JSON.toJSONString(state));
|
||||
}
|
||||
|
||||
|
||||
private void createPromotionWithGift(String fromWxid, String message) {
|
||||
String key = INTERACTION_STATE_PREFIX + fromWxid;
|
||||
UserInteractionState state = userInteractionStates.get(key);
|
||||
|
||||
// 修改点3:在createPromotionWithGift方法开始处增加状态校验
|
||||
if (state == null || state.getCurrentStep() == null) {
|
||||
logger.warn("非法状态访问: {}", fromWxid);
|
||||
wxUtil.sendTextMessage(fromWxid, "⚠️ 会话超时,请重新开始流程", 1, fromWxid);
|
||||
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();
|
||||
private void handlePromotionState(String wxid, String message, UserInteractionState state) {
|
||||
if ("content".equals(state.getCurrentField())) {
|
||||
processContentInput(wxid, message, state);
|
||||
} else if ("confirm".equals(state.getCurrentField())) {
|
||||
handleGiftMoneyConfirmation(wxid, message, state);
|
||||
}
|
||||
}
|
||||
|
||||
state.updateLastInteractionTime();
|
||||
userInteractionStates.put(key, state); // 确保状态保存
|
||||
private void handleGiftMoneyFlow(String wxid, String message, UserInteractionState state) {
|
||||
if (!state.validateStep(state.getCurrentStep())) {
|
||||
wxUtil.sendTextMessage(wxid, "流程顺序异常,请重新开始", 1, wxid);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
switch (state.getCurrentStep()) {
|
||||
case STEP_CONFIRM_GIFT:
|
||||
if ("1".equals(message)) {
|
||||
state.setCurrentStep(STEP_AMOUNT);
|
||||
wxUtil.sendTextMessage(fromWxid, "请输入开通金额(元):", 1, fromWxid);
|
||||
} else if ("2".equals(message)) {
|
||||
// 不开通礼金,直接生成转链
|
||||
String cachedData = cacheMap.get("text" + 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);
|
||||
} else {
|
||||
wxUtil.sendTextMessage(fromWxid, "未找到缓存的商品链接,请重新开始流程", 1, fromWxid);
|
||||
}
|
||||
state.reset();
|
||||
userInteractionStates.put(key, state); // 在外部保存
|
||||
} else {
|
||||
wxUtil.sendTextMessage(fromWxid, "无效的选择,请重新输入:\n回复 1 - 是\n回复 2 - 否", 1, fromWxid);
|
||||
}
|
||||
break;
|
||||
|
||||
case STEP_AMOUNT:
|
||||
logger.debug("用户 {} 输入金额:{}", fromWxid, message);
|
||||
if (message == null || message.trim().isEmpty()) {
|
||||
wxUtil.sendTextMessage(fromWxid, "金额不能为空,请输入数字(如:100.00)", 1, fromWxid);
|
||||
return;
|
||||
}
|
||||
if (!isValidAmount(message)) {
|
||||
wxUtil.sendTextMessage(fromWxid, "金额格式错误,请输入数字(如:100.00)", 1, fromWxid);
|
||||
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);
|
||||
processAmountInput(wxid, message, state);
|
||||
break;
|
||||
|
||||
case STEP_QUANTITY:
|
||||
logger.debug("用户 {} 输入数量:{}", fromWxid, message); // 新增
|
||||
if (!isValidQuantity(message)) {
|
||||
wxUtil.sendTextMessage(fromWxid, "数量格式错误,请输入整数", 1, fromWxid);
|
||||
return;
|
||||
}
|
||||
|
||||
int quantity = Integer.parseInt(message);
|
||||
if (quantity < 1 || quantity > 100) {
|
||||
wxUtil.sendTextMessage(fromWxid, "数量需在1-100之间", 1, fromWxid);
|
||||
return;
|
||||
}
|
||||
|
||||
// 从缓存中获取 amount
|
||||
String amountStr = state.getCollectedFields().get("amount");
|
||||
if (amountStr == null || amountStr.trim().isEmpty()) {
|
||||
wxUtil.sendTextMessage(fromWxid, "未找到金额,请重新开始流程", 1, fromWxid);
|
||||
state.reset();
|
||||
userInteractionStates.put(key, state); // 在外部保存
|
||||
return;
|
||||
}
|
||||
amount = Double.parseDouble(amountStr);
|
||||
|
||||
logger.debug("礼金参数准备完成:金额={}元,数量={}", amount, quantity); // 新增
|
||||
|
||||
String cachedData = cacheMap.get("text" + fromWxid);
|
||||
if (cachedData != null) {
|
||||
JSONObject jsonObject = JSONObject.parseObject(cachedData);
|
||||
String skuId = jsonObject.getString("materialUrl");
|
||||
String giftKey = createGiftCoupon(skuId, amount, quantity, "pop");
|
||||
if (giftKey == null) {
|
||||
logger.error("用户 {} 礼金创建失败:SKU={}, 金额={}元,数量={}", fromWxid, skuId, amount, quantity); // 新增
|
||||
wxUtil.sendTextMessage(fromWxid, "❌ 礼金创建失败,请检查商品是否符合要求", 1, fromWxid);
|
||||
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);
|
||||
state.reset();
|
||||
userInteractionStates.put(key, state); // 在外部保存
|
||||
} else {
|
||||
wxUtil.sendTextMessage(fromWxid, "未找到缓存的商品链接,请重新开始流程", 1, fromWxid);
|
||||
state.reset();
|
||||
userInteractionStates.put(key, state); // 在外部保存
|
||||
}
|
||||
processQuantityInput(wxid, message, state);
|
||||
break;
|
||||
|
||||
default:
|
||||
state.setCurrentStep(STEP_CONFIRM_GIFT);
|
||||
wxUtil.sendTextMessage(fromWxid, "是否需要开通礼金?\n回复 1 - 是\n回复 2 - 否", 1, fromWxid);
|
||||
break;
|
||||
state.setCurrentStep(STEP_AMOUNT);
|
||||
wxUtil.sendTextMessage(wxid, "请输入金额(1-50元):", 1, wxid);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("转链和礼金流程异常,用户 {} 当前步骤:{}", fromWxid, state.getCurrentStep(), e);
|
||||
wxUtil.sendTextMessage(fromWxid, "❌ 系统异常,请稍后重试", 1, fromWxid);
|
||||
state.reset();
|
||||
userInteractionStates.put(key, state); // 在外部保存
|
||||
}
|
||||
}
|
||||
|
||||
private void processAmountInput(String wxid, String message, UserInteractionState state) {
|
||||
if (!isValidAmount(message)) {
|
||||
wxUtil.sendTextMessage(wxid, "金额格式错误,请输入1-50元", 1, wxid);
|
||||
return;
|
||||
}
|
||||
|
||||
state.getCollectedFields().put("amount", message);
|
||||
state.setCurrentStep(STEP_QUANTITY);
|
||||
wxUtil.sendTextMessage(wxid, "请输入数量(1-100):", 1, wxid);
|
||||
}
|
||||
|
||||
private void processQuantityInput(String wxid, String message, UserInteractionState state) {
|
||||
if (!isValidQuantity(message)) {
|
||||
wxUtil.sendTextMessage(wxid, "数量格式错误,请输入1-100的整数", 1, wxid);
|
||||
return;
|
||||
}
|
||||
String cachedData = cacheMap.get("productData" + wxid);
|
||||
String finalWenAn = cacheMap.get("finalWenAn" + wxid);
|
||||
if (cachedData == null) {
|
||||
wxUtil.sendTextMessage(wxid, "数据丢失,请重新开始流程", 1, wxid);
|
||||
resetState(wxid, state);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
JSONObject jsonObject = JSON.parseObject(cachedData);
|
||||
String skuId = jsonObject.getString("materialUrl");
|
||||
String owner = jsonObject.getString("owner");
|
||||
String skuName = jsonObject.getString("skuName");
|
||||
double amount = Double.parseDouble(state.getCollectedFields().get("amount"));
|
||||
int quantity = Integer.parseInt(message);
|
||||
|
||||
String giftKey = createGiftCoupon(skuId, amount, quantity, owner, skuName);
|
||||
if (giftKey == null) {
|
||||
wxUtil.sendTextMessage(wxid, "礼金创建失败,请重试", 1, wxid);
|
||||
return;
|
||||
}
|
||||
// 记录成功日志
|
||||
logger.info("礼金创建成功 - 用户: {}, SKU: {}, 金额: {}, 数量: {}",
|
||||
wxid, skuId, amount, quantity);
|
||||
// 生成转链
|
||||
String transferUrl = transfer(skuId, giftKey);
|
||||
wxUtil.sendTextMessage(wxid, "附带礼金的链接:\n" + transferUrl, 1, wxid);
|
||||
wxUtil.sendTextMessage(wxid, "附带礼金的方案:\n", 1, wxid);
|
||||
|
||||
wxUtil.sendTextMessage(wxid, finalWenAn.replaceAll(jsonObject.getString("url"), transferUrl), 1, wxid);
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("礼金处理异常 - 用户: {}", wxid, e);
|
||||
wxUtil.sendTextMessage(wxid, "处理异常,请重试", 1, wxid);
|
||||
} finally {
|
||||
resetState(wxid, state);
|
||||
cacheMap.remove("text" + wxid);
|
||||
cacheMap.remove("finalWenAn" + wxid);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理用户输入的推广方案内容
|
||||
*
|
||||
* @param wxid 用户微信ID
|
||||
* @param message 用户输入的方案内容
|
||||
* @param state 当前交互状态
|
||||
*/
|
||||
private void processContentInput(String wxid, String message, UserInteractionState state) {
|
||||
try {
|
||||
// 1. 清除旧缓存
|
||||
cacheMap.remove("productData" + wxid);
|
||||
cacheMap.remove("finalWenAn" + wxid);
|
||||
|
||||
// 2. 生成推广内容
|
||||
HashMap<String, List<String>> contentResult = generatePromotionContent(message);
|
||||
|
||||
// 3. 发送文本内容
|
||||
for (String text : contentResult.get("text")) {
|
||||
wxUtil.sendTextMessage(wxid, text, 1, wxid);
|
||||
}
|
||||
|
||||
// 4. 发送图片(如果有)
|
||||
List<String> images = contentResult.get("images");
|
||||
if (images != null) {
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException ignored) {
|
||||
|
||||
}
|
||||
for (String imageUrl : images) {
|
||||
if (imageUrl != null) {
|
||||
wxUtil.sendImageMessage(wxid, imageUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 缓存商品数据
|
||||
if (!contentResult.get("data").isEmpty()) {
|
||||
String productData = contentResult.get("data").get(0);
|
||||
cacheMap.put("productData" + wxid, productData);
|
||||
cacheMap.put("finalWenAn" + wxid, contentResult.get("finalWenAn").get(0));
|
||||
|
||||
// 6. 进入确认礼金步骤
|
||||
state.setCurrentField("confirm");
|
||||
wxUtil.sendTextMessage(wxid,
|
||||
"是否需要开通礼金?\n回复 1 - 是\n回复 2 - 否",
|
||||
1, wxid);
|
||||
} else {
|
||||
wxUtil.sendTextMessage(wxid, "未获取到商品数据,请检查链接格式", 1, wxid);
|
||||
state.reset();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("处理推广内容异常 - 用户: {}", wxid, e);
|
||||
wxUtil.sendTextMessage(wxid, "处理内容时发生异常,请重试", 1, wxid);
|
||||
state.reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理用户对礼金开通的确认
|
||||
*
|
||||
* @param wxid 用户微信ID
|
||||
* @param message 用户回复(1或2)
|
||||
* @param state 当前交互状态
|
||||
*/
|
||||
private void handleGiftMoneyConfirmation(String wxid, String message, UserInteractionState state) {
|
||||
try {
|
||||
if ("1".equals(message)) {
|
||||
// 用户选择开通礼金
|
||||
state.setCurrentState(UserInteractionState.ProcessState.GIFT_MONEY_FLOW);
|
||||
state.setCurrentStep(UserInteractionState.GiftMoneyStep.STEP_AMOUNT);
|
||||
state.getCollectedFields().clear();
|
||||
|
||||
wxUtil.sendTextMessage(wxid,
|
||||
"请输入开通金额(1-50元,支持小数点后两位):\n" +
|
||||
"示例:20.50",
|
||||
1, wxid);
|
||||
|
||||
} else if ("2".equals(message)) {
|
||||
// 用户选择不开通礼金
|
||||
String cachedData = cacheMap.get("productData" + wxid);
|
||||
if (cachedData != null) {
|
||||
JSONObject productInfo = JSON.parseObject(cachedData);
|
||||
String skuUrl = productInfo.getString("materialUrl");
|
||||
String transferUrl = transfer(skuUrl, null);
|
||||
String finalWenAn = cacheMap.get("finalWenAn" + wxid);
|
||||
|
||||
finalWenAn = (finalWenAn.replace(productInfo.getString("url"), transferUrl));
|
||||
wxUtil.sendTextMessage(wxid,
|
||||
"不开礼金,只转链的方案:\n",
|
||||
1, wxid);
|
||||
wxUtil.sendTextMessage(wxid,
|
||||
finalWenAn,
|
||||
1, wxid);
|
||||
} else {
|
||||
wxUtil.sendTextMessage(wxid, "未找到商品信息,请重新开始流程", 1, wxid);
|
||||
}
|
||||
state.reset();
|
||||
cacheMap.remove("productData" + wxid);
|
||||
cacheMap.remove("finalWenAn" + wxid);
|
||||
|
||||
|
||||
} else {
|
||||
// 无效输入
|
||||
wxUtil.sendTextMessage(wxid,
|
||||
"请输入有效选项:\n" +
|
||||
"回复 1 - 开通礼金\n" +
|
||||
"回复 2 - 直接转链",
|
||||
1, wxid);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("处理礼金确认异常 - 用户: {}", wxid, e);
|
||||
wxUtil.sendTextMessage(wxid, "处理请求时发生异常,请重试", 1, wxid);
|
||||
state.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private void resetState(String wxid, UserInteractionState state) {
|
||||
state.reset();
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
// 修改点3:在createPromotionWithGift方法开始处增加状态校验
|
||||
if (state == null || state.getCurrentStep() == null) {
|
||||
logger.warn("非法状态访问: {}", fromWxid);
|
||||
wxUtil.sendTextMessage(fromWxid, "⚠️ 会话超时,请重新开始流程", 1, fromWxid);
|
||||
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);
|
||||
} 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);
|
||||
} else {
|
||||
wxUtil.sendTextMessage(fromWxid, "未找到缓存的商品链接,请重新开始流程", 1, fromWxid);
|
||||
}
|
||||
state.reset();
|
||||
userInteractionStates.put(key, state); // 在外部保存
|
||||
} else {
|
||||
wxUtil.sendTextMessage(fromWxid, "无效的选择,请重新输入:\n回复 1 - 是\n回复 2 - 否", 1, fromWxid);
|
||||
}
|
||||
break;
|
||||
|
||||
case STEP_AMOUNT:
|
||||
logger.debug("用户 {} 输入金额:{}", fromWxid, message);
|
||||
if (message == null || message.trim().isEmpty()) {
|
||||
wxUtil.sendTextMessage(fromWxid, "金额不能为空,请输入数字(如:100.00)", 1, fromWxid);
|
||||
return;
|
||||
}
|
||||
if (!isValidAmount(message)) {
|
||||
wxUtil.sendTextMessage(fromWxid, "金额格式错误,请输入数字(如:100.00)", 1, fromWxid);
|
||||
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);
|
||||
sendStepPrompt(fromWxid, 1, 3);
|
||||
break;
|
||||
|
||||
case STEP_QUANTITY:
|
||||
logger.debug("用户 {} 输入数量:{}", fromWxid, message); // 新增
|
||||
if (!isValidQuantity(message)) {
|
||||
wxUtil.sendTextMessage(fromWxid, "数量格式错误,请输入整数", 1, fromWxid);
|
||||
return;
|
||||
}
|
||||
|
||||
int quantity = Integer.parseInt(message);
|
||||
if (quantity < 1 || quantity > 100) {
|
||||
wxUtil.sendTextMessage(fromWxid, "数量需在1-100之间", 1, fromWxid);
|
||||
return;
|
||||
}
|
||||
|
||||
// 从缓存中获取 amount
|
||||
String amountStr = state.getCollectedFields().get("amount");
|
||||
if (amountStr == null || amountStr.trim().isEmpty()) {
|
||||
wxUtil.sendTextMessage(fromWxid, "未找到金额,请重新开始流程", 1, fromWxid);
|
||||
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);
|
||||
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);
|
||||
|
||||
wxUtil.sendTextMessage(fromWxid, "附带礼金的方案:\n" + finalWenAn.replaceAll(jsonObject.getString("url"), transferUrl), 1, fromWxid);
|
||||
state.reset();
|
||||
userInteractionStates.put(key, state); // 在外部保存
|
||||
} else {
|
||||
wxUtil.sendTextMessage(fromWxid, "未找到缓存的商品链接,请重新开始流程", 1, fromWxid);
|
||||
state.reset();
|
||||
userInteractionStates.put(key, state); // 在外部保存
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
state.setCurrentStep(STEP_CONFIRM_GIFT);
|
||||
wxUtil.sendTextMessage(fromWxid, "是否需要开通礼金?\n回复 1 - 是\n回复 2 - 否", 1, fromWxid);
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("转链和礼金流程异常,用户 {} 当前步骤:{}", fromWxid, state.getCurrentStep(), e);
|
||||
wxUtil.sendTextMessage(fromWxid, "❌ 系统异常,请稍后重试", 1, fromWxid);
|
||||
state.reset();
|
||||
userInteractionStates.put(key, state); // 在外部保存
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成转链和文案的方法
|
||||
* 生成转链和方案的方法
|
||||
*
|
||||
* @param message 文案内容,包含商品链接
|
||||
* @return 处理后的文案,附带商品信息
|
||||
* @param message 方案内容,包含商品链接
|
||||
* @return 处理后的方案,附带商品信息
|
||||
*/
|
||||
public HashMap<String, List<String>> generatePromotionContent(String message) {
|
||||
HashMap<String, List<String>> finallMessage = new HashMap<>();
|
||||
List<String> textList = new ArrayList<>();
|
||||
List<String> imagesList = new ArrayList<>();
|
||||
List<String> dataList = new ArrayList<>();
|
||||
// 最终的方案
|
||||
List<String> finalWenAn = new ArrayList<>();
|
||||
|
||||
// 提取文案中的所有 u.jd.com 链接
|
||||
|
||||
// 提取方案中的所有 u.jd.com 链接
|
||||
List<String> urls = extractUJDUrls(message);
|
||||
if (urls.isEmpty()) {
|
||||
textList.add("文案中未找到有效的商品链接,请检查格式是否正确。");
|
||||
textList.add("方案中未找到有效的商品链接,请检查格式是否正确。");
|
||||
finallMessage.put("text", textList);
|
||||
return finallMessage;
|
||||
}
|
||||
@@ -1133,11 +1368,11 @@ private void createPromotionWithGift(String fromWxid, String message) {
|
||||
//},
|
||||
//"skuName": "松下(Panasonic)白月光4.0Ultra 洗烘套装 10kg滚筒洗衣机+变频热泵烘干机 除毛升级2.0 水氧SPA护理 8532N+8532NR",
|
||||
//"spuid": 100137629936,
|
||||
dataList.add(JSONObject.toJSONString(productInfo.getData()[0]));
|
||||
|
||||
JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(productInfo.getData()[0]));
|
||||
jsonObject.put("url", url);
|
||||
dataList.add(JSONObject.toJSONString(jsonObject));
|
||||
finallMessage.put("data", dataList);
|
||||
|
||||
|
||||
HashMap<String, String> itemMap = new HashMap<>();
|
||||
itemMap.put("url", url);
|
||||
itemMap.put("materialUrl", productInfo.getData()[0].getMaterialUrl());
|
||||
@@ -1148,12 +1383,13 @@ private void createPromotionWithGift(String fromWxid, String message) {
|
||||
itemMap.put("skuName", productInfo.getData()[0].getSkuName());
|
||||
String replaceAll = itemMap.get("skuName").replaceAll("国家", "").replaceAll("补贴", "");
|
||||
itemMap.put("spuid", String.valueOf(productInfo.getData()[0].getSpuid()));
|
||||
itemMap.put("commission", String.valueOf(productInfo.getData()[0].getCommissionInfo().getCommission()));
|
||||
itemMap.put("commissionShare", String.valueOf(productInfo.getData()[0].getCommissionInfo().getCommissionShare()));
|
||||
//for (HashMap.Entry<String, String> entry : itemMap.entrySet()) {
|
||||
//couponInfo.append(" ").append(entry.getKey()).append(": ").append(entry.getValue()).append("\n");
|
||||
//}
|
||||
couponInfo.append(" ").append("店铺:\n").append(itemMap.get("shopName")).append("\n")
|
||||
.append("标题:\n").append(replaceAll).append("\n")
|
||||
.append("自营 POP:\n").append(itemMap.get("owner"));
|
||||
couponInfo.append(" ").append("店铺:\n").append(itemMap.get("shopName")).append("\n").append(" 标题:\n").append(replaceAll).append("\n").append("自营 POP:\n").append(itemMap.get("owner").equals("g") ? " 自营 " : " POP ")
|
||||
.append("佣金:\n").append(itemMap.get("commission")).append("\n").append("佣金比例:\n").append(itemMap.get("commissionShare"));
|
||||
|
||||
|
||||
//StringBuilder images = new StringBuilder();
|
||||
@@ -1168,6 +1404,17 @@ private void createPromotionWithGift(String fromWxid, String message) {
|
||||
//textList.add(String.valueOf(images));
|
||||
resultList.add(itemMap);
|
||||
|
||||
/*直接生成闲鱼的商品文案*/
|
||||
StringBuilder sb1 = new StringBuilder();
|
||||
// 新建格式好日期
|
||||
DateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒");
|
||||
sb1.append(replaceAll).append("\n").append(WENAN_FANAN.replaceAll("更新", dateFormat.format(new Date()) + "更新"));
|
||||
textList.add("闲鱼方案的文案:\n");
|
||||
textList.add(String.valueOf(sb1));
|
||||
StringBuilder sb2 = new StringBuilder();
|
||||
sb2.append(replaceAll).append("\n").append(WENAN_ZCXS);
|
||||
textList.add("闲鱼正常销售:\n");
|
||||
textList.add(String.valueOf(sb2));
|
||||
}
|
||||
textList.add(String.valueOf(couponInfo));
|
||||
|
||||
@@ -1179,25 +1426,29 @@ private void createPromotionWithGift(String fromWxid, String message) {
|
||||
finallMessage.put("text", textList);
|
||||
}
|
||||
}
|
||||
StringBuilder wenan = new StringBuilder().append("文案生成: \n");
|
||||
// 完成转链后替换链接为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 = 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));
|
||||
//}
|
||||
wenan = new StringBuilder(message);
|
||||
//textList.add(String.valueOf(wenan));
|
||||
finalWenAn.add(String.valueOf(wenan));
|
||||
|
||||
}
|
||||
|
||||
textList.add(String.valueOf(wenan));
|
||||
|
||||
finallMessage.put("text", textList);
|
||||
finallMessage.put("images", imagesList);
|
||||
finallMessage.put("finalWenAn", finalWenAn);
|
||||
return finallMessage;
|
||||
|
||||
}
|
||||
|
||||
private String downloadImage(String imageUrl, String destinationFile) {
|
||||
try (BufferedInputStream in = new BufferedInputStream(new URL(imageUrl).openStream());
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(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) {
|
||||
@@ -1211,9 +1462,9 @@ private void createPromotionWithGift(String fromWxid, String message) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 提取文案中的所有 u.jd.com 链接
|
||||
* 提取方案中的所有 u.jd.com 链接
|
||||
*
|
||||
* @param message 文案内容
|
||||
* @param message 方案内容
|
||||
* @return 包含所有 u.jd.com 链接的列表
|
||||
*/
|
||||
private List<String> extractUJDUrls(String message) {
|
||||
@@ -1273,7 +1524,8 @@ private void createPromotionWithGift(String fromWxid, String message) {
|
||||
}
|
||||
|
||||
// 在JDUtil类中新增方法实现商品详情查询接口
|
||||
public UnionOpenGoodsBigfieldQueryResponse getUnionOpenGoodsBigfieldQueryResponse(String skuId) throws Exception {
|
||||
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();
|
||||
@@ -1315,7 +1567,7 @@ private void createPromotionWithGift(String fromWxid, String message) {
|
||||
|
||||
|
||||
// 新增礼金创建方法
|
||||
public String createGiftCoupon(String skuId, double amount, int quantity, String owner) throws Exception {
|
||||
public String createGiftCoupon(String skuId, double amount, int quantity, String owner, String skuName) throws Exception {
|
||||
logger.debug("准备创建礼金:SKU={}, 金额={}元,数量={}, Owner={}", skuId, amount, quantity, owner);
|
||||
|
||||
// 参数校验
|
||||
@@ -1341,18 +1593,28 @@ private void createPromotionWithGift(String fromWxid, String message) {
|
||||
if ("pop".equals(owner)) {
|
||||
startTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH"));
|
||||
endTime = LocalDateTime.now().plusDays(6).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH"));
|
||||
couponReq.setEffectiveDays(7);
|
||||
|
||||
} else {
|
||||
startTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH"));
|
||||
endTime = LocalDateTime.now().plusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH"));
|
||||
couponReq.setEffectiveDays(1);
|
||||
|
||||
}
|
||||
|
||||
couponReq.setReceiveStartTime(startTime);
|
||||
couponReq.setReceiveEndTime(endTime);
|
||||
couponReq.setEffectiveDays(7);
|
||||
couponReq.setIsSpu(1);
|
||||
couponReq.setExpireType(1);
|
||||
couponReq.setShare(-1);
|
||||
couponReq.setCouponTitle(skuId);
|
||||
if (skuName.length() >= 25) {
|
||||
skuName = skuName.substring(0, 25);
|
||||
}
|
||||
// 新建格式日期
|
||||
DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
skuName = skuName + " " + dateFormat.format(new Date());
|
||||
|
||||
couponReq.setCouponTitle(skuName);
|
||||
couponReq.setContentMatch(1);
|
||||
|
||||
request.setCouponReq(couponReq);
|
||||
@@ -1363,7 +1625,7 @@ private void createPromotionWithGift(String fromWxid, String message) {
|
||||
UnionOpenCouponGiftGetResponse response = client.execute(request);
|
||||
logger.debug("API响应:{}", JSON.toJSONString(response));
|
||||
|
||||
if ("200".equals(response.getCode())) {
|
||||
if ("0".equals(response.getCode()) && response.getGetResult().getCode() == 200) {
|
||||
String giftKey = response.getGetResult().getData().getGiftCouponKey();
|
||||
logger.debug("礼金创建成功:批次ID={}, 返回数据:{}", giftKey, response.getGetResult().getData());
|
||||
return giftKey;
|
||||
@@ -1376,15 +1638,6 @@ private void createPromotionWithGift(String fromWxid, String message) {
|
||||
|
||||
// 修改activateGiftMoney方法调用真实接口
|
||||
private boolean activateGiftMoney(String skuId, double amount, int quantity, String owner) {
|
||||
try {
|
||||
String giftKey = createGiftCoupon(skuId, amount, quantity, owner);
|
||||
if (giftKey != null) {
|
||||
// 可在此处保存礼金批次ID到用户状态
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("礼金创建失败", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1407,7 +1660,7 @@ private void createPromotionWithGift(String fromWxid, String message) {
|
||||
}
|
||||
|
||||
|
||||
private boolean isValidAmount(String input) {
|
||||
boolean isValidAmount(String input) {
|
||||
// 新增:直接处理 null 或空字符串
|
||||
if (input == null || input.trim().isEmpty()) {
|
||||
return false;
|
||||
@@ -1439,6 +1692,16 @@ private void createPromotionWithGift(String fromWxid, String message) {
|
||||
}
|
||||
}
|
||||
|
||||
// 将状态存储迁移到Redis
|
||||
public void saveState(String wxid, UserInteractionState state) {
|
||||
String key = INTERACTION_STATE_PREFIX + wxid;
|
||||
redisTemplate.opsForValue().set(key, JSON.toJSONString(state), 10, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
public UserInteractionState loadState(String wxid) {
|
||||
String json = redisTemplate.opsForValue().get(INTERACTION_STATE_PREFIX + wxid);
|
||||
return JSON.parseObject(json, UserInteractionState.class);
|
||||
}
|
||||
|
||||
// 定义一个内部类来存储用户交互状态
|
||||
@Getter
|
||||
@@ -1466,32 +1729,42 @@ private void createPromotionWithGift(String fromWxid, String message) {
|
||||
public void reset() {
|
||||
this.currentState = INIT;
|
||||
this.collectedFields.clear();
|
||||
this.currentStep = STEP_CONFIRM_GIFT ; // 明确重置步骤
|
||||
this.currentStep = STEP_CONFIRM_GIFT; // 明确重置步骤
|
||||
updateLastInteractionTime();
|
||||
}
|
||||
|
||||
// 在UserInteractionState类中增加状态校验方法
|
||||
public boolean validateStep(GiftMoneyStep expectedStep) {
|
||||
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
|
||||
}
|
||||
|
||||
public enum GiftMoneyStep {
|
||||
STEP_CONFIRM_GIFT(0), // 显式指定序号
|
||||
STEP_AMOUNT(1),
|
||||
STEP_QUANTITY(2);
|
||||
private final int code;
|
||||
public enum GiftMoneyStep {
|
||||
STEP_CONFIRM_GIFT(0), // 显式指定序号
|
||||
STEP_AMOUNT(1), STEP_QUANTITY(2);
|
||||
private final int code;
|
||||
|
||||
GiftMoneyStep(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
GiftMoneyStep(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1512,7 +1785,6 @@ public enum GiftMoneyStep {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 统计指标DTO
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
@@ -1529,5 +1801,4 @@ public enum GiftMoneyStep {
|
||||
private long violations; // 违规订单数
|
||||
private double violationCommission;// 违规佣金
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user