记得上下班打卡 | git大法好,push需谨慎

Commit 3ffd1b5a authored by 姜秀龙's avatar 姜秀龙

快递 100接入初版

parent 931332ff
package com.liquidnet.service.goblin.constant;
import com.liquidnet.service.goblin.dto.vo.GoblinExpressCompanyVo;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* 常用快递公司列表(发货选择,写死;来源:常用快递公司筛选.xlsx)
*/
public final class GoblinExpressCompanyConst {
private GoblinExpressCompanyConst() {
}
public static final List<GoblinExpressCompanyVo> COMMON_LIST = Collections.unmodifiableList(Arrays.asList(
new GoblinExpressCompanyVo("德邦快递", "debangkuaidi", "国内运输商"),
new GoblinExpressCompanyVo("德邦物流", "debangwuliu", "国内运输商"),
new GoblinExpressCompanyVo("顺丰速运", "shunfeng", "国际运输商"),
new GoblinExpressCompanyVo("京东物流", "jd", "国内运输商"),
new GoblinExpressCompanyVo("中通快递", "zhongtong", "国内运输商"),
new GoblinExpressCompanyVo("圆通速递", "yuantong", "国内运输商"),
new GoblinExpressCompanyVo("韵达快递", "yunda", "国内运输商"),
new GoblinExpressCompanyVo("申通快递", "shentong", "国内运输商"),
new GoblinExpressCompanyVo("极兔速递", "jtexpress", "国内运输商"),
new GoblinExpressCompanyVo("菜鸟速递", "danniao", "国内运输商"),
new GoblinExpressCompanyVo("百世快递", "huitongkuaidi", "国内运输商"),
new GoblinExpressCompanyVo("邮政快递包裹", "youzhengguonei", "国际邮政"),
new GoblinExpressCompanyVo("EMS", "ems", "国际邮政"),
new GoblinExpressCompanyVo("邮政电商标快", "youzhengdsbk", "国内运输商"),
new GoblinExpressCompanyVo("邮政标准快递", "youzhengbk", "国内运输商"),
new GoblinExpressCompanyVo("中国邮政(CHINA POST)", "chinapost", "国际邮政"),
new GoblinExpressCompanyVo("宅急送", "zhaijisong", "国内运输商"),
new GoblinExpressCompanyVo("苏宁物流", "suning", "国内运输商"),
new GoblinExpressCompanyVo("中通快运", "zhongtongkuaiyun", "国内运输商"),
new GoblinExpressCompanyVo("安能快运", "annengwuliu", "国内运输商"),
new GoblinExpressCompanyVo("跨越速运", "kuayue", "国内运输商"),
new GoblinExpressCompanyVo("顺丰冷链", "shunfenglengyun", "国内运输商"),
new GoblinExpressCompanyVo("中通冷链", "ztocc", "国内运输商"),
new GoblinExpressCompanyVo("DHL-全球件", "dhlen", "国际运输商"),
new GoblinExpressCompanyVo("FedEx-国际件", "fedex", "国际运输商"),
new GoblinExpressCompanyVo("UPS", "ups", "国际运输商"),
new GoblinExpressCompanyVo("EMS-国际件", "emsguoji", "国际邮政")
));
}
...@@ -135,6 +135,10 @@ public class GoblinRedisConst { ...@@ -135,6 +135,10 @@ public class GoblinRedisConst {
public static final String REDIS_CAN_BUY = PREFIX.concat("canBuy:");//可以购买的用户 key:$skuId:$mobile public static final String REDIS_CAN_BUY = PREFIX.concat("canBuy:");//可以购买的用户 key:$skuId:$mobile
public static final String REDIS_ZZ_MUSIC_TAG = PREFIX.concat("music:tag:ZZ:");//根据场次音乐人标签搜索列表 key:$musicTag:$performanceId public static final String REDIS_ZZ_MUSIC_TAG = PREFIX.concat("music:tag:ZZ:");//根据场次音乐人标签搜索列表 key:$musicTag:$performanceId
public static final String REDIS_GOBLIN_MAIL = PREFIX.concat("mail:orderId:");//快递 $key:$orderId public static final String REDIS_GOBLIN_MAIL = PREFIX.concat("mail:orderId:");//快递 $key:$orderId
/**
* 快递100物流缓存 {goblin:mail:track:${mailId}, GoblinMailTrackCache}
*/
public static final String REDIS_GOBLIN_MAIL_TRACK = PREFIX.concat("mail:track:");
public static final String REDIS_GOBLIN_TEMP_COUPON_MARKET = PREFIX.concat("temp:coupon:marketId:");//id 列表 $key:$marketId public static final String REDIS_GOBLIN_TEMP_COUPON_MARKET = PREFIX.concat("temp:coupon:marketId:");//id 列表 $key:$marketId
public static final String REDIS_GOBLIN_TEMP_COUPON = PREFIX.concat("temp:coupon:");//详情 $key:$ucouponId public static final String REDIS_GOBLIN_TEMP_COUPON = PREFIX.concat("temp:coupon:");//详情 $key:$ucouponId
......
package com.liquidnet.service.goblin.dto.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 常用快递公司(发货选择)
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel("常用快递公司")
public class GoblinExpressCompanyVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("公司名称")
private String name;
@ApiModelProperty("公司编码(快递100小写编码)")
private String code;
@ApiModelProperty("公司类型")
private String type;
}
package com.liquidnet.service.goblin.dto.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* Redis 物流缓存:subscribe + track
*/
@Data
@ApiModel("快递物流缓存")
public class GoblinMailTrackCache implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("包裹ID")
private String mailId;
@ApiModelProperty("订单ID")
private String orderId;
@ApiModelProperty("订阅元数据")
private GoblinMailTrackSubscribeVo subscribe;
@ApiModelProperty("物流轨迹")
private GoblinMailTrackInfoVo track;
}
package com.liquidnet.service.goblin.dto.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 快递轨迹节点
*/
@Data
@ApiModel("快递轨迹节点")
public class GoblinMailTrackDataVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("时间原始格式")
private String time;
@ApiModelProperty("格式化时间")
private String ftime;
@ApiModelProperty("轨迹描述")
private String context;
@ApiModelProperty("物流状态名称")
private String status;
@ApiModelProperty("高级物流状态值")
private String statusCode;
@ApiModelProperty("行政区域编码")
private String areaCode;
@ApiModelProperty("行政区域名称")
private String areaName;
@ApiModelProperty("行政区域经纬度")
private String areaCenter;
@ApiModelProperty("行政区域拼音")
private String areaPinYin;
@ApiModelProperty("快件当前地点")
private String location;
}
package com.liquidnet.service.goblin.dto.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 快递物流轨迹本体(Redis 双层结构 - track)
*/
@Data
@ApiModel("快递物流轨迹")
public class GoblinMailTrackInfoVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("快递单状态")
private String state;
@ApiModelProperty("是否签收 0/1")
private String ischeck;
@ApiModelProperty("快递公司编码")
private String com;
@ApiModelProperty("快递单号")
private String nu;
@ApiModelProperty("轨迹节点全量倒序")
private List<GoblinMailTrackDataVo> data;
@ApiModelProperty("轨迹地图链接")
private String trailUrl;
@ApiModelProperty("路由信息")
private GoblinMailTrackRouteInfoVo routeInfo;
@ApiModelProperty("预计到达时间")
private String arrivalTime;
@ApiModelProperty("到达还需时间")
private String remainTime;
@ApiModelProperty("平均耗时")
private String totalTime;
@ApiModelProperty("最近主动查询时间")
private String lastQueryAt;
@ApiModelProperty("最近更新时间")
private String updatedAt;
@ApiModelProperty("数据来源 subscribe|query|admin")
private String source;
}
package com.liquidnet.service.goblin.dto.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel("快递路由位置")
public class GoblinMailTrackPositionVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("政区编码")
private String number;
@ApiModelProperty("政区名称")
private String name;
}
package com.liquidnet.service.goblin.dto.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel("快递路由信息")
public class GoblinMailTrackRouteInfoVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("出发地")
private GoblinMailTrackPositionVo from;
@ApiModelProperty("当前地")
private GoblinMailTrackPositionVo cur;
@ApiModelProperty("目的地")
private GoblinMailTrackPositionVo to;
}
package com.liquidnet.service.goblin.dto.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 快递100订阅元数据(Redis 双层结构 - subscribe)
*/
@Data
@ApiModel("快递订阅元数据")
public class GoblinMailTrackSubscribeVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("当前是否处于有效订阅")
private Boolean subscribed;
@ApiModelProperty("polling|shutdown|abort|subscribe_failed|quota_exceeded")
private String subscribeStatus;
@ApiModelProperty("是否需要重新订阅")
private Boolean needResubscribe;
@ApiModelProperty("本自然月已订阅次数")
private Integer subscribeCount;
@ApiModelProperty("订阅计数所属自然月 yyyy-MM")
private String subscribeMonth;
@ApiModelProperty("首次订阅时间")
private String firstSubscribeAt;
@ApiModelProperty("最近一次订阅时间")
private String lastSubscribeAt;
@ApiModelProperty("最近失败原因")
private String lastFailReason;
@ApiModelProperty("最近失败时间")
private String lastFailAt;
@ApiModelProperty("本月订阅是否已超限(>=4)")
private Boolean quotaExceeded;
}
...@@ -28,6 +28,19 @@ public class GoblinMailVo implements Serializable, Cloneable { ...@@ -28,6 +28,19 @@ public class GoblinMailVo implements Serializable, Cloneable {
@ApiModelProperty(value = "orderSkuVo") @ApiModelProperty(value = "orderSkuVo")
private List<GoblinOrderSkuVo> orderSkuVos; private List<GoblinOrderSkuVo> orderSkuVos;
@ApiModelProperty(value = "物流状态值")
private String state;
@ApiModelProperty(value = "物流状态文案")
private String stateText;
@ApiModelProperty(value = "最新物流描述")
private String latestContext;
@ApiModelProperty(value = "最新物流时间")
private String latestTime;
@ApiModelProperty(value = "轨迹地图链接")
private String trailUrl;
@ApiModelProperty(value = "是否签收 0/1")
private String ischeck;
private static final GoblinMailVo obj = new GoblinMailVo(); private static final GoblinMailVo obj = new GoblinMailVo();
public static GoblinMailVo getNew() { public static GoblinMailVo getNew() {
......
package com.liquidnet.service.goblin.dto.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
@ApiModel("同店推荐商品")
public class GoblinStoreRecommendGoodsVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("商品ID")
private String spuId;
@ApiModelProperty("商品名称")
private String name;
@ApiModelProperty("封面图")
private String coverPic;
@ApiModelProperty("展示价")
private BigDecimal price;
}
package com.liquidnet.service.goblin.service;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.vo.GoblinMailTrackCache;
import com.liquidnet.service.goblin.dto.vo.GoblinMailTrackInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinMailVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreRecommendGoodsVo;
import java.util.List;
import java.util.Map;
/**
* 快递100物流轨迹服务
*/
public interface IGoblinMailTrackService {
/**
* 发货后初始化并异步订阅
*/
void initAndSubscribeAsync(String orderId, String mailId, String mailNo, String logisticsCode, String logisticsCompany);
/**
* C 端读路径:按订阅状态决定只读 / 重订 / 主动查询
*/
GoblinMailTrackCache resolveTrackForRead(String orderId, String mailId);
/**
* 填充邮件摘要字段
*/
void fillMailSummary(GoblinMailVo mailVo, GoblinMailTrackCache cache);
/**
* 快递100地图订阅回调
*/
Map<String, Object> handleCallback(String param, String sign, String mailId, String orderId);
/**
* Admin:查看完整 Redis 缓存
*/
ResponseDto<GoblinMailTrackCache> adminGetTrack(String orderId, String mailId);
/**
* Admin:主动同步物流
*/
ResponseDto<GoblinMailTrackInfoVo> adminSyncTrack(String orderId, String mailId);
/**
* Admin:重新订阅
*/
ResponseDto<Boolean> adminResubscribe(String orderId, String mailId);
/**
* 同店最新上架商品前 2 个
*/
ResponseDto<List<GoblinStoreRecommendGoodsVo>> recommendStoreGoods(String orderId);
}
...@@ -29,4 +29,8 @@ public interface IGoblinOrderAppService { ...@@ -29,4 +29,8 @@ public interface IGoblinOrderAppService {
// String huiFuSync(HttpServletRequest request); // String huiFuSync(HttpServletRequest request);
ResponseDto<List<GoblinMailVo>> getMail(String orderId, String mailId); ResponseDto<List<GoblinMailVo>> getMail(String orderId, String mailId);
ResponseDto<GoblinMailTrackCache> logisticsDetail(String orderId, String mailId, String uid);
ResponseDto<List<GoblinStoreRecommendGoodsVo>> recommendStoreGoods(String orderId, String uid);
} }
...@@ -37,8 +37,10 @@ public interface IGoblinStoreOrderService { ...@@ -37,8 +37,10 @@ public interface IGoblinStoreOrderService {
ResponseDto<Boolean> refundOrderSku(String orderId, String orderSkuId, BigDecimal price); ResponseDto<Boolean> refundOrderSku(String orderId, String orderSkuId, BigDecimal price);
ResponseDto<Boolean> express(String orderId, String orderSkuIds, String mailNo, String uid, String orderCode); ResponseDto<Boolean> express(String orderId, String orderSkuIds, String mailNo, String uid, String orderCode,
String logisticsCode, String logisticsCompany);
ResponseDto<Boolean> changeExpressMailNo(String orderId, String mailId, String mailNo); ResponseDto<Boolean> changeExpressMailNo(String orderId, String mailId, String mailNo,
String logisticsCode, String logisticsCompany);
} }
...@@ -254,6 +254,13 @@ liquidnet: ...@@ -254,6 +254,13 @@ liquidnet:
jAddress: 朝阳区广渠路1号北京市商业储运公司3-12号 摩登天空 jAddress: 朝阳区广渠路1号北京市商业储运公司3-12号 摩登天空
expressType: 2 # 默认顺丰特快 expressType: 2 # 默认顺丰特快
depositumInfo: 演出纸质票 depositumInfo: 演出纸质票
kuaidi100:
customer: "FF2515DE9F4940F3DB30B86BCA353347"
key: "SFqxbtIL5054"
salt: "devYPAaju5rkunVk6eTeFJPwB3gQgesZ8FU"
callbackurl: ${liquidnet.service.goblin.url}/goblin/callback/kuaidi100/map
from: "北京市朝阳区摩登天空"
queryDebounceSeconds: 60
erp: erp:
wdt: wdt:
url: https://sandbox.wangdian.cn/openapi2/ url: https://sandbox.wangdian.cn/openapi2/
......
...@@ -253,6 +253,13 @@ liquidnet: ...@@ -253,6 +253,13 @@ liquidnet:
jAddress: 朝阳区广渠路1号北京市商业储运公司3-12号 摩登天空 jAddress: 朝阳区广渠路1号北京市商业储运公司3-12号 摩登天空
expressType: 2 # 默认顺丰特快 expressType: 2 # 默认顺丰特快
depositumInfo: 演出纸质票 depositumInfo: 演出纸质票
kuaidi100:
customer: "FF2515DE9F4940F3DB30B86BCA353347"
key: "SFqxbtIL5054"
salt: "testYPAaju5rkunVk6eTeFJPwB3gQgesZ8FU"
callbackurl: ${liquidnet.service.goblin.url}/goblin/callback/kuaidi100/map
from: "北京市朝阳区摩登天空"
queryDebounceSeconds: 60
erp: erp:
wdt: wdt:
url: https://sandbox.wangdian.cn/openapi2/ url: https://sandbox.wangdian.cn/openapi2/
......
...@@ -121,6 +121,12 @@ ...@@ -121,6 +121,12 @@
<artifactId>liquidnet-common-third-sqb</artifactId> <artifactId>liquidnet-common-third-sqb</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>com.github.kuaidi100-api</groupId>
<artifactId>sdk</artifactId>
<version>1.1.3</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
package com.liquidnet.service.goblin.controller;
import com.liquidnet.service.goblin.service.IGoblinMailTrackService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* 快递100地图订阅回调
*/
@Slf4j
@Api(tags = "快递100回调")
@RestController
@RequestMapping("/callback/kuaidi100")
public class GoblinKuaidi100CallbackController {
@Autowired
private IGoblinMailTrackService goblinMailTrackService;
@PostMapping("/map")
@ApiOperation("地图轨迹订阅推送回调")
public Map<String, Object> mapCallback(@RequestParam(value = "param", required = false) String param,
@RequestParam(value = "sign", required = false) String sign,
@RequestParam(value = "mailId", required = false) String mailId,
@RequestParam(value = "orderId", required = false) String orderId) {
log.info("[kuaidi100-callback] mailId={}, orderId={}, sign={}", mailId, orderId, sign);
return goblinMailTrackService.handleCallback(param, sign, mailId, orderId);
}
}
...@@ -111,4 +111,24 @@ public class GoblinOrderAppController { ...@@ -111,4 +111,24 @@ public class GoblinOrderAppController {
@RequestParam("mailId") @Valid String mailId) { @RequestParam("mailId") @Valid String mailId) {
return goblinOrderAppService.getMail(orderId, mailId); return goblinOrderAppService.getMail(orderId, mailId);
} }
@PostMapping("logistics/detail")
@ApiOperation("物流轨迹详情(文字轨迹+地图)")
@ApiImplicitParams({
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "orderId", value = "订单id"),
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mailId", value = "快递id"),
})
public ResponseDto<GoblinMailTrackCache> logisticsDetail(@RequestParam("orderId") @Valid String orderId,
@RequestParam("mailId") @Valid String mailId) {
return goblinOrderAppService.logisticsDetail(orderId, mailId, CurrentUtil.getCurrentUid());
}
@PostMapping("store/recommendGoods")
@ApiOperation("同店最新上架商品推荐(前2个)")
@ApiImplicitParams({
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "orderId", value = "订单id"),
})
public ResponseDto<List<GoblinStoreRecommendGoodsVo>> recommendStoreGoods(@RequestParam("orderId") @Valid String orderId) {
return goblinOrderAppService.recommendStoreGoods(orderId, CurrentUtil.getCurrentUid());
}
} }
...@@ -3,8 +3,13 @@ package com.liquidnet.service.goblin.controller.manage; ...@@ -3,8 +3,13 @@ package com.liquidnet.service.goblin.controller.manage;
import com.github.xiaoymin.knife4j.annotations.ApiSupport; import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.liquidnet.commons.lang.util.CurrentUtil; import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.service.base.ResponseDto; import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.constant.GoblinExpressCompanyConst;
import com.liquidnet.service.goblin.dto.vo.GoblinExpressCompanyVo;
import com.liquidnet.service.goblin.dto.vo.GoblinMailTrackCache;
import com.liquidnet.service.goblin.dto.vo.GoblinMailTrackInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreOrderListPageVo; import com.liquidnet.service.goblin.dto.vo.GoblinStoreOrderListPageVo;
import com.liquidnet.service.goblin.dto.vo.GoblinStoreOrderListVo; import com.liquidnet.service.goblin.dto.vo.GoblinStoreOrderListVo;
import com.liquidnet.service.goblin.service.IGoblinMailTrackService;
import com.liquidnet.service.goblin.service.manage.IGoblinStoreOrderService; import com.liquidnet.service.goblin.service.manage.IGoblinStoreOrderService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
...@@ -21,6 +26,7 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -21,6 +26,7 @@ import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid; import javax.validation.Valid;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List;
@ApiSupport(order = 149101) @ApiSupport(order = 149101)
@Api(tags = "店铺-订单") @Api(tags = "店铺-订单")
...@@ -31,8 +37,8 @@ import java.math.BigDecimal; ...@@ -31,8 +37,8 @@ import java.math.BigDecimal;
public class GoblinStoreOrderController { public class GoblinStoreOrderController {
@Autowired @Autowired
IGoblinStoreOrderService goblinStoreOrderService; IGoblinStoreOrderService goblinStoreOrderService;
// @Autowired @Autowired
// IGoblinOrderService goblinOrderService; IGoblinMailTrackService goblinMailTrackService;
@ApiOperation(value = "订单列表") @ApiOperation(value = "订单列表")
@ApiImplicitParams({ @ApiImplicitParams({
...@@ -148,17 +154,28 @@ public class GoblinStoreOrderController { ...@@ -148,17 +154,28 @@ public class GoblinStoreOrderController {
return goblinStoreOrderService.refundOrderSku(orderId, orderSkuId, price); return goblinStoreOrderService.refundOrderSku(orderId, orderSkuId, price);
} }
@ApiOperation(value = "常用快递公司列表(发货选择)")
@GetMapping(value = "express/companies")
public ResponseDto<List<GoblinExpressCompanyVo>> expressCompanies() {
return ResponseDto.success(GoblinExpressCompanyConst.COMMON_LIST);
}
@ApiOperation(value = "发货") @ApiOperation(value = "发货")
@ApiImplicitParams({ @ApiImplicitParams({
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "orderId", value = "订单id"), @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "orderId", value = "订单id"),
@ApiImplicitParam(type = "form", required = false, dataType = "String", name = "orderSkuIds", value = "逗号隔开orderSkuId"), @ApiImplicitParam(type = "form", required = false, dataType = "String", name = "orderSkuIds", value = "逗号隔开orderSkuId"),
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mailNo", value = "快递单号"), @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mailNo", value = "快递单号"),
@ApiImplicitParam(type = "form", required = false, dataType = "String", name = "logisticsCode", value = "快递公司编码(小写,如jt/yuantong)"),
@ApiImplicitParam(type = "form", required = false, dataType = "String", name = "logisticsCompany", value = "快递公司名称"),
}) })
@GetMapping(value = "express") @GetMapping(value = "express")
public ResponseDto<Boolean> express(@RequestParam(value = "orderId", required = true) @Valid String orderId, public ResponseDto<Boolean> express(@RequestParam(value = "orderId", required = true) @Valid String orderId,
@RequestParam(value = "orderSkuIds", required = false) @Valid String orderSkuIds, @RequestParam(value = "orderSkuIds", required = false) @Valid String orderSkuIds,
@RequestParam(value = "mailNo", required = true) @Valid String mailNo) { @RequestParam(value = "mailNo", required = true) @Valid String mailNo,
return goblinStoreOrderService.express(orderId, orderSkuIds, mailNo, CurrentUtil.getCurrentUid(), ""); @RequestParam(value = "logisticsCode", required = false) String logisticsCode,
@RequestParam(value = "logisticsCompany", required = false) String logisticsCompany) {
return goblinStoreOrderService.express(orderId, orderSkuIds, mailNo, CurrentUtil.getCurrentUid(), "",
logisticsCode, logisticsCompany);
} }
@ApiOperation(value = "修改快递单号") @ApiOperation(value = "修改快递单号")
...@@ -166,12 +183,49 @@ public class GoblinStoreOrderController { ...@@ -166,12 +183,49 @@ public class GoblinStoreOrderController {
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "orderId", value = "订单id"), @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "orderId", value = "订单id"),
@ApiImplicitParam(type = "form", required = false, dataType = "String", name = "mailId", value = "快递id"), @ApiImplicitParam(type = "form", required = false, dataType = "String", name = "mailId", value = "快递id"),
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mailNo", value = "快递单号"), @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mailNo", value = "快递单号"),
@ApiImplicitParam(type = "form", required = false, dataType = "String", name = "logisticsCode", value = "快递公司编码"),
@ApiImplicitParam(type = "form", required = false, dataType = "String", name = "logisticsCompany", value = "快递公司名称"),
}) })
@GetMapping(value = "express/change") @GetMapping(value = "express/change")
public ResponseDto<Boolean> changeExpressMailNo(@RequestParam(value = "orderId", required = true) @Valid String orderId, public ResponseDto<Boolean> changeExpressMailNo(@RequestParam(value = "orderId", required = true) @Valid String orderId,
@RequestParam(value = "mailId", required = false) @Valid String mailId, @RequestParam(value = "mailId", required = false) @Valid String mailId,
@RequestParam(value = "mailNo", required = true) @Valid String mailNo) { @RequestParam(value = "mailNo", required = true) @Valid String mailNo,
return goblinStoreOrderService.changeExpressMailNo(orderId, mailId, mailNo); @RequestParam(value = "logisticsCode", required = false) String logisticsCode,
@RequestParam(value = "logisticsCompany", required = false) String logisticsCompany) {
return goblinStoreOrderService.changeExpressMailNo(orderId, mailId, mailNo, logisticsCode, logisticsCompany);
}
@ApiOperation(value = "查看物流订阅与轨迹缓存")
@ApiImplicitParams({
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "orderId", value = "订单id"),
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mailId", value = "快递id"),
})
@GetMapping(value = "logistics/cache")
public ResponseDto<GoblinMailTrackCache> logisticsCache(@RequestParam("orderId") String orderId,
@RequestParam("mailId") String mailId) {
return goblinMailTrackService.adminGetTrack(orderId, mailId);
}
@ApiOperation(value = "同步物流")
@ApiImplicitParams({
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "orderId", value = "订单id"),
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mailId", value = "快递id"),
})
@GetMapping(value = "logistics/sync")
public ResponseDto<GoblinMailTrackInfoVo> logisticsSync(@RequestParam("orderId") String orderId,
@RequestParam("mailId") String mailId) {
return goblinMailTrackService.adminSyncTrack(orderId, mailId);
}
@ApiOperation(value = "重新订阅物流")
@ApiImplicitParams({
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "orderId", value = "订单id"),
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mailId", value = "快递id"),
})
@GetMapping(value = "logistics/resubscribe")
public ResponseDto<Boolean> logisticsResubscribe(@RequestParam("orderId") String orderId,
@RequestParam("mailId") String mailId) {
return goblinMailTrackService.adminResubscribe(orderId, mailId);
} }
} }
package com.liquidnet.service.goblin.express.kuaidi100;
import com.google.gson.Gson;
import com.kuaidi100.sdk.api.AutoNum;
import com.kuaidi100.sdk.api.QueryTrackMap;
import com.kuaidi100.sdk.api.SubscribeWithMap;
import com.kuaidi100.sdk.contant.ApiInfoConstant;
import com.kuaidi100.sdk.core.IBaseClient;
import com.kuaidi100.sdk.pojo.HttpResult;
import com.kuaidi100.sdk.request.*;
import com.kuaidi100.sdk.response.AutoNumResp;
import com.kuaidi100.sdk.response.QueryTrackMapResp;
import com.kuaidi100.sdk.response.SubscribeResp;
import com.kuaidi100.sdk.utils.SignUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 快递100 客户端:地图查询 / 地图订阅 / 单号识别
*/
@Slf4j
@Component
public class Kuaidi100Client {
public static final String RESULT_V2_QUERY = "5";
/** 订阅接口高级状态对应 resultv2=4(与查询侧 5 能力对齐) */
public static final String RESULT_V2_SUBSCRIBE = "4";
private final Gson gson = new Gson();
@Value("${liquidnet.express.kuaidi100.customer:}")
private String customer;
@Value("${liquidnet.express.kuaidi100.key:}")
private String key;
@Value("${liquidnet.express.kuaidi100.salt:}")
private String salt;
@Value("${liquidnet.express.kuaidi100.callbackurl:}")
private String callbackurl;
@Value("${liquidnet.express.kuaidi100.from:北京市朝阳区}")
private String defaultFrom;
public String getCallbackurl() {
return callbackurl;
}
public String getSalt() {
return salt;
}
public String getDefaultFrom() {
return defaultFrom;
}
public boolean isConfigured() {
return StringUtils.isNotBlank(customer) && StringUtils.isNotBlank(key);
}
/**
* 地图轨迹主动查询(含文字轨迹 + trailUrl)
*/
public QueryTrackMapResp queryMapTrack(String com, String num, String phone, String from, String to) throws Exception {
QueryTrackParam queryTrackParam = new QueryTrackParam();
queryTrackParam.setCom(com);
queryTrackParam.setNum(num);
queryTrackParam.setPhone(phone);
queryTrackParam.setFrom(StringUtils.isNotBlank(from) ? from : defaultFrom);
queryTrackParam.setTo(to);
queryTrackParam.setResultv2(RESULT_V2_QUERY);
queryTrackParam.setShow("0");
queryTrackParam.setOrder("desc");
String param = gson.toJson(queryTrackParam);
QueryTrackReq queryTrackReq = new QueryTrackReq();
queryTrackReq.setParam(param);
queryTrackReq.setCustomer(customer);
queryTrackReq.setSign(SignUtils.querySign(param, key, customer));
IBaseClient baseClient = new QueryTrackMap();
HttpResult result = baseClient.execute(queryTrackReq);
log.info("[kuaidi100] queryMapTrack status={}, body={}", result.getStatus(), result.getBody());
if (result.getStatus() == 200 && StringUtils.isNotBlank(result.getBody())) {
return gson.fromJson(result.getBody(), QueryTrackMapResp.class);
}
return null;
}
/**
* 地图轨迹订阅
*/
public SubscribeResp subscribeWithMap(String com, String num, String phone, String from, String to,
String callbackUrlWithParams) throws Exception {
SubscribeParameters subscribeParameters = new SubscribeParameters();
subscribeParameters.setCallbackurl(callbackUrlWithParams);
subscribeParameters.setPhone(phone);
subscribeParameters.setResultv2(RESULT_V2_SUBSCRIBE);
if (StringUtils.isNotBlank(salt)) {
subscribeParameters.setSalt(salt);
}
SubscribeParam subscribeParam = new SubscribeParam();
subscribeParam.setParameters(subscribeParameters);
subscribeParam.setCompany(com);
subscribeParam.setNumber(num);
subscribeParam.setFrom(StringUtils.isNotBlank(from) ? from : defaultFrom);
subscribeParam.setTo(to);
subscribeParam.setKey(key);
SubscribeReq subscribeReq = new SubscribeReq();
subscribeReq.setSchema(ApiInfoConstant.SUBSCRIBE_SCHEMA);
subscribeReq.setParam(gson.toJson(subscribeParam));
IBaseClient subscribe = new SubscribeWithMap();
HttpResult httpResult = subscribe.execute(subscribeReq);
log.info("[kuaidi100] subscribeWithMap status={}, body={}", httpResult.getStatus(), httpResult.getBody());
if (httpResult.getStatus() == 200 && StringUtils.isNotBlank(httpResult.getBody())) {
return gson.fromJson(httpResult.getBody(), SubscribeResp.class);
}
return null;
}
/**
* 单号识别快递公司(取置信度最高的第一个)
*/
public AutoNumResp autoComDetail(String mailNo) {
try {
AutoNumReq autoNumReq = new AutoNumReq();
autoNumReq.setKey(key);
autoNumReq.setNum(mailNo);
AutoNum autoNum = new AutoNum();
List<AutoNumResp> list = autoNum.getComByNumList(autoNumReq);
if (list != null && !list.isEmpty()) {
return list.get(0);
}
} catch (Exception e) {
log.error("[kuaidi100] autoComDetail error, mailNo={}", mailNo, e);
}
return null;
}
/**
* 单号识别快递公司编码(取置信度最高的第一个)
*/
public String autoComByNum(String mailNo) {
AutoNumResp resp = autoComDetail(mailNo);
return resp == null ? null : resp.getComCode();
}
public boolean verifyCallbackSign(String param, String sign) {
if (StringUtils.isBlank(sign)) {
return StringUtils.isBlank(salt);
}
String ourSign = SignUtils.sign(param + (salt == null ? "" : salt));
return ourSign.equalsIgnoreCase(sign);
}
}
...@@ -49,7 +49,7 @@ public class GoblinImportServiceImpl implements IGoblinImportService { ...@@ -49,7 +49,7 @@ public class GoblinImportServiceImpl implements IGoblinImportService {
if (mailNo == null || mailNo.equals("")) { if (mailNo == null || mailNo.equals("")) {
log.error("发货失败 orderId = " + orderId + "skuIds = " + skuIds + " 快递单号空"); log.error("发货失败 orderId = " + orderId + "skuIds = " + skuIds + " 快递单号空");
} }
ResponseDto<Boolean> express = iGoblinStoreOrderService.express(orderId, skuIds, mailNo, CurrentUtil.getCurrentUid(),""); ResponseDto<Boolean> express = iGoblinStoreOrderService.express(orderId, skuIds, mailNo, CurrentUtil.getCurrentUid(),"", null, null);
if (express.getCode().equals("0")) { if (express.getCode().equals("0")) {
} else { } else {
log.error("发货失败 orderId = " + orderId + "skuIds = " + skuIds + " mailNo = " + mailNo); log.error("发货失败 orderId = " + orderId + "skuIds = " + skuIds + " mailNo = " + mailNo);
......
...@@ -16,6 +16,7 @@ import com.liquidnet.service.goblin.dto.vo.*; ...@@ -16,6 +16,7 @@ import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.entity.GoblinBackOrder; import com.liquidnet.service.goblin.entity.GoblinBackOrder;
import com.liquidnet.service.goblin.entity.GoblinBackOrderLog; import com.liquidnet.service.goblin.entity.GoblinBackOrderLog;
import com.liquidnet.service.goblin.param.GoblinAppOrderRefundParam; import com.liquidnet.service.goblin.param.GoblinAppOrderRefundParam;
import com.liquidnet.service.goblin.service.IGoblinMailTrackService;
import com.liquidnet.service.goblin.service.IGoblinOrderAppService; import com.liquidnet.service.goblin.service.IGoblinOrderAppService;
import com.liquidnet.service.goblin.service.impl.helper.GoblinRefundHelper; import com.liquidnet.service.goblin.service.impl.helper.GoblinRefundHelper;
import com.liquidnet.service.goblin.util.*; import com.liquidnet.service.goblin.util.*;
...@@ -50,6 +51,8 @@ public class GoblinOrderAppServiceImpl implements IGoblinOrderAppService { ...@@ -50,6 +51,8 @@ public class GoblinOrderAppServiceImpl implements IGoblinOrderAppService {
GoblinOrderUtils orderUtils; GoblinOrderUtils orderUtils;
@Autowired @Autowired
GoblinRefundHelper refundHelper; GoblinRefundHelper refundHelper;
@Autowired
IGoblinMailTrackService goblinMailTrackService;
@Override @Override
...@@ -174,6 +177,12 @@ public class GoblinOrderAppServiceImpl implements IGoblinOrderAppService { ...@@ -174,6 +177,12 @@ public class GoblinOrderAppServiceImpl implements IGoblinOrderAppService {
for (GoblinMailVo mailVo : mailVos) { for (GoblinMailVo mailVo : mailVos) {
mailVo.setOrderSkuVos(null); mailVo.setOrderSkuVos(null);
mailVo.setOrderSkuVoIds(null); mailVo.setOrderSkuVoIds(null);
try {
GoblinMailTrackCache cache = goblinMailTrackService.resolveTrackForRead(orderId, mailVo.getMailId());
goblinMailTrackService.fillMailSummary(mailVo, cache);
} catch (Exception e) {
log.warn("[orderDetails] fill mail track fail orderId={}, mailId={}", orderId, mailVo.getMailId(), e);
}
} }
vo.setMailVos(mailVos); vo.setMailVos(mailVos);
vo.setRefuseSize(orderRefundIds.size()); vo.setRefuseSize(orderRefundIds.size());
...@@ -949,6 +958,28 @@ public class GoblinOrderAppServiceImpl implements IGoblinOrderAppService { ...@@ -949,6 +958,28 @@ public class GoblinOrderAppServiceImpl implements IGoblinOrderAppService {
return ResponseDto.success(voList); return ResponseDto.success(voList);
} }
@Override
public ResponseDto<GoblinMailTrackCache> logisticsDetail(String orderId, String mailId, String uid) {
GoblinStoreOrderVo orderVo = redisUtils.getGoblinOrder(orderId);
if (orderVo == null || (uid != null && !orderVo.getUserId().equals(uid))) {
return ResponseDto.failure(ErrorMapping.get("20003"));
}
GoblinMailTrackCache cache = goblinMailTrackService.resolveTrackForRead(orderId, mailId);
if (cache == null) {
return ResponseDto.failure("快递信息不存在");
}
return ResponseDto.success(cache);
}
@Override
public ResponseDto<List<GoblinStoreRecommendGoodsVo>> recommendStoreGoods(String orderId, String uid) {
GoblinStoreOrderVo orderVo = redisUtils.getGoblinOrder(orderId);
if (orderVo == null || (uid != null && !orderVo.getUserId().equals(uid))) {
return ResponseDto.failure(ErrorMapping.get("20003"));
}
return goblinMailTrackService.recommendStoreGoods(orderId);
}
//获取 订单剩余可支付时间[S] //获取 订单剩余可支付时间[S]
private long getRestTime(GoblinStoreOrderVo orderVo) { private long getRestTime(GoblinStoreOrderVo orderVo) {
long restTime = 0L; long restTime = 0L;
......
...@@ -414,7 +414,7 @@ public class WdtServiceImpl implements IGoblinErpService { ...@@ -414,7 +414,7 @@ public class WdtServiceImpl implements IGoblinErpService {
int recId = vo.getRec_id(); int recId = vo.getRec_id();
String code; String code;
try { try {
ResponseDto<Boolean> response = goblinStoreOrderService.express("", null, mailNo, "ERP", orderCode); ResponseDto<Boolean> response = goblinStoreOrderService.express("", null, mailNo, "ERP", orderCode, null, null);
code = response.getCode(); code = response.getCode();
log.info("response:{}",response); log.info("response:{}",response);
if (response.getMessage() != null && ("无法发货".equals(response.getMessage()) || "无法查看".equals(response.getMessage()))) { if (response.getMessage() != null && ("无法发货".equals(response.getMessage()) || "无法查看".equals(response.getMessage()))) {
......
...@@ -16,6 +16,7 @@ import com.liquidnet.service.goblin.entity.GoblinBackOrderLog; ...@@ -16,6 +16,7 @@ import com.liquidnet.service.goblin.entity.GoblinBackOrderLog;
import com.liquidnet.service.goblin.entity.GoblinOrderOperationLog; import com.liquidnet.service.goblin.entity.GoblinOrderOperationLog;
import com.liquidnet.service.goblin.param.BackCouponParam; import com.liquidnet.service.goblin.param.BackCouponParam;
import com.liquidnet.service.goblin.service.GoblinCouponService; import com.liquidnet.service.goblin.service.GoblinCouponService;
import com.liquidnet.service.goblin.service.IGoblinMailTrackService;
import com.liquidnet.service.goblin.service.manage.IGoblinStoreOrderService; import com.liquidnet.service.goblin.service.manage.IGoblinStoreOrderService;
import com.liquidnet.service.goblin.util.*; import com.liquidnet.service.goblin.util.*;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -50,6 +51,8 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService { ...@@ -50,6 +51,8 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService {
QueueUtils queueUtils; QueueUtils queueUtils;
@Autowired @Autowired
GoblinCouponService goblinCouponService; GoblinCouponService goblinCouponService;
@Autowired
IGoblinMailTrackService goblinMailTrackService;
@Value("${liquidnet.service.order.url-pay.goblinRefundUrl}") @Value("${liquidnet.service.order.url-pay.goblinRefundUrl}")
private String synUrl; private String synUrl;
@Value("${liquidnet.service.dragon.urls.refundApply}") @Value("${liquidnet.service.dragon.urls.refundApply}")
...@@ -791,7 +794,8 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService { ...@@ -791,7 +794,8 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService {
} }
@Override @Override
public ResponseDto<Boolean> express(String orderId, String orderSkuIds, String mailNo, String uid, String orderCode) { public ResponseDto<Boolean> express(String orderId, String orderSkuIds, String mailNo, String uid, String orderCode,
String logisticsCode, String logisticsCompany) {
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
String nowStr = DateUtil.getNowTime(); String nowStr = DateUtil.getNowTime();
LinkedList<String> sqls = CollectionUtil.linkedListString(); LinkedList<String> sqls = CollectionUtil.linkedListString();
...@@ -801,17 +805,13 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService { ...@@ -801,17 +805,13 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService {
sqls.add(SqlMapping.get("goblin_order.store.express")); sqls.add(SqlMapping.get("goblin_order.store.express"));
sqls.add(SqlMapping.get("goblin_order.store.orderSkuStatus")); sqls.add(SqlMapping.get("goblin_order.store.orderSkuStatus"));
sqls.add(SqlMapping.get("goblin_order.mail")); sqls.add(SqlMapping.get("goblin_order.mail"));
// GoblinStoreInfoVo storeInfoVo = redisUtils.getStoreInfoVoByUid(uid);
// if (storeInfoVo == null) {
// return ResponseDto.failure("无法查看");
// }
GoblinStoreOrderVo orderVo = null; GoblinStoreOrderVo orderVo = null;
if (null == orderCode || "".equals(orderCode)) { if (null == orderCode || "".equals(orderCode)) {
orderVo = redisUtils.getGoblinOrder(orderId); orderVo = redisUtils.getGoblinOrder(orderId);
} else { } else {
orderVo = mongoUtils.getGoblinStoreOrderVoByCode(orderCode); orderVo = mongoUtils.getGoblinStoreOrderVoByCode(orderCode);
} }
if (orderVo == null) {//|| !orderVo.getStoreId().equals(storeInfoVo.getStoreId()) if (orderVo == null) {
return ResponseDto.failure("无法查看"); return ResponseDto.failure("无法查看");
} }
orderId = orderVo.getOrderId(); orderId = orderVo.getOrderId();
...@@ -836,7 +836,8 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService { ...@@ -836,7 +836,8 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService {
mailVo.setOrderId(orderVo.getOrderId()); mailVo.setOrderId(orderVo.getOrderId());
mailVo.setMailNo(mailNo); mailVo.setMailNo(mailNo);
mailVo.setDeliveryTime(nowStr); mailVo.setDeliveryTime(nowStr);
mailVo.setLogisticsCompany("松鼠德邦"); mailVo.setLogisticsCompany(StringUtils.isNotBlank(logisticsCompany) ? logisticsCompany : "");
mailVo.setLogisticsCode(StringUtils.isNotBlank(logisticsCode) ? logisticsCode.toLowerCase() : "");
mailVo.setOrderSkuVoIds(skuIds); mailVo.setOrderSkuVoIds(skuIds);
//redis //redis
...@@ -846,7 +847,7 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService { ...@@ -846,7 +847,7 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService {
//mysql //mysql
sqlsMail.add(new Object[]{ sqlsMail.add(new Object[]{
mailVo.getMailId(), mailVo.getOrderId(), mailVo.getMailNo(), mailVo.getDeliveryTime(), mailVo.getMailId(), mailVo.getOrderId(), mailVo.getMailNo(), mailVo.getDeliveryTime(),
mailVo.getLogisticsCompany(), StringUtils.join(mailVo.getOrderSkuVoIds(), ","), now mailVo.getLogisticsCompany(), mailVo.getLogisticsCode(), StringUtils.join(mailVo.getOrderSkuVoIds(), ","), now
}); });
for (String orderSkuId : skuIds) { for (String orderSkuId : skuIds) {
...@@ -879,7 +880,7 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService { ...@@ -879,7 +880,7 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService {
GoblinOrderOperationLog log = initLog(orderId, uid, now); GoblinOrderOperationLog log = initLog(orderId, uid, now);
log.setType(GoblinStatusConst.Status.ORDER_LOG_STATUS_13.getValue()); log.setType(GoblinStatusConst.Status.ORDER_LOG_STATUS_13.getValue());
log.setRemark("发货:orderId=[" + orderId + "],orderSkuId=[" + StringUtils.join(skuIds, ",") + "],mailNo=[" + mailNo + "]"); log.setRemark("发货:orderId=[" + orderId + "],orderSkuId=[" + StringUtils.join(skuIds, ",") + "],mailNo=[" + mailNo + "],logisticsCode=[" + mailVo.getLogisticsCode() + "]");
//redis //redis
...@@ -899,11 +900,15 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService { ...@@ -899,11 +900,15 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService {
log.getOrderLogId(), log.getOrderId(), log.getType(), log.getRemark(), log.getOperationName(), now log.getOrderLogId(), log.getOrderId(), log.getType(), log.getRemark(), log.getOperationName(), now
) )
); );
// 快递100订阅
goblinMailTrackService.initAndSubscribeAsync(orderId, mailVo.getMailId(), mailVo.getMailNo(),
mailVo.getLogisticsCode(), mailVo.getLogisticsCompany());
return ResponseDto.success(); return ResponseDto.success();
} }
@Override @Override
public ResponseDto<Boolean> changeExpressMailNo(String orderId, String mailId, String mailNo) { public ResponseDto<Boolean> changeExpressMailNo(String orderId, String mailId, String mailNo,
String logisticsCode, String logisticsCompany) {
String uid = CurrentUtil.getCurrentUid(); String uid = CurrentUtil.getCurrentUid();
GoblinStoreInfoVo storeInfoVo = redisUtils.getStoreInfoVoByUid(uid); GoblinStoreInfoVo storeInfoVo = redisUtils.getStoreInfoVoByUid(uid);
if (storeInfoVo == null) { if (storeInfoVo == null) {
...@@ -917,15 +922,35 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService { ...@@ -917,15 +922,35 @@ public class GoblinStoreOrderServiceImpl implements IGoblinStoreOrderService {
vo.setMailNo(mailNo); vo.setMailNo(mailNo);
vo.setMailId(mailId); vo.setMailId(mailId);
vo.setOrderId(orderId); vo.setOrderId(orderId);
if (StringUtils.isNotBlank(logisticsCompany)) {
vo.setLogisticsCompany(logisticsCompany);
}
if (StringUtils.isNotBlank(logisticsCode)) {
vo.setLogisticsCode(logisticsCode.toLowerCase());
}
redisUtils.changeGoblinMail(orderId, vo); redisUtils.changeGoblinMail(orderId, vo);
mongoUtils.updateGoblinMailVo(mailId, vo); mongoUtils.updateGoblinMailVo(mailId, vo);
//添加日志 //添加日志
GoblinMailVo cached = null;
for (GoblinMailVo m : redisUtils.getGoblinMail(orderId)) {
if (mailId.equals(m.getMailId())) {
cached = m;
break;
}
}
queueUtils.sendMsgByRedis( queueUtils.sendMsgByRedis(
MQConst.GoblinQueue.GOBLIN_STORE_ORDER_OPERA.getKey(), MQConst.GoblinQueue.GOBLIN_STORE_ORDER_OPERA.getKey(),
SqlMapping.get("goblin_order.mail.update", SqlMapping.get("goblin_order.mail.update",
vo.getMailNo(), LocalDateTime.now(), vo.getMailId() vo.getMailNo(),
cached != null ? cached.getLogisticsCompany() : "",
cached != null ? cached.getLogisticsCode() : "",
LocalDateTime.now(), vo.getMailId()
) )
); );
if (cached != null) {
goblinMailTrackService.initAndSubscribeAsync(orderId, mailId, cached.getMailNo(),
cached.getLogisticsCode(), cached.getLogisticsCompany());
}
return ResponseDto.success(); return ResponseDto.success();
} }
......
...@@ -1543,6 +1543,12 @@ public class GoblinRedisUtils { ...@@ -1543,6 +1543,12 @@ public class GoblinRedisUtils {
for (GoblinMailVo item : list) { for (GoblinMailVo item : list) {
if (item.getMailId().equals(vo.getMailId())) { if (item.getMailId().equals(vo.getMailId())) {
item.setMailNo(vo.getMailNo()); item.setMailNo(vo.getMailNo());
if (StringUtils.hasText(vo.getLogisticsCompany())) {
item.setLogisticsCompany(vo.getLogisticsCompany());
}
if (StringUtils.hasText(vo.getLogisticsCode())) {
item.setLogisticsCode(vo.getLogisticsCode());
}
break; break;
} }
} }
...@@ -1560,6 +1566,27 @@ public class GoblinRedisUtils { ...@@ -1560,6 +1566,27 @@ public class GoblinRedisUtils {
} }
} }
/** 快递100物流缓存 TTL:40 天(秒) */
public static final long MAIL_TRACK_TTL_SECONDS = 40L * 24 * 60 * 60;
public void setMailTrackCache(String mailId, GoblinMailTrackCache cache) {
if (!StringUtils.hasText(mailId) || cache == null) {
return;
}
String redisKey = GoblinRedisConst.REDIS_GOBLIN_MAIL_TRACK.concat(mailId);
redisUtil.set(redisKey, cache, MAIL_TRACK_TTL_SECONDS);
}
public GoblinMailTrackCache getMailTrackCache(String mailId) {
if (!StringUtils.hasText(mailId)) {
return null;
}
Object obj = redisUtil.get(GoblinRedisConst.REDIS_GOBLIN_MAIL_TRACK.concat(mailId));
if (obj == null) {
return null;
}
return (GoblinMailTrackCache) obj;
}
// 获取 订单相关vo // 获取 订单相关vo
public GoblinStoreOrderVo getGoblinOrder(String orderId) { public GoblinStoreOrderVo getGoblinOrder(String orderId) {
......
...@@ -120,8 +120,8 @@ goblin_order.store.orderPush=UPDATE goblin_store_order SET status = ? ,zhengzai_ ...@@ -120,8 +120,8 @@ goblin_order.store.orderPush=UPDATE goblin_store_order SET status = ? ,zhengzai_
goblin_order.store.express=UPDATE goblin_store_order SET status = ? , updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null) goblin_order.store.express=UPDATE goblin_store_order SET status = ? , updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
goblin_order.store.expressTime=UPDATE goblin_store_order SET status = ?, delivery_time = ? , updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null) goblin_order.store.expressTime=UPDATE goblin_store_order SET status = ?, delivery_time = ? , updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
goblin_order.mail=INSERT INTO goblin_mail (`mail_id`,`order_id`,`mail_no`,`delivery_time`,`logistics_company`,`order_sku_ids`,`created_at`) VALUES (?,?,?,?,?,?,?) goblin_order.mail=INSERT INTO goblin_mail (`mail_id`,`order_id`,`mail_no`,`delivery_time`,`logistics_company`,`logistics_code`,`order_sku_ids`,`created_at`) VALUES (?,?,?,?,?,?,?,?)
goblin_order.mail.update=UPDATE goblin_mail SET mail_no = ? , updated_at = ? WHERE mail_id = ? goblin_order.mail.update=UPDATE goblin_mail SET mail_no = ? , logistics_company = ? , logistics_code = ? , updated_at = ? WHERE mail_id = ?
goblin_order.store.address=UPDATE goblin_order_attr SET express_contacts = ? ,express_address_detail = ? , express_phone = ? , updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null) goblin_order.store.address=UPDATE goblin_order_attr SET express_contacts = ? ,express_address_detail = ? , express_phone = ? , updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
goblin_order.store.orderPrice=UPDATE goblin_store_order SET price_modify = ? ,price_voucher = ? , price_actual = ? , updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null) goblin_order.store.orderPrice=UPDATE goblin_store_order SET price_modify = ? ,price_voucher = ? , price_actual = ? , updated_at = ? WHERE order_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
goblin_order.store.orderSkuPrice=UPDATE goblin_order_sku SET price_modify = ? ,price_voucher = ? , sku_price_actual = ? , updated_at = ? WHERE order_sku_id = ? and (updated_at <= ? or created_at = ? or updated_at is null) goblin_order.store.orderSkuPrice=UPDATE goblin_order_sku SET price_modify = ? ,price_voucher = ? , sku_price_actual = ? , updated_at = ? WHERE order_sku_id = ? and (updated_at <= ? or created_at = ? or updated_at is null)
......
package com.liquidnet.service.goblin.test;
import com.kuaidi100.sdk.utils.SignUtils;
import com.liquidnet.service.goblin.constant.GoblinExpressCompanyConst;
import com.liquidnet.service.goblin.dto.vo.GoblinExpressCompanyVo;
import com.liquidnet.service.goblin.express.kuaidi100.Kuaidi100Client;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.List;
/**
* 快递100相关:不依赖真实 customer/key 的纯逻辑单测。
* 真接口冒烟需配置账号后另跑联调(见类末注释)。
*/
public class Kuaidi100ClientTest {
@Test
public void verifyCallbackSign_okWhenSaltMatches() {
Kuaidi100Client client = new Kuaidi100Client();
ReflectionTestUtils.setField(client, "salt", "test-salt");
String param = "{\"status\":\"polling\",\"lastResult\":{}}";
String sign = SignUtils.sign(param + "test-salt");
Assert.assertTrue(client.verifyCallbackSign(param, sign));
}
@Test
public void verifyCallbackSign_rejectWrongSign() {
Kuaidi100Client client = new Kuaidi100Client();
ReflectionTestUtils.setField(client, "salt", "test-salt");
Assert.assertFalse(client.verifyCallbackSign("{\"a\":1}", "deadbeef"));
}
@Test
public void verifyCallbackSign_allowEmptySignWhenNoSalt() {
Kuaidi100Client client = new Kuaidi100Client();
ReflectionTestUtils.setField(client, "salt", "");
Assert.assertTrue(client.verifyCallbackSign("{\"a\":1}", null));
Assert.assertTrue(client.verifyCallbackSign("{\"a\":1}", ""));
}
@Test
public void isConfigured_requiresCustomerAndKey() {
Kuaidi100Client client = new Kuaidi100Client();
ReflectionTestUtils.setField(client, "customer", "");
ReflectionTestUtils.setField(client, "key", "k");
Assert.assertFalse(client.isConfigured());
ReflectionTestUtils.setField(client, "customer", "c");
ReflectionTestUtils.setField(client, "key", "k");
Assert.assertTrue(client.isConfigured());
}
@Test
public void commonExpressList_putsDebangSfJdFirst() {
List<GoblinExpressCompanyVo> list = GoblinExpressCompanyConst.COMMON_LIST;
Assert.assertTrue(list.size() >= 4);
Assert.assertEquals("debangkuaidi", list.get(0).getCode());
Assert.assertEquals("debangwuliu", list.get(1).getCode());
Assert.assertEquals("shunfeng", list.get(2).getCode());
Assert.assertEquals("jd", list.get(3).getCode());
}
/*
* 真接口联调(需配置 liquidnet.express.kuaidi100.customer/key,建议本地手动跑):
*
* 1) AutoNum:client.autoComDetail("运单号")
* 2) QueryTrackMap:client.queryMapTrack(com, num, phone后四位, from, to)
* 3) SubscribeWithMap:需公网 callbackurl,否则推送收不到
*
* 顺丰/京东等强校验手机号,phone 必传。
*/
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment