This commit is contained in:
雷欧(林平凡)
2025-08-15 14:53:32 +08:00
parent f97a5b0130
commit 37fc0697b3
2 changed files with 418 additions and 1 deletions

View File

@@ -1,7 +1,11 @@
package cn.van.business.controller.jd;
import cn.van.business.controller.wx.WXListener;
import cn.van.business.util.JDProductService;
import cn.van.business.util.JDUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -19,7 +23,11 @@ import java.util.List;
@Controller
@RequestMapping("/jd")
@RestController
@Slf4j
public class JDInnerController {
private static final Logger logger = LoggerFactory.getLogger(JDInnerController.class);
private final static String skey = "2192057370ef8140c201079969c956a3";
private boolean checkSkey(String skey) {
return skey.equals(this.skey);
@@ -32,7 +40,8 @@ public class JDInnerController {
}
@RequestMapping("/generatePromotionContent")
public HashMap<String, List<String>> generatePromotionContent(String message) {
public HashMap<String, List<String>> generatePromotionContent(String message,String skey) {
loo
if (!checkSkey(skey)) {
return null;
}

View File

@@ -0,0 +1,408 @@
package cn.van.business.util;
import cn.van.business.model.cj.XbMessage;
import cn.van.business.model.cj.XbMessageItem;
import cn.van.business.repository.XbMessageItemRepository;
import cn.van.business.repository.XbMessageRepository;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
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.GoodsService.request.query.GoodsReq;
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.promotionbysubunioni.PromotionService.request.get.PromotionCodeReq;
import com.jd.open.api.sdk.request.kplunion.UnionOpenCouponGiftGetRequest;
import com.jd.open.api.sdk.request.kplunion.UnionOpenGoodsQueryRequest;
import com.jd.open.api.sdk.request.kplunion.UnionOpenPromotionBysubunionidGetRequest;
import com.jd.open.api.sdk.response.kplunion.UnionOpenCouponGiftGetResponse;
import com.jd.open.api.sdk.response.kplunion.UnionOpenGoodsQueryResponse;
import com.jd.open.api.sdk.response.kplunion.UnionOpenPromotionBysubunionidGetResponse;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import static cn.van.business.util.JDUtil.*;
/**
* 京东商品服务类抽取来源于JDUtil
*/
@Service
@Slf4j
public class JDProductService {
// 京东开放平台配置
private static final String LPF_APP_KEY_WZ = "98e21c89ae5610240ec3f5f575f86a59";
private static final String LPF_SECRET_KEY_WZ = "3dcb6b23a1104639ac433fd07adb6dfb";
private static final String SERVER_URL = "https://api.jd.com/routerjson";
private static final String ACCESS_TOKEN = "";
private static final Logger logger = LoggerFactory.getLogger(JDProductService.class);
private final StringRedisTemplate redisTemplate;
private final XbMessageRepository xbMessageRepository;
private final XbMessageItemRepository xbMessageItemRepository;
@Autowired
public JDProductService(StringRedisTemplate redisTemplate, XbMessageRepository xbMessageRepository, XbMessageItemRepository xbMessageItemRepository) {
this.redisTemplate = redisTemplate;
this.xbMessageRepository = xbMessageRepository;
this.xbMessageItemRepository = xbMessageItemRepository;
}
/**
* 生成转链和方案的方法
*
* @param message 方案内容,包含商品链接
* @param fromWxid
* @return 处理后的方案,附带商品信息
*/
public synchronized HashMap<String, List<String>> generatePromotionContent(String message) {
HashMap<String, List<String>> finallyMessage = 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 链接
List<String> urlList = new ArrayList<>();
List<String> priceList = new ArrayList<>();
// 提取方案中的所有 u.jd.com 链接
List<String> urls = extractUJDUrls(message);
if (urls.isEmpty()) {
textList.add("方案中未找到有效的商品链接,请检查格式是否正确。");
finallyMessage.put("text", textList);
return finallyMessage;
}
// 如果需要图片和SKU名称则代表要把图片下载发过去还有对应的skuName
StringBuilder couponInfo = null;
ArrayList<HashMap<String, String>> resultList = new ArrayList<>();
String format = null;
DateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒");
for (String url : urls) {
try {
// 重置。不然会一直追加文本内容
couponInfo = new StringBuilder();
// 新建格式好日期
format = dateFormat.format(new Date());
// 查询商品信息
GoodsQueryResult productInfo = queryProductInfoByUJDUrl(url);
if (productInfo == null || productInfo.getCode() != 200) {
couponInfo.append("链接查询失败:").append(url).append("\n");
continue;
}
long totalCount = productInfo.getTotalCount();
if (totalCount == 0) {
//couponInfo.append("链接类型:优惠券\n\n");
} else {
couponInfo.append(url).append("\n");
urlList.add(url);
couponInfo.append("链接类型:商品\n\n");
JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(productInfo.getData()[0]));
jsonObject.put("url", url);
dataList.add(jsonObject.toString());
HashMap<String, String> itemMap = new HashMap<>();
itemMap.put("url", url);
itemMap.put("materialUrl", productInfo.getData()[0].getMaterialUrl());
itemMap.put("oriItemId", productInfo.getData()[0].getOriItemId());
itemMap.put("owner", productInfo.getData()[0].getOwner());
itemMap.put("shopId", String.valueOf(productInfo.getData()[0].getShopInfo().getShopId()));
itemMap.put("shopName", productInfo.getData()[0].getShopInfo().getShopName());
itemMap.put("skuName", productInfo.getData()[0].getSkuName());
String replaceAll = itemMap.get("skuName").replaceAll("以旧|政府|换新|领取|国家|补贴|15%|20%|国补|立减|【|】", "");
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(itemMap.get("shopName")).append("\n").append("标题: ").append(replaceAll).append("\n").append("自营 POP ").append(itemMap.get("owner").equals("g") ? " 自营 " : " POP ").append("\n").append("佣金比例: ").append(itemMap.get("commissionShare")).append("\n").append("佣金: ").append(itemMap.get("commission")).append("\n");
//StringBuilder images = new StringBuilder();
if (productInfo.getData()[0].getImageInfo() != null) {
//images.append(" ").append("图片信息:\n");
//int index = 1;
for (UrlInfo image : productInfo.getData()[0].getImageInfo().getImageList()) {
//images.append("图片 ").append(index++).append("\n").append(image.getUrl()).append("\n");
imagesList.add(image.getUrl());
}
}
//textList.add(String.valueOf(images));
resultList.add(itemMap);
String title = "";
try {
if (!message.equals(url)) {
String[] lines = message.split("\\r?\\n");
if (lines.length > 0) {
title = lines[0];
// 有的换行了
if (lines[1].length() > 3 && !lines[1].contains("u.jd")) {
title = title + lines[1];
}
logger.info("文案首行 {}", title);
title = title.replaceAll("@|所有人", "");
}
}
} catch (Exception e) {
logger.error("文案首行异常", e);
}
/*直接生成闲鱼的商品文案*/
StringBuilder sb1 = new StringBuilder();
sb1.append("(标价到手) ").append(title).append(replaceAll).append("\n").append(WENAN_FANAN_LQD.replaceAll("更新", format + "更新"));
//textList.add("闲鱼方案的文案:\n");
textList.add(String.valueOf(sb1));
StringBuilder sb2 = new StringBuilder();
sb2.append("(一键代下) ").append(title).append(replaceAll).append("\n").append(WENAN_ZCXS);
//textList.add("闲鱼正常销售:\n");
textList.add(String.valueOf(sb2));
StringBuilder sb3 = new StringBuilder();
sb3.append("(标价到手) ").append(title).append(replaceAll).append("\n").append(WENAN_FANAN_HG.replaceAll("更新", format + "更新"));
textList.add(String.valueOf(sb3));
StringBuilder sb4 = new StringBuilder();
sb4.append("【教你下单】 ").append(title).append(replaceAll).append("\n").append(WENAN_FANAN_BX.replaceAll("信息更新日期:", "信息更新日期:" + format));
textList.add(String.valueOf(sb4));
}
textList.add(String.valueOf(couponInfo));
finallyMessage.put("data", dataList);
finallyMessage.put("urlList", urlList);
} catch (Exception e) {
logger.error("处理商品链接时发生异常:{}", url, e);
couponInfo.append(" 处理商品链接时发生异常:").append(url).append("\n");
textList.add(String.valueOf(couponInfo));
finallyMessage.put("text", textList);
}
}
/**
* 因为在这里转链返回,没有什么意义,后面走转链不转链,会重新发方案
* */
StringBuilder wenan = new StringBuilder();
wenan = new StringBuilder().append(format).append(FANAN_COMMON).append(message);
finalWenAn.add(String.valueOf(wenan));
finallyMessage.put("text", textList);
finallyMessage.put("images", imagesList);
finallyMessage.put("finalWenAn", finalWenAn);
return finallyMessage;
}
/**
* 查询商品信息
*
* @param uJDUrl 京东商品链接
* @return 商品查询结果
* @throws Exception 查询异常
*/
public GoodsQueryResult queryProductInfoByUJDUrl(String uJDUrl) throws Exception {
UnionOpenGoodsQueryResponse response = getUnionOpenGoodsQueryRequest(uJDUrl);
if (response == null || response.getQueryResult() == null) {
return null;
}
GoodsQueryResult queryResult = response.getQueryResult();
if (queryResult.getCode() != 200) {
return null;
}
return queryResult;
}
/**
* 调用京东开放平台接口查询商品信息
*
* @param uJDUrl 京东商品链接
* @return 京东商品查询响应
* @throws Exception 查询异常
*/
public UnionOpenGoodsQueryResponse getUnionOpenGoodsQueryRequest(String uJDUrl) throws Exception {
JdClient client = new DefaultJdClient(SERVER_URL, ACCESS_TOKEN, LPF_APP_KEY_WZ, LPF_SECRET_KEY_WZ);
UnionOpenGoodsQueryRequest request = new UnionOpenGoodsQueryRequest();
GoodsReq goodsReq = new GoodsReq();
goodsReq.setKeyword(uJDUrl);
goodsReq.setSceneId(1);
request.setGoodsReqDTO(goodsReq);
request.setVersion("1.0");
request.setSignmethod("md5");
// 时间戳格式为yyyy-MM-dd HH:mm:ss时区为GMT+8
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
request.setTimestamp(simpleDateFormat.format(date));
UnionOpenGoodsQueryResponse execute = client.execute(request);
return execute;
}
/**
* 创建礼金
*
* @param skuId 商品SKU ID
* @param amount 礼金金额
* @param quantity 礼金数量
* @param owner 商品所有者(g:自营, pop:POP商家)
* @param skuName 商品名称
* @return 礼金Key
* @throws Exception 创建异常
*/
public String createGiftCoupon(String skuId, double amount, int quantity, String owner, String skuName) throws Exception {
log.debug("准备创建礼金SKU={}, 金额={}元,数量={}, Owner={}", skuId, amount, quantity, owner);
// 参数校验
if (skuId == null || amount <= 0 || quantity <= 0) {
log.error("礼金创建失败参数错误SKU={}, 金额={}元,数量={}", skuId, amount, quantity);
return null;
}
// 设置默认值
owner = (owner != null) ? owner : "g";
JdClient client = new DefaultJdClient(SERVER_URL, ACCESS_TOKEN, LPF_APP_KEY_WZ, LPF_SECRET_KEY_WZ);
UnionOpenCouponGiftGetRequest request = new UnionOpenCouponGiftGetRequest();
CreateGiftCouponReq couponReq = new CreateGiftCouponReq();
couponReq.setSkuMaterialId(skuId); // 使用SKU或链接
couponReq.setDiscount(amount);
couponReq.setAmount(quantity);
// 自营的只能设置一天pop的只能设置7天默认为自营
String startTime;
String endTime;
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.setIsSpu(1);
couponReq.setExpireType(1);
couponReq.setShare(-1);
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);
request.setVersion("1.0");
log.debug("请求参数:{}", JSON.toJSONString(request));
UnionOpenCouponGiftGetResponse response = client.execute(request);
log.debug("API响应{}", JSON.toJSONString(response));
if ("0".equals(response.getCode()) && response.getGetResult().getCode() == 200) {
String giftKey = response.getGetResult().getData().getGiftCouponKey();
log.debug("礼金创建成功批次ID={}, 返回数据:{}", giftKey, response.getGetResult().getData());
return giftKey;
} else {
log.error("礼金创建失败:错误码={}, 错误信息={}", response.getCode(), response.getMsg());
}
return null;
}
/**
* 转链接口:通过商品链接、领券链接、活动链接获取普通推广链接或优惠券二合一推广链接
*
* @param url 原始链接
* @param giftCouponKey 礼金Key可选
* @return 转换后的短链接
*/
public 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();
PromotionCodeReq promotionCodeReq = new PromotionCodeReq();
promotionCodeReq.setSceneId(1);
promotionCodeReq.setMaterialId(url);
if (giftCouponKey != null) {
promotionCodeReq.setGiftCouponKey(giftCouponKey);
}
request.setPromotionCodeReq(promotionCodeReq);
request.setVersion("1.0");
UnionOpenPromotionBysubunionidGetResponse response;
try {
response = client.execute(request);
} catch (Exception e) {
throw new RuntimeException(e);
}
String result = "";
if (response != null) {
if ("0".equals(response.getCode()) && response.getGetResult().getCode() == 200) {
result = response.getGetResult().getData().getShortURL();
}
} else {
result = null;
}
return result;
}
/**
* 将礼金信息写入Redis
*
* @param skuId 商品SKU ID
* @param giftKey 礼金Key
* @param skuName 商品名称
* @param owner 商品所有者
*/
public void saveGiftCouponToRedis(String skuId, String giftKey, String skuName, String owner) {
String key = "gift_coupon:" + skuId;
String hashKey = giftKey;
LocalDateTime expireTime = LocalDateTime.now().plus("g".equals(owner) ? 1 : 7, TimeUnit.DAYS.toChronoUnit());
Map<String, Object> data = new HashMap<>();
data.put("giftKey", giftKey);
data.put("skuName", skuName);
data.put("owner", owner);
data.put("expireTime", expireTime.format(DateTimeFormatter.ISO_DATE_TIME));
// 存入 Redis Hash
redisTemplate.opsForHash().put(key, hashKey, JSON.toJSONString(data));
}
}