提交 87dac465 authored 作者: 吕本才's avatar 吕本才

增加旺店通奇门采集订单定时任务和接口

上级 62a311f0
......@@ -135,6 +135,11 @@
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<dependency>
<groupId>com.taobao</groupId>
<artifactId>taobao-sdk-java</artifactId>
</dependency>
</dependencies>
<build>
......
package com.sfa.job.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "wangdiantong.qimen")
public class WdtQimenConfig {
private String serverUrl;
private String appKey;
private String appSecret;
private String wdtSid;
private String wdtAppKey;
private String wdtAppSecret;
private String targetAppSecret;
}
package com.sfa.job.controller.order;
import com.sfa.job.pojo.response.SyncOrderDetailDto;
import com.sfa.job.service.order.WdtQimenOrderSyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* @author : liqiulin
* @date : 2025-07-08 13
* @describe : 订单 - 发货单物流查询
*/
@RestController
@RequestMapping("/order/qimen")
public class WdtQimenOrderController {
@Autowired
private WdtQimenOrderSyncService orderQimenSyncService;
@GetMapping("/sync")
public Object sync(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")Date startTime,
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime,
@RequestParam(value = "pageSize", required = false, defaultValue = "200") Long pageSize
) {
SyncOrderDetailDto syncOrderDetailDto = orderQimenSyncService.syncWdtQimenOrder(startTime, endTime, 1, pageSize);
return syncOrderDetailDto;
}
}
package com.sfa.job.domain.order.dao;
import com.sfa.job.domain.order.entity.FinanceOrder;
import com.sfa.job.domain.order.entity.WdtQimenOrder;
import java.util.List;
public interface WdtQimenOrderDao {
void saveOrUpdateBatch(List<WdtQimenOrder> mergeList);
}
package com.sfa.job.domain.order.dao;
import com.sfa.job.domain.order.entity.WdtQimenOrderDetail;
import java.util.List;
public interface WdtQimenOrderDetailDao {
void saveOrUpdateBatch(List<WdtQimenOrderDetail> mergeList);
}
package com.sfa.job.domain.order.dao.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.sfa.job.domain.order.dao.WdtQimenOrderDao;
import com.sfa.job.domain.order.entity.WdtQimenOrder;
import com.sfa.job.domain.order.mapper.WdtQimenOrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.List;
@DS("bi")
@Repository
public class WdtQimenOrderDaoImpl implements WdtQimenOrderDao {
private static final int BATCH_SIZE = 1000;
@Autowired
private WdtQimenOrderMapper wdtQimenOrderMapper;
@Override
public void saveOrUpdateBatch(List<WdtQimenOrder> mergeList) {
for (int i = 0; i < mergeList.size(); i += BATCH_SIZE) {
int toIndex = Math.min(i + BATCH_SIZE, mergeList.size());
List<WdtQimenOrder> batchLists = mergeList.subList(i, toIndex);
wdtQimenOrderMapper.saveOrUpdateBatch(batchLists);
}
}
}
package com.sfa.job.domain.order.dao.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.sfa.job.domain.order.dao.WdtQimenOrderDetailDao;
import com.sfa.job.domain.order.entity.WdtQimenOrderDetail;
import com.sfa.job.domain.order.mapper.WdtQimenOrderDetailMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.List;
@DS("bi")
@Repository
public class WdtQimenOrderDetailDaoImpl implements WdtQimenOrderDetailDao {
private static final int BATCH_SIZE = 1000;
@Autowired
private WdtQimenOrderDetailMapper wdtQimenOrderDetailMapper;
@Override
public void saveOrUpdateBatch(List<WdtQimenOrderDetail> mergeList) {
for (int i = 0; i < mergeList.size(); i += BATCH_SIZE) {
int toIndex = Math.min(i + BATCH_SIZE, mergeList.size());
List<WdtQimenOrderDetail> batchLists = mergeList.subList(i, toIndex);
wdtQimenOrderDetailMapper.saveOrUpdateBatch(batchLists);
}
}
}
......@@ -95,6 +95,10 @@ public class CollectOrderLog implements Serializable {
*/
private Date updateTime;
/**
* 同步类型,
* 接口为1手动同步,0 xxljob自动同步
*/
private Integer syncType;
......
package com.sfa.job.domain.order.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sfa.job.domain.order.entity.WdtQimenOrderDetail;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface WdtQimenOrderDetailMapper extends BaseMapper<WdtQimenOrderDetail> {
void saveOrUpdateBatch(@Param(value = "list") List<WdtQimenOrderDetail> mergeList);
}
package com.sfa.job.domain.order.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sfa.job.domain.order.entity.WdtQimenOrder;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface WdtQimenOrderMapper extends BaseMapper<WdtQimenOrder> {
void saveOrUpdateBatch(List<WdtQimenOrder> batchLists);
}
package com.sfa.job.pojo.order.request;
import com.sfa.job.pojo.order.response.WdtSalesTradeQueryQueryWithDetailDto;
import com.taobao.api.ApiRuleException;
import com.taobao.api.BaseTaobaoRequest;
import com.taobao.api.internal.mapping.ApiField;
import com.taobao.api.internal.util.TaobaoHashMap;
import com.taobao.api.internal.util.json.JSONWriter;
import java.util.Map;
public class WdtSalesTradeQueryQueryWithDetailVo extends BaseTaobaoRequest<WdtSalesTradeQueryQueryWithDetailDto> {
private String datetime;
private String pager;
private String params;
private String wdtAppkey;
private String wdtSalt;
private String wdtSign;
private String topContentType;
private String topResponseType = "qimen1";
private String topApiVersion = "1.0";
private String topApiFormat;
public WdtSalesTradeQueryQueryWithDetailVo() {
}
public void setDatetime(String datetime) {
this.datetime = datetime;
}
public String getDatetime() {
return this.datetime;
}
public void setPager(String pager) {
this.pager = pager;
}
public void setPager(WdtSalesTradeQueryQueryWithDetailVo.Pager pager) {
this.pager = (new JSONWriter(false, false, true)).write(pager);
}
public String getPager() {
return this.pager;
}
public void setParams(String params) {
this.params = params;
}
public void setParams(WdtSalesTradeQueryQueryWithDetailVo.Params params) {
this.params = (new JSONWriter(false, false, true)).write(params);
}
public String getParams() {
return this.params;
}
public void setWdtAppkey(String wdtAppkey) {
this.wdtAppkey = wdtAppkey;
}
public String getWdtAppkey() {
return this.wdtAppkey;
}
public void setWdtSalt(String wdtSalt) {
this.wdtSalt = wdtSalt;
}
public String getWdtSalt() {
return this.wdtSalt;
}
public void setWdtSign(String wdtSign) {
this.wdtSign = wdtSign;
}
public String getWdtSign() {
return this.wdtSign;
}
public String getApiMethodName() {
return "wdt.sales.tradequery.querywithdetail";
}
public String getTopContentType() {
return this.topContentType;
}
public void setTopContentType(String topContentType) {
this.topContentType = topContentType;
}
public String getTopResponseType() {
return this.topResponseType;
}
public void setTopResponseType(String topResponseType) {
this.topResponseType = topResponseType;
}
public String getTopApiVersion() {
return this.topApiVersion;
}
public void setTopApiVersion(String topApiVersion) {
this.topApiVersion = topApiVersion;
}
public String getTopApiFormat() {
return this.topApiFormat;
}
public void setTopApiFormat(String topApiFormat) {
this.topApiFormat = topApiFormat;
}
public Map<String, String> getTextParams() {
TaobaoHashMap txtParams = new TaobaoHashMap();
txtParams.put("datetime", this.datetime);
txtParams.put("pager", this.pager);
txtParams.put("params", this.params);
txtParams.put("wdt_appkey", this.wdtAppkey);
txtParams.put("wdt_salt", this.wdtSalt);
txtParams.put("wdt_sign", this.wdtSign);
if (this.udfParams != null) {
txtParams.putAll(this.udfParams);
}
return txtParams;
}
public Class<WdtSalesTradeQueryQueryWithDetailDto> getResponseClass() {
return WdtSalesTradeQueryQueryWithDetailDto.class;
}
public void check() throws ApiRuleException {
}
public static class Pager {
@ApiField("page_no")
private Long pageNo;
@ApiField("page_size")
private Long pageSize;
public Pager() {
}
public Long getPageNo() {
return this.pageNo;
}
public void setPageNo(Long pageNo) {
this.pageNo = pageNo;
}
public Long getPageSize() {
return this.pageSize;
}
public void setPageSize(Long pageSize) {
this.pageSize = pageSize;
}
}
public static class Params {
@ApiField("start_time")
private String startTime;
@ApiField("end_time")
private String endime;
@ApiField("shop_no")
private String shopNo;
@ApiField("order_type")
private String orderType;
/**
* 1:修改时间 2:付款时间 默认1
*/
@ApiField("time_type")
private int timeType;
@ApiField("cal_share_post_amount")
private Boolean calSharePostAmount;
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndime() {
return endime;
}
public void setEndime(String endime) {
this.endime = endime;
}
public String getShopNo() {
return shopNo;
}
public void setShopNo(String shopNo) {
this.shopNo = shopNo;
}
public String getOrderType() {
return orderType;
}
public void setOrderType(String orderType) {
this.orderType = orderType;
}
public int getTimeType() {
return timeType;
}
public void setTimeType(int timeType) {
this.timeType = timeType;
}
public Boolean getCalSharePostAmount() {
return calSharePostAmount;
}
public void setCalSharePostAmount(Boolean calSharePostAmount) {
this.calSharePostAmount = calSharePostAmount;
}
}
}
package com.sfa.job.pojo.order.response;
import lombok.Data;
@Data
public class WdtQimenBodyDto {
private static final long serialVersionUID = 4632382792982436956L;
private WdtQimenResponseDto response;
private String message;
private Integer status;
}
package com.sfa.job.pojo.order.response;
import com.sfa.job.domain.order.entity.WdtQimenOrder;
import lombok.Data;
import java.util.List;
@Data
public class WdtQimenDataDto {
private static final long serialVersionUID = 4632382792982436956L;
private List<WdtQimenOrder> order;
private Integer totalCount;
}
package com.sfa.job.pojo.order.response;
import lombok.Data;
@Data
public class WdtQimenResponseDto {
private static final long serialVersionUID = 4632382792982436956L;
private WdtQimenDataDto data;
private String message;
private Integer status;
}
package com.sfa.job.pojo.order.response;
import com.alibaba.fastjson.JSONObject;
import com.taobao.api.TaobaoResponse;
import com.taobao.api.internal.mapping.ApiField;
public class WdtSalesTradeQueryQueryWithDetailDto extends TaobaoResponse {
private static final long serialVersionUID = 4632382792982436956L;
@ApiField("data")
private Object data;
@ApiField("message")
private String message;
@ApiField("status")
private Long status;
public WdtSalesTradeQueryQueryWithDetailDto() {
}
public void setData(Object data) {
this.data = JSONObject.toJSON(data);
}
public Object getData() {
return this.data;
}
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return this.message;
}
public void setStatus(Long status) {
this.status = status;
}
public Long getStatus() {
return this.status;
}
}
package com.sfa.job.pojo.response;
import cn.hutool.core.date.DateUtil;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.sfa.common.core.utils.DateUtils;
import lombok.Data;
import org.apache.commons.lang3.ObjectUtils;
import java.util.Date;
......@@ -22,7 +25,9 @@ public class SyncOrderDetailDto {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
private Date latestTime;
/**
* 同步类型 ,接口为1手动同步,0 xxljob自动同步
*/
private Integer syncType;
private String batchNo;
private Integer pageNo;
......@@ -47,4 +52,43 @@ public class SyncOrderDetailDto {
this.setRemark(remark);
return this;
}
public boolean validateStartTime() {
Date currentLatest = DateUtils.addHours(new Date(), -2);
if (currentLatest.compareTo(this.getEndTime()) < 0) {
this.setTotalCount(0);
String message = String.format("结束时间%s不能大于当前时间%s", DateUtil.formatDateTime(this.getEndTime()), DateUtil.formatDateTime(currentLatest));
this.setMessage(message);
return false;
}
return true;
}
/**
* 初始化时间范围
*
* @param interval
* @param collectOrderLog
*/
public void setupTimeRange(Integer interval, CollectOrderLogDto collectOrderLog) {
Date latestTime = null;
// startTime 为空,默认是定时任务调用
if (ObjectUtils.isEmpty(this.getStartTime())) {
// 查询最新的采集时间
if (ObjectUtils.isNotEmpty(collectOrderLog)) {
latestTime = collectOrderLog.getLatestTime();
// 调用查询旺店通接口api 获取最新日期前的一个小时
this.setStartTime(DateUtils.addMinutes(latestTime, -5));
this.setEndTime(DateUtils.addMinutes(this.getStartTime(), interval));
} else {
// 默认上个月的第一天 00:00:00
this.setStartTime(DateUtil.beginOfDay(DateUtil.beginOfMonth(DateUtil.lastMonth())));
this.setEndTime(DateUtils.addMinutes(this.getStartTime(), interval));
}
}
this.latestTime = this.getEndTime();
this.setLatestTime(latestTime);
}
}
package com.sfa.job.service.order;
import com.sfa.job.pojo.response.SyncOrderDetailDto;
import java.util.Date;
public interface WdtQimenOrderSyncService {
SyncOrderDetailDto syncWdtQimenOrder(Date startTime, Date endTime, Integer syncType, Long pageSize);
}
......@@ -96,13 +96,13 @@ public class FinanceOrderSyncServiceImpl implements FinanceOrderSyncService {
if (currentLatest.compareTo(startTime) < 0) {
detailDto.setMessage(String.format("开始时间%s不能大于当前时间%s", DateUtil.formatDateTime(startTime), DateUtil.formatDateTime(currentLatest)));
log.warn(String.format("开始时间%s不能大于当前时间%s", DateUtil.formatDateTime(startTime), DateUtil.formatDateTime(currentLatest)));
// log.warn(String.format("开始时间%s不能大于当前时间%s", DateUtil.formatDateTime(startTime), DateUtil.formatDateTime(currentLatest)));
return detailDto;
}
if (!validateStartTime(detailDto )) {
return detailDto;
}
log.info("查询订单参数:开始时间{},结束时间{},当前页:{}", DateUtil.formatDateTime(startTime), DateUtil.formatDateTime(endTime), detailDto.getPageNo());
// log.info("查询订单参数:开始时间{},结束时间{},当前页:{}", DateUtil.formatDateTime(startTime), DateUtil.formatDateTime(endTime), detailDto.getPageNo());
WdtOrderQueryVO wdtOrderQueryVO = new WdtOrderQueryVO();
wdtOrderQueryVO.setStart_time(com.alibaba.fastjson2.util.DateUtils.format(startTime));
......
......@@ -20,17 +20,6 @@ import java.util.List;
@Component
public class WangdiantongUtil {
// @Value("${wangdiantong.url}")
// private String url;
// @Value("${wangdiantong.sid}")
// private String sid ;
// @Value("${wangdiantong.key}")
// private String key ;
// @Value("${wangdiantong.salt}")
// private String salt ;
// @Value("${wangdiantong.appsecret}")
// private String appsecret;
private final WangdiantongConfig wangdiantongConfig;
@Autowired
......
package com.sfa.job.util;
import com.alibaba.fastjson.JSON;
import com.taobao.api.BaseTaobaoRequest;
import com.taobao.api.TaobaoResponse;
import org.apache.commons.codec.digest.DigestUtils;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
/**
* 奇门自定义接口工具类
*/
public class WdtQimenUtil {
private WdtQimenUtil() {
}
private static final List<String> QIMEN_CRM_SIGNED_FIELDS = Arrays
.asList("pageNo", "pageSize", "fields", "extendProps", "customerid", "method", "sd_code", "startModified",
"endModified");
private static final List<String> QIMEN_EXCLUDE_SIGN_FIELDS = Arrays.asList("wdt3_customer_id", "wdt_sign");
/**
* 获取奇门自定义接口的签名
*
* @param request 请求
* @param wdtSecret app_secret的前半部分
* @return 签名值
*/
public static <T extends TaobaoResponse> String getQimenCustomWdtSign(BaseTaobaoRequest<T> request, String wdtSecret) {
Map<String, String> params = request.getTextParams();
params.put("method", request.getApiMethodName());
StringBuilder toBeSignedStringBuilder = new StringBuilder();
getToBeSignedString(toBeSignedStringBuilder, params);
toBeSignedStringBuilder.insert(0, wdtSecret).append(wdtSecret);
return DigestUtils.md5Hex(toBeSignedStringBuilder.toString());
}
public static boolean isValidJson(String content) {
if (null == content)
return false;
String trimmedContent = content.trim();
if (!(trimmedContent.startsWith("{") && trimmedContent.endsWith("}")) && !(trimmedContent.startsWith("[") && trimmedContent.endsWith("]")))
return false;
return JSON.isValid(content);
}
@SuppressWarnings("unchecked")
private static void getToBeSignedString(StringBuilder stringBuilder, Object object) {
if (object instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> map = (Map<String, Object>) object;
map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEachOrdered(p -> {
if (QIMEN_EXCLUDE_SIGN_FIELDS.contains(p.getKey()) ||
null == p.getValue())
return;
stringBuilder.append(p.getKey());
Object value = p.getValue();
if (value instanceof Integer) {
stringBuilder.append(value);
} else if (value instanceof String) {
if (JSON.isValidObject(value.toString())) {
getToBeSignedString(stringBuilder, JSON.parseObject(p.getValue().toString(), Map.class));
} else if (JSON.isValidArray(value.toString())) {
for (Object obj : JSON.parseArray(value.toString(), Object.class)) {
getToBeSignedString(stringBuilder, obj);
}
} else {
stringBuilder.append((String) value);
}
} else if (value instanceof BigDecimal) {
stringBuilder.append(((BigDecimal) value).toPlainString());
} else if (value instanceof Long) {
stringBuilder.append(value);
} else if (value instanceof Boolean) {
stringBuilder.append(((Boolean) value).booleanValue());
} else if (value instanceof Float) {
stringBuilder.append(value);
} else if (value instanceof Double) {
stringBuilder.append(value);
} else {
getToBeSignedString(stringBuilder, value);
}
});
} else if (object instanceof List) {
for (Map map : (List<Map>) object) {
getToBeSignedString(stringBuilder, map);
}
} else {
stringBuilder.append(object.toString());
}
}
static <T extends TaobaoResponse> String getQimenOfficialWdtSign(BaseTaobaoRequest<T> request, String secret) {
Map<String, String> params = request.getTextParams();
params.put("method", request.getApiMethodName());
params.entrySet().removeIf(e -> !QIMEN_CRM_SIGNED_FIELDS.contains(e.getKey()));
StringBuilder toBeSignedStringBuilder = new StringBuilder();
getToBeSignedString(toBeSignedStringBuilder, params);
toBeSignedStringBuilder.insert(0, secret).append(secret);
return DigestUtils.md5Hex(toBeSignedStringBuilder.toString());
}
}
package com.sfa.job.xxljob.order;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.sfa.job.pojo.response.SyncOrderDetailDto;
import com.sfa.job.service.order.WdtQimenOrderSyncService;
import com.xxl.job.core.context.XxlJobContext;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @author : 吕本才
* @date : 2025年08月14日
* @describe : 旺店通奇门订单数据
*/
@Component
@Slf4j
public class WdtQimenOrderTask {
@Autowired
WdtQimenOrderSyncService qimenSyncService;
/**
* 同步财务订单数据
*/
@XxlJob("syncOrderQimenDetail")
public SyncOrderDetailDto syncWdtQimenOrderDetail() {
Long st = System.currentTimeMillis();
// 暂不考虑分片
XxlJobContext xxlJobContext = XxlJobContext.getXxlJobContext();
int shardingTotalCount = xxlJobContext.getShardTotal();
int shardingItem = xxlJobContext.getShardIndex();
XxlJobHelper.log(">>>>>>>>>>syncWangdiantongOrderDetail Job start<<<<<<<<<<");
String jobParam = xxlJobContext.getJobParam();
boolean jsonFlag = JSONUtil.isJson(jobParam);
Date startTime = null;
Date endTime = null;
if (jsonFlag) {
JSONObject jobParamJson = JSONObject.parseObject(jobParam);
startTime = jobParamJson.getDate("startTime");
endTime = jobParamJson.getDate("endTime");
}
// 简单模拟分片处理,这里输出每个分片的信息
XxlJobHelper.log("分片总数: " + shardingTotalCount + ", 当前分片: " + shardingItem);
XxlJobHelper.log("xxl-job开始同步-旺店通订单明细api接口数据");
// 定时任务不设定开始时间和结束时间
SyncOrderDetailDto detailDto = qimenSyncService.syncWdtQimenOrder(startTime, endTime, 0, 200L);
XxlJobHelper.log("xxl-job结束同步-旺店通订单明细api接口数据, 共同步订单{}条数据,订单明细{}条,订单批次号:{},订单的开始时间{}和结束时间{}",
detailDto.getOrderCount(), detailDto.getOrderDetailCount(), detailDto.getBatchNo(),
DateUtil.formatDateTime(detailDto.getStartTime()), DateUtil.formatDateTime(detailDto.getEndTime()));
if (ObjectUtil.equals(HttpStatus.HTTP_OK, detailDto.getCode())) {
XxlJobHelper.handleSuccess(JSONObject.toJSONString(detailDto));
} else {
XxlJobHelper.handleFail(detailDto.getMessage());
}
return detailDto;
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论