|
|
@ -1,14 +1,15 @@ |
|
|
package com.project.logistics.domain.strategy.handler; |
|
|
package com.project.logistics.domain.strategy.handler; |
|
|
|
|
|
|
|
|
|
|
|
import cn.hutool.core.util.StrUtil; |
|
|
import cn.hutool.json.JSONUtil; |
|
|
import cn.hutool.json.JSONUtil; |
|
|
import com.alibaba.fastjson.JSON; |
|
|
import com.alibaba.fastjson.JSON; |
|
|
import com.alibaba.fastjson.JSONArray; |
|
|
import com.alibaba.fastjson.JSONArray; |
|
|
import com.alibaba.fastjson.JSONObject; |
|
|
import com.alibaba.fastjson.JSONObject; |
|
|
import com.jayway.jsonpath.JsonPath; |
|
|
import com.jayway.jsonpath.JsonPath; |
|
|
|
|
|
import com.project.logistics.config.FixedRuleProperties; |
|
|
import com.project.logistics.domain.entity.ApiRetryTaskEntity; |
|
|
import com.project.logistics.domain.entity.ApiRetryTaskEntity; |
|
|
import com.project.logistics.domain.entity.LogisticsOrderEntity; |
|
|
import com.project.logistics.domain.entity.LogisticsOrderEntity; |
|
|
import com.project.logistics.domain.enums.OrderStatusEnum; |
|
|
import com.project.logistics.domain.enums.*; |
|
|
import com.project.logistics.domain.enums.RetryActionEnum; |
|
|
|
|
|
import com.project.logistics.domain.service.SfApiService; |
|
|
import com.project.logistics.domain.service.SfApiService; |
|
|
import com.project.logistics.domain.service.WebDavService; |
|
|
import com.project.logistics.domain.service.WebDavService; |
|
|
import com.project.logistics.domain.service.base.ApiRetryTaskService; |
|
|
import com.project.logistics.domain.service.base.ApiRetryTaskService; |
|
|
@ -19,6 +20,8 @@ import org.springframework.beans.factory.annotation.Autowired; |
|
|
import org.springframework.stereotype.Component; |
|
|
import org.springframework.stereotype.Component; |
|
|
import org.springframework.transaction.annotation.Transactional; |
|
|
import org.springframework.transaction.annotation.Transactional; |
|
|
|
|
|
|
|
|
|
|
|
import java.util.Objects; |
|
|
|
|
|
|
|
|
@Slf4j |
|
|
@Slf4j |
|
|
@Component |
|
|
@Component |
|
|
public class SfCreateOrderHandler implements ApiTaskHandler { |
|
|
public class SfCreateOrderHandler implements ApiTaskHandler { |
|
|
@ -32,6 +35,9 @@ public class SfCreateOrderHandler implements ApiTaskHandler { |
|
|
@Autowired |
|
|
@Autowired |
|
|
private WebDavService webDavService; |
|
|
private WebDavService webDavService; |
|
|
|
|
|
|
|
|
|
|
|
@Autowired |
|
|
|
|
|
private FixedRuleProperties fixedRuleProperties; |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public String getActionCode() { |
|
|
public String getActionCode() { |
|
|
return RetryActionEnum.SF_CREATE_ORDER.getCode(); |
|
|
return RetryActionEnum.SF_CREATE_ORDER.getCode(); |
|
|
@ -50,40 +56,74 @@ public class SfCreateOrderHandler implements ApiTaskHandler { |
|
|
msgData.put("language", "zh-CN"); |
|
|
msgData.put("language", "zh-CN"); |
|
|
msgData.put("orderId", order.getOrderNo()); // 客户订单号
|
|
|
msgData.put("orderId", order.getOrderNo()); // 客户订单号
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String transportMethod = u9Data.getString(ShipmentOrderInfoFieldEnum.transportMethod.name()); |
|
|
|
|
|
if (StrUtil.isBlank(transportMethod) || !transportMethod.contains("顺丰")) { |
|
|
|
|
|
// 需要终止任务,匹配字段失败,失败原因:运输方式及货场名称不为顺丰
|
|
|
|
|
|
terminateBusinessTask(task, order, "匹配字段失败:运输方式及货场名称不为顺丰 (" + transportMethod + ")"); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
String payer = u9Data.getString(ShipmentOrderInfoFieldEnum.payer.name()); |
|
|
|
|
|
SfPayMethodEnum senderPayByU9Desc = SfPayMethodEnum.getSenderPayByU9Desc(payer); |
|
|
|
|
|
if (Objects.isNull(senderPayByU9Desc)) { |
|
|
|
|
|
// 需要终止任务,匹配字段失败,失败原因:运费承担字段匹配失败
|
|
|
|
|
|
terminateBusinessTask(task, order, "匹配字段失败:运费承担字段 (" + payer + ") 无法匹配顺丰付款方式"); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
String expressType = u9Data.getString(ShipmentOrderInfoFieldEnum.expressType.name()); |
|
|
|
|
|
SfExpressTypeEnum sfStandardExpressByCode = SfExpressTypeEnum.getSfStandardExpressByCode(expressType); |
|
|
|
|
|
if (Objects.isNull(sfStandardExpressByCode)) { |
|
|
|
|
|
// 需要终止任务,匹配字段失败,失败原因:未匹配快件产品类别
|
|
|
|
|
|
terminateBusinessTask(task, order, "匹配字段失败:单据产品类别 (" + expressType + ") 未匹配到顺丰业务类型"); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
msgData.put("cargoDesc", "交换机"); |
|
|
|
|
|
JSONArray cargoDetails = new JSONArray(); |
|
|
|
|
|
JSONObject item = new JSONObject(); |
|
|
|
|
|
item.put("name", "交换机"); |
|
|
|
|
|
cargoDetails.add(item); |
|
|
|
|
|
msgData.put("cargoDetails", cargoDetails); |
|
|
|
|
|
|
|
|
// 2.1 构造收寄双方信息 (根据你之前 SELECT * 看到的 U9 字段名来取值)
|
|
|
// 2.1 构造收寄双方信息 (根据你之前 SELECT * 看到的 U9 字段名来取值)
|
|
|
JSONArray contactInfoList = new JSONArray(); |
|
|
JSONArray contactInfoList = new JSONArray(); |
|
|
|
|
|
|
|
|
// 寄件方 (通常写死公司信息,或从配置取)
|
|
|
// 寄件方 (通常写死公司信息,或从配置取)
|
|
|
JSONObject sender = new JSONObject(); |
|
|
JSONObject sender = new JSONObject(); |
|
|
sender.put("contactType", 1); |
|
|
sender.put("contactType", SfContactTypeEnum.SENDER.getCode()); |
|
|
sender.put("contact", "您的公司名"); |
|
|
// 寄付取业务的名字,到付取固定
|
|
|
sender.put("mobile", "13800000000"); |
|
|
sender.put("contact", SfPayMethodEnum.SENDER_PAY.equals(senderPayByU9Desc) ? |
|
|
sender.put("address", "公司详细地址"); |
|
|
u9Data.getString(ShipmentOrderInfoFieldEnum.payer.name()) : |
|
|
|
|
|
fixedRuleProperties.getSenderPayContact()); |
|
|
|
|
|
sender.put("mobile", fixedRuleProperties.getSenderMobile()); |
|
|
|
|
|
sender.put("address", fixedRuleProperties.getSenderAddress()); |
|
|
contactInfoList.add(sender); |
|
|
contactInfoList.add(sender); |
|
|
|
|
|
|
|
|
// 收件方 (从 U9 快照中动态获取)
|
|
|
// 收件方 (从 U9 快照中动态获取)
|
|
|
JSONObject receiver = new JSONObject(); |
|
|
JSONObject receiver = new JSONObject(); |
|
|
receiver.put("contactType", 2); |
|
|
receiver.put("contactType", SfContactTypeEnum.SENDER.getCode()); |
|
|
receiver.put("contact", u9Data.getString("Receiver_Contact")); // 假设 U9 字段名是这个
|
|
|
receiver.put("contact", u9Data.getString(ShipmentOrderInfoFieldEnum.recipientContact.name())); // 假设 U9 字段名是这个
|
|
|
receiver.put("mobile", u9Data.getString("Receiver_Phone")); |
|
|
receiver.put("mobile", u9Data.getString(ShipmentOrderInfoFieldEnum.recipientMobile.name())); |
|
|
receiver.put("province", u9Data.getString("Receiver_Province")); |
|
|
receiver.put("address", u9Data.getString(ShipmentOrderInfoFieldEnum.recipientAddress.name())); |
|
|
receiver.put("city", u9Data.getString("Receiver_City")); |
|
|
|
|
|
receiver.put("address", u9Data.getString("Receiver_Address")); |
|
|
|
|
|
contactInfoList.add(receiver); |
|
|
contactInfoList.add(receiver); |
|
|
|
|
|
|
|
|
msgData.put("contactInfoList", contactInfoList); |
|
|
msgData.put("contactInfoList", contactInfoList); |
|
|
|
|
|
|
|
|
// 2.2 货物信息与支付方式
|
|
|
// 2.2 货物信息与支付方式
|
|
|
msgData.put("monthlyCard", u9Data.getString("MonthlyCard")); // 月结卡号
|
|
|
// 月结卡号
|
|
|
msgData.put("payMethod", u9Data.getInteger("PayMethod")); // 付款方式
|
|
|
if (SfPayMethodEnum.SENDER_PAY.equals(senderPayByU9Desc)) { |
|
|
msgData.put("expressTypeId", "1"); // 标准快递
|
|
|
msgData.put("monthlyCard" , fixedRuleProperties.getMonthlyCard()); |
|
|
|
|
|
} |
|
|
|
|
|
msgData.put("expressTypeId", sfStandardExpressByCode.getSfCode()); // 标准快递
|
|
|
|
|
|
|
|
|
// 2.3 【关键步骤】绑定电子回单增值服务
|
|
|
// 2.3 【关键步骤】绑定电子回单增值服务
|
|
|
if (order.getResourceCode() != null) { |
|
|
if (StrUtil.isNotBlank(order.getResourceCode())) { |
|
|
JSONArray serviceList = new JSONArray(); |
|
|
JSONArray serviceList = new JSONArray(); |
|
|
JSONObject receiptService = new JSONObject(); |
|
|
JSONObject receiptService = new JSONObject(); |
|
|
receiptService.put("name", "IN149"); // 电子回单服务代码
|
|
|
receiptService.put("name", "IN149"); // 电子回单服务代码
|
|
|
receiptService.put("value", order.getResourceCode()); |
|
|
receiptService.put("value", "3"); |
|
|
|
|
|
receiptService.put("value1", order.getResourceCode()); |
|
|
serviceList.add(receiptService); |
|
|
serviceList.add(receiptService); |
|
|
msgData.put("serviceList", serviceList); |
|
|
msgData.put("serviceList", serviceList); |
|
|
} |
|
|
} |
|
|
@ -121,8 +161,9 @@ public class SfCreateOrderHandler implements ApiTaskHandler { |
|
|
log.error(">>> 顺丰下单成功但文件移位失败: {}", e.getMessage()); |
|
|
log.error(">>> 顺丰下单成功但文件移位失败: {}", e.getMessage()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 7. 触发下一个任务:回写 U9 运单号
|
|
|
// 7. 触发下阶段任务:回写 U9 运单号 + 下载面单(可并行)
|
|
|
apiRetryTaskService.createNextTask(order.getOrderNo(), RetryActionEnum.ERP_UPDATE_WAYBILL); |
|
|
apiRetryTaskService.createNextTask(order.getOrderNo(), RetryActionEnum.ERP_UPDATE_WAYBILL); |
|
|
|
|
|
apiRetryTaskService.createNextTask(order.getOrderNo(), RetryActionEnum.SF_DOWNLOAD_WAYBILL); |
|
|
|
|
|
|
|
|
} else { |
|
|
} else { |
|
|
String errorMsg = JsonPath.read(innerJsonStr, "$.errorMsg"); |
|
|
String errorMsg = JsonPath.read(innerJsonStr, "$.errorMsg"); |
|
|
@ -133,4 +174,18 @@ public class SfCreateOrderHandler implements ApiTaskHandler { |
|
|
throw e; |
|
|
throw e; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
private void terminateBusinessTask(ApiRetryTaskEntity task, LogisticsOrderEntity order, String reason) { |
|
|
|
|
|
log.error(">>> 订单 {} 业务校验不通过: {}", order.getOrderNo(), reason); |
|
|
|
|
|
|
|
|
|
|
|
// 1. 更新主表为 ERROR 状态
|
|
|
|
|
|
order.setOrderStatus(OrderStatusEnum.ERROR.getCode()); |
|
|
|
|
|
logisticsOrderService.updateById(order); |
|
|
|
|
|
|
|
|
|
|
|
// 2. 将当前任务设为取消/死信状态,防止定时任务继续重试
|
|
|
|
|
|
task.setTaskStatus(TaskStatusEnum.CANCELLED.getCode()); |
|
|
|
|
|
task.setErrorMessage(reason); |
|
|
|
|
|
// 注意:任务表的最终 update 会由 ApiRetryJob 在 handle 执行完后统一处理
|
|
|
|
|
|
// 此处抛出一个特定异常或正常返回即可。由于 ApiRetryJob 会根据异常重试,
|
|
|
|
|
|
// 我们这里选择不抛异常,让 ApiRetryJob 认为执行“结束”了(但状态已改)。
|
|
|
|
|
|
} |
|
|
} |
|
|
} |