完成基本京粉功能推送,订单统计,订单拉取的稳定版初版

This commit is contained in:
Leo
2024-11-11 00:02:27 +08:00
parent 19f1095a7c
commit 9c1c18b71d
38 changed files with 4628 additions and 185 deletions

View File

@@ -1,17 +1,22 @@
package cn.van.business.util;
import cn.van.business.model.GoodsInfoVO;
import cn.van.business.model.OrderRow;
import cn.van.business.enums.ValidCodeConverter;
import cn.van.business.model.jd.GoodsInfoVO;
import cn.van.business.model.jd.OrderRow;
import cn.van.business.repository.OrderRowRepository;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.util.DateUtils;
import com.jd.open.api.sdk.DefaultJdClient;
import com.jd.open.api.sdk.JdClient;
import com.jd.open.api.sdk.domain.kplunion.OrderService.request.query.OrderRowReq;
import com.jd.open.api.sdk.domain.kplunion.OrderService.response.query.GoodsInfo;
import com.jd.open.api.sdk.domain.kplunion.OrderService.response.query.OrderRowResp;
import com.jd.open.api.sdk.domain.kplunion.promotioncommon.PromotionService.request.get.PromotionCodeReq;
import com.jd.open.api.sdk.request.kplunion.UnionOpenOrderRowQueryRequest;
import com.jd.open.api.sdk.request.kplunion.UnionOpenPromotionCommonGetRequest;
import com.jd.open.api.sdk.response.kplunion.UnionOpenOrderRowQueryResponse;
import com.jd.open.api.sdk.response.kplunion.UnionOpenPromotionCommonGetResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
@@ -21,9 +26,12 @@ import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import static java.lang.Thread.sleep;
@@ -37,109 +45,31 @@ import static java.lang.Thread.sleep;
public class JDUtils {
private static final String SERVER_URL =
"https://api.jd.com/routerjson";
// van论坛
private static final String APP_KEY =
"98e21c89ae5610240ec3f5f575f86a59";
private static final String SECRET_KEY =
"3dcb6b23a1104639ac433fd07adb6dfb";
// 导购的
//private static final String APP_KEY = "faf410cb9587dc80dc7b31e321d7d322";
//private static final String SECRET_KEY =
// "a4fb15d7bedd4316b97b4e96e4effc1c";
//accessToken
private static final String ACCESS_TOKEN = "";
//标记唯一订单行:订单+sku维度的唯一标识
private static final String ORDER_ROW_KEY = "jd:order:row:";
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private OrderRowRepository orderRowRepository;
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
/**
* 拉取最新的订单
*/
@Scheduled(cron = "0 * * * * ?") // 每分钟执行一次
public void fetchLatestOrder() throws Exception {
LocalDateTime now = LocalDateTime.now();
LocalDateTime lastMinute = now.minusMinutes(1).withSecond(0).withNano(0);
UnionOpenOrderRowQueryResponse response = fetchOrdersForDateTime(lastMinute, true); // 真实代表实时订单
if (response != null){
int code = response.getQueryResult().getCode();
if (code == 200) {
if (response.getQueryResult().getCode() == 200) {
OrderRowResp[] orderRowResps = response.getQueryResult().getData();
if (orderRowResps == null) {
return;
}
for (OrderRowResp orderRowResp : orderRowResps) {
// 固化到数据库
OrderRow orderRow = createOrderRow(orderRowResp);
// 订单号不存在就保存,存在就更新订单状态
orderRowRepository.save(orderRow);
}
}
}
}
}
/**
* 拉取历史订单
*/
public void fetchHistoricalOrders() throws Exception {
// 从设定的开始日期到昨天的同一时间
LocalDateTime startDate = LocalDateTime.of(2024, 7, 1, 0, 0);
LocalDateTime now = LocalDateTime.now();
LocalDateTime lastHour = now.minusHours(1).withMinute(0).withSecond(0).withNano(0);
while (!startDate.isEqual(lastHour)) {
UnionOpenOrderRowQueryResponse response = fetchOrdersForDateTime(startDate, false); // 假的代表历史订单
if (response != null){
int code = response.getQueryResult().getCode();
if (code == 200) {
if (response.getQueryResult().getCode() == 200) {
OrderRowResp[] orderRowResps = response.getQueryResult().getData();
if (orderRowResps == null) {
continue;
}
for (OrderRowResp orderRowResp : orderRowResps) {
// 固化到数据库
OrderRow orderRow = createOrderRow(orderRowResp);
// 订单号不存在就保存,存在就更新订单状态
orderRowRepository.save(orderRow);
}
}
}
sleep(1000);
}
startDate = startDate.plusHours(1);
}
}
/**
* 根据指定的日期时间拉取订单
*/
public UnionOpenOrderRowQueryResponse fetchOrdersForDateTime(LocalDateTime dateTime, boolean isRealTime) throws Exception {
LocalDateTime endTime = isRealTime ? dateTime.plusMinutes(1) : dateTime.plusHours(1);
String key = dateTime.format(DATE_TIME_FORMATTER);
String hourRange = isRealTime ? "minute" : "hour";
SetOperations<String, String> setOps = redisTemplate.opsForSet();
// 检查是否标记为已拉取
if (Boolean.TRUE.equals(setOps.isMember(key, hourRange))) {
System.out.println(dateTime.format(DATE_TIME_FORMATTER) + " 已经拉取,跳过");
return null;
}
// 调用 API 以拉取订单
UnionOpenOrderRowQueryResponse unionOpenOrderRowQueryResponse = getUnionOpenOrderRowQueryResponse(dateTime, endTime);
// 标记已拉取
setOps.add(key, hourRange);
return unionOpenOrderRowQueryResponse;
}
@Autowired
private WXUtil wxUtil;
/**
* 将 响应参数转化为 OrderRow并返回
* */
*/
private static OrderRow createOrderRow(OrderRowResp orderRowResp) {
OrderRow orderRow = new OrderRow();
orderRow.setOrderId(orderRowResp.getOrderId());
@@ -212,6 +142,240 @@ public class JDUtils {
return orderRow;
}
private static List<OrderRow> filterOrdersByDate(List<OrderRow> orderRows, int daysBack) {
LocalDate now = LocalDate.now();
return orderRows.stream()
.filter(order -> {
// 将 Date 转换为 LocalDate
LocalDate orderDate = order.getOrderTime().toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();
// 计算是否在给定的天数内
return !orderDate.isBefore(now.minusDays(daysBack)) && !orderDate.isAfter(now);
})
.collect(Collectors.toList());
}
/**
* 拉取最新的订单 1440分钟
*/
@Scheduled(cron = "0 * * * * ?") // 每分钟执行一次
public void fetchLatestOrder() throws Exception {
LocalDateTime now = LocalDateTime.now();
LocalDateTime lastMinute = now.minusMinutes(10).withSecond(0).withNano(0);
UnionOpenOrderRowQueryResponse response = fetchOrdersForDateTime(lastMinute, true); // 真实代表实时订单
if (response != null) {
int code = response.getQueryResult().getCode();
if (code == 200) {
if (response.getQueryResult().getCode() == 200) {
OrderRowResp[] orderRowResps = response.getQueryResult().getData();
if (orderRowResps == null) {
return;
}
for (OrderRowResp orderRowResp : orderRowResps) {
// 固化到数据库
OrderRow orderRow = createOrderRow(orderRowResp);
// 订单号不存在就保存,存在就更新订单状态
orderRowRepository.save(orderRow);
}
}
}
}
}
@Scheduled(cron = "0 * * * * ?") // 每分钟执行一次
public void sendOrderToWx() {
int[] parm = {-1, 17};
List<OrderRow> orderRows = orderRowRepository.findByValidCodeNotInOrderByOrderTimeDesc(parm);
if (!orderRows.isEmpty()) {
for (OrderRow orderRow : orderRows) {
orderToWx(orderRow, true);
}
}
}
/**
* 指令
*/
public void sendOrderToWxByOrder(String order) {
int[] parm = {-1};
List<OrderRow> orderRows = orderRowRepository.findByValidCodeNotInOrderByOrderTimeDesc(parm);
/**
* 菜单:
* 今日统计
* 昨天统计
* 最近七天统计
* 最近一个月统计
* 今天订单
* 昨天订单
* */
String content = null;
switch (order) {
case "菜单":
content = "菜单:京粉 +命令 \n 如: 京粉 今日统计\r";
content += "今日统计\r";
content += "昨天统计\r";
content += "最近七天统计\r";
content += "最近一个月统计\r";
content += "今天订单\r";
content += "昨天订单\r";
break;
case "今日统计": {
List<OrderRow> todayOrders = filterOrdersByDate(orderRows, 0);
// 订单总数,已付款,已取消,佣金总计
content = "今日统计:";
content += "订单总数:" + todayOrders.size() + "\r";
content += "已付款:" + todayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).count() + "\r";
content += "已取消:" + todayOrders.stream().filter(orderRow -> orderRow.getValidCode() != 16).count() + "\r";
content += "佣金总计:" + todayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).mapToDouble(OrderRow::getEstimateFee).sum();
break;
}
case "昨天统计": {
List<OrderRow> yesterdayOrders = filterOrdersByDate(orderRows, 1);
content = "昨天统计:";
content += "订单总数:" + yesterdayOrders.size() + "\r";
content += "已付款:" + yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).count() + "\r";
content += "已取消:" + yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() != 16).count() + "\r";
content += "佣金总计:" + yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).mapToDouble(OrderRow::getEstimateFee).sum();
break;
}
case "最近七天统计":
List<OrderRow> last7DaysOrders = filterOrdersByDate(orderRows, 7);
content = "最近七天统计:";
content += "订单总数:" + last7DaysOrders.size() + "\r";
content += "已付款:" + last7DaysOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).count() + "\r";
content += "已取消:" + last7DaysOrders.stream().filter(orderRow -> orderRow.getValidCode() != 16).count() + "\r";
content += "佣金总计:" + last7DaysOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).mapToDouble(OrderRow::getEstimateFee).sum();
break;
case "最近一个月统计":
List<OrderRow> last30DaysOrders = filterOrdersByDate(orderRows, 30);
content = "最近一个月统计:";
content += "订单总数:" + last30DaysOrders.size() + "\r";
content += "已付款:" + last30DaysOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).count() + "\r";
content += "已取消:" + last30DaysOrders.stream().filter(orderRow -> orderRow.getValidCode() != 16).count() + "\r";
content += "佣金总计:" + last30DaysOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).mapToDouble(OrderRow::getEstimateFee).sum();
break;
case "今天订单": {
List<OrderRow> todayOrders = filterOrdersByDate(orderRows, 0);
// 订单总数,已付款,已取消,佣金总计
content = "今日统计:";
content += "订单总数:" + todayOrders.size() + "\r";
content += "已付款:" + todayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).count() + "\r";
content += "已取消:" + todayOrders.stream().filter(orderRow -> orderRow.getValidCode() != 16).count() + "\r";
content += "佣金总计:" + todayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).mapToDouble(OrderRow::getEstimateFee).sum();
for (OrderRow orderRow : todayOrders) {
orderToWx(orderRow, false);
}
break;
}
case "昨天订单": {
List<OrderRow> yesterdayOrders = filterOrdersByDate(orderRows, 1);
content = "昨天统计:";
content += "订单总数:" + yesterdayOrders.size() + "\r";
content += "已付款:" + yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).count() + "\r";
content += "已取消:" + yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() != 16).count() + "\r";
content += "佣金总计:" + yesterdayOrders.stream().filter(orderRow -> orderRow.getValidCode() == 16).mapToDouble(OrderRow::getEstimateFee).sum();
for (OrderRow orderRow : yesterdayOrders) {
orderToWx(orderRow, false);
}
break;
}
}
if (content != null) {
wxUtil.sendTextMessage(WXUtil.super_admin_wxid, content, 1, WXUtil.super_admin_wxid);
}
}
private void orderToWx(OrderRow orderRow, Boolean isAutoFlush) {
// 查询订单状态
Integer newValidCode = orderRow.getValidCode();
String oldValidCode = redisTemplate.opsForValue().get(ORDER_ROW_KEY + orderRow.getId());
Integer lastValidCode = 0;
// 更新 Redis 状态
redisTemplate.opsForValue().set(ORDER_ROW_KEY + orderRow.getId(), String.valueOf(orderRow.getValidCode()));
if (Util.isNotEmpty(oldValidCode)) {
lastValidCode = Integer.valueOf(oldValidCode);
}
// 如果订单状态没变化,就不发送
if (isAutoFlush && lastValidCode.equals(newValidCode)) {
} else {
String content;
content = getFormattedOrderInfo(orderRow);
// 推送
wxUtil.sendTextMessage(WXUtil.super_admin_wxid, content, 1, WXUtil.super_admin_wxid);
try {
sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public String getFormattedOrderInfo(OrderRow orderRow) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ValidCodeConverter converter = new ValidCodeConverter();
String orderInfo =
"商品名称:" + orderRow.getSkuName() + "\r"
+ "订单+sku" + orderRow.getId() + "\r"
+ "订单号:" + orderRow.getOrderId() + "(" + (orderRow.getPlus() == 1 ? "plus" : "非plus") + ")\r"
+ "佣金比例:" + orderRow.getCommissionRate() + "%\r\r"
+ "商品单价:" + orderRow.getPrice() + "\r"
+ "商品数量:" + orderRow.getSkuNum() + "\r"
+ "商品总价:" + (orderRow.getPrice() * orderRow.getSkuNum()) + "\r"
+ "订单总价:" + (orderRow.getActualCosPrice() * orderRow.getSkuNum()) + "\r"
+ "预估计佣金额:" + orderRow.getEstimateCosPrice() + "\n"
+ "推客的预估佣金:" + orderRow.getEstimateFee() + "\r"
+ "实际计算佣金的金额:" + orderRow.getActualCosPrice() + "\r"
+ "下单时间:" + formatter.format(orderRow.getOrderTime()) + "\r"
+ "完成时间:" + (orderRow.getFinishTime() != null ? formatter.format(orderRow.getFinishTime()) : "未完成") + "\r\n"
+ "订单状态:" + (converter.getCodeDescription(orderRow.getValidCode())) + "\r";
return orderInfo + "祝 财源滚滚";
}
/**
* 根据指定的日期时间拉取订单
*/
public UnionOpenOrderRowQueryResponse fetchOrdersForDateTime(LocalDateTime dateTime, boolean isRealTime) throws Exception {
LocalDateTime endTime = isRealTime ? dateTime.plusMinutes(10) : dateTime.plusHours(1);
String key = dateTime.format(DATE_TIME_FORMATTER);
String hourRange = isRealTime ? "minute" : "hour";
SetOperations<String, String> setOps = redisTemplate.opsForSet();
// 检查是否标记为已拉取
//if (Boolean.TRUE.equals(setOps.isMember(key, hourRange))) {
// System.out.println(dateTime.format(DATE_TIME_FORMATTER) + " 已经拉取,跳过");
// return null;
//}
// 调用 API 以拉取订单
UnionOpenOrderRowQueryResponse unionOpenOrderRowQueryResponse = getUnionOpenOrderRowQueryResponse(dateTime, endTime);
// 标记已拉取
setOps.add(key, hourRange);
return unionOpenOrderRowQueryResponse;
}
/**
* 获取订单列表
*
@@ -224,11 +388,10 @@ public class JDUtils {
String startTime = start.format(DATE_TIME_FORMATTER);
String endTime = end.format(DATE_TIME_FORMATTER);
// 模拟 API 调用
System.out.println("调用API - 从 " + startTime
+ "" + endTime);
//System.out.println("调用API - 从 " + startTime
// + " 到 " + endTime);
// 实际的 API 调用逻辑应在这里进行
String accessToken = "";
JdClient client = new DefaultJdClient(SERVER_URL, accessToken, APP_KEY, SECRET_KEY);
JdClient client = new DefaultJdClient(SERVER_URL, ACCESS_TOKEN, APP_KEY, SECRET_KEY);
UnionOpenOrderRowQueryRequest request = new UnionOpenOrderRowQueryRequest();
OrderRowReq orderReq = new OrderRowReq();
orderReq.setPageIndex(1);
@@ -250,4 +413,78 @@ public class JDUtils {
return client.execute(request);
}
/**
* 转链
*/
String transfer(String url) throws Exception {
JdClient client = new DefaultJdClient(SERVER_URL, ACCESS_TOKEN, APP_KEY, SECRET_KEY);
UnionOpenPromotionCommonGetRequest request = new UnionOpenPromotionCommonGetRequest();
request.setVersion("1.0");
request.setSignmethod("md5");
PromotionCodeReq promotionCodeReq = new PromotionCodeReq();
promotionCodeReq.setMaterialId(url);
promotionCodeReq.setSiteId(
"4101253066");
promotionCodeReq.setSceneId(1);
promotionCodeReq.setCommand(1);
promotionCodeReq.setProType(5);
request.setPromotionCodeReq(promotionCodeReq);
UnionOpenPromotionCommonGetResponse response = client.execute(request);
String jsonString = JSON.toJSONString(response);
System.out.println(jsonString);
//
//System.out.println(request.getAppJsonParams());
//System.out.println(request.getPromotionCodeReq());
//
//System.out.println("--------");
//System.out.println(response.getGetResult().getCode());
//System.out.println(response.getGetResult().getMessage());
//System.out.println(response.getGetResult().getData().getClickURL());
//System.out.println(response.getGetResult().getData().getJCommand());
return response.getGetResult().getData().getClickURL();
}
// 拉取历史订单 2880 次请求
@Scheduled(cron = "0 0 8,23 * * ?")
public void fetchHistoricalOrders() throws Exception {
// 从设定的开始日期到昨天的同一时间
System.out.println("开始拉取历史订单");
// 拉最近两个月的订单
// 获取当前时间,并调整为整点开始
LocalDateTime startDate = LocalDateTime.now().minusMonths(2).truncatedTo(ChronoUnit.HOURS);
LocalDateTime now = LocalDateTime.now();
LocalDateTime lastHour = now.minusHours(1).withMinute(0).withSecond(0).withNano(0);
while (!startDate.isEqual(lastHour)) {
UnionOpenOrderRowQueryResponse response = fetchOrdersForDateTime(startDate, false); // 假的代表历史订单
if (response != null) {
int code = response.getQueryResult().getCode();
if (code == 200) {
if (response.getQueryResult().getCode() == 200) {
OrderRowResp[] orderRowResps = response.getQueryResult().getData();
if (orderRowResps == null) {
continue;
}
for (OrderRowResp orderRowResp : orderRowResps) {
// 固化到数据库
OrderRow orderRow = createOrderRow(orderRowResp);
// 订单号不存在就保存,存在就更新订单状态
orderRowRepository.save(orderRow);
sleep(1000);
}
}
}
}
startDate = startDate.plusHours(1);
}
}
}