From 7a1d5d0a34868cabee047b5c0fc1839348dd0db9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E5=AE=87=E5=A5=87?= Date: Thu, 17 Apr 2025 18:02:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=AE=A2=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ler.java => AlipayCallbackController.java} | 4 +- .../xkt/ExpressCallbackController.java | 53 ++++++ .../xkt/vo/express/ZtoPrintOrderReqVO.java | 27 +++ .../xkt/vo/express/ZtoPrintOrderRespVO.java | 46 +++++ .../src/main/resources/application.yml | 8 + .../framework/config/SecurityConfig.java | 4 +- .../com/ruoyi/xkt/enums/EExpressChannel.java | 4 +- .../manager/impl/YtoExpressManagerImpl.java | 132 +++++++++++++ .../manager/impl/ZtoExpressManagerImpl.java | 47 +++-- .../thirdpart/yto/YtoCreateOrderParam.java | 179 ++++++++++++++++++ .../xkt/thirdpart/yto/YtoPrintOrderParam.java | 25 +++ .../xkt/thirdpart/yto/YtoPublicRequest.java | 39 ++++ .../ruoyi/xkt/thirdpart/yto/YtoSignUtil.java | 31 +++ ...erReqDTO.java => ZtoCreateOrderParam.java} | 2 +- ...derReqDTO.java => ZtoPrintOrderParam.java} | 2 +- 15 files changed, 582 insertions(+), 21 deletions(-) rename ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/{AlipayController.java => AlipayCallbackController.java} (98%) create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/ExpressCallbackController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/express/ZtoPrintOrderReqVO.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/express/ZtoPrintOrderRespVO.java create mode 100644 xkt/src/main/java/com/ruoyi/xkt/manager/impl/YtoExpressManagerImpl.java create mode 100644 xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoCreateOrderParam.java create mode 100644 xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoPrintOrderParam.java create mode 100644 xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoPublicRequest.java create mode 100644 xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoSignUtil.java rename xkt/src/main/java/com/ruoyi/xkt/thirdpart/zto/{ZtoCreateOrderReqDTO.java => ZtoCreateOrderParam.java} (99%) rename xkt/src/main/java/com/ruoyi/xkt/thirdpart/zto/{ZtoPrintOrderReqDTO.java => ZtoPrintOrderParam.java} (93%) diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AlipayController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AlipayCallbackController.java similarity index 98% rename from ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AlipayController.java rename to ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AlipayCallbackController.java index 8df4ce822..909de9e42 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AlipayController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AlipayCallbackController.java @@ -29,8 +29,8 @@ import java.util.Map; */ @Api(tags = "支付宝回调接口") @RestController -@RequestMapping("/rest/v1/alipay") -public class AlipayController extends XktBaseController { +@RequestMapping("/rest/v1/alipay-callback") +public class AlipayCallbackController extends XktBaseController { private static final String SUCCESS = "success"; private static final String FAILURE = "failure"; diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/ExpressCallbackController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/ExpressCallbackController.java new file mode 100644 index 000000000..6fba0dae2 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/ExpressCallbackController.java @@ -0,0 +1,53 @@ +package com.ruoyi.web.controller.xkt; + +import cn.hutool.core.util.StrUtil; +import com.ruoyi.common.core.controller.XktBaseController; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.web.controller.xkt.vo.express.ZtoPrintOrderReqVO; +import com.ruoyi.web.controller.xkt.vo.express.ZtoPrintOrderRespVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.concurrent.TimeUnit; + +/** + * @author liangyq + * @date 2025-04-17 14:18 + */ +@Api(tags = "物流回调接口") +@RestController +@RequestMapping("/rest/v1/express-callback") +public class ExpressCallbackController extends XktBaseController { + + @Autowired + private RedisCache redisCache; + + /** + * 中通-生成面单图片/PDF回推 + *

+ * 采用http协议,字符集编码为UTF-8,ContentType:"application/json",请求方式:POST + * 开放平台会根据三方返回的status字段判断此次推送是否成功 + * 若三方返回false,或触达出现异常,开放平台侧会进行推送重试,重试最大次数为16次 + * + * @param vo + * @return + */ + @ApiOperation("中通-生成面单图片/PDF回推") + @PostMapping("zto/print-order") + public ZtoPrintOrderRespVO ztoPrintOrder(@RequestBody ZtoPrintOrderReqVO vo) { + if (StrUtil.isNotEmpty(vo.getBillCode()) + && StrUtil.isNotEmpty(vo.getResult())) { + //缓存30分钟 + redisCache.setCacheObject("ZTO-"+vo.getBillCode(),vo.getResult(),30, TimeUnit.MINUTES); + return ZtoPrintOrderRespVO.success(); + } + return ZtoPrintOrderRespVO.failure(); + } + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/express/ZtoPrintOrderReqVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/express/ZtoPrintOrderReqVO.java new file mode 100644 index 000000000..a90466517 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/express/ZtoPrintOrderReqVO.java @@ -0,0 +1,27 @@ +package com.ruoyi.web.controller.xkt.vo.express; + +import lombok.Data; + +/** + * @author liangyq + * @date 2025-04-17 16:40 + */ +@Data +public class ZtoPrintOrderReqVO { + /** + * 运单号 + */ + private String billCode; + /** + * 打印类型(0:JPG, 1:PDF.默认为PDF) + */ + private String printType; + /** + * 图片或PDF的Base64编码 + */ + private String result; + /** + * 消息签名dataDigest=base64(md5(result+billCode)) + */ + private String dataDigest; +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/express/ZtoPrintOrderRespVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/express/ZtoPrintOrderRespVO.java new file mode 100644 index 000000000..a4e32b195 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/express/ZtoPrintOrderRespVO.java @@ -0,0 +1,46 @@ +package com.ruoyi.web.controller.xkt.vo.express; + +import lombok.Data; + +/** + * @author liangyq + * @date 2025-04-17 16:34 + */ +@Data +public class ZtoPrintOrderRespVO { + /** + * 默认false,中通根据status=true来判断是否推送成功 + */ + private Boolean status; + /** + * 响应说明 + */ + private String message; + /** + * 响应结果 + */ + private String result; + /** + * 响应状态码 + */ + private String statusCode; + + public static ZtoPrintOrderRespVO success() { + ZtoPrintOrderRespVO vo = new ZtoPrintOrderRespVO(); + vo.setStatus(true); + vo.setMessage("success"); + vo.setResult("success"); + vo.setStatusCode("0"); + return vo; + } + + public static ZtoPrintOrderRespVO failure() { + ZtoPrintOrderRespVO vo = new ZtoPrintOrderRespVO(); + vo.setStatus(false); + vo.setMessage("failure"); + vo.setResult("failure"); + vo.setStatusCode("0"); + return vo; + } + +} diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index b8f61328e..cddac173d 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -178,6 +178,14 @@ zto: accountId: test accountPassword: ZTO123 +# 圆通配置 +yto: + appKey: K9991024989 + appSecret: u2Z1F7Fh + appKey2: TEST + appSecret2: 123456 + gatewayUrl: https://openuat.yto56test.com:6443/ + # 支付宝配置 alipay: appId: 9021000144616672 diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java index fca5d57b1..efca121e1 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java @@ -116,7 +116,9 @@ public class SecurityConfig .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll() .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() //支付宝回调 - .antMatchers("/rest/v1/alipay-notify").permitAll() + .antMatchers("/rest/v1/alipay-callback/**").permitAll() + //物流回调 + .antMatchers("/rest/v1/express-callback/**").permitAll() // 除上面外的所有请求全部需要鉴权认证 .anyRequest().authenticated(); }) diff --git a/xkt/src/main/java/com/ruoyi/xkt/enums/EExpressChannel.java b/xkt/src/main/java/com/ruoyi/xkt/enums/EExpressChannel.java index f5c64a89f..126fb58f8 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/enums/EExpressChannel.java +++ b/xkt/src/main/java/com/ruoyi/xkt/enums/EExpressChannel.java @@ -11,7 +11,9 @@ import lombok.Getter; @AllArgsConstructor public enum EExpressChannel { - ZTO(1, "中通", 1L, "ZTO"); + ZTO(1, "中通", 1L, "ZTO"), + YTO(2, "圆通", 2L, "YTO"), + ; private final Integer value; private final String label; diff --git a/xkt/src/main/java/com/ruoyi/xkt/manager/impl/YtoExpressManagerImpl.java b/xkt/src/main/java/com/ruoyi/xkt/manager/impl/YtoExpressManagerImpl.java new file mode 100644 index 000000000..d48120183 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/manager/impl/YtoExpressManagerImpl.java @@ -0,0 +1,132 @@ +package com.ruoyi.xkt.manager.impl; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.xkt.dto.express.ExpressShipReqDTO; +import com.ruoyi.xkt.enums.EExpressChannel; +import com.ruoyi.xkt.manager.ExpressManager; +import com.ruoyi.xkt.thirdpart.yto.YtoCreateOrderParam; +import com.ruoyi.xkt.thirdpart.yto.YtoPrintOrderParam; +import com.ruoyi.xkt.thirdpart.yto.YtoPublicRequest; +import com.ruoyi.xkt.thirdpart.yto.YtoSignUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; + +/** + * @author liangyq + * @date 2025-04-17 16:55 + */ +@Slf4j +@Component +public class YtoExpressManagerImpl implements ExpressManager { + + @Value("${yto.appKey:}") + private String appKey; + + @Value("${yto.appSecret:}") + private String appSecret; + + @Value("${yto.appKey2:}") + private String appKey2; + + @Value("${yto.appSecret2:}") + private String appSecret2; + + @Value("${yto.gatewayUrl:}") + private String gatewayUrl; + + @Override + public EExpressChannel channel() { + return EExpressChannel.YTO; + } + + @Override + public String shipStoreOrder(ExpressShipReqDTO shipReqDTO) { + YtoCreateOrderParam createOrderParam = trans2CreateOrderReq(shipReqDTO); + try { + String param = JSONUtil.toJsonStr(createOrderParam); + String sign = YtoSignUtil.sign("privacy_create_adapter", "v1", param, appSecret); + YtoPublicRequest request = YtoPublicRequest.builder() + .timestamp(System.currentTimeMillis()) + .param(param) + .format(YtoPublicRequest.EFormat.JSON) + .sign(sign).build(); + String rtnStr = HttpUtil.post(gatewayUrl + "open/privacy_create_adapter/v1/N364gM/" + appKey, + JSONUtil.toJsonStr(request)); + log.info("圆通订单创建返回信息: {}", rtnStr); + JSONObject rtnJson = JSONUtil.parseObj(rtnStr); + String waybillNo = rtnJson.getStr("mailNo"); + if (StrUtil.isNotEmpty(waybillNo)) { + return waybillNo; + } + } catch (Exception e) { + log.error("圆通订单创建异常", e); + } + throw new ServiceException("圆通订单创建失败"); + } + + @Override + public String printOrder(String waybillNo) { + YtoPrintOrderParam printOrderParam = YtoPrintOrderParam.builder().waybillNo(waybillNo).build(); + try { + String param = JSONUtil.toJsonStr(printOrderParam); + String sign = YtoSignUtil.sign("waybill_print_adapter", "v1", param, appSecret); + YtoPublicRequest request = YtoPublicRequest.builder() + .timestamp(System.currentTimeMillis()) + .param(param) + .format(YtoPublicRequest.EFormat.JSON) + .sign(sign).build(); + String rtnStr = HttpUtil.post(gatewayUrl + "open/waybill_print_adapter/v1/N364gM/" + appKey, + JSONUtil.toJsonStr(request)); + log.info("圆通打印回单返回信息: {}", rtnStr); + JSONObject rtnJson = JSONUtil.parseObj(rtnStr); + String rtn = rtnJson.getJSONObject("data").getStr("pdfBase64"); + if (StrUtil.isNotEmpty(rtn)) { + return rtn; + } + } catch (Exception e) { + log.error("圆通打印回单异常", e); + } + throw new ServiceException("圆通打印回单失败"); + } + + + private YtoCreateOrderParam trans2CreateOrderReq(ExpressShipReqDTO shipReqDTO) { + YtoCreateOrderParam reqDTO = new YtoCreateOrderParam(); + reqDTO.setLogisticsNo(shipReqDTO.getExpressReqNo()); + + reqDTO.setSenderName(shipReqDTO.getOriginContactName()); + reqDTO.setSenderProvinceName(shipReqDTO.getOriginProvinceName()); + reqDTO.setSenderCityName(shipReqDTO.getOriginCityName()); + reqDTO.setSenderCountyName(shipReqDTO.getOriginCountyName()); + reqDTO.setSenderAddress(shipReqDTO.getOriginDetailAddress()); + reqDTO.setSenderMobile(shipReqDTO.getOriginContactPhoneNumber()); + + reqDTO.setRecipientName(shipReqDTO.getDestinationContactName()); + reqDTO.setRecipientProvinceName(shipReqDTO.getDestinationProvinceName()); + reqDTO.setRecipientCityName(shipReqDTO.getDestinationCityName()); + reqDTO.setRecipientCountyName(shipReqDTO.getDestinationCountyName()); + reqDTO.setRecipientAddress(shipReqDTO.getDestinationDetailAddress()); + reqDTO.setRecipientMobile(shipReqDTO.getDestinationContactPhoneNumber()); + + int goodsSize = shipReqDTO.getOrderItems().size(); + if (shipReqDTO.getOrderItems().size() > 20) { + throw new ServiceException("圆通每次发货物品在20个以内!"); + } + reqDTO.setGoods(new ArrayList<>(goodsSize)); + for (ExpressShipReqDTO.OrderItem item : shipReqDTO.getOrderItems()) { + YtoCreateOrderParam.OrderGoods goods = new YtoCreateOrderParam.OrderGoods(); + reqDTO.getGoods().add(goods); + goods.setName(item.getName()); + goods.setQuantity(item.getQuantity()); + } + return reqDTO; + } + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/manager/impl/ZtoExpressManagerImpl.java b/xkt/src/main/java/com/ruoyi/xkt/manager/impl/ZtoExpressManagerImpl.java index ef0beb0a2..85feccb8d 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/manager/impl/ZtoExpressManagerImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/manager/impl/ZtoExpressManagerImpl.java @@ -2,24 +2,30 @@ package com.ruoyi.xkt.manager.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; +import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.xkt.dto.express.ExpressShipReqDTO; import com.ruoyi.xkt.enums.EExpressChannel; import com.ruoyi.xkt.manager.ExpressManager; import com.ruoyi.xkt.thirdpart.zto.*; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import java.util.concurrent.TimeUnit; + /** * @author liangyq * @date 2025-04-15 15:45 */ @Slf4j @Component -public class ZtoExpressManagerImpl implements ExpressManager { +public class ZtoExpressManagerImpl implements ExpressManager, InitializingBean { private static final String CREATE_ORDER_URI = "zto.open.createOrder"; @@ -42,19 +48,23 @@ public class ZtoExpressManagerImpl implements ExpressManager { @Value("${zto.accountPassword:}") private String accountPassword; + @Autowired + private RedisCache redisCache; + + private ZopClient client; + @Override public EExpressChannel channel() { - return EExpressChannel.ZTO; + return EExpressChannel.YTO; } @Override public String shipStoreOrder(ExpressShipReqDTO shipReqDTO) { Assert.notNull(shipReqDTO); Assert.notEmpty(shipReqDTO.getExpressReqNo()); - ZtoCreateOrderReqDTO createOrderReq = trans2CreateOrderReq(shipReqDTO); - ZopClient client = new ZopClient(appKey, appSecret); + ZtoCreateOrderParam createOrderParam = trans2CreateOrderReq(shipReqDTO); ZopPublicRequest request = new ZopPublicRequest(); - request.setBody(JSONUtil.toJsonStr(createOrderReq)); + request.setBody(JSONUtil.toJsonStr(createOrderParam)); request.setUrl(gatewayUrl + CREATE_ORDER_URI); request.setEncryptionType(EncryptionType.MD5); try { @@ -75,9 +85,8 @@ public class ZtoExpressManagerImpl implements ExpressManager { @Override public String printOrder(String waybillNo) { Assert.notEmpty(waybillNo); - ZopClient client = new ZopClient(appKey, appSecret); ZopPublicRequest request = new ZopPublicRequest(); - request.setBody(JSONUtil.toJsonStr(new ZtoPrintOrderReqDTO(1,waybillNo,true))); + request.setBody(JSONUtil.toJsonStr(new ZtoPrintOrderParam(1, waybillNo, true))); request.setUrl(gatewayUrl + ORDER_PRINT_URI); request.setEncryptionType(EncryptionType.MD5); try { @@ -87,7 +96,12 @@ public class ZtoExpressManagerImpl implements ExpressManager { boolean success = bodyJson.getBool("status"); if (success) { //TODO 测试环境接口不通 - return bodyJson.getJSONObject("result").getStr("billCode"); + //等待推送 + TimeUnit.SECONDS.sleep(3); + String rtn = redisCache.getCacheObject("ZTO_" + waybillNo); + if (StrUtil.isNotEmpty(rtn)) { + return rtn; + } } } catch (Exception e) { log.error("中通订单打印异常", e); @@ -102,7 +116,6 @@ public class ZtoExpressManagerImpl implements ExpressManager { * @return */ public JSONObject structureNamePhoneAddress(String str) { - ZopClient client = new ZopClient(appKey, appSecret); ZopPublicRequest request = new ZopPublicRequest(); JSONObject body = new JSONObject(); body.set("address", str); @@ -123,8 +136,8 @@ public class ZtoExpressManagerImpl implements ExpressManager { throw new ServiceException("中通智能解析失败"); } - private ZtoCreateOrderReqDTO trans2CreateOrderReq(ExpressShipReqDTO expressShipReqDTO) { - ZtoCreateOrderReqDTO reqDTO = new ZtoCreateOrderReqDTO(); + private ZtoCreateOrderParam trans2CreateOrderReq(ExpressShipReqDTO expressShipReqDTO) { + ZtoCreateOrderParam reqDTO = new ZtoCreateOrderParam(); //合作模式 ,1:集团客户;2:非集团客户 reqDTO.setPartnerType("2"); //partnerType为1时,orderType:1:全网件 2:预约件。 partnerType为2时,orderType:1:全网件 2:预约件(返回运单号) 3:预约件(不返回运单号) 4:星联全网件 @@ -133,7 +146,7 @@ public class ZtoExpressManagerImpl implements ExpressManager { reqDTO.setPartnerOrderCode(expressShipReqDTO.getExpressReqNo()); //账号信息 - ZtoCreateOrderReqDTO.AccountInfo accountInfo = new ZtoCreateOrderReqDTO.AccountInfo(); + ZtoCreateOrderParam.AccountInfo accountInfo = new ZtoCreateOrderParam.AccountInfo(); reqDTO.setAccountInfo(accountInfo); //电子面单账号(partnerType为2,orderType传1,2,4时必传) accountInfo.setAccountId(accountId); @@ -145,7 +158,7 @@ public class ZtoExpressManagerImpl implements ExpressManager { accountInfo.setCustomerId(null); //发件人信息 - ZtoCreateOrderReqDTO.SenderInfo senderInfo = new ZtoCreateOrderReqDTO.SenderInfo(); + ZtoCreateOrderParam.SenderInfo senderInfo = new ZtoCreateOrderParam.SenderInfo(); reqDTO.setSenderInfo(senderInfo); senderInfo.setSenderName(expressShipReqDTO.getOriginCountyName()); senderInfo.setSenderPhone(expressShipReqDTO.getOriginContactPhoneNumber()); @@ -155,7 +168,7 @@ public class ZtoExpressManagerImpl implements ExpressManager { senderInfo.setSenderAddress(expressShipReqDTO.getOriginDetailAddress()); //收件人信息 - ZtoCreateOrderReqDTO.ReceiveInfo receiveInfo = new ZtoCreateOrderReqDTO.ReceiveInfo(); + ZtoCreateOrderParam.ReceiveInfo receiveInfo = new ZtoCreateOrderParam.ReceiveInfo(); reqDTO.setReceiveInfo(receiveInfo); receiveInfo.setReceiverName(expressShipReqDTO.getDestinationContactName()); receiveInfo.setReceiverPhone(expressShipReqDTO.getDestinationContactPhoneNumber()); @@ -166,10 +179,14 @@ public class ZtoExpressManagerImpl implements ExpressManager { //货物信息 reqDTO.setOrderItems(BeanUtil.copyToList(expressShipReqDTO.getOrderItems(), - ZtoCreateOrderReqDTO.OrderItem.class)); + ZtoCreateOrderParam.OrderItem.class)); return reqDTO; } + @Override + public void afterPropertiesSet() throws Exception { + this.client = new ZopClient(appKey, appSecret); + } } diff --git a/xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoCreateOrderParam.java b/xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoCreateOrderParam.java new file mode 100644 index 000000000..1dc62c076 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoCreateOrderParam.java @@ -0,0 +1,179 @@ +package com.ruoyi.xkt.thirdpart.yto; + +import lombok.Data; + +import java.util.List; + +/** + * @author liangyq + * @date 2025-04-15 19:20 + */ +@Data +public class YtoCreateOrderParam { + /** + * 物流单号,打印拉取运单号前,物流单号和渠道唯一确定一笔快递物流订单。注:最低长度为7 + */ + private String logisticsNo; + /** + * 寄件人姓名 + */ + private String senderName; + /** + * 寄件人省名称 + */ + private String senderProvinceName; + /** + * 寄件人市名称 + */ + private String senderCityName; + /** + * 寄件人区县名称 + */ + private String senderCountyName; + /** + * 寄件人乡镇名称 + */ + private String senderTownName; + /** + * 寄件人详细地址 + */ + private String senderAddress; + /** + * 寄件人联系电话 + */ + private String senderMobile; + /** + * 收件人姓名 + */ + private String recipientName; + /** + * 收件人省名称 + */ + private String recipientProvinceName; + /** + * 收件人市名称 + */ + private String recipientCityName; + /** + * 收件人区县名称 + */ + private String recipientCountyName; + /** + * 收件人乡镇名称 + */ + private String recipientTownName; + /** + * 收件人详细地址 + */ + private String recipientAddress; + /** + * 收件人联系电话 + */ + private String recipientMobile; + /** + * 备注,打印在面单上的备注内容 + */ + private String remark; + /** + * 寄件码或取件码 + */ + private String gotCode; + /** + * 增值服务列表 + */ + private List increments; + /** + * 物品列表,注:支持20个以内 + */ + private List goods; + /** + * 预约上门取件开始时间,”yyyy-MM-dd HH:mm:ss”格式化,注:预约取件时间规则为下单当天的00:00:00至下单当天+6天的23:59:59。 + */ + private String startTime; + /** + * 预约上门取件结束时间,”yyyy-MM-dd HH:mm:ss”格式化,注:预约取件时间规则为下单当天的00:00:00至下单当天+6天的23:59:59。 + */ + private String endTime; + /** + * 客户业务类型,可以对客户订单进行业务或渠道区分。 + */ + private String cstBusinessType; + /** + * 客户的订单号 + */ + private String cstOrderNo; + /** + * 实名信息 + */ + private String realNameInfo; + /** + * 下单总重量,单位:千克,小数后三位 + */ + private String weight; + /** + * 产品编号:YZD-圆准达;XTCTK-同城特快;HKJ-航空件;PK-普快,默认PK + */ + private String productCode; + + @Data + public static class OrderIncrement { + /** + * 增值类型:1-代收货款;2-到付;4-保价,注:增值服务不能同时选择代收和到付。 + */ + private Integer type; + /** + * 金额,单位:元,代收货款金额:[3,20000];到付金额:[1,5000];保价金额:[100,30000]。 + */ + private String amount; + } + + @Data + public static class OrderGoods { + /** + * 物品名称 + */ + private String name; + /** + * 重量,单位:千克 + */ + private String weight; + /** + * 长,单位:米 + */ + private String length; + /** + * 宽,单位:米 + */ + private String width; + /** + * 高,单位:米 + */ + private String height; + /** + * 单价,单位:元 + */ + private String price; + /** + * 数量 + */ + private Integer quantity; + } + + @Data + public static class RealNameInfo { + /** + * 姓名 + */ + private String name; + /** + * 证件号 + */ + private String cerNum; + /** + * 证件类型: 11:居民身份证;12:临时居民身份证;13:户口簿;14:中国人民解放军军人身份证件;15:中国人民武装警察身份证件;16:港澳居民来往内地通行证;17:台湾居民通往大陆通行证;18:外国公民护照;19:中国公民护照;20:港澳台居民居住证;101:机构代码;102:税务登记号:103:统一社会信用代码 + */ + private String cerType; + } + + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoPrintOrderParam.java b/xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoPrintOrderParam.java new file mode 100644 index 000000000..62c2a9d82 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoPrintOrderParam.java @@ -0,0 +1,25 @@ +package com.ruoyi.xkt.thirdpart.yto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author liangyq + * @date 2025-04-15 19:20 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class YtoPrintOrderParam { + /** + * 圆通运单号 + */ + private String waybillNo; + /** + * 备注,最多130个字符 + */ + private String remark; +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoPublicRequest.java b/xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoPublicRequest.java new file mode 100644 index 000000000..5bbc850d8 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoPublicRequest.java @@ -0,0 +1,39 @@ +package com.ruoyi.xkt.thirdpart.yto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author liangyq + * @date 2025-03-14 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class YtoPublicRequest { + /** + * 签名 + */ + private String sign; + /** + * 时间戳 + */ + private Long timestamp; + /** + * 传递的参数 + */ + private String param; + /** + * param格式 + */ + private EFormat format; + + public enum EFormat { + JSON, + XML + } + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoSignUtil.java b/xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoSignUtil.java new file mode 100644 index 000000000..f4c33b095 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/thirdpart/yto/YtoSignUtil.java @@ -0,0 +1,31 @@ +package com.ruoyi.xkt.thirdpart.yto; + +import cn.hutool.core.codec.Base64; +import cn.hutool.crypto.digest.DigestUtil; + +/** + * @author liangyq + * @date 2025-03-14 + */ +public class YtoSignUtil { + /** + * 序号 步骤 + * 1 在POST时用“sign”字段进行签名验证。 + * 2 将 param+method(方法)+v(版本) 拼接得到 data,将 data和 客户密钥 拼接。(通过 控制台——接口管理,添加自己所需接口,即可得到相应的测试地址、客户编码、客户密钥、方法和版本) + * 3 假设data内容为: opentest, partnerId(客户密钥)为123456。 则要签名的内容为opentest123456,然后对opentest123456先进行MD5加密,然后转换为base64字符串。 即经过md5(16位byte)和base64后的内容就为 YLstCNa3x8ijQx16e/jqOA== + * + * @return + */ + public static String sign(String method, String version, String param, String secret) { + String data = param + method + version; + return sign(data, secret); + } + + + public static String sign(String data, String secret) { + //进行md5加密,然后对数组进行base64编码 + byte[] bytes = DigestUtil.md5(data + secret); + return Base64.encodeStr(bytes, false, false); + } + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/thirdpart/zto/ZtoCreateOrderReqDTO.java b/xkt/src/main/java/com/ruoyi/xkt/thirdpart/zto/ZtoCreateOrderParam.java similarity index 99% rename from xkt/src/main/java/com/ruoyi/xkt/thirdpart/zto/ZtoCreateOrderReqDTO.java rename to xkt/src/main/java/com/ruoyi/xkt/thirdpart/zto/ZtoCreateOrderParam.java index 1052bedfc..739219d93 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/thirdpart/zto/ZtoCreateOrderReqDTO.java +++ b/xkt/src/main/java/com/ruoyi/xkt/thirdpart/zto/ZtoCreateOrderParam.java @@ -11,7 +11,7 @@ import java.util.List; * @date 2025-04-15 19:20 */ @Data -public class ZtoCreateOrderReqDTO { +public class ZtoCreateOrderParam { /** * 合作模式 ,1:集团客户;2:非集团客户 */ diff --git a/xkt/src/main/java/com/ruoyi/xkt/thirdpart/zto/ZtoPrintOrderReqDTO.java b/xkt/src/main/java/com/ruoyi/xkt/thirdpart/zto/ZtoPrintOrderParam.java similarity index 93% rename from xkt/src/main/java/com/ruoyi/xkt/thirdpart/zto/ZtoPrintOrderReqDTO.java rename to xkt/src/main/java/com/ruoyi/xkt/thirdpart/zto/ZtoPrintOrderParam.java index 08025e69f..b87019692 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/thirdpart/zto/ZtoPrintOrderReqDTO.java +++ b/xkt/src/main/java/com/ruoyi/xkt/thirdpart/zto/ZtoPrintOrderParam.java @@ -11,7 +11,7 @@ import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor -public class ZtoPrintOrderReqDTO { +public class ZtoPrintOrderParam { /** * 打印类型(0:JPG, 1:PDF.默认为PDF) */