From 06fb54c65c968fbb7a07bd1ca0592a5ce5ddb64d Mon Sep 17 00:00:00 2001 From: chc <1501738723@qq.com> Date: Wed, 8 Mar 2023 10:32:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=9B=86=E6=88=90=E9=A1=BA=E4=B8=B0?= =?UTF-8?q?=E5=BC=80=E6=94=BE=E5=B9=B3=E5=8F=B0=E5=8A=9F=E8=83=BD,?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=95=86=E5=AE=B6=E5=BF=98=E8=AE=B0=E5=AF=86?= =?UTF-8?q?=E7=A0=81,=E6=89=8B=E6=9C=BA=E5=8F=B7=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- framework/pom.xml | 7 + .../java/cn/lili/common/enums/ResultCode.java | 1 + .../modules/logistics/LogisticsPlugin.java | 7 +- .../logistics/LogisticsPluginFactory.java | 3 + .../logistics/entity/enums/LogisticsEnum.java | 2 +- .../logistics/plugin/kdniao/KdniaoPlugin.java | 16 +- .../plugin/kuaidi100/Kuaidi100Plugin.java | 9 +- .../plugin/shunfeng/ShunfengPlugin.java | 243 ++++++++++++++++++ .../modules/member/service/MemberService.java | 8 + .../member/serviceimpl/MemberServiceImpl.java | 17 +- .../order/order/service/OrderService.java | 8 + .../order/serviceimpl/OrderServiceImpl.java | 12 + .../system/entity/dto/LogisticsSetting.java | 28 ++ .../system/service/LogisticsService.java | 34 ++- .../serviceimpl/LogisticsServiceImpl.java | 44 +++- .../SF-CSIM-EXPRESS-SDK-V2.1.7.jar | Bin 0 -> 23371 bytes .../order/OrderStoreController.java | 10 +- .../other/LogisticsStoreController.java | 25 ++ .../passport/StorePassportController.java | 50 +++- 19 files changed, 503 insertions(+), 21 deletions(-) create mode 100644 framework/src/main/java/cn/lili/modules/logistics/plugin/shunfeng/ShunfengPlugin.java create mode 100644 framework/src/main/resources/maven-repository/SF-CSIM-EXPRESS-SDK-V2.1.7.jar diff --git a/framework/pom.xml b/framework/pom.xml index 9f127491..3003fb45 100644 --- a/framework/pom.xml +++ b/framework/pom.xml @@ -457,6 +457,13 @@ sdk ${kuaidi100-api.version} + + com.qiyuesuo.sdk + SDK + 2.1.7 + system + ${project.basedir}/src/main/resources/maven-repository/SF-CSIM-EXPRESS-SDK-V2.1.7.jar + diff --git a/framework/src/main/java/cn/lili/common/enums/ResultCode.java b/framework/src/main/java/cn/lili/common/enums/ResultCode.java index 635a0370..a81b4987 100644 --- a/framework/src/main/java/cn/lili/common/enums/ResultCode.java +++ b/framework/src/main/java/cn/lili/common/enums/ResultCode.java @@ -416,6 +416,7 @@ public enum ResultCode { STORE_DELIVER_GOODS_ADDRESS(50007,"请填写商家发货地址"), FREIGHT_TEMPLATE_NOT_EXIST(50010, "当前模版不存在"), STORE_STATUS_ERROR(50011, "店铺状态异常,无法申请"), + STORE_DELIVER_ADDRESS_EXIST(50012,"请填写发货地址"), /** * 结算单 diff --git a/framework/src/main/java/cn/lili/modules/logistics/LogisticsPlugin.java b/framework/src/main/java/cn/lili/modules/logistics/LogisticsPlugin.java index d77bc8f9..5a0ab4e7 100644 --- a/framework/src/main/java/cn/lili/modules/logistics/LogisticsPlugin.java +++ b/framework/src/main/java/cn/lili/modules/logistics/LogisticsPlugin.java @@ -2,9 +2,12 @@ package cn.lili.modules.logistics; import cn.lili.modules.logistics.entity.dto.LabelOrderDTO; import cn.lili.modules.logistics.entity.enums.LogisticsEnum; +import cn.lili.modules.order.order.entity.vo.OrderDetailVO; import cn.lili.modules.system.entity.dos.Logistics; import cn.lili.modules.system.entity.vo.Traces; +import java.util.Map; + /** * 物流插件接口 * @@ -48,6 +51,8 @@ public interface LogisticsPlugin { * @param labelOrderDTO 电子面单DTO * @return */ - String labelOrder(LabelOrderDTO labelOrderDTO); + Map labelOrder(LabelOrderDTO labelOrderDTO); + + String createOrder(OrderDetailVO orderDetailVO); } diff --git a/framework/src/main/java/cn/lili/modules/logistics/LogisticsPluginFactory.java b/framework/src/main/java/cn/lili/modules/logistics/LogisticsPluginFactory.java index b40c4ebb..4ecc4bfe 100644 --- a/framework/src/main/java/cn/lili/modules/logistics/LogisticsPluginFactory.java +++ b/framework/src/main/java/cn/lili/modules/logistics/LogisticsPluginFactory.java @@ -5,6 +5,7 @@ import cn.lili.common.exception.ServiceException; import cn.lili.modules.logistics.entity.enums.LogisticsEnum; import cn.lili.modules.logistics.plugin.kdniao.KdniaoPlugin; import cn.lili.modules.logistics.plugin.kuaidi100.Kuaidi100Plugin; +import cn.lili.modules.logistics.plugin.shunfeng.ShunfengPlugin; import cn.lili.modules.system.entity.dos.Setting; import cn.lili.modules.system.entity.dto.LogisticsSetting; import cn.lili.modules.system.entity.enums.SettingEnum; @@ -44,6 +45,8 @@ public class LogisticsPluginFactory { return new KdniaoPlugin(logisticsSetting); case KUAIDI100: return new Kuaidi100Plugin(logisticsSetting); + case SHUNFENG: + return new ShunfengPlugin(logisticsSetting); default: throw new ServiceException(); } diff --git a/framework/src/main/java/cn/lili/modules/logistics/entity/enums/LogisticsEnum.java b/framework/src/main/java/cn/lili/modules/logistics/entity/enums/LogisticsEnum.java index 2783c27e..20c9bba8 100644 --- a/framework/src/main/java/cn/lili/modules/logistics/entity/enums/LogisticsEnum.java +++ b/framework/src/main/java/cn/lili/modules/logistics/entity/enums/LogisticsEnum.java @@ -11,5 +11,5 @@ public enum LogisticsEnum { /** * 快递查询渠道 */ - KDNIAO, KUAIDI100; + KDNIAO, KUAIDI100,SHUNFENG; } diff --git a/framework/src/main/java/cn/lili/modules/logistics/plugin/kdniao/KdniaoPlugin.java b/framework/src/main/java/cn/lili/modules/logistics/plugin/kdniao/KdniaoPlugin.java index a2f13e75..4b567388 100644 --- a/framework/src/main/java/cn/lili/modules/logistics/plugin/kdniao/KdniaoPlugin.java +++ b/framework/src/main/java/cn/lili/modules/logistics/plugin/kdniao/KdniaoPlugin.java @@ -8,6 +8,7 @@ import cn.lili.modules.logistics.entity.dto.LabelOrderDTO; import cn.lili.modules.logistics.entity.enums.LogisticsEnum; import cn.lili.modules.order.order.entity.dos.Order; import cn.lili.modules.order.order.entity.dos.OrderItem; +import cn.lili.modules.order.order.entity.vo.OrderDetailVO; import cn.lili.modules.store.entity.dos.StoreLogistics; import cn.lili.modules.store.entity.dto.StoreDeliverGoodsAddressDTO; import cn.lili.modules.system.entity.dos.Logistics; @@ -111,8 +112,9 @@ public class KdniaoPlugin implements LogisticsPlugin { } @Override - public String labelOrder(LabelOrderDTO labelOrderDTO) { + public Map labelOrder(LabelOrderDTO labelOrderDTO) { try { + Map resultMap = new HashMap(); //订单 Order order = labelOrderDTO.getOrder(); //订单货物 @@ -198,18 +200,24 @@ public class KdniaoPlugin implements LogisticsPlugin { JSONObject obj = JSONObject.parseObject(result); log.info("电子面单响应:{}", result); if (!"100".equals(obj.getString("ResultCode"))) { - return obj.getString("Reason"); + resultMap.put("Reason",obj.getString("Reason")); + return resultMap; } JSONObject orderJson = JSONObject.parseObject(obj.getString("Order")); - - return obj.getString("PrintTemplate"); + resultMap.put("printTemplate",obj.getString("PrintTemplate")); + return resultMap; } catch (Exception e) { e.printStackTrace(); } return null; } + @Override + public String createOrder(OrderDetailVO orderDetailVO) { + return null; + } + /** * MD5加密 diff --git a/framework/src/main/java/cn/lili/modules/logistics/plugin/kuaidi100/Kuaidi100Plugin.java b/framework/src/main/java/cn/lili/modules/logistics/plugin/kuaidi100/Kuaidi100Plugin.java index 62e8b633..b66980f8 100644 --- a/framework/src/main/java/cn/lili/modules/logistics/plugin/kuaidi100/Kuaidi100Plugin.java +++ b/framework/src/main/java/cn/lili/modules/logistics/plugin/kuaidi100/Kuaidi100Plugin.java @@ -6,6 +6,7 @@ import cn.lili.modules.logistics.entity.enums.LogisticsEnum; import cn.lili.modules.logistics.plugin.kuaidi100.utils.Kuaidi100SignUtils; import cn.lili.modules.order.order.entity.dos.Order; import cn.lili.modules.order.order.entity.dos.OrderItem; +import cn.lili.modules.order.order.entity.vo.OrderDetailVO; import cn.lili.modules.store.entity.dos.StoreLogistics; import cn.lili.modules.store.entity.dto.StoreDeliverGoodsAddressDTO; import cn.lili.modules.system.entity.dos.Logistics; @@ -121,7 +122,7 @@ public class Kuaidi100Plugin implements LogisticsPlugin { } @Override - public String labelOrder(LabelOrderDTO labelOrderDTO) { + public Map labelOrder(LabelOrderDTO labelOrderDTO) { try { //订单 Order order = labelOrderDTO.getOrder(); @@ -181,4 +182,10 @@ public class Kuaidi100Plugin implements LogisticsPlugin { return null; } + @Override + public String createOrder(OrderDetailVO orderDetailVO) { + return null; + } + + } diff --git a/framework/src/main/java/cn/lili/modules/logistics/plugin/shunfeng/ShunfengPlugin.java b/framework/src/main/java/cn/lili/modules/logistics/plugin/shunfeng/ShunfengPlugin.java new file mode 100644 index 00000000..ed1bac33 --- /dev/null +++ b/framework/src/main/java/cn/lili/modules/logistics/plugin/shunfeng/ShunfengPlugin.java @@ -0,0 +1,243 @@ +package cn.lili.modules.logistics.plugin.shunfeng; + +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import cn.lili.common.enums.ResultCode; +import cn.lili.common.exception.ServiceException; +import cn.lili.common.utils.SpringContextUtil; +import cn.lili.modules.logistics.LogisticsPlugin; +import cn.lili.modules.logistics.entity.dto.LabelOrderDTO; +import cn.lili.modules.logistics.entity.enums.LogisticsEnum; +import cn.lili.modules.order.order.entity.dos.Order; +import cn.lili.modules.order.order.entity.dos.OrderItem; +import cn.lili.modules.order.order.entity.vo.OrderDetailVO; +import cn.lili.modules.store.entity.dto.StoreDeliverGoodsAddressDTO; +import cn.lili.modules.store.service.StoreDetailService; +import cn.lili.modules.system.entity.dos.Logistics; +import cn.lili.modules.system.entity.dto.LogisticsSetting; +import cn.lili.modules.system.entity.vo.Traces; +import com.sf.csim.express.service.CallExpressServiceTools; +import com.sf.csim.express.service.HttpClientUtil; +import com.sf.csim.express.service.IServiceCodeStandard; +import com.sf.csim.express.service.code.ExpressServiceCodeEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.io.UnsupportedEncodingException; +import java.util.*; + +/** + * 顺丰插件 + * @author admin + */ +@Slf4j +@Component +public class ShunfengPlugin implements LogisticsPlugin { + + /** + * ExpressServiceCodeEnum 对应速运类-快递APIs + * POSTServiceCodeEnum 对应速运类-驿站APIs + * YJTServiceCodeEnum 对应解决方案-医寄通APIs + * EPSServiceCodeEnum 对应解决方案-快递管家APIs + * 详情见code目录下枚举类,客户可自行修改引用的该类 + **/ + private LogisticsSetting logisticsSetting; + + public ShunfengPlugin(){} + + public ShunfengPlugin(LogisticsSetting logisticsSetting) { + this.logisticsSetting = logisticsSetting; + } + + @Override + public LogisticsEnum pluginName() { + return LogisticsEnum.SHUNFENG; + } + + /** + * 文档地址:https://open.sf-express.com/Api/ApiDetails?level3=393&interName=%E4%B8%8B%E8%AE%A2%E5%8D%95%E6%8E%A5%E5%8F%A3-EXP_RECE_CREATE_ORDER + * + * @param orderDetailVO + */ + public String createOrder(OrderDetailVO orderDetailVO) { + StoreDetailService storeService = SpringContextUtil.getBean(StoreDetailService.class); + StoreDeliverGoodsAddressDTO storeDeliverGoodsAddressDTO = storeService.getStoreDeliverGoodsAddressDto(orderDetailVO.getOrder().getStoreId()); + if(storeDeliverGoodsAddressDTO == null){ + throw new ServiceException(ResultCode.STORE_DELIVER_ADDRESS_EXIST); + } + try { + Order order = orderDetailVO.getOrder(); + Map msgDataMap = new HashMap(); + msgDataMap.put("language", "zh-CN"); + msgDataMap.put("orderId", order.getSn()); + //托寄物信息 + List> cargoDetails = new ArrayList<>(); + for (OrderItem orderItem : orderDetailVO.getOrderItems()) { + Map map = new HashMap<>(); + map.put("name", orderItem.getGoodsName()); + cargoDetails.add(map); + } + msgDataMap.put("cargoDetails", cargoDetails); + + //收寄双方信息 + List> contactInfoList = new ArrayList<>(); + Map storeContactInfoMap = new HashMap<>(); + storeContactInfoMap.put("contactType", 1); + storeContactInfoMap.put("contact", storeDeliverGoodsAddressDTO.getSalesConsignorName()); + storeContactInfoMap.put("mobile", storeDeliverGoodsAddressDTO.getSalesConsignorMobile()); + //国家或地区2位代码 参照附录 + storeContactInfoMap.put("country", "CN"); + //详细地址,若有四级行政区划,如镇/街道等信息可拼接至此字段,格式样例:镇/街道+详细地址。若province/city 字段的值不传,此字段必须包含省市信息,避免影响原寄地代码识别,如:广东省深圳市福田区新洲十一街万基商务大厦10楼;此字段地址必须详细,否则会影响目的地中转识别; + storeContactInfoMap.put("address", storeDeliverGoodsAddressDTO.getSalesConsignorAddressPath() + storeDeliverGoodsAddressDTO.getSalesConsignorDetail()); + contactInfoList.add(storeContactInfoMap); + + Map memberContactInfoMap = new HashMap<>(); + memberContactInfoMap.put("contactType", 2); + memberContactInfoMap.put("contact", order.getConsigneeName()); + memberContactInfoMap.put("mobile", order.getConsigneeMobile()); + //国家或地区2位代码 参照附录 + memberContactInfoMap.put("country", "CN"); + //详细地址,若有四级行政区划,如镇/街道等信息可拼接至此字段,格式样例:镇/街道+详细地址。若province/city 字段的值不传,此字段必须包含省市信息,避免影响原寄地代码识别,如:广东省深圳市福田区新洲十一街万基商务大厦10楼;此字段地址必须详细,否则会影响目的地中转识别; + memberContactInfoMap.put("address", order.getConsigneeAddressPath() + order.getConsigneeDetail()); + contactInfoList.add(memberContactInfoMap); + msgDataMap.put("contactInfoList", contactInfoList); + + msgDataMap.put("expressTypeId", 1); + msgDataMap.put("isReturnRoutelabel", 1); + + + String result = sendPost(ExpressServiceCodeEnum.EXP_RECE_CREATE_ORDER, msgDataMap); + JSONObject resultData = JSONUtil.parseObj(result).getJSONObject("apiResultData"); + if(Boolean.TRUE.toString().equals(resultData.get("success").toString())){ + return resultData.getJSONObject("msgData").getJSONArray("waybillNoInfoList").getJSONObject(0).get("waybillNo").toString(); + } + throw new ServiceException(resultData.get("errorMsg").toString()); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + /** + * 文档地址:https://open.sf-express.com/Api/ApiDetails?apiServiceCode=EXP_RECE_SEARCH_ROUTES&category=1&apiClassify=1&interName=%E8%B7%AF%E7%94%B1%E6%9F%A5%E8%AF%A2%E6%8E%A5%E5%8F%A3-EXP_RECE_SEARCH_ROUTES + * + * @param logistics 物流公司 + * @param expNo + * @param phone + * @return + */ + @Override + public Traces pollQuery(Logistics logistics, String expNo, String phone) { + try { + Map msgDataMap = new HashMap(); + msgDataMap.put("language", "zh-CN"); + /** + * 查询号类别: + * 1:根据顺丰运单号查询,trackingNumber将被当作顺丰运单号处理 + * 2:根据客户订单号查询,trackingNumber将被当作客户订单号处理 + */ + msgDataMap.put("trackingType", 1); + List trackingNumber = new ArrayList<>(); + trackingNumber.add(expNo); + msgDataMap.put("trackingNumber", trackingNumber); + JSONObject result = JSONUtil.parseObj(sendPost(ExpressServiceCodeEnum.EXP_RECE_SEARCH_ROUTES, msgDataMap)); + JSONObject resultData = result.getJSONObject("apiResultData"); + if(Boolean.TRUE.toString().equals(resultData.get("success").toString())){ + JSONArray routesJson = resultData.getJSONObject("msgData").getJSONArray("routeResps").getJSONObject(0).getJSONArray("routes"); + List routes = routesJson.toList(Map.class); + return new Traces(logistics.getName(),expNo,routes); + } + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + return null; + } + + @Override + public Traces pollMapTrack(Logistics logistics, String expNo, String phone, String from, String to) { + return null; + } + + /** + * 文档地址:http://open.sf-express.com/Api/ApiDetails?level3=317&interName=%E4%BA%91%E6%89%93%E5%8D%B0%E9%9D%A2%E5%8D%952.0%E6%8E%A5%E5%8F%A3-COM_RECE_CLOUD_PRINT_WAYBILLS + * + * @param labelOrderDTO 电子面单DTO + * @return + */ + @Override + public Map labelOrder(LabelOrderDTO labelOrderDTO) { + try { + Map msgDataMap = new HashMap<>(); + //模板编码 + //关联云打印接口后,点击查看,可在接口详情页获取模板编码,类似:fm_76130_standard_{partnerId} + msgDataMap.put("templateCode", logisticsSetting.getTemplateCode()); + //业务数据 + Map documents = new HashMap<>(); + documents.put("masterWaybillNo", labelOrderDTO.getOrder().getLogisticsNo()); + msgDataMap.put("documents",documents); + msgDataMap.put("sync",true); + /** + * 版本号,传固定值:2.0 + */ + msgDataMap.put("version", "2.0"); + JSONObject result = JSONUtil.parseObj(sendPost(ExpressServiceCodeEnum.COM_RECE_CLOUD_PRINT_WAYBILLS, msgDataMap)); + JSONObject resultData = result.getJSONObject("apiResultData"); + if(Boolean.TRUE.toString().equals(resultData.get("success").toString())){ + return resultData.getJSONObject("obj").getJSONArray("files").toList(Map.class).get(0); + } + throw new ServiceException(resultData.getJSONArray("errorMessage").get(0).toString()); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + /** + * 文档地址:https://open.sf-express.com/Api/ApiDetails?level3=409&interName=%E9%A2%84%E8%AE%A1%E6%B4%BE%E9%80%81%E6%97%B6%E9%97%B4%E6%8E%A5%E5%8F%A3-EXP_RECE_SEARCH_PROMITM + * + * @param searchNo + * @param checkNos + */ + public String searchPromitm(String searchNo, String checkNos) { + try { + Map msgDataMap = new HashMap(); + //顺丰运单号 + msgDataMap.put("searchNo", searchNo); + //校验类型 1,电话号码校验 2,月结卡号校验 + msgDataMap.put("checkType", 1); + //校验值 当校验类型为1时传电话号码 当校验类型为2时传月结卡号 + List mobileList= new ArrayList<>(); + mobileList.add(checkNos); + msgDataMap.put("checkNos", mobileList); + JSONObject result = JSONUtil.parseObj(sendPost(ExpressServiceCodeEnum.EXP_RECE_SEARCH_PROMITM, msgDataMap)); + JSONObject resultData = result.getJSONObject("apiResultData"); + if(Boolean.TRUE.toString().equals(resultData.get("success").toString())){ + return resultData.getJSONObject("msgData").get("promiseTm").toString(); + } + throw new ServiceException(resultData.get("errorMsg").toString()); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + private String sendPost(IServiceCodeStandard standardService, Map msgDataMap) throws UnsupportedEncodingException { + CallExpressServiceTools tools = CallExpressServiceTools.getInstance(); + Map params = new HashMap(); + String timeStamp = String.valueOf(System.currentTimeMillis()); + // 顾客编码 + params.put("partnerID", logisticsSetting.getClientCode()); + params.put("requestID", UUID.randomUUID().toString().replace("-", "")); + // 接口服务码 + params.put("serviceCode", standardService.getCode()); + params.put("timestamp", timeStamp); + params.put("msgData", JSONUtil.toJsonStr(msgDataMap)); + + params.put("msgDigest", tools.getMsgDigest(params.get("msgData"), timeStamp, logisticsSetting.getCheckWord())); + String result = HttpClientUtil.post(logisticsSetting.getCallUrl(), params); + + log.info("===调用地址 ===" + logisticsSetting.getCallUrl()); + log.info("===顾客编码 ===" + logisticsSetting.getClientCode()); + log.info("===返回结果:" + result); + + return result; + } +} diff --git a/framework/src/main/java/cn/lili/modules/member/service/MemberService.java b/framework/src/main/java/cn/lili/modules/member/service/MemberService.java index 1b1d8be8..27aab633 100644 --- a/framework/src/main/java/cn/lili/modules/member/service/MemberService.java +++ b/framework/src/main/java/cn/lili/modules/member/service/MemberService.java @@ -74,6 +74,14 @@ public interface MemberService extends IService { */ Token usernameStoreLogin(String username, String password); + /** + * 商家登录:用户名、密码登录 + * + * @param mobilePhone 用户名 + * @return token + */ + Token mobilePhoneStoreLogin(String mobilePhone); + /** * 注册:手机号、验证码登录 * diff --git a/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberServiceImpl.java b/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberServiceImpl.java index 4060e39c..db29096d 100644 --- a/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/member/serviceimpl/MemberServiceImpl.java @@ -198,6 +198,22 @@ public class MemberServiceImpl extends ServiceImpl impleme throw new ServiceException(ResultCode.USER_PASSWORD_ERROR); } //对店铺状态的判定处理 + return checkMemberStore(member); + } + + @Override + public Token mobilePhoneStoreLogin(String mobilePhone) { + Member member = this.findMember(mobilePhone); + //如果手机号不存在则自动注册用户 + if (member == null) { + throw new ServiceException(ResultCode.USER_NOT_EXIST); + } + loginBindUser(member); + //对店铺状态的判定处理 + return checkMemberStore(member); + } + + private Token checkMemberStore(Member member) { if (Boolean.TRUE.equals(member.getHaveStore())) { Store store = storeService.getById(member.getStoreId()); if (!store.getStoreDisable().equals(StoreStatusEnum.OPEN.name())) { @@ -206,7 +222,6 @@ public class MemberServiceImpl extends ServiceImpl impleme } else { throw new ServiceException(ResultCode.USER_NOT_EXIST); } - return storeTokenGenerate.createToken(member, false); } diff --git a/framework/src/main/java/cn/lili/modules/order/order/service/OrderService.java b/framework/src/main/java/cn/lili/modules/order/order/service/OrderService.java index 5fd2e961..86ba90bd 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/service/OrderService.java +++ b/framework/src/main/java/cn/lili/modules/order/order/service/OrderService.java @@ -165,6 +165,14 @@ public interface OrderService extends IService { */ Order delivery(String orderSn, String invoiceNumber, String logisticsId); + /** + * 订单发货 + * + * @param orderSn 订单编号 + * @return 订单 + */ + Order shunFengDelivery(String orderSn); + /** * 获取物流踪迹 * diff --git a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java index 1c202c1f..9af389f3 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java @@ -18,7 +18,9 @@ import cn.lili.common.security.context.UserContext; import cn.lili.common.security.enums.UserEnums; import cn.lili.common.utils.SnowFlake; import cn.lili.modules.goods.entity.dto.GoodsCompleteMessage; +import cn.lili.modules.logistics.entity.enums.LogisticsEnum; import cn.lili.modules.member.entity.dto.MemberAddressDTO; +import cn.lili.modules.member.service.StoreLogisticsService; import cn.lili.modules.order.cart.entity.dto.TradeDTO; import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum; import cn.lili.modules.order.order.aop.OrderLogPoint; @@ -44,6 +46,7 @@ import cn.lili.modules.store.entity.dto.StoreDeliverGoodsAddressDTO; import cn.lili.modules.store.service.StoreDetailService; import cn.lili.modules.system.aspect.annotation.SystemLogPoint; import cn.lili.modules.system.entity.dos.Logistics; +import cn.lili.modules.system.entity.dto.LogisticsSetting; import cn.lili.modules.system.entity.vo.Traces; import cn.lili.modules.system.service.LogisticsService; import cn.lili.mybatis.util.PageUtil; @@ -460,6 +463,15 @@ public class OrderServiceImpl extends ServiceImpl implements return order; } + @Override + @Transactional(rollbackFor = Exception.class) + public Order shunFengDelivery(String orderSn) { + OrderDetailVO orderDetailVO = this.queryDetail(orderSn); + String logisticsNo = logisticsService.sfCreateOrder(orderDetailVO); + Logistics logistics = logisticsService.getOne(new LambdaQueryWrapper().eq(Logistics::getCode,"SF")); + return delivery(orderSn,logisticsNo,logistics.getId()); + } + @Override public Traces getTraces(String orderSn) { //获取订单信息 diff --git a/framework/src/main/java/cn/lili/modules/system/entity/dto/LogisticsSetting.java b/framework/src/main/java/cn/lili/modules/system/entity/dto/LogisticsSetting.java index 8409f80d..3eb5a893 100644 --- a/framework/src/main/java/cn/lili/modules/system/entity/dto/LogisticsSetting.java +++ b/framework/src/main/java/cn/lili/modules/system/entity/dto/LogisticsSetting.java @@ -1,5 +1,7 @@ package cn.lili.modules.system.entity.dto; +import io.swagger.annotations.ApiModelProperty; +import cn.lili.modules.logistics.entity.enums.LogisticsEnum; import lombok.Data; import java.io.Serializable; @@ -16,6 +18,7 @@ public class LogisticsSetting implements Serializable { /** * 快递查询类型 + * @see LogisticsEnum */ private String type; @@ -36,4 +39,29 @@ public class LogisticsSetting implements Serializable { * 快递100 Key */ private String kuaidi100Key; + + /** + * 顺丰顾客编码 + */ + String clientCode; + + /** + * 顺丰校验码 + */ + String checkWord; + + /** + * 顺丰请求地址 + */ + String callUrl; + + /** + * 顺丰打印模板 + */ + String templateCode; + + /** + * 顺丰月结号 + */ + String monthlyCardNo; } diff --git a/framework/src/main/java/cn/lili/modules/system/service/LogisticsService.java b/framework/src/main/java/cn/lili/modules/system/service/LogisticsService.java index 6e552da9..54bf557a 100644 --- a/framework/src/main/java/cn/lili/modules/system/service/LogisticsService.java +++ b/framework/src/main/java/cn/lili/modules/system/service/LogisticsService.java @@ -1,10 +1,13 @@ package cn.lili.modules.system.service; +import cn.lili.modules.order.order.entity.vo.OrderDetailVO; import cn.lili.modules.system.entity.dos.Logistics; +import cn.lili.modules.system.entity.dto.LogisticsSetting; import cn.lili.modules.system.entity.vo.Traces; import com.baomidou.mybatisplus.extension.service.IService; import java.util.List; +import java.util.Map; /** * 物流公司业务层 @@ -24,10 +27,31 @@ public interface LogisticsService extends IService { */ Traces getLogisticTrack(String logisticsId, String logisticsNo, String phone); - + /** + * 获取物流信息 + * @param logisticsId + * @param logisticsNo + * @param phone + * @param from + * @param to + * @return + */ Traces getLogisticMapTrack(String logisticsId, String logisticsNo, String phone, String from, String to); - String labelOrder(String orderSn, String logisticsId); + /** + * 打印电子面单 + * @param orderSn 订单编号 + * @param logisticsId 物流Id + * @return + */ + Map labelOrder(String orderSn, String logisticsId); + + /** + * 顺丰平台下单 + * @param orderDetailVO 订单信息 + * @return 顺丰单号 + */ + String sfCreateOrder(OrderDetailVO orderDetailVO); /** * 获取已开启的物流公司列表 @@ -35,4 +59,10 @@ public interface LogisticsService extends IService { * @return 物流公司列表 */ List getOpenLogistics(); + + /** + * 获取物流设置 + * @return + */ + LogisticsSetting getLogisticsSetting(); } \ No newline at end of file diff --git a/framework/src/main/java/cn/lili/modules/system/serviceimpl/LogisticsServiceImpl.java b/framework/src/main/java/cn/lili/modules/system/serviceimpl/LogisticsServiceImpl.java index d1121dbf..36e6ce20 100644 --- a/framework/src/main/java/cn/lili/modules/system/serviceimpl/LogisticsServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/system/serviceimpl/LogisticsServiceImpl.java @@ -1,25 +1,33 @@ package cn.lili.modules.system.serviceimpl; +import cn.hutool.json.JSONUtil; import cn.lili.common.enums.ResultCode; import cn.lili.common.enums.SwitchEnum; import cn.lili.common.exception.ServiceException; import cn.lili.common.security.OperationalJudgment; +import cn.lili.common.utils.BeanUtil; import cn.lili.modules.logistics.LogisticsPluginFactory; import cn.lili.modules.logistics.entity.dto.LabelOrderDTO; +import cn.lili.modules.logistics.entity.enums.LogisticsEnum; import cn.lili.modules.member.service.StoreLogisticsService; import cn.lili.modules.order.order.entity.dos.Order; import cn.lili.modules.order.order.entity.dos.OrderItem; import cn.lili.modules.order.order.entity.enums.DeliverStatusEnum; import cn.lili.modules.order.order.entity.enums.OrderStatusEnum; +import cn.lili.modules.order.order.entity.vo.OrderDetailVO; import cn.lili.modules.order.order.service.OrderItemService; import cn.lili.modules.order.order.service.OrderService; import cn.lili.modules.store.entity.dos.StoreLogistics; import cn.lili.modules.store.entity.dto.StoreDeliverGoodsAddressDTO; import cn.lili.modules.store.service.StoreDetailService; import cn.lili.modules.system.entity.dos.Logistics; +import cn.lili.modules.system.entity.dos.Setting; +import cn.lili.modules.system.entity.dto.LogisticsSetting; +import cn.lili.modules.system.entity.enums.SettingEnum; import cn.lili.modules.system.entity.vo.Traces; import cn.lili.modules.system.mapper.LogisticsMapper; import cn.lili.modules.system.service.LogisticsService; +import cn.lili.modules.system.service.SettingService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -28,6 +36,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Map; /** * 物流公司业务层实现 @@ -49,6 +58,9 @@ public class LogisticsServiceImpl extends ServiceImpl orderItems = orderItemService.getByOrderSn(orderSn); //获取对应物流 - Logistics logistics = this.getById(logisticsId); + Logistics logistics; + + if(LogisticsEnum.SHUNFENG.name().equals(logisticsSetting.getType())){ + logistics = this.getOne(new LambdaQueryWrapper().eq(Logistics::getCode,"SF")); + }else{ + logistics = this.getById(logisticsId); + } // 店铺-物流公司设置 LambdaQueryWrapper lambdaQueryWrapper = Wrappers.lambdaQuery(); - lambdaQueryWrapper.eq(StoreLogistics::getLogisticsId, logisticsId); + lambdaQueryWrapper.eq(StoreLogistics::getLogisticsId, logistics.getId()); lambdaQueryWrapper.eq(StoreLogistics::getStoreId, order.getStoreId()); StoreLogistics storeLogistics = storeLogisticsService.getOne(lambdaQueryWrapper); //获取店家信息 @@ -105,6 +123,12 @@ public class LogisticsServiceImpl extends ServiceImpl getOpenLogistics() { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); @@ -112,4 +136,10 @@ public class LogisticsServiceImpl extends ServiceImplYN+qP}n=l#|?`|Q1|&id9$CHaw5rC0Lf zx?5}g?va-Q20{4+0RizVB1&EP*Z;Ah`~vwUBcd!oBOxnFCnF#$Au6JzOe-V$J^t(0 zgUsZFv=j~P9IO-#<@DrCgChMR)9%s!5zsGrDR78-U!ZI3e;$ST&msT+4e-nB{~mzj zpSwnOHgry=bVg1VHgqQL_Kqe_PIOKtj;(CM315JynU+Und819jdKX@uq@^?7cs^%r}8ajdm)hrCJm*%02N_Q&W zOSN5NXJWBJ74kD3p-Q3ABglIBtVd*D2r-T7jDLaz2wG6tv-`pmTI@Jho~~Bo^3u#M zrllc-!n>1D1<9=D8#MGjKQVw$8J@m9a9$6n`Wdf5Js@^}Wxb(30!L$lc&BX;k`dO* zhyhJeRIfX8|3yjQF6JMd!sTRcgs>jlsAkcukkcD$Ae2 zl$Gvcs+nuVGX96y7KJVd4x`>brY;^Eken8a1@4S9NVvROsY=rVh}{r>VpRaq0`(9a zLBug>3D)&i+Wnq}{r$9`3YJXo*)lGt-p#{9hwaVXh>I)dchys+$mums^Zu}O8>n^8 z27D1FbdlQ1^iZD?bHVQC<5#6-narn$!R_Em4nZ@X`c(j3Z5t?p$Ro$Zq--XJBMle zh&8M%Kjq;ne+60W6lW9jxDvZi*K{l{j&A1isosVvpwMjjS$@`m_1$^=E2mwxu{`gp4JVLgXYWBXXeM#8TDFk? zMdxHp(_bA@V0+^pJ8*aVn360~qgmAdUV@1k6pZWU+>4w@W;uLej3&*;qTt&6_Y4?# z=@te^vl+~KG|Qo?6`>1t!+iKesky#m%-41(r?v+S%k)}52Wn@!UZZgU1h;btbe-5RKNp!ca?k!?YmR6%pMps@N~N;Kh+z0T$S1Uf9S|Ziu%CvgxKY~O zKGX(NlFb6?$95oGaTp2i$gQ|LoTejPPfh9U?{6vVo-i3If_gqLzvD~z9R;7Pa7b&l zYgZBRbmd%da`5N7Hwc|;G3*ui0w>H1JfG&=GqiQ)OP;blcs`}f!uxNC0WoI)$2mgR z9f`BFD^0%BZ=N=6_fIf5y8W?j;bto{L&TZKVYlHLI8k9b^01zdTO2h9&2x->N&)N6bRug$2eCgFTK)7AV=<<7`5Zis z>GDo%)z{eU1@up(-HAgNsnR*b_gP`s7{re?4%wHwB^8bNpNfO(;6kJOEw^CHb7HR1 zN(K1vjGwmtTT-cVNRyI`-tN4T#qe~(V~-TA41YL6(GBL^(jRiOCv}I@1mniUpEnRY zNP6<&e!{23%}1HPgWm#YA*jQUD#=fL7m|!wQ?jS&3``k6SWH3DcBANb&Rb{-wy38z z-$;x}ouFT(zM%)j+N&#)eNonqsNEXY{1CgdhE%t;x$L9sfn0{?hCIbgQ>wuGC)`Dz zl+bF*FPrNtbO$abZNb+(fbAUROzUCm^vX~c>^(3!>v}})4c#-K9I$!{>Pv++8Yk+F zFKCvAlFzGKRNlKpyn45>rmC2gzY28>3s2PYtVTu^WPLLc}Ej@17~v)TNj)EEL2H}I!f3o7$ZL+oi_b~ z1DbXG5j6QSKsMA(OK9Qp5UdEJ>!8+}jkITiDPzzL*cfdCvSytQqGBV^T@IbjoJ#A9 zk|VNxR$n+4ds6JYC&ofb5OBK2ISoIVCoMA@9KK%>0CWM6cS+*I64B z4kAP*YOhLd)F({WL(7x%&Vx4UHWin_*@O=KyDP<*{@C)4vw(59%5-5ZG-jOd9-;=@ z@BeMo1*0fd-Tbsv%y3>-v~)J(h*zeXpjx3S_l(1Uk=!?-*6d?+dKj$iF~4Gb3<1}=uquk`_)Xt9Za$y@W|tGtjj^5~>{ZjK z1}XOuwn94qTmzC5hztXJl&d@ic}f$ETr}mmQL)q2`XhDreZw-apW0&b$}Sp@uupS* z-AM>X){p$*@-Wne|3czC5zF33N2m!IxPJO;TE4KTCMS9M+P3Dqk?x=phR+NHkXb`t z`U7_W4CNocR@07SuORvt_?$$${Fk{UPHzZzXic_FmG_&T0L*x4NJ>qxF^*vDo_zl# zCbHC;#z6X_850BfEphDN3bBojO0#4b$1AuXc;1!Y(uV6H6v6sSVyc(^aY=WO)pHVy zG*WsJC+KRYy~<|snL70IL2AVfL_=?Hw_$(donTTdQFeD5zkXAwOLAN)>Z)z4 zi%k&YAopk39<|OB2Fen49w^9C8W1`|?j@>mRCQ7X;t_V9C{0t`K=1h@{2?ilJ45g1 zpZ$mgs3DFtCU%6%(i~CbOG$Y|oX#nB6VaMel!gAjLZszG>4RTr$WjC=S`jXDk=Hb% z$TN_%3Rg@ocr-F3`4>c`AaOil+=)kgFbwNDqPCuS1WNWsEK7c} z_HoimR_kw4L=#DBEW0yoJw`zSvgky{80)h~?Lzrh{XBzKY5zKU1OOY$TXDu*xn7s< zU5<>jp0nqWC5bI*4<0S1Qq{+u9~|MjHSzc@cV!H_o*$O%^<2{v72f&+Lq%}+Me+4L zzf=sE?Ry~SKv(=g|BEM^jJ|zOz`uT-f&V+6(Em3)Q8jV2F!d0!Gd59iwy^$Bq(muO zscncNbXna>DM0k~A>g?P;=Lx3=fxHW6%YN^Y+}y73$Xsb$70v1dkER=7T_Xp_IT!cSQ+}aF z5>yjKLJTCu8-!okc934`=vqMrhs75?s0M8Wd%?qrZ2=D$jHZ0^6{rNOPwYR@2mx)% zq)d-qwKf~DsxjT*i8v$~jB~M4%LJoM$*z!8?Am}Hh>LHpV33CFsh|KDaEDNY4F5XN z>JGU~(hrUqHhSqOC*{MWD>1~ph?Bi7VfLSW2^M1vMM1MXEs%>F2-LTtzItffl(te` zU@mJV6X%OFO=gPl-lSL0p=H##%sIeLDA$Ho4vsQN=cv_t>TC6gTLMVKJ%Mqvub9)J zHgdsrtV%_PXMOxWOMPLaGv9Tkg}YPSw5xx#kF$1(0P9al zGDP_=LXPSQ&(QNfVc~MO6akddS+tSx0OHbIAykfP z+ySNaL^f3v>-`4uW(-pvHL+8j4SP?`v}$6zaM%J09JQenaz<@Ss1|chS~i#cpWB_A zJ^REZjP63uIT!30lamR`=AvngJhVU6_JEWcWiOf4Rv!Z9^xkF@&UEUG>Lr+j4IZ1>P|E%LyRLA2 zW0#T7^J=bcMN5~c)W$Z0KSg+~g2pGV3AQ4Jp=qx->N;BJ-|}R%vY*~(F&T?nh@*Oe zt_C-lMQl;3qE_slfvec-fw>^Ey(-%ICFfkTf6|uOhwVuqe1u{PkPbl(RDe>+kKR*1 zc~qy5K2p6M{FPaJ12Z<9|9os4yn#gA^E{M*yJNe>lKo1v{mt-)6w)ian{=VELsloN zk7hD{1qb%7Q_LjITzvZFjIL~Q?>8ROIy>pv!zXW?9O9EneYCtZ4wbvG8UCxk`S*kK z^K0U_VlGcI&v3}d>+3De8}!NHNbU8J@*zLyU5{ciLRDECSGa}(<&~Cy&V}cOa!%GQ{@XVFJ z(`a#V&cm|uRd@z`8zXK-n`z`j4ZH*bQo6;3H&OUy_KK#X3F3N&pCEYp$ES2_4J|dp z>uu}wi@BawTMtM-|KX-dn*(4k{s9TYzXb{Fe*+SU|JOtR3nfa<2DZiqj>i9q6Rsz_ z6<#nfFk&!TS1?jhuz|3t{QAj5W$zh%hye~h5|&l~ z106{nc~F*LP@Dh(RUNeg9~lFk&JG_16-!%SoF5NQ6M&!&5D+IIEVKYlh_9`fn3iG- ztMH34G|rETy{D0!V~K_dd^B#*Gz?Fi51Sa67?=qdg8uiFv5CIXueB+-d_P7U0tYbJ z|M&)|W>W;Y|GeSsKgWNaDExOY6?b;F7qYf6v3366FzwQS^ukfW{no7?vu0gjmDreV zEP~~6a`hCHkVKqM4kooAw8?7(T9^W?xzd@ESrj;uhx{$Y@eg+l(**HzObs9)AV?On zE&cnq^zXj+&f-m1nzbui2ZMm`F}PFbi|^0DM^1zH{?`ZIuUciCGD5LjN(9)CgR5_T zZj9#)Porean2&?vC0v-)@26&5D+ti3(5@l4U}kraa97N&U_N7E&QEN&YewK^ejoDn zIRi}~5*dYx0etu-x}76CMXM*EZ52OxdZb1*=tEUyThv=-;SFhgC_gZ2+TWo?<4UzPz3VjxDYQt37NjowRzNS3(btEEJCF- z40=H=SSs?Jt)Wj9Ng;ekg>oaP&c*p_m|;-M^x&y4L$WfY6$b1hAY`Cqi`8SS zhOJX5g)$S=Bw}ar<5`68VVSTIdMYUN)B+>ge`2ZjTG4g%^YT=?_$BtZ zKA7?zzuS(6ko?jHGOA<&NmAAmG85sNLF&P%SjkLF^Fmr9aqQulD7Z>&3FyIUtZtff zJc>#0<5gJEXsMOY{tCVa!%d#Rrju}@#M0xmRDcCT5GtbU*4QvM(i5mxPUK)nYRr}t zkYPOh$)>D1)^kz}M5PSIRMB|Is%FI1E$cz$Y%BE?#U7j^mP+(gF0c>g%v3_~hEp>8 z{nPES_ISc)W@dPgnh2L+-%Jxs9+|$@DEJjZ0pF2@*40DG5V^!is z6I(|AWOOoUb3gOJ;(cE0K~s(U=GkTj3+=WhgcALXU?osexC_A2oC8)fQ+{MK>pLJV zV}bIVN^arSz^_Py-&tVCFlbp6$QsF}ew}^S(*X?FcjDNkiOQQEVYXIDKOG4nZv!|h z7?llEWm-oJ8v{+#b1}XcntEJ69ojkgK>8W?G`7^4F)|^Bb-lPqk@7=hX`e{aQnzI= z(*lu+n)a5OOHx6J(i~=CeldFy8T(vHYTjHeN<0Q-X1Rv60Z2nqa|O4hY%ZeVG_q?i z7CrIeg0)KDGse1G+e8gjJr*}<@peOKodM(d5}U*}XTgD`de29?cr=!`5|}tnih){)x}Aq~_ZdT`yVUUl zpR733tTK?OL3AZR@Ib;eOf>8jmeY1nX8LdY@>N1wZDQso*xA6;YkF`ERAPxz8H(HJ zA^8~Q^~I_f?p3K#Yw!M~z6m}~*K2TZCrm*w!zD1;0rRHl)6J*4YMYItAiSiERXd@Lls=N(P-Z{j&g$tS|v z_f@(2QTu7z`g~Vr1XvQk7WNEP4OxV$4-m@{lXm#1)3_A73-@2}jLZiEc^saPw+0LM zuB4_Zs2XIyQA==2>kmx@e_DgZFujG0){@0Lsn8-co7ajpJ8;T_`zXv|U4>Ki(7w99 z_`-Erk||7FjxoP~WzXKSQ~9FlbD%bXbA8h0!k){FB)ErXkGa8C_egoWW6fB)2kRN)@3uyt+;U@+>5NA~lu!tsDB8jWPnn~CHP`3g1zbGmN2e5q z?i(P|9%%1&F_DbHJ9iREgp1E(!Ctb4kRKjfar%U=a6DZmN^8W8geY}IZnC+2LfCP{ zT~M1*dll5hArH%`3q-0*CtJ~NCo{zvtRXH~YAc1h-8sSX88JyhQsT01OJ#%x2QSA- zDK6=qzb0j-L$hC1v%%({4%xk0A|tv+*h{;1@0`8zeE05U$q2$V1Or)@7Rr^4syF`t za@p7qJgRWOx?Z8@3VHJMdt+^1ZmPB#%;acFHtcD7wx!L~tKG=vj208AVZSn>dk*j? ztsU$CXdaEKaRU@Fr%6~}efMI6Uz8B`f~Q5v+*!%RbhV;QiYUymx1Qbw-NDN z$`M1SD1!`HO7|fzFk|?i^o%s2i-A4&&Zed%vg2GaWK@crl>0et#Cz=vwQsjXbwU9&64h_PCkF5C-i#E^XWyJmroYOgkWVvbRQlJAWc;Ei4lTZ4+` z$*FLxc1-KyRmI7QDq0^`AM|L6%s26H0mMD;&Q}$>Tjiei2TD?y&+8@kl(zdYH*m$P z>1f2biAY0Q0_Wj@*6pGEou1`OyoxiQ3xpkJVR4U9+6}%(B8qt%{l!RBO2tKnF1qv~ zak6Hjg684Ti14PXbUS3f{j)xQA0ILM;j&bwTG5 zc|VjQj!1e^m=51y5>es-`}|Q{ zO7y`T|Hty}r1c@rK8aqyY^~}5B$g#J^SuUbWoB;V)-DE>>O(B^AFimX2bg>dEqu-M z`|*3QItQ&Wi6(Dz+}>rJOhpx*P~462dr8@wku-1fl+r_F)T&9PWIBVrfQX2dzM+fV zdAFAJF-3HMoKSNc1qIQwd`Iq zE`P6a1-XvbM5$~oR7E^T+hNlnxJAGC~|#f`9G98npcegF1m+$PhVuL|%eGd$5p!ax;H#G0z}wFo646 z+cy`zviBdh7OnAwUz*Q(FKq~Av(q)h;!B1>DdhYg=jyq^0dmcY+&QA!z41)zSV-VQj=Spjm9Gu=)hS5&b-f_v+3xNk=i zD{3k)2cO6BZ!|2xuZ6w8cxmhl&B{wKz-R8 zZ1WA-sECufq%D@~#zWs;fu@Y$3sqP4rBF2aNn(`dw8AA`89h7_&m+fQ7}N%a7S*0} zDUZo4Zjf2}|>Cr#Q_`@le#zNn?Y7^p@#_tG>${dlJ)erh)40C_7{qO_EM zdX*;RS8JB}8r8=0!Q+=I)!?fj7_Xe?z$)Bk{)JWS+NpkUP2U<5lB+Kh*Ww z-QF#K???ytyuXB2hFuch$0?T<5-^Buk{yq)mh$QR>*i2?bY1t;pQ`72#4f9ZFZnYK zK1^4U=Woxr^IHjjRx`ZRMC0!`;@jBU@3*?CGiCZoI~MEBes zpU{`bbbHL5k+wL68+xY4-TnH$sNU{T+InO=Z1#T}RwCS`+KP0hAi$HD4tE3`Qd5he z7NBhn(!&H4NQ*0Od!#r+0*0 zVZ%8#NFzMF4f}%21?udza!M~zRb-aV{61J4c5%VZJD~CuuTc&2)d8PgTreDlbx@l) zb;8-mQbUZ}Qm=#XX@N`(FO>zLr*IlljH4%z4*w@W7? zuk?SI-~S!WXQ@~zVX0yGL~FbDRi)c>Vp|zD{zdE*&H%Ae)~14mG8jrMrqOXIutLlP z&E))2qG3H}UXbQ{5p#LZ1`a@H^@+uN-g?M<=uA1`Il1il`FcX^h4G1-9j4Eq!xbIB zA$qHK!C>&^sh@J>P-ML_qOudcFVbPkFLLhUjh>UIQiUgJ#pHyGG$K}{5BH4YJT^&f zpVIgYNAEI3af9_t5r`sTbF`o-J|dT;P19YPhj9wyGDbDQXg!u*NnWUX(&kKCn|BWG zUKVeYwses)!f@SRQY&QP8KQT#>AQ$bo<4qTVw+e?awqEBJ*H5g36qj}47WjjAt!r@ zQ&=-IUtwj!j%i6j#>}4h+~86rr#pmJohzqiYz6AGahxGD5oi2^iHAVOjcZH8>?Kc& z`lWxWM*mj;>_%{4B7)y){!XXw z#W_DfQ**6l9A-XSLn5rpi4VcLNJ`!GvqWE zJMU{KNSwy5DxtH*c8+SXG$(%um3qGjzowSZFIsqIY7)hoNJ0e{JE%O(YlPlMCE;+| zFRexx_x#ZavZgK4na-JO6l3$4su{(Yf27X}2RBWmU5zv=xtSlfO*r-j#rQ5BP?~t2 z@PsxvIQJahSVlDi)Yp-v!{^gKgXFkU#6h7ZJ-^)x7cf(6a{$oeDrvu0RRvVaE=?x8AZv>Pppfdd@AJ@Hb4ylED-7Z*G*{QZZZ=d}w{`U%zXx z?@0S~h&$L^)mzwdgL|$mv!6N@rEjN(l8=Ax?8Y_9kDW2ya zlT5tlk$geqF{4;hkz^AxnF>q#l*??j(6_XBlb971I5PU zS+>ZFRF=~T2cbtic+{W=-S>)}QW@=dr;Br8#yj3=vEb(MrX+Zip ziRzJ|qxWdr9#(gEgp94LuJ{ixC&ycG3<9Coa!vg#sO!(~59S(J&;2%dsnvj=|De+z zsLCrF$gf{TkpGTOJpZIs|E|O3Kk4*;wYdB%p8MZ~DpJ*QMqWYP3W#D!9(jHR8iqHQ zAOL}mrC!5`)IleP&n3_Z7iBEXON&0L;~|h57iVObNiURHV6{nSX7(;Vqw;RCAnGs3 z%X_;#H|uGC-(^d(Y8@4NQ7)mRKycs)5g5RRqK1Js&C~mfzq2>HQQp zvY^RmbXqbkV`0i}27Hx~YJKI?_LiE^u zd(E8^sdyINM)n-d7(leA%vr`_+t+rsmdI)(e3}Mh6}EW%)C#G{P)>;x)21SFaE3`7 zSLoqZaPe~O&dkf>XEK87Y@bGSpyd2MAoeMnr`QY=x0tHOWLTV)L9_Ujqnc~)T@sn#%s3$S zRW#n|8zlVZG8gGDOM4#gkbZ*qqQ|;&e5GA&Os%P^gQhS$WU|G0O8NvQ0}=mSdpw$ANhp5$Eo8t?!v=(`sxZQ_NBp;)8r`X^yUG|qdjfR zEdU3HcSonr;h99otw)}~aXvmnsjuB8GkgNLgp96IJFlK3Ute<^(#T<~(Z|lI*8$UL zrE`ybCeUj}gUQI2U8YRFm?r_t;x-?0yp*wOXoLV?6Ew)1Wo8X zT3*vnrK7_5JIUuQ(noeH0lB5XWjCd&dQ3xRGJPV9PHsH4nR&MQ*+I}{-na5b^9h!; zb$P!;yUd0PV~GCqnC`!|D#F&$X`KRaPp))SZ%n-c4^C&nq!pLXx!dJ(rpE>)qjHV@ zT#UZi1IP2q;q3oPm+P-{C*QV4`9!djlrMdo^OR;oS}0>e3clXxz$%t=r#R4p>W-?= z{RH8A*eyX?j9Q|2<=8GJnQd09e9aI1isC}a=`lB%K$cOx8p3`h*;&+^Q?aTq6LQkN z!v^gcx+#528_G{Aar@abotH`MFd-VlN9hcxSah2RS|<=e9-1GM#>4n?t9mVhdgEz- zwJoDja3RU%i^~RR%!oFsHh~to@2DAT7EYH({FV%5(K!l0U-##`b9(>#?qYOkKTVyK z-bJ4O@-0ss@#je}Xnl+#V<)cfIPB94txB^c<(~9L5h;5M!Q$Qzoq@$+r)H+1CMUAYp|)yS9`(_vl1VGXm#1rP<=n3Bi+0_y$z!(o2Pm{d(d z%r=0mONRDOh?jFfzE@z^E7kMfjXTKCpwDN7<5$L?TVL|`ky{ByI7v!431D_=9%(*! zctV0GL-lk)dCs8N#9Xd>76po*lAIzIH$_+)=aFB>T&)+Ry3e@X(P~~_RV#Pr@9h|x z|4jOOaf`BDlUJRlhBk#9-_O~FZS?ZpeaIiYMwu7k)Ety&Q1Fu@+CFu~sBKq)+aVt& zLX<9o*z$+<^lXl$n}hZ4+H}U1?RT)<7HGZR$$a|zcl`nG>Gs>PgTb_g;5ZGo9>Kq> z#&(QEy3_QmaHnu;9&#gN8v8=A!t4xsfwPGuU2?0*TECNF3y#6yJvWKJL9_J+IrE*_ z@ZZ>fGxH+9o%a0?0Wqi}6tVozgkCQEzY`GuBYUGEsr>(MZ&bC^kkwGWqanutFbHrE zB8^Sri1Nq?0w|pzjN;7vlK}H_)?j*l1f+Bj%C4Q87f%~sAvNp^lO>gu8ShKG)0@+C zUNWITz%Bps_~m5F$%bc+_r&MdPEO1(oS_-lOT$yC!W8Z`4mqL>?R$)tWF}G8i!rRU zCFA~Ezj+?k1^) zE>0JPsSBel>%wB?VxoeWf7ZSG(+<|8m2EEs;r)^mm~j>i8b}MJMNg8^wxwJ^~L%!;ylPj%Ou6od5{gH+d=2N zuaej~58^}6Gg~hQ784m%O{O*?Jy;mj@X5Qj*0Lfl3U1p2ga?bK+V4gKdvaH`kaX$M zp3l)C=7|0116(+=JNkNoBy*)>XOgq7*mYI0RL6JD1JO>#o+65X|@OSRlF%S+9ghZtkC{;tyw#&hLSw2t# z1S>B>6R9CE#4Ks8yJL%1jCK_IL+b|kpG+A&B|ne7ucAt*sW3w*7Wk*8eQ(d>t#QYT zSZa$9quf#D?Nc<;FM`HX7&)3)437pLFhvAoY&a8jv*XSHhPptqYV~!cA!J;Xiu%Zz zzx=~ZnZxuVC|wJ}h8f(5(@bh-u-kGsA)~T%j-0u43#(M2Vk!aXW>JyA8kMVYM(nLy z(GaFEdjglBs1@#EuD~RuXpg}onC;Cvbl9arviHr!L_v+nHM=Zax+eBXqQ(0zodPAA zQFPT9N=}Ou*iMWr4f+5_A=K%!LB?$)3$F|Vw;*O$nFz9Nl{>uc5)~9ZT~@`%9Jj*x z0+ZM@+OtC;RD41iiqRtIaY0DYqw}V*+A_+3EFG?m4q2~gx~o@1C(Gq}jsV9W)NWJz zL8i1Og_Plxlf zB(%M-W9u?8${ne zzvAJPIAt_!B$pCdiYr-6vM6+lE7?fcOadsdg9d3CP83<8&(?{Xp|&=}JHV?@rgZ;q z6??wd#)arBbkFp^+?CuI{opoA)+%4>vyC;OqjPJ!viOShCBT>A)a9V4Nu|nb?L+p{-^YPIo`W+_Sj^h~?852Vdmv=cXWo#)W#aA-%$t(Yqbn%d8c?&7Or&HO9O&(0q^@4KgS2@q2 zjPLxI-Tp|u;B`bFyGFav+4R~^8IW9IEkFHzUgUbePH1yQRy|8Q){W33EQUfqN341; zV72sEI3^3KiEqe}E_RG(%hNmYa%cL2-|7K>vpE3XgQ~NBSb%pXN;50X78%`QJ1?Yo zT0SaVpXg-`+%^v2x`pIr83PUsSI@Xl4b!c4<_m|5pp;eD#NTZgC|Xu$@PyN(-$`X{ zheXsQGuwi{y)vq;^60n?===`NDeU~>`&T*^6d_r^3i|7p`9BHSf87tk`9JZW@^VW5 zRsFD1!%{=pVk2PM6&{;f;I3i`iv=-MUevFWq>sX(CxV~8=CvNDjA zWZ$i*4xb^%O5LCcsU~gJ5X(03c3+Q~Eq7+o^?UG?N4LC+%AU!&5;H@z)jUyk0CsY~ zev3lWPzz2;dP5RS@k*EF|>t zO8oH}@^Tk*d4O+n>fNI!SAw?RHn`~=zIVwrac!~>y|#H3G)S|twcuQ$l<>g8!^Dyy zj+|S<2wiuDaSdDWp6W-oW1FVi1XZLGKSl#EHjkMxG4(_zOGs;-rvJRnEw3_n2Z}(^V^<-koTdi>p;*Ls+oLF+=f z0fvQAM%6{_+GyIeFAa(gs}!-Pv$%z-mJ`v>;MyIHVs2Aoeg$dK5i!r;IvvHeb*!;6 zN7t4a>Sc8sjpLd>gtM3hd8rMLv#}kF<61x5UbI)Y=Ti0(RuR9h1%A1Tvk87x7Yc!x zD>DqwlMBXxokECToSXd?>%t_+>w{O}-deJU8NuXC2#V)W)6!$C zYOGUc7U4>K5OtWVh1%Eg=WUHeDzVMp6RsFoW*3LXiuR8vX$&Ubbsn#Xfkp*0S*o0# z(B)c2UzJjeHDPbV&Mrp{pC~>W67nkFMI10G+0JN@juU9i2%d>Gx`py^d`LLMTsI!+ z-s+2bC(p_=Kz#8Y9Z=?PSncUxhNV(3nptNKXJKj*w5e4}T%1o&s}a@mDusuaN8qex zz_H6S(pRV?w^SDkd*4`HrI$+l(X1%)B+#NuGZq?1X_Yf7(X?g9_C!cvnj)Skw!yrD z#<9i(maQ6;$qcxt&#Tx6r3SRGGcYsT=WS(Iq}i)2W@ZShtIUO69RH>B$= zCey=YU1_dNS#@l1zlCpywaMG1-Ee>GEYLVyhNdCtFSt{It|}$kWI9)0($OD@Tlslc zN?fz_13MSybIyydV>3(IKBx^o`p4#?!KTB8WdpC-Cd7uz<^mlpM3_m+Q(67Tf`RjN zOK2OJU1Cl4_a#zSM31jtfQd&+gxlQ$ox?L`JIU<9G0&$Eq;_KO5vxzyiv$6=Uj?2| zl3oJ8I?xx?%?TTTp4=~VoY+epr~oPSorimT1i(le2ien4_F5=xh!pmrf_Jijly>L& zLo}%(){^bA;-E0oyo9*ekj>fuN43mIex}?d@?3*Y;J_FnB972r)Hj%`M+!II89pwY zUm=;inP30heqVUVhL0a@V;UEyp^;bWz7c!W+T$+7=R z_JMBg#23!{1~-mvdk(S7jM6Z4Vv*MHIcfE+=^sdgWm5eOurPTpz%n%k)z{hJfq z{+Ii2V4uY2lK)KfD$|X1&;LpE?x6o2QU6DRTvSf}zYyeB{}SX|D}n0<8kXL^{lp(T3{2J2*}3WE!uvF7n3`?dNN$6{30 z2n{N3mXz7^7ln2e=p_~SO_(gI;dI1l?4TlhTq`s7js$h#>d#sY~_M- zJh`DKbH%7aWp7%JGE&UxA-A~AQ`V_bYvm|Ab37Z(3{|BkQ2$0}?x9=Fg+G8ec{4H> z8lJqJP-9ZVJNAHieQmjlvB>OD5llF?HVaDtX4YJS(-}&PN3KQPHA_)Bj95Ba{JFEV z)SWg?53v@JNU>4F!k<7Sr0o%`iMTO|alL{Jac5FSM75{WNUW~*w0QApnc{*n<3C1m zvFeG+o1M}B7}S)HGL=hhgD|KwTFfMqU^o|6@2f#CK(;DNa9l>mCYr_MxHO}4Ew;>F)&ANIfXt_3mocvJ;&>= zW?cdFHzZwb#_j|Xx038*_OW94FlnNFjrSQuPNqFDbY|~>Ovig1C>o6FZeg=55=&y;ucGji5^1YTDD6$fqD}-kn|e@zY%|jed?`+i85rtt!pucHQwb z*mW&NW7!R=J)!|Z*$xCstzaA43)ec$wZxm$$ga$Fiand)ul(wO=)-&y7I#F z1IL1IA;JyK@g%Cxwse&eV`qnEJ;6#|(mX!{u_g8V_H*WWnRhjl*R~N}$OdJ*JqKE2 zF4&sDNbgOlxLh0es6a_q1}zpUSC@dA6zlWqU^UHPpfJ6y zSchNWnC<&*{w!KLI<=Q5@B><%=2&kY1Jie&zu$NJWwzB@%q6v+l)BWm6Yike-`KNYSJ6`T z7XSxv_sj}joyc*EFhcqxd7Fov=LP1Vm>Q|PiTa-QDSbUGOqeFhj$s7&6R#koNx6!Z zbn)rp$*xCUzWQ!viST;6RPf!_w4t;;p%?(dK$4`?irJHE!Y;32oee zqd=Ni%CGDv{Xt@)nT9xu>NohMOH!?kJetX0{oy_CLP8On*mGdlug!w9!g!7K-YBgF zThb)$2@9+_tTYgs9A}BK#OUKcJcdvlPk0N3X$R|M?8Q>p7?S!UqzF$Oe!mbgKEq_x(q z+~#)|;Wlk=Ekfc2h*<1h!-9jVh!IfNjJ}Db`k%<95^`RFq`}9L)*lRfn_b{b_3pzY#!iJ*^>)eY=c6jia%px-bf6t>6ak^vQc3NulGh8+ z<@nvHwxw5ZC-Kl(>qG8kQJ}kLWg zTukP`c9!Rf$MN>b^yK%`%+1a3$^1(}@B!^+cO3E?@cN@ohu+sRW2_^`T=5%(G}&mKS|(@wvywjqHRy0aEIA1V@0|7az!9o*(4OsWBlK9|wr2a5 z;#0RS{%KG8M2$(1LreOCQ{3>yD+6(%!}R!V0@)KV0Wyzh4$R$o!&(J(;`GL#O{}ZC zvf@#nA-I;|mX`FgX(I(=fs(rhc+n(HG*p${p+hP%6M-#kOo%LTyC|;NYyn7b1VyS0 zPC>wuo4WHe?+v3n{aFSNQrpYeGPvp;! zbHA@LEgH9eE14035X>}cgquZvQ>1-G#nORHTiA`#KhZkUCQ>lwu)Ao(6ebI+9H8GX zXUyIySFAr3G}8)<^|=WyGj?yUR~9lxb7O7QTBbiyO zmCE$VOOnmWi#ii;^)`^rIV!J42j7ZEGi5Fc@4K0>0G+2XiZY~)G2o)Nba2q8i)YU! zr~|?D)Xudg=kVS$_-vTTx&whQt9oODVPTi*_KVsGTw#5oP?Qu++M2<=h6fFH)&#!l zIV!Sb^^sp_J_tm}&dHQf(Op(0>--IwxLvNwZV}M#X>3e2VRQbd4{bqvAQjAIWBgeB z8o9#QJ>=%>_^3EWK8wn}WNR5Q5ido3-vxu40T3ushhEl1Kw1e?DwNUD$h_UY?7r2< z523};PCBmCW)T0tiN@G$w>URjGdzpzTM^B)$5u<-;o56%+NPGkj`k>ldUP>2hCO<6 zY}?{NZhIffx0)+Jm7A=*V;-3i@x37OiO#ib+7u9|$xLOws0=eX5*@3d)q}QrDbv=? z$O|wl=mEZN`t73yWW1I9q~5$xUvJXUDgw^e*8l9d;Tf|7$Ly;3h`dR<%*FhkG5q=R zz*XBgZ>IE~_zexy+2_6IuCIni4j*JB%r1&MUV7hV9|;|@QudlCv3CnS(kPXtY8q%H z%YIB^qN{-rJ*0bre^{^LpeMCafiX89O*!1u*Z|d&?5e_0QdC5V*2Jd%t^(*0oIzBO zXM>y-5_z0|MLRA{g{1^Y6kRHv>4mL*%HdN~w5|ZM11k4DnVtPqb{4fjyn&xvAiQ@~ z^-E54;{BkeHf@mYf#O-uw1%<3hxEpdNIHe#llw9B|3Q%^>-ptiJzaMH>$R z9$3IX64@E*-$`Wd{~~m7HgR&MQ~u}lfBe@$*2GOf{(r4ZVfH8zshd`bpI55O2VYA-oSBws2zC|k4Q9DN4k>U8@52brsP3|8Glz$pP1WytU zd^7!e`Z}0lbJypPIj1)AV289mKTBau`g6_UIsG>CHhuKt`+YM)^{f0Y>Td^zD%oS= z&ibC5y5)GyC5!Y>{b#e`+PABwe|>R~)1<12+*Yx;HUs!#pdwB05WQ6iH^B!B$JR;A z)3q`ZtB?mh7Gz8F3y4u3eE=CJC1Q&V%NDwRD&FEkGEK>qti}X6(YQEOdsADP%Zrb< zz8Q7^*D3}a>x=Wyx*!oCSaRdC5)O`fXP$(O>ZuIXv%N`YB17#;vm$7v@Br3^3bRmO zhk1Qr4(+Ne#s-lgp>M@*BUt64WYt*cNu%q1yXgO^y>Ld`LnNepZl!) ztbOfkUlaJociVH+#-5MZuP!Yb0k~|f!-kuISYJd*qOIdgHAf4Zd?9aZ3ZvTqW6`11 zqvg`=G<{|Xl-i@pHZ0>s30u&zTnEejfMS=P+@5vGQM02WGWgq%Da?VbE;&zy`tQs) zJY(3O5pZ?0zt3kIt8qL1%_0P(Jbp@R#c4`WZ^hZ|AfCahv(p=5Z!!*BCPSVLx8|AL zTY!;=VQTReC-fmGKJJoDyBJn6akVXL!Ms9g9j&8L)tv@H1rjyo0K)PZ$UA?VP8}hi zEZc(`B#inlmxHO8&dq$_q{NO_TnV8ZXGJI}3FWBP$n%D`8jrM8mk*@n$5#~aCT{5o z7>z0w2RwSP5qN!0y@D2ZuTfQ-WOR`J5ibN?n7{AN3WBFj-Kyf`ekHenpc`w15dZnh zT#SzCf0~X2GHg)v;7(PKhEih3G6t8wB>ZcV4Hys@fF-HqNJ&XWY125Igi!aty_`mJ;~cB3ElrbRFiim>izY^H6GUDvtE{_R$D=h?#c3H(NM!y4jSS`e7Jl~ z)n)2Vj9}Xer$#0TBeH>Tfkn7sM-u;*n=eG|^=+m`q#+^hz{rSQV>lcQpN}h*t0=-5 zh$$4CD|5|xW$4OH|?$nbZKb&0}3`LCgHhT zlEIkg)8hGjWsjV8-+CJ>P1v4aQk+?lhHGxkq1lNfw5He}EtFv{OJ6t9Y2~EN6yAl^ zjY&lJ067C8qT|OSF{GA4mKW+(OZq2)Tk$d4%UdN$$_@7EhO>@R zrYtd7vD7adM#B0u?5+{K#JX;%ZCHDQnT=Wb_6AR|TtnB;s+>BV?BH$p2?}@NQ_7a0 zVewa@-tHss6}p$e2|t<`p&}(Y_)g*+ma$N@ryq^n;}-97F%`&13g8|&34G$PiXlSH zhq>K;+hNKbzqr|q;bTMATd8Nb`RGkY{WNhJ3j5Vp^o_iXUX)c|rWIk5oCHTw^pr&kNX_g2&80eLmESkJ`a|^5u3aEy5{v zs+r5E5P)NBoK;rGT`9^RTqF5qXd8W&zl@ICX2$#!M zolI<)pUSwBlcU8X;stysL6k9;`{m!iNlnC(h~>Pj#55dyUEG|25G93hph?=nNvUmN zh_tcny7$p}!JZL}!KJo9a$~o}kvNTbo8b(>?x|3a5J>MCIT}eY=>XGM%%t^!J@hMo+C=i2Zg#iBoYL9k5A+M7y#xE?W$3vp1j%oScA@{`pZ6bX z=s!O@ZLre^Ez&c)C!osB=CSMo17P6&&1{z#-J~%d%v}bxEvAUkYO7l^I;FJCmD!3= zV7UowpcPN>(&gL{Q?5uc;!BI;jUmB5yFQOdOhkDWSZT+al z=L}PtRR?2?4_T-mmy%g5{z!kVD6XFt^t^7lCt7fyv;Ho{&Al0;2`!%62#2RK`Z`Yy z`IL9{AihOBvT#8E&`c5TK}Z}s>_LlIS5`iV33i8y0^dT&|CLS;rky$mW{QBKzNYp* zd&flM5iJCnGD!oA{PaVGQ#IF2UVtK!)x2_Wq_^RndCUm6CPO5@bSods+_)rhH!628 z9HRYrx+AtSm<48P_$*hdYfFDzF!ZgVos;e?8~gF{U=OQZlWIL^5${o`Pb3V*dOCiv}JQ>l4n zbHb|8swNvL*(?Te3bnG`(w*_pXniW-vCog!Mw08^H@(-SN;2S@GwRu1Wvh31C@mtZ z%S|fkYw_aVO%_#6*C(|BKo~mnXLH;xZQR)D*=WmxkbKlv<*-_nbyU@)g7^ms9uL;2 z$i-W8PY7-8)PFhC75`h&%OiXh|WTxSE?+?2;>o5)^lDX)*Lhy*~r zx$2amXGHWYe)9+#mMg??wYn^GJ>V(P7d`~=-pq{AkNr-$!!nRDi0`GjJw?bORi*O_ zK<^UPBCkHq>^C`y$kEiWVT#T>YO2tF>F%L~{D&r_BnhNZW%cyh0E7d);j!Oph_ft0 z^-1{c)vdvn4`&8WSFU!FT?uf`Q6A|BIs@DLr*7PT2W%LyCTYfnf`7iX00 zDeh4U7uI%Zk}2wojFOAe-~9UVfQ(jMHwE{h_GIm%J3{qw&VZAPV_<$%F&ZYkgS=ig zAYykK!z>L4O(M>?tF5spKTND+H_`Z|GUZBtXbJRH9HrVg%ZYHA!jeio;kLI+btVCB z1X@$KAW1*tOg*;atS-pPb~}&(e~1D{c*rwq?I!-BgGt|+G;;pb-*U^taIXDGTV{x~@TLrMRp+w>VaMR8_ zy5Z77x$oE-B=Vt27(HDmM!H3ylm8lQZ+?`FdnTdjg0yNAItIbF!~o!wA~qQ zO#~;zNoSu2fc^81#q;u+k^QQR8{M$>U4>Kc0G(f0~*QJ1? za_MRDP#5yB>cYH)H0eC;Uw{GR^q=nD1Rvq ze%1!mj48hbM{ya&uu}bOj z4mLP}*-=q~ZP|5#+|TMTfHX1`ZWgdEwKO;QbGMJq;-k&aPiPIFNa#pn^;^0Q`kZYZ z84n!q`_OsgrUUFbYn9TaVh6EOyxL++&HX!NdWC6NKT<_ftLzd@2qY>dzPFbg7NSt4 zIE+c;Cw0S^_%xZfZ=x`$igBa!h?-qDot-93;UwC0(f4!kOWt>_uN|HVh!7FiiX{(< zm8Loc9jLTD7-maHcpOR&eGuVTz&ny_Cy3ml4R$RW!Vp%C{6z8j{cOEcm*QcDbDy%l zp%=lcclbx|m|gcHt7)fM(*qlxR8(ZR+1ehp28SA8qD7b5h^5HDatzE{DF^9h);{5A z`F+s2^wHG@>$R;DjPGErVz#EWx6TZ2xxSSfrDw$v9(>!Umk{8S5JJ=h7ShYaNH_m$fvK@I8M zXOu=W=qk!$jn}%P$NQ68v3@Z2RRcJ!t`?Y&o4y?3AtGbv0w{yZxI?6&p#4yFusPP3*SZgN|xu7RW92w5cV7TKj zNWsZM%*xEi=Aho6uA3pb(xHPvI&-dJd=n~Pt}V#4cO0Gtq4u-&!-hx1SwCK@g3niG zN{9>rG|FX7o?(yq*_iuD)eB7J85r4iDeyjD0^OR9-#1x`TBbtep}T6{(Jp_+h+^q4 z9=0&&uO!oZ&}8KNB;IdGqgz8qXa*-Pg`fEw^kvFlbMqf6C691;l>+xZ%BNgdSQ zh3t!w%+?p-eA+3auyH1u!(NJ>*mBN?;Q?mRBI4{C#Nd(7MIZ$3q>`;VhOPd3mgiz= zM}5r5)P~cFP1Hk6u^cloCHe49+hu8AJff|`OgjHtSQN8<6&V?pHLxH;i`ftR5^1rd z?^0Vbx2bd$dsu~VeWfz%kD+pCHODrcVhp#@IDlj?Rr<52fN=E$j1T4f^;~J6J0O9q zE)w*#W@dqQa%EPiJT9=s_3tdbV5SJSQ|DP+o)5 z8-Q0%>O6hecD+3iueB)DSgxC~i){L2%gp-t18c-Ia!xe84OaZMu{ivoV#AV(DF}R5 zcCfPL7FvxlZ*zl*`3S6J3EOwg7GexTWDtygo<*z0I_#$)jNX4a@tttb;} zC%O`B-4E*C5x~3G#Vb1O(#sFE0;&ipJHNmHkl)vk9|_CbDfY9#m>9o#AMP}Q+3_Y@ zWgyIWQRJ34cez(#nf7V~2F zehgzPumiMsggA1=ShIcABL|zk&Chx&>I6oeeGgqc{N(FPJFoZJ#acLLy0crJZkWcp z#B(qwDxE&MK?ra_+tdfmiN(c9=PZ*{E+6*~)PPy>f+$gr=-L4O>ITSq$4ZoTQ*t%$ zc#Vxvi8oz|JIS$M3jbk(M)z7Q&z%q1lEVH1FXLz3ZC6@+IRlH5(xF?1)pkoKYx0{0 zwMJEzO>vtpVG}hwyelr@gZ5FxD+Y=Z20U5EO~kz-$F^)llS>Ak)@E3q)booCMDrai z&}VBkK@#)P)(F-ZOQzM9FUyg7Lma03QcL7#=Jn~e1HCqG1dl=N zTaQeLyaW`#9-b&zY%9i!zdJzR7A@sD67ncai|#)dA3W_p=m#2W5+(8n>WEX#1-W2; z&bQy-$Hy|?9>et(^M^P8<;#%zMXRWxWz}v0Nb8$r73^J~=r3Hpx;yI7R11y?6Ebq7 zA;=(YnL%?gqr<0lMOW(JUdX-0!S8niK|3t-9A_FzHu}3|F{ED&*pKZ`|8|s{Z48Sl zJg*(h{;nOaqmf?w>9l&;BK5*)_1E|}-_-};pII*KR4;qhU33_J2ITzqccUklNVxwL zB$v!pufklmvf}=Uaeha3E@Ay0%>T2)yPEp4xy^-r%g-=BZ^ZvD^*=ddUCn;kHs-=0 z=Vz3i>u!IS{r^bGi+P-1?Q*VSTpm>Xbp=&~zsL9|JDRK6FAp01y2ClZ-)H~d;i7*T zeY^^DS&n=$we&M&8UF<4H#1CEp)O0;eqB)j=N~}*o7(v*%w;{tg%0j#!1?|F=3iBD zS8*=4|9)K#K;#c_{!J@#73MPc{ws{y`F{QGOaA*i__xmDRhY|k#|4r9GeqzIGt8gT z`d5)I*9#Z)$3;xEsIp=J literal 0 HcmV?d00001 diff --git a/seller-api/src/main/java/cn/lili/controller/order/OrderStoreController.java b/seller-api/src/main/java/cn/lili/controller/order/OrderStoreController.java index f8fb7c2c..d1345a1b 100644 --- a/seller-api/src/main/java/cn/lili/controller/order/OrderStoreController.java +++ b/seller-api/src/main/java/cn/lili/controller/order/OrderStoreController.java @@ -120,6 +120,14 @@ public class OrderStoreController { return ResultUtil.data(orderService.delivery(orderSn, logisticsNo, logisticsId)); } + @PreventDuplicateSubmissions + @ApiOperation(value = "订单顺丰发货") + @ApiImplicitParam(name = "orderSn", value = "订单sn", required = true, dataType = "String", paramType = "path") + @PostMapping(value = "/{orderSn}/shunfeng/delivery") + public ResultMessage shunFengDelivery(@NotNull(message = "参数非法") @PathVariable String orderSn) { + return ResultUtil.data(orderService.shunFengDelivery(orderSn)); + } + @PreventDuplicateSubmissions @ApiOperation(value = "取消订单") @ApiImplicitParams({ @@ -200,7 +208,7 @@ public class OrderStoreController { @ApiImplicitParam(name = "logisticsId", value = "物流公司", required = true, dataType = "String", paramType = "query") }) public ResultMessage createElectronicsFaceSheet(@NotNull(message = "参数非法") @PathVariable String orderSn, - @NotNull(message = "请选择物流公司") String logisticsId) throws Exception { + @NotNull(message = "请选择物流公司") String logisticsId) { return ResultUtil.data(logisticsService.labelOrder(orderSn, logisticsId)); } } \ No newline at end of file diff --git a/seller-api/src/main/java/cn/lili/controller/other/LogisticsStoreController.java b/seller-api/src/main/java/cn/lili/controller/other/LogisticsStoreController.java index 2571ab17..40c0f783 100644 --- a/seller-api/src/main/java/cn/lili/controller/other/LogisticsStoreController.java +++ b/seller-api/src/main/java/cn/lili/controller/other/LogisticsStoreController.java @@ -1,13 +1,21 @@ package cn.lili.controller.other; +import cn.hutool.json.JSONUtil; +import cn.lili.common.enums.ResultCode; import cn.lili.common.enums.ResultUtil; +import cn.lili.common.exception.ServiceException; import cn.lili.common.security.context.UserContext; import cn.lili.common.vo.ResultMessage; import cn.lili.modules.member.service.StoreLogisticsService; import cn.lili.modules.store.entity.dos.StoreLogistics; import cn.lili.modules.store.entity.dto.StoreLogisticsCustomerDTO; +import cn.lili.modules.system.entity.dos.Setting; +import cn.lili.modules.system.entity.dto.ImSetting; +import cn.lili.modules.system.entity.dto.LogisticsSetting; +import cn.lili.modules.system.entity.enums.SettingEnum; import cn.lili.modules.system.entity.vo.StoreLogisticsVO; +import cn.lili.modules.system.service.SettingService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; @@ -36,6 +44,9 @@ public class LogisticsStoreController { @Autowired private StoreLogisticsService storeLogisticsService; + @Autowired + private SettingService settingService; + @ApiOperation(value = "获取商家物流公司列表,如果已选择则checked有值") @GetMapping public ResultMessage> get() { @@ -99,4 +110,18 @@ public class LogisticsStoreController { return ResultUtil.data(storeLogisticsService.getStoreLogisticsInfo(logisticsId)); } + @ApiOperation(value = "获取IM接口前缀") + @GetMapping("/setting") + public ResultMessage getUrl() { + String logisticsType; + try { + Setting logisticsSettingVal = settingService.get(SettingEnum.LOGISTICS_SETTING.name()); + LogisticsSetting logisticsSetting = JSONUtil.toBean(logisticsSettingVal.getSettingValue(), LogisticsSetting.class); + logisticsType = logisticsSetting.getType(); + } catch (Exception e) { + throw new ServiceException(ResultCode.ORDER_LOGISTICS_ERROR); + } + return ResultUtil.data(logisticsType); + } + } diff --git a/seller-api/src/main/java/cn/lili/controller/passport/StorePassportController.java b/seller-api/src/main/java/cn/lili/controller/passport/StorePassportController.java index 864cd1b8..d9c95721 100644 --- a/seller-api/src/main/java/cn/lili/controller/passport/StorePassportController.java +++ b/seller-api/src/main/java/cn/lili/controller/passport/StorePassportController.java @@ -11,6 +11,7 @@ import cn.lili.common.security.enums.UserEnums; import cn.lili.common.vo.ResultMessage; import cn.lili.modules.member.entity.dos.Member; import cn.lili.modules.member.service.MemberService; +import cn.lili.modules.sms.SmsUtil; import cn.lili.modules.verification.entity.enums.VerificationEnums; import cn.lili.modules.verification.service.VerificationService; import io.swagger.annotations.Api; @@ -41,6 +42,9 @@ public class StorePassportController { @Autowired private MemberService memberService; + @Autowired + private SmsUtil smsUtil; + @Autowired private VerificationService verificationService; @@ -59,6 +63,22 @@ public class StorePassportController { } } + @ApiOperation(value = "短信登录接口") + @ApiImplicitParams({ + @ApiImplicitParam(name = "mobile", value = "手机号", required = true, paramType = "query"), + @ApiImplicitParam(name = "code", value = "验证码", required = true, paramType = "query") + }) + @PostMapping("/smsLogin") + public ResultMessage smsLogin(@NotNull(message = "手机号为空") @RequestParam String mobile, + @NotNull(message = "验证码为空") @RequestParam String code, + @RequestHeader String uuid) { + if (smsUtil.verifyCode(mobile, VerificationEnums.LOGIN, uuid, code)) { + return ResultUtil.data(memberService.mobilePhoneStoreLogin(mobile)); + } else { + throw new ServiceException(ResultCode.VERIFICATION_SMS_CHECKED_ERROR); + } + } + @ApiOperation(value = "注销接口") @PostMapping("/logout") public ResultMessage logout() { @@ -66,6 +86,33 @@ public class StorePassportController { return ResultUtil.success(); } + @ApiOperation(value = "通过短信重置密码") + @ApiImplicitParams({ + @ApiImplicitParam(name = "mobile", value = "手机号", required = true, paramType = "query"), + @ApiImplicitParam(name = "password", value = "是否保存登录", required = true, paramType = "query") + }) + @PostMapping("/resetByMobile") + public ResultMessage resetByMobile(@NotNull(message = "手机号为空") @RequestParam String mobile, + @NotNull(message = "验证码为空") @RequestParam String code, + @RequestHeader String uuid) { + //校验短信验证码是否正确 + if (smsUtil.verifyCode(mobile, VerificationEnums.FIND_USER, uuid, code)) { + //校验是否通过手机号可获取会员,存在则将会员信息存入缓存,有效时间3分钟 + memberService.findByMobile(uuid, mobile); + return ResultUtil.success(); + } else { + throw new ServiceException(ResultCode.VERIFICATION_SMS_CHECKED_ERROR); + } + } + @ApiOperation(value = "修改密码") + @ApiImplicitParams({ + @ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "query") + }) + @PostMapping("/resetPassword") + public ResultMessage resetByMobile(@NotNull(message = "密码为空") @RequestParam String password, @RequestHeader String uuid) { + return ResultUtil.data(memberService.resetByMobile(uuid, password)); + } + @ApiOperation(value = "修改密码") @ApiImplicitParams({ @ApiImplicitParam(name = "password", value = "旧密码", required = true, paramType = "query"), @@ -86,7 +133,4 @@ public class StorePassportController { public ResultMessage refreshToken(@NotNull(message = "刷新token不能为空") @PathVariable String refreshToken) { return ResultUtil.data(this.memberService.refreshStoreToken(refreshToken)); } - - - }