erp:
url: http://api.wangdian.cn/xxxx/
sid: xxxx
appkey: xxxx
appsecret: xxxxxxxxxxxxxxxxxxxxx
shopNo: 'xx'
@Data
@Configuration
@ConfigurationProperties(prefix = "erp")
public class ErpConfig {
String url;
String sid;
String appkey;
String appsecret;
String shopNo;
}
/**
* 推送订单到旺店通服务
*/
@Slf4j
@Component("wdtOrderLogisticsSyncTask")
@AllArgsConstructor
public class WdtOrderLogisticsSyncTask {
@Autowired
private DeliveryService deliveryService;
@Autowired
private DeliveryOrderService deliveryOrderService;
@Autowired
private final OrderItemService orderItemService;
@Autowired
private OrderService orderService;
@Autowired
private final SysConfigMapper sysConfigMapper;
//测试环境
private final String baseUrl = "https://sandbox.wangdian.cn/openapi2/";
//物流同步查询
private final String logisticsSyncQuery = "logistics_sync_query.php";
//物流同步回写
private final String logisticsSyncAck = "logistics_sync_ack.php";
/**
* 获取物流待同步的订单
*/
public String wdtOrderLogisticsTask() {
log.info("------- 推送订单到旺店通服务 ----> 时间:" + DateUtils.dateToString(new Date()));
SysConfig wdtParamKey = sysConfigMapper.queryByKey("WDT_PARAM_KEY");
if(Validator.isEmpty(wdtParamKey) || Validator.isEmpty(wdtParamKey.getParamValue())){
log.error("====== 推送订单到旺店通失败,旺店通账户参数配置异常!======>>>> ");
return "";
}
Map<String,String> wdtParam = FastJsonHelper.stringToCollect(wdtParamKey.getParamValue());
//查询所有的未推送 且待发货状态的订单列表
String responseStr = selectLogisticsWdt(wdtParam);
//解析响应参数
JSONObject stringToMap = JSONObject.parseObject(responseStr);
//状态码:0表示成功,其他表示失败
if(!Validator.equal(stringToMap.get("code").toString(),"0")){
log.error("====== 查询旺店通物流信息同步接口请求错误 ======>>>> 旺店通返回信息:{}",responseStr);
return responseStr;
}else {
log.info("====== 查询旺店通物流信息同步接口请求成功 ======>>>> {}",responseStr);
//设置订单发货
List<TreeMap<String, String>> logisticsList = orderDelivery(stringToMap);
if(logisticsList.size() == 0){
log.info("====== 旺店通物流信息同步完成,暂无订单信息需要同步。 ======>>>>");
return "";
}
//物流同步回写请求参数
TreeMap<String,String> mapParam = new TreeMap<>();
mapParam.put("logistics_list",FastJsonHelper.toJSONString(logisticsList));
//请求旺店通 物流同步回写 接口
String responseSyncStr = logisticsSyncAckWdt(mapParam,wdtParam);
//解析响应参数
JSONObject responseSyncMap = JSONObject.parseObject(responseSyncStr);
//状态码:0表示成功,其他表示失败
if(Validator.equal(responseSyncMap.get("code").toString(),"0")){
log.info("====== 旺店通物流信息同步回写接口请求成功 ======>>>>");
}else {
log.error("====== 旺店通物流信息同步回写接口请求失败 ======>>>> 旺店通返回信息:{}",responseSyncStr);
}
return responseSyncStr;
}
}
/**
* 解析旺店通物流同步返回数据并处理本地本地订单发货
* @param jsonObject
*/
private List<TreeMap<String,String>> orderDelivery(JSONObject jsonObject) {
List<LogisticsSyncVO> trades = FastJsonHelper.toList(jsonObject.get("trades").toString(), LogisticsSyncVO.class);
if(Validator.isEmpty(trades)){
return new ArrayList<>();
}
//同步成功的物流回写列表
List<TreeMap<String,String>> logisticsList = new ArrayList<>();
//遍历待同步的物流信息
for (LogisticsSyncVO trade : trades) {
//单个物流同步回写订单信息
TreeMap<String,String> logisticsSyncAckParam = new TreeMap<>();
//回写的记录id
logisticsSyncAckParam.put("rec_id",trade.getRec_id());
//判断是否已发货
Order order = orderService.getOrderByOrderNumber(trade.getTid());
if(Validator.isNotEmpty(order)){
//订单状态 1:待付款 2:待发货 3:待收货 4:待评价 5:成功 6:失败 7:待成团
if(!Validator.equal(order.getStatus(),2)){
//如果当前订单不是代发货状态 回调旺店通 通知下次不用发送该订单
//回写状态 回写状态: 0成功 1失败
logisticsSyncAckParam.put("status","0");
//保存到已更新列表里
logisticsList.add(logisticsSyncAckParam);
continue;
}
}else {
// 如果该订单查询不到 则跳过本次循环
// 回调旺店通 通知下次不用发送该订单
logisticsSyncAckParam.put("status","0");
//保存到已更新列表里
logisticsList.add(logisticsSyncAckParam);
continue;
}
//获取物流类型 具体类型详见 旺铺通-API文档-物流代码表
String logisticsType = trade.getLogistics_type();
//查询本地物流表是否有该物流信息
Delivery delivery = deliveryService.getOne(Wrappers.<Delivery>lambdaQuery().eq(Delivery::getLogisticsType, logisticsType).last(" LIMIT 1 "));
//如果是空 则添加一条该物流信息
if(Validator.isEmpty(delivery)){
delivery = new Delivery();
delivery.setLogisticsType(logisticsType);//类型
delivery.setDvyName(trade.getLogistics_name());//物流名字
//保存该条物流信息
deliveryService.save(delivery);
}
//组装订单物流信息
DeliveryOrderItemParam deliveryOrderParam = new DeliveryOrderItemParam();
deliveryOrderParam.setOrderNumber(trade.getTid());
deliveryOrderParam.setDvyId(delivery.getDvyId());
deliveryOrderParam.setDvyFlowId(trade.getLogistics_no());
// 1-自己联系快递 3-无需快递 4-同城配送
deliveryOrderParam.setDeliveryType(1);
List<OrderItem> orderItemsByOrderNumber = orderItemService.getOrderItemsByOrderNumber(trade.getTid(), 1);
deliveryOrderParam.setSelectOrderItems(orderItemsByOrderNumber);
//设置是旺店通发货标识
deliveryOrderParam.setIsWdt(1);
//捕捉异常防止全部更新失败
try {
//发货操作
deliveryOrderService.saveDeliveriesInfo(deliveryOrderParam);
//回写状态 回写状态: 0成功 1失败
logisticsSyncAckParam.put("status","0");
}catch (Exception e){
log.error("====== 订单物流同步本地更新失败,订单号:{} ======>>>> 错误信息:{}",trade.getTid(),e);
//回写状态 回写状态: 0成功 1失败
logisticsSyncAckParam.put("status","1");
}
//保存到已更新列表里
logisticsList.add(logisticsSyncAckParam);
}
return logisticsList;
}
/**
* 查询旺店通物流同步 PS:后台发货接口:/orderItemsDelivery
* @return
*/
public String selectLogisticsWdt(Map<String,String> wdtParam) {
log.info("进入查询旺店通物流同步通方法============>>>>>>> 时间:" + DateUtils.dateToString(new Date()));
try {
TreeMap<String,String> mapParam = new TreeMap();
//构建请求参数
//获取条数
mapParam.put("limit","50");
//店铺编号
mapParam.put("shop_no",wdtParam.get("shop_no"));//wdtParam.get()
//构建请求对象
WdtClient client = new WdtClient(wdtParam.get("sid"), wdtParam.get("appkey"), wdtParam.get("appsecret"), wdtParam.get("baseUrl"));
// 发送HTTP请求...
String response = client.execute(logisticsSyncQuery, mapParam);
//格式化解析响应参数
String responseStr = UnicodeUtil.toString(response);
log.info("============ 查询旺店通物流同步请求结果响应 ===========>>>>>>>>>>>> {}",responseStr);
return responseStr;
}catch (Exception e){
log.error("====== 查询旺店通物流同步失败 ======>>>> 信息:{} ------->>>>:{}",e.getMessage());
}
return "";
}
/**
* 旺店通物流同步回写
* @param mapParam 参数信息
* @return
*/
public String logisticsSyncAckWdt(TreeMap<String,String> mapParam,Map<String,String> wdtParam) {
try {
//构建请求对象
WdtClient client = new WdtClient(wdtParam.get("sid"), wdtParam.get("appkey"), wdtParam.get("appsecret"), wdtParam.get("baseUrl"));
// 发送HTTP请求...
String response = client.execute(logisticsSyncAck, mapParam);
//格式化解析响应参数
String responseStr = UnicodeUtil.toString(response);
return responseStr;
}catch (Exception e){
log.error("====== 查询旺店通物流同步失败 ======>>>> 信息:{} ------->>>>:{}",e.getMessage());
}
return "";
}
/**
* 手动订单发货 !!临时方法
*/
@Transactional(rollbackFor = Exception.class)
public void manualOrderShipment(){
List<OrderLogistics> orderLogistics = orderService.queryAllOrderLogistics();
log.error("======= 查询到需要手动发货的订单数量:{}条 ======>>>>",orderLogistics.size());
if(orderLogistics.size() == 0){
log.error("======= 暂未查询到需要手动发货的订单 ======>>>>");
return;
}
//待发货订单数据列表
List<DeliveryOrderItemParam> orderItemParams = new ArrayList<>();
//遍历所有信息
for (OrderLogistics orderLogistic : orderLogistics) {
if(Validator.isEmpty(orderLogistic.getOrderNumber())){
continue;
}
//是否是多个订单
if(!orderLogistic.getOrderNumber().contains(";")){
//判断是否已发货
Order order = orderService.getOrderByOrderNumber(orderLogistic.getOrderNumber());
if(Validator.isEmpty(order)){
continue;
}
//订单状态 1:待付款 2:待发货 3:待收货 4:待评价 5:成功 6:失败 7:待成团
if(!Validator.equal(order.getStatus(),2)){
continue;
}
//获取物流类型 具体类型详见 旺铺通-API文档-物流代码表
String logisticsName = orderLogistic.getLogisticsName();
//查询本地物流表是否有该物流信息
Delivery delivery = deliveryService.getOne(Wrappers.<Delivery>lambdaQuery().eq(Delivery::getDvyName, logisticsName).last(" LIMIT 1 "));
//如果是空 则添加一条该物流信息
if(Validator.isEmpty(delivery)){
delivery = new Delivery();
delivery.setLogisticsType("");//类型
delivery.setDvyName(logisticsName);//物流名字
//保存该条物流信息
deliveryService.save(delivery);
}
//组装订单物流信息
DeliveryOrderItemParam deliveryOrderParam = new DeliveryOrderItemParam();
deliveryOrderParam.setOrderNumber(orderLogistic.getOrderNumber());
deliveryOrderParam.setDvyId(delivery.getDvyId());
deliveryOrderParam.setDvyFlowId(orderLogistic.getLogisticsNumber());
// 1-自己联系快递 3-无需快递 4-同城配送
deliveryOrderParam.setDeliveryType(1);
List<OrderItem> orderItemsByOrderNumber = orderItemService.getOrderItemsByOrderNumber(orderLogistic.getOrderNumber(), 1);
deliveryOrderParam.setSelectOrderItems(orderItemsByOrderNumber);
//设置是旺店通发货标识
deliveryOrderParam.setIsWdt(1);
//保存到集合里
orderItemParams.add(deliveryOrderParam);
}else {
//存在多个订单
List<String> orderNumbers = Arrays.asList(orderLogistic.getOrderNumber().split(";"));
if(Validator.isEmpty(orderNumbers)){
continue;
}
//获取物流类型 具体类型详见 旺铺通-API文档-物流代码表
String logisticsName = orderLogistic.getLogisticsName();
//查询本地物流表是否有该物流信息
Delivery delivery = deliveryService.getOne(Wrappers.<Delivery>lambdaQuery().eq(Delivery::getDvyName, logisticsName).last(" LIMIT 1 "));
//如果是空 则添加一条该物流信息
if(Validator.isEmpty(delivery)){
delivery = new Delivery();
delivery.setLogisticsType("");//类型
delivery.setDvyName(logisticsName);//物流名字
//保存该条物流信息
deliveryService.save(delivery);
}
//遍历订单编号列表
numberIds : for (String number : orderNumbers) {
//判断是否已发货
Order order = orderService.getOrderByOrderNumber(number);
if(Validator.isEmpty(order)){
continue numberIds;
}
//订单状态 1:待付款 2:待发货 3:待收货 4:待评价 5:成功 6:失败 7:待成团
if(!Validator.equal(order.getStatus(),2)){
continue numberIds;
}
//组装订单物流信息
DeliveryOrderItemParam deliveryOrderParam = new DeliveryOrderItemParam();
deliveryOrderParam.setOrderNumber(number);
deliveryOrderParam.setDvyId(delivery.getDvyId());
deliveryOrderParam.setDvyFlowId(orderLogistic.getLogisticsNumber());
// 1-自己联系快递 3-无需快递 4-同城配送
deliveryOrderParam.setDeliveryType(1);
List<OrderItem> orderItemsByOrderNumber = orderItemService.getOrderItemsByOrderNumber(number, 1);
deliveryOrderParam.setSelectOrderItems(orderItemsByOrderNumber);
//设置是旺店通发货标识
deliveryOrderParam.setIsWdt(1);
//保存到集合里
orderItemParams.add(deliveryOrderParam);
}
}
}
log.info("================待手动发货订单共计:{} 个=============>>>>>>>>>>",orderItemParams.size());
//发货操作
for (DeliveryOrderItemParam orderItemParam : orderItemParams) {
deliveryOrderService.saveDeliveriesInfo(orderItemParam);
}
}
}
由于业务原因 一个回传的物流字段是多个子物流单号拼接起来的 这个时候同步回传就不适用了 同步回传会把下面的子订单号给回传掉 旺店通会默认将当前订单默认为已处理掉的
@Slf4j
@Component("erpTask")
public class ErpInfoTask {
@Autowired
ErpConfig erpConfig;
@Autowired
ITbOrderService orderService;
@Autowired
JedisClusterUtils jedisClusterUtils;
//测试环境
private final String baseUrl = "https://sandbox.wangdian.cn/openapi2/";
//查询销售出库单
private final String stockoutOrderQuery = "stockout_order_query_trade.php";
private final String COUNT = "Erp_Info_Task_Count";
private final String TIME = "ERP_PAGE_TIME";
private final String TIME_END = "ERP_PAGE_TIME_END";
private final String format = "yyyy-MM-dd HH:mm:ss";
public void getErpInfoTask() {
getStockoutOrder(0);
}
public void getStockoutOrder(int i) {
WdtClient client = new WdtClient(erpConfig.getSid(), erpConfig.getAppkey(), erpConfig.getAppsecret(), erpConfig.getUrl());
Map<String, String> params = new HashMap<>();
// 设置开始结束时间
Date date = new Date();
String begin = null;
if(StringUtils.isBlank(jedisClusterUtils.getString(TIME))) {
// 第一次启动 从前一天查看
begin = DateUtil.format(DateUtil.offsetDay(DateUtil.beginOfDay(date),-1), this.format);
}else if (DateUtil.hour(date, true) == 17 && DateUtil.minute(date) <= 10 && DateUtil.minute(date) > 0 && i == 0){
// 到今日发货时间 查今日所有
begin = DateUtil.format(DateUtil.offsetDay(DateUtil.beginOfDay(date),-2), this.format);
} else {
// 正常执行走上一次查询结束时间
begin = jedisClusterUtils.getString(TIME);
}
// 初始值 选用当前时间
String end = null;
if(StringUtils.isBlank(jedisClusterUtils.getString(TIME_END))){
end = DateUtil.format(new Date(), this.format);
}else {
end = jedisClusterUtils.getString(TIME_END);
}
int size = 50;
// 设置参数 查询当天的 已发货的
params.put("shop_no", erpConfig.getShopNo());
params.put("start_time", begin);
params.put("end_time", end);
params.put("page_size", Integer.toString(size));
params.put("page_no", Integer.toString(i));
params.put("status", "95");
// 发送请求
try {
String execute = client.execute(stockoutOrderQuery, params);
ErpOrderResult orderResult = JSONObject.parseObject(execute, ErpOrderResult.class);
if (orderResult.getCode() == 0) {
if (i == 0) {
// 分页总条数
Integer count = orderResult.getTotalCount();
// 剩余调用次数
Integer pageCount = (count / 50) + 1;
if (pageCount > 0) {
jedisClusterUtils.deleteKey(COUNT);
jedisClusterUtils.incrby(COUNT, pageCount);
}
}
List<StockoutList> stockoutList = orderResult.getStockoutList();
if (CollUtil.isEmpty(stockoutList)) {
log.info("====== 暂无出库订单信息 ======>>>>");
// 更新每次分页请求时间 保证下一次开始时间的连贯性
jedisClusterUtils.saveString(TIME,end);
// 查询次数用完移除分页结束时间
jedisClusterUtils.deleteKey(TIME_END);
} else {
log.info("====== 订单信息 ======");
for (StockoutList list : stockoutList) {
log.info("list===>>>:{}", list);
// 根据单号查询数据
log.info("====== 订单已发货 ======");
StringBuilder no = new StringBuilder();
TbOrder tbOrder = orderService.selectTbOrderById(list.getSrcTradeNo());
log.info("tbOrder===>>>:{}", tbOrder);
log.info("物流单号===>>>:{}", list.getLogisticsNo());
if (StringUtils.isBlank(tbOrder.getSendOutBill())) {
no.append(list.getLogisticsNo());
} else {
// 不包含就拼接
if (!tbOrder.getSendOutBill().contains(list.getLogisticsNo())) {
no.append(tbOrder.getSendOutBill()).append(",").append(list.getLogisticsNo());
} else {
continue;
}
}
if (no.length() > 0
&& !"null".equals(no.toString())
&& !"".equals(no.toString())) {
log.info("更新{}订单物流===>>>:{}", no, list.getLogisticsNo());
orderService.updateErpSendOutBill(no.toString(), list.getSrcTradeNo());
}
}
// 调用分页
if (jedisClusterUtils.decrby(COUNT, 1) > 0) {
if(i == 0) {
// 保证这一批次时间的一直性 结束时间按照第一次的请求时间
jedisClusterUtils.saveString(TIME_END,end);
}
log.info("count=====>>>{}",jedisClusterUtils.getString(COUNT));
getStockoutOrder(i+1);
}else {
// 更新每次分页请求时间 保证下一次开始时间的连贯性
jedisClusterUtils.saveString(TIME,end);
// 查询次数用完移除分页结束时间
jedisClusterUtils.deleteKey(TIME_END);
}
}
} else {
log.info("======查询失败======>>>{}", orderResult.getMessage());
}
} catch (IOException e) {
log.info("====请求旺店通查询销售出库单接口失败===>>{}", e.getMessage());
}
}
}