|
@@ -3,9 +3,11 @@ package com.fs.hisStore.service.impl;
|
|
|
import java.net.URLEncoder;
|
|
import java.net.URLEncoder;
|
|
|
import java.security.MessageDigest;
|
|
import java.security.MessageDigest;
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
|
|
+import java.util.Arrays;
|
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
import cn.hutool.http.HttpUtil;
|
|
import cn.hutool.http.HttpUtil;
|
|
@@ -29,6 +31,8 @@ import com.fs.hisStore.param.FsStoreOrderExpressParam;
|
|
|
import com.fs.live.domain.LiveOrder;
|
|
import com.fs.live.domain.LiveOrder;
|
|
|
import com.fs.live.mapper.LiveOrderMapper;
|
|
import com.fs.live.mapper.LiveOrderMapper;
|
|
|
import com.fs.system.service.ISysConfigService;
|
|
import com.fs.system.service.ISysConfigService;
|
|
|
|
|
+import com.fs.system.service.ISysDictTypeService;
|
|
|
|
|
+import com.fs.common.core.domain.entity.SysDictData;
|
|
|
import org.apache.commons.lang.StringUtils;
|
|
import org.apache.commons.lang.StringUtils;
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
import org.slf4j.LoggerFactory;
|
|
@@ -48,6 +52,8 @@ import org.springframework.util.Base64Utils;
|
|
|
@Service
|
|
@Service
|
|
|
public class FsExpressScrmServiceImpl implements IFsExpressScrmService
|
|
public class FsExpressScrmServiceImpl implements IFsExpressScrmService
|
|
|
{
|
|
{
|
|
|
|
|
+ private static final String STORE_EXPRESS_SENDER_PHONE_SUBSCRIBE = "store_express_sender_phone";
|
|
|
|
|
+
|
|
|
Logger logger = LoggerFactory.getLogger(FsExpressScrmServiceImpl.class);
|
|
Logger logger = LoggerFactory.getLogger(FsExpressScrmServiceImpl.class);
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private FsExpressScrmMapper fsExpressMapper;
|
|
private FsExpressScrmMapper fsExpressMapper;
|
|
@@ -56,6 +62,9 @@ public class FsExpressScrmServiceImpl implements IFsExpressScrmService
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private ISysConfigService configService;
|
|
private ISysConfigService configService;
|
|
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private ISysDictTypeService sysDictTypeService;
|
|
|
|
|
+
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private LiveOrderMapper liveOrderMapper;
|
|
private LiveOrderMapper liveOrderMapper;
|
|
|
/**
|
|
/**
|
|
@@ -134,11 +143,12 @@ public class FsExpressScrmServiceImpl implements IFsExpressScrmService
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public ExpressInfoDTO getExpressInfo(String OrderCode, String ShipperCode, String LogisticCode, String lastFourNumber) {
|
|
public ExpressInfoDTO getExpressInfo(String OrderCode, String ShipperCode, String LogisticCode, String lastFourNumber) {
|
|
|
|
|
+ String customerName = resolveExpressQueryPhone(OrderCode, ShipperCode, lastFourNumber);
|
|
|
|
|
|
|
|
//处理顺丰查询轨迹需手机号码后4位
|
|
//处理顺丰查询轨迹需手机号码后4位
|
|
|
String requestData;
|
|
String requestData;
|
|
|
if (ShipperCode.equals(ShipperCodeEnum.SF.getValue()) || ShipperCode.equals(ShipperCodeEnum.ZTO.getValue())) {
|
|
if (ShipperCode.equals(ShipperCodeEnum.SF.getValue()) || ShipperCode.equals(ShipperCodeEnum.ZTO.getValue())) {
|
|
|
- requestData = "{'OrderCode':'" + OrderCode + "','ShipperCode':'" + ShipperCode + "','LogisticCode':'" + LogisticCode + "','CustomerName':'" + lastFourNumber + "'}";
|
|
|
|
|
|
|
+ requestData = "{'OrderCode':'" + OrderCode + "','ShipperCode':'" + ShipperCode + "','LogisticCode':'" + LogisticCode + "','CustomerName':'" + customerName + "'}";
|
|
|
} else {
|
|
} else {
|
|
|
requestData = "{'OrderCode':'" + OrderCode + "','ShipperCode':'" + ShipperCode + "','LogisticCode':'" + LogisticCode + "'}";
|
|
requestData = "{'OrderCode':'" + OrderCode + "','ShipperCode':'" + ShipperCode + "','LogisticCode':'" + LogisticCode + "'}";
|
|
|
}
|
|
}
|
|
@@ -215,7 +225,57 @@ public class FsExpressScrmServiceImpl implements IFsExpressScrmService
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public void subscribeEspress(String orderCode, String deliverySn, String deliveryId, String userPhone) {
|
|
public void subscribeEspress(String orderCode, String deliverySn, String deliveryId, String userPhone) {
|
|
|
- //处理顺丰查询轨迹需手机号码后4位
|
|
|
|
|
|
|
+ ExpressInfoDTO dto = doSubscribeRequest(orderCode, deliverySn, deliveryId, userPhone);
|
|
|
|
|
+ if (dto == null || !dto.isSuccess()) {
|
|
|
|
|
+ logger.error("订阅物流失败:orderCode={}, deliveryId={}, reason={}",
|
|
|
|
|
+ orderCode, deliveryId, dto != null ? dto.getReason() : "订阅物流返回为空");
|
|
|
|
|
+ afterExpressFailure(orderCode, deliveryId, dto != null ? dto.getReason() : "订阅物流返回为空");
|
|
|
|
|
+ throw new CustomException(dto != null && StringUtils.isNotBlank(dto.getReason()) ? dto.getReason() : "订阅物流失败");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void subscribeEspressWithSenderPhones(String orderCode, String deliverySn, String deliveryId, String userPhone, String senderPhones) {
|
|
|
|
|
+ List<String> senderPhoneList = parseSenderPhones(senderPhones);
|
|
|
|
|
+ if (!senderPhoneList.isEmpty()) {
|
|
|
|
|
+ for (String senderPhone : senderPhoneList) {
|
|
|
|
|
+ String customerName = resolveCustomerName(deliverySn, senderPhone);
|
|
|
|
|
+ ExpressInfoDTO dto = doSubscribeRequest(orderCode, deliverySn, deliveryId, customerName);
|
|
|
|
|
+ if (dto != null && dto.isSuccess()) {
|
|
|
|
|
+ logger.info("订阅物流成功(发货人手机号): orderCode={}, phone={}", orderCode, senderPhone);
|
|
|
|
|
+ updateOrderSenderPhoneByOrderCode(orderCode, senderPhone);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isPhoneError(dto)) {
|
|
|
|
|
+ logger.warn("发货人手机号订阅失败,尝试下一个: orderCode={}, phone={}, reason={}",
|
|
|
|
|
+ orderCode, senderPhone, dto != null ? dto.getReason() : null);
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ logger.warn("订阅物流失败(非手机号错误),改用收货人手机号: orderCode={}, reason={}",
|
|
|
|
|
+ orderCode, dto != null ? dto.getReason() : null);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ExpressInfoDTO receiverDto = doSubscribeRequest(orderCode, deliverySn, deliveryId, userPhone);
|
|
|
|
|
+ if (receiverDto == null || !receiverDto.isSuccess()) {
|
|
|
|
|
+ logger.error("订阅物流失败(收货人手机号):orderCode={}, deliveryId={}, reason={}",
|
|
|
|
|
+ orderCode, deliveryId, receiverDto != null ? receiverDto.getReason() : "订阅物流返回为空");
|
|
|
|
|
+ afterExpressFailure(orderCode, deliveryId, receiverDto != null ? receiverDto.getReason() : "订阅物流返回为空");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ logger.info("订阅物流成功(收货人手机号): orderCode={}", orderCode);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void subscribeExpressSmart(String orderCode, String deliverySn, String deliveryId, String userPhone, String senderPhones) {
|
|
|
|
|
+ if (isSenderPhoneSubscribeEnabled()) {
|
|
|
|
|
+ subscribeEspressWithSenderPhones(orderCode, deliverySn, deliveryId, userPhone, senderPhones);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ subscribeEspress(orderCode, deliverySn, deliveryId, userPhone);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private ExpressInfoDTO doSubscribeRequest(String orderCode, String deliverySn, String deliveryId, String userPhone) {
|
|
|
String requestData;
|
|
String requestData;
|
|
|
if (deliverySn.equals(ShipperCodeEnum.SF.getValue()) || deliverySn.equals(ShipperCodeEnum.ZTO.getValue())) {
|
|
if (deliverySn.equals(ShipperCodeEnum.SF.getValue()) || deliverySn.equals(ShipperCodeEnum.ZTO.getValue())) {
|
|
|
requestData = "{'OrderCode':'" + orderCode + "','ShipperCode':'" + deliverySn + "','LogisticCode':'" + deliveryId + "','CustomerName':'" + userPhone + "'}";
|
|
requestData = "{'OrderCode':'" + orderCode + "','ShipperCode':'" + deliverySn + "','LogisticCode':'" + deliveryId + "','CustomerName':'" + userPhone + "'}";
|
|
@@ -226,25 +286,69 @@ public class FsExpressScrmServiceImpl implements IFsExpressScrmService
|
|
|
Map<String, Object> params = new HashMap<>();
|
|
Map<String, Object> params = new HashMap<>();
|
|
|
try {
|
|
try {
|
|
|
String json = this.configService.selectConfigByKey("his.config");
|
|
String json = this.configService.selectConfigByKey("his.config");
|
|
|
- FSSysConfig sysConfig= JSON.parseObject(json,FSSysConfig.class);
|
|
|
|
|
|
|
+ FSSysConfig sysConfig = JSON.parseObject(json, FSSysConfig.class);
|
|
|
params.put("RequestData", URLEncoder.encode(requestData, "UTF-8"));
|
|
params.put("RequestData", URLEncoder.encode(requestData, "UTF-8"));
|
|
|
- params.put("EBusinessID",sysConfig.getKdnId().trim());
|
|
|
|
|
- params.put("RequestType", "8001");
|
|
|
|
|
|
|
+ params.put("EBusinessID", sysConfig.getKdnId().trim());
|
|
|
|
|
+ params.put("RequestType", "8008");
|
|
|
String dataSign = encrypt(requestData, sysConfig.getKdnKeyId().trim(), "UTF-8");
|
|
String dataSign = encrypt(requestData, sysConfig.getKdnKeyId().trim(), "UTF-8");
|
|
|
params.put("DataSign", URLEncoder.encode(dataSign, "UTF-8"));
|
|
params.put("DataSign", URLEncoder.encode(dataSign, "UTF-8"));
|
|
|
params.put("DataType", "2");
|
|
params.put("DataType", "2");
|
|
|
String result = HttpUtil.post(sysConfig.getKdnSubscribeUrl().trim(), params);
|
|
String result = HttpUtil.post(sysConfig.getKdnSubscribeUrl().trim(), params);
|
|
|
- logger.info("订阅物流:"+result);
|
|
|
|
|
- ExpressInfoDTO dto = JSONUtil.toBean(result, ExpressInfoDTO.class);
|
|
|
|
|
- if (dto == null || !dto.isSuccess()) {
|
|
|
|
|
- logger.error("订阅物流失败:{}:{}", result, requestData);
|
|
|
|
|
- afterExpressFailure(orderCode, deliveryId, dto != null ? dto.getReason() : "订阅物流返回为空");
|
|
|
|
|
|
|
+ logger.info("订阅物流:{}", result);
|
|
|
|
|
+ return JSONUtil.toBean(result, ExpressInfoDTO.class);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ logger.error("订阅物流异常: orderCode={}, deliveryId={}", orderCode, deliveryId, e);
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean isSenderPhoneSubscribeEnabled() {
|
|
|
|
|
+ List<SysDictData> dictList = sysDictTypeService.selectDictDataByType(STORE_EXPRESS_SENDER_PHONE_SUBSCRIBE);
|
|
|
|
|
+ if (dictList == null || dictList.isEmpty()) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ return dictList.stream()
|
|
|
|
|
+ .filter(item -> "0".equals(item.getStatus()))
|
|
|
|
|
+ .anyMatch(item -> "1".equals(StringUtils.trimToEmpty(item.getDictValue())));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private List<String> parseSenderPhones(String senderPhones) {
|
|
|
|
|
+ if (StringUtils.isBlank(senderPhones)) {
|
|
|
|
|
+ return new ArrayList<>();
|
|
|
|
|
+ }
|
|
|
|
|
+ return Arrays.stream(senderPhones.split("[,,]"))
|
|
|
|
|
+ .map(String::trim)
|
|
|
|
|
+ .filter(StringUtils::isNotBlank)
|
|
|
|
|
+ .limit(3)
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private String resolveCustomerName(String deliverySn, String phone) {
|
|
|
|
|
+ if (StringUtils.isBlank(phone)) {
|
|
|
|
|
+ return "";
|
|
|
|
|
+ }
|
|
|
|
|
+ if (deliverySn.equals(ShipperCodeEnum.SF.getValue()) || deliverySn.equals(ShipperCodeEnum.ZTO.getValue())) {
|
|
|
|
|
+ if (phone.length() == 11) {
|
|
|
|
|
+ return StrUtil.sub(phone, phone.length(), -4);
|
|
|
}
|
|
}
|
|
|
|
|
+ }
|
|
|
|
|
+ return phone;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- afterExpressFailure(orderCode, deliveryId, e.getMessage());
|
|
|
|
|
- throw new CustomException(e.getMessage());
|
|
|
|
|
|
|
+ private boolean isPhoneError(ExpressInfoDTO dto) {
|
|
|
|
|
+ if (dto == null || dto.isSuccess()) {
|
|
|
|
|
+ return false;
|
|
|
}
|
|
}
|
|
|
|
|
+ String reason = StringUtils.trimToEmpty(dto.getReason());
|
|
|
|
|
+ if (StringUtils.isBlank(reason)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ return reason.contains("手机尾号不正确")
|
|
|
|
|
+ || reason.contains("手机尾号")
|
|
|
|
|
+ || reason.contains("手机")
|
|
|
|
|
+ || reason.contains("电话")
|
|
|
|
|
+ || reason.contains("CustomerName")
|
|
|
|
|
+ || reason.contains("号码");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
@@ -376,6 +480,44 @@ public class FsExpressScrmServiceImpl implements IFsExpressScrmService
|
|
|
return lastFourNumber;
|
|
return lastFourNumber;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据订单号查询物流订阅成功的发货人手机号
|
|
|
|
|
+ */
|
|
|
|
|
+ private String getOrderSenderPhoneByOrderCode(String orderCode) {
|
|
|
|
|
+ if (StringUtils.isBlank(orderCode)) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ return fsStoreOrderMapper.selectSenderPhoneByOrderCode(orderCode);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 解析物流查询使用的手机号:字典开启且订单有发货人手机号时优先使用,否则使用收货人手机尾号
|
|
|
|
|
+ */
|
|
|
|
|
+ private String resolveExpressQueryPhone(String orderCode, String shipperCode, String lastFourNumber) {
|
|
|
|
|
+ if (!isSenderPhoneSubscribeEnabled() || StringUtils.isBlank(orderCode)) {
|
|
|
|
|
+ return lastFourNumber;
|
|
|
|
|
+ }
|
|
|
|
|
+ String senderPhone = getOrderSenderPhoneByOrderCode(orderCode);
|
|
|
|
|
+ if (StringUtils.isBlank(senderPhone)) {
|
|
|
|
|
+ return lastFourNumber;
|
|
|
|
|
+ }
|
|
|
|
|
+ return resolveCustomerName(shipperCode, senderPhone);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据订单号更新物流订阅成功的发货人手机号
|
|
|
|
|
+ */
|
|
|
|
|
+ private void updateOrderSenderPhoneByOrderCode(String orderCode, String senderPhone) {
|
|
|
|
|
+ if (StringUtils.isBlank(orderCode) || StringUtils.isBlank(senderPhone)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ fsStoreOrderMapper.updateSenderPhoneByOrderCode(orderCode, senderPhone);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ logger.error("更新订单发货人手机号异常: orderCode={}, senderPhone={}", orderCode, senderPhone, e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 快递查询/订阅失败或异常时更新订单物流状态为问题件
|
|
* 快递查询/订阅失败或异常时更新订单物流状态为问题件
|
|
|
*/
|
|
*/
|