diff --git a/script/idea/http-client.env.json b/script/idea/http-client.env.json index e6e8a7c..f69838b 100644 --- a/script/idea/http-client.env.json +++ b/script/idea/http-client.env.json @@ -1,10 +1,10 @@ { "local": { - "baseUrl": "http://127.0.0.1:48080/admin-api", + "baseUrl": "http://127.0.0.1:48088/admin-api", "token": "test1", "adminTenantId": "1", - "appApi": "http://127.0.0.1:48080/app-api", + "appApi": "http://127.0.0.1:48088/app-api", "appToken": "test247", "appTenantId": "1" }, diff --git a/yudao-framework/yudao-common/pom.xml b/yudao-framework/yudao-common/pom.xml index f364df7..85cdbd7 100644 --- a/yudao-framework/yudao-common/pom.xml +++ b/yudao-framework/yudao-common/pom.xml @@ -133,6 +133,7 @@ transmittable-thread-local + com.fhs-opensource easy-trans-anno diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java index 1e65aec..d185339 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java @@ -38,6 +38,9 @@ public interface ErrorCodeConstants { ErrorCode ORDER_CANCEL_PAID_FAIL = new ErrorCode(1_011_000_033, "交易订单取消支付失败,原因:订单不是【{}】状态"); ErrorCode ORDER_PICK_UP_FAIL_NOT_VERIFY_USER = new ErrorCode(1_011_000_034, "交易订单自提失败,原因:你没有核销该门店订单的权限"); ErrorCode ORDER_CREATE_FAIL_INSUFFICIENT_USER_POINTS = new ErrorCode(1_011_000_035, "交易订单创建失败,原因:用户积分不足"); + ErrorCode OMS_EXPRESS_ORDER_CREATE_ERROR = new ErrorCode(1_011_000_036, "快递订单创建失败,原因:{}"); + ErrorCode ORDER_DELIVERY_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1_011_000_037, "交易订单取消发货失败,订单不是【已发货】状态"); + ErrorCode OMS_EXPRESS_ORDER_CANCEL_ERROR = new ErrorCode(1_011_000_036, "快递订单取消失败,原因:{}"); // ========== After Sale 模块 1-011-000-100 ========== ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在"); diff --git a/yudao-module-mall/yudao-module-trade-biz/pom.xml b/yudao-module-mall/yudao-module-trade-biz/pom.xml index fb046ee..cdb8fb1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/pom.xml +++ b/yudao-module-mall/yudao-module-trade-biz/pom.xml @@ -92,6 +92,14 @@ cn.iocoder.boot yudao-spring-boot-starter-excel + + + + com.github.kuaidi100-api + sdk + 1.0.23 + compile + diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.http b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.http index 5255d1b..1ebe27e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.http +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.http @@ -11,4 +11,20 @@ tenant-id: {{adminTenantId}} ### 获得交易订单的物流轨迹 => 成功 GET {{baseUrl}}/trade/order/get-express-track-list?id=21 Authorization: Bearer {{token}} -tenant-id: {{adminTenantId}} \ No newline at end of file +tenant-id: {{adminTenantId}} + + +### 申通快递订单创建 +PUT {{baseUrl}}/trade/order/delivery-STO?id=14 +Authorization: Bearer {{token}} +tenant-id: {{adminTenantId}} + +### 快递100订单创建 +PUT {{baseUrl}}/trade/order/delivery-kuaidi100?id=14 +Authorization: Bearer {{token}} +tenant-id: {{adminTenantId}} + +### 快递100订单取消 +PUT {{baseUrl}}/trade/order/cancel-kuaidi100?id=14 +Authorization: Bearer {{token}} +tenant-id: {{adminTenantId}} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java index a517ea1..6a4d449 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderLogDO; import cn.iocoder.yudao.module.trade.service.order.TradeOrderLogService; import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; +import com.kuaidi100.sdk.response.PrintBaseResp; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -115,6 +116,28 @@ public class TradeOrderController { return success(true); } + @PutMapping("/delivery-STO") + @Operation(summary = "申通快递订单创建") + @PreAuthorize("@ss.hasPermission('trade:order:update')") + public CommonResult deliverySto(@RequestParam("id") Long id) { + tradeOrderUpdateService.deliverySto(id); + return success(true); + } + + @PutMapping("/delivery-kuaidi100") + @Operation(summary = "申通快递(快递100)订单创建") + @PreAuthorize("@ss.hasPermission('trade:order:update')") + public CommonResult deliveryKuaidi100(@RequestParam("id") Long id) { + return success(tradeOrderUpdateService.deliveryKuaidi100(id)); + } + + @PutMapping("/cancel-kuaidi100") + @Operation(summary = "申通快递(快递100)面单取消") + @PreAuthorize("@ss.hasPermission('trade:order:update')") + public CommonResult cancelKuaidi100(@RequestParam("id") Long id) { + return success(tradeOrderUpdateService.cancelKuaidi100(id)); + } + @PutMapping("/update-remark") @Operation(summary = "订单备注") @PreAuthorize("@ss.hasPermission('trade:order:update')") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderBaseVO.java index 88f5b0c..83949b6 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderBaseVO.java @@ -105,6 +105,9 @@ public class TradeOrderBaseVO { @Schema(description = "发货物流单号", example = "1024") private String logisticsNo; + @Schema(description = "发货物流面单短链", example = "1024") + private String logisticsLabel; + @Schema(description = "发货时间") private LocalDateTime deliveryTime; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java index bd6ed90..be91e38 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java @@ -210,6 +210,12 @@ public class TradeOrderDO extends BaseDO { * 如果无需发货,则 logisticsNo 设置 ""。原因是,不想再添加额外字段 */ private String logisticsNo; + /** + * 发货物流面单短链 + * + * 如果无需发货,则 logisticsLabel 设置 ""。原因是,不想再添加额外字段 + */ + private String logisticsLabel; /** * 发货时间 */ diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java index cd1cee7..bd1cc11 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettle import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import com.kuaidi100.sdk.response.PrintBaseResp; import javax.validation.constraints.NotNull; import java.util.List; @@ -218,4 +219,9 @@ public interface TradeOrderUpdateService { */ void updateOrderGiveCouponIds(Long userId, Long orderId, List giveCouponIds); + void deliverySto(Long id); + + String deliveryKuaidi100(Long id); + + String cancelKuaidi100(Long id); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 3cae537..cc53379 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -13,8 +13,11 @@ import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.module.member.api.address.MemberAddressApi; import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO; +import cn.iocoder.yudao.module.member.api.point.MemberPointApi; +import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; @@ -52,23 +55,49 @@ import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryPickUpStoreService; import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.StoOrderCreateContentBo; +import cn.iocoder.yudao.module.trade.service.order.bo.StoRequestBo; +import cn.iocoder.yudao.module.trade.service.order.bo.StoResponseBo; import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler; import cn.iocoder.yudao.module.trade.service.price.TradePriceService; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper; +import cn.iocoder.yudao.module.trade.util.SignatureUtils; +import com.alibaba.fastjson.JSON; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.kuaidi100.sdk.api.LabelV2; +import com.kuaidi100.sdk.contant.ApiInfoConstant; +import com.kuaidi100.sdk.contant.CompanyConstant; +import com.kuaidi100.sdk.contant.PrintType; +import com.kuaidi100.sdk.core.IBaseClient; +import com.kuaidi100.sdk.pojo.HttpResult; +import com.kuaidi100.sdk.request.LabelCancelParam; +import com.kuaidi100.sdk.request.ManInfo; +import com.kuaidi100.sdk.request.PrintReq; +import com.kuaidi100.sdk.request.labelV2.OrderReq; +import com.kuaidi100.sdk.response.PrintBaseResp; +import com.kuaidi100.sdk.response.PrintCloudData; +import com.kuaidi100.sdk.response.labelV2.OrderResult; +import com.kuaidi100.sdk.response.labelV2.Result; +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.http.*; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; import javax.validation.constraints.NotNull; +import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Set; +import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; @@ -120,11 +149,32 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Resource public PayRefundApi payRefundApi; + @Resource + private MemberPointApi memberPointApi; + @Resource private TradeOrderProperties tradeOrderProperties; + private static final String key = "moaqEZhD6889"; + private static final String secret = "f46d0c0071be4841818482c5ed8c27b5"; + // =================== Order =================== + @Value("${sto.api_url}") + private String api_url; + + @Value("${sto.from_appkey}") + private String from_appkey; + + @Value("${sto.from_code}") + private String from_code; + + @Value("${sto.to_appkey}") + private String to_appkey; + + @Value("${sto.to_code}") + private String to_code; + @Override public AppTradeOrderSettlementRespVO settlementOrder(Long userId, AppTradeOrderSettlementReqVO settlementReqVO) { // 1. 获得收货地址 @@ -403,6 +453,303 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { getSelf().sendDeliveryOrderMessage(order, deliveryReqVO); } + @Override + public void deliverySto(Long id) { + // 1.1 校验并获得交易订单(可发货) + TradeOrderDO order = validateOrderDeliverable(id); + // 1.2 校验 deliveryType 是否为快递,是快递才可以发货 + if (ObjectUtil.notEqual(order.getDeliveryType(), DeliveryTypeEnum.EXPRESS.getType())) { + throw exception(ORDER_DELIVERY_FAIL_DELIVERY_TYPE_NOT_EXPRESS); + } + if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus())) { + throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); + } + StoOrderCreateContentBo orderCreateContentBo = new StoOrderCreateContentBo(); + orderCreateContentBo.setOrderNo(order.getNo()); + //todo + orderCreateContentBo.setOrderSource("WMYKT"); + + orderCreateContentBo.setBillType("00"); + orderCreateContentBo.setOrderType("01"); + orderCreateContentBo.setSender(new StoOrderCreateContentBo.Sender() + .setName("杨林").setMobile("15325380110") + .setProvince("浙江省").setCity("嘉兴市").setArea("南湖区") + .setAddress("新嘉街道建国北路锦江商务楼3A") + ); + +// String area = AreaUtils.format(order.getReceiverAreaId()); + String[] areas = AreaUtils.format(order.getReceiverAreaId()).split(" "); + orderCreateContentBo.setReceiver(new StoOrderCreateContentBo.Receiver() + .setName(order.getReceiverName()).setMobile(order.getReceiverMobile()) + .setProvince(areas.length > 0 ? areas[0] : "") + .setCity(areas.length > 1 ? areas[1] : "") + .setArea(areas.length > 2 ? areas[2] : "") + .setAddress(order.getReceiverDetailAddress()) + ); + //todo + orderCreateContentBo.setCargo(new StoOrderCreateContentBo.Cargo() + .setBattery("10") + .setGoodsType("小件") + .setGoodsName("测试物品") + ); + orderCreateContentBo.setCustomer(new StoOrderCreateContentBo.Customer() + .setSiteCode("314056") + .setCustomerName("314056015779") + .setSitePwd("JXsto123") + ); + /* orderCreateContentBo.setCustomer(new StoOrderCreateContentBo.Customer() + .setSiteCode("666666") + .setCustomerName("666666000001") + .setSitePwd("abc123") + );*/ + String content = JSON.toJSONString(orderCreateContentBo); + // 创建申通发货订单 + /* StoRequestBo requestBo = new StoRequestBo(); + requestBo.setApi_name("OMS_EXPRESS_ORDER_CREATE"); + requestBo.setContent(content); + requestBo.setFrom_appkey(from_appkey); + requestBo.setFrom_code(from_code); + requestBo.setTo_appkey(to_appkey); + requestBo.setTo_code(to_code); + requestBo.setData_digest(SignatureUtils.getSignature(content, from_appkey));*/ + + // 设置请求头 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + + // 将 StoRequestBo 转换为表单参数 + MultiValueMap formData = new LinkedMultiValueMap<>(); + formData.add("api_name", "OMS_EXPRESS_ORDER_CREATE"); + formData.add("content", content); + formData.add("from_appkey", from_appkey); + formData.add("from_code", from_code); + formData.add("to_appkey", to_appkey); + formData.add("to_code", to_code); + formData.add("data_digest", SignatureUtils.getSignature(content, from_appkey)); + // 创建请求实体 + HttpEntity> requestEntity = new HttpEntity<>(formData, headers); + + // 创建RestTemplate + RestTemplate restTemplate = new RestTemplate(); +// try { + // 发送请求并解析响应 + ResponseEntity response = restTemplate.exchange( + api_url, + HttpMethod.POST, + requestEntity, + String.class + ); + String responseBody = new String(response.getBody().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); + +// String responseBody = response.getBody(); + log.info("[deliverySto][申通快递响应内容: {}]", responseBody); + // 手动解析响应 + + StoResponseBo body = JSON.parseObject(responseBody, StoResponseBo.class); + +// StoResponseBo body = response.getBody(); + if (body != null && body.isSuccess()) { + // 2. 更新订单为已发货 + TradeOrderDO updateOrderObj = new TradeOrderDO(); + // 2.1 快递发货 + DeliveryExpressDO express = null; + TradeOrderDeliveryReqVO deliveryReqVO = new TradeOrderDeliveryReqVO(); + deliveryReqVO.setId(order.getId()); + //1是申通 + deliveryReqVO.setLogisticsId(1L); + deliveryReqVO.setLogisticsNo(body.getData().getWaybillNo()); + if (ObjectUtil.notEqual(deliveryReqVO.getLogisticsId(), TradeOrderDO.LOGISTICS_ID_NULL)) { + express = deliveryExpressService.validateDeliveryExpress(deliveryReqVO.getLogisticsId()); + updateOrderObj.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo()); + } else { + // 2.2 无需发货 + updateOrderObj.setLogisticsId(0L).setLogisticsNo(""); + } + // 执行更新 + updateOrderObj.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now()); + int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), updateOrderObj); + if (updateCount == 0) { + throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); + } + + // 3. 记录订单日志 + TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.DELIVERED.getStatus(), + MapUtil.builder().put("deliveryName", express != null ? express.getName() : "") + .put("logisticsNo", express != null ? deliveryReqVO.getLogisticsNo() : "").build()); + + // 4.1 发送站内信 + tradeMessageService.sendMessageWhenDeliveryOrder(new TradeOrderMessageWhenDeliveryOrderReqBO() + .setOrderId(order.getId()).setUserId(order.getUserId()).setMessage(null)); + // 4.2 发送订阅消息 + getSelf().sendDeliveryOrderMessage(order, deliveryReqVO); + } else { + if (body != null) { + throw exception(OMS_EXPRESS_ORDER_CREATE_ERROR, body.getErrorMsg()); + } else { + throw exception(OMS_EXPRESS_ORDER_CREATE_ERROR, "接口无返回内容"); + } + } +// } catch (Exception e) { +// log.error("[deliverySto][申通快递订单创建失败,订单ID:{}]", id, e); +// throw exception(OMS_EXPRESS_ORDER_CREATE_ERROR, e.getMessage()); +// } + + } + + @Override + public String deliveryKuaidi100(Long id) { + // 1.1 校验并获得交易订单(可发货) + TradeOrderDO order = validateOrderDeliverable(id); + // 1.2 校验 deliveryType 是否为快递,是快递才可以发货 + if (ObjectUtil.notEqual(order.getDeliveryType(), DeliveryTypeEnum.EXPRESS.getType())) { + throw exception(ORDER_DELIVERY_FAIL_DELIVERY_TYPE_NOT_EXPRESS); + } + if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus())) { + throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); + } + + //授权码 +// String key = "moaqEZhD6889"; +// String secret = "f46d0c0071be4841818482c5ed8c27b5"; + + ManInfo recManInfo = new ManInfo(); + recManInfo.setName(order.getReceiverName()); + recManInfo.setMobile(order.getReceiverMobile()); + recManInfo.setPrintAddr(AreaUtils.format( + order.getReceiverAreaId()).replace(" ", "") + +order.getReceiverDetailAddress()); + + ManInfo sendManInfo = new ManInfo(); + sendManInfo.setName("杨林"); + sendManInfo.setMobile("15325380110"); + sendManInfo.setPrintAddr("浙江省嘉兴市南湖区新嘉街道建国北路锦江商务楼3A"); + + OrderReq orderReq = new OrderReq(); + orderReq.setKuaidicom(CompanyConstant.ST); + orderReq.setCount(1); + orderReq.setPartnerId("314056015875");//电子面单客户账户或月结账号 + orderReq.setPartnerKey("123456");//电子面单密码 + orderReq.setNet("314056");//收件网点名称 + orderReq.setCode("44");//电子面单承载编号 +// orderReq.setSiid("siid"); + orderReq.setTempId("bc7291b4521c40d981767247c1e8f52d");//主单模板 + orderReq.setSendMan(sendManInfo); + orderReq.setRecMan(recManInfo); + +// orderReq.setPrintType(PrintType.CLOUD); + orderReq.setPrintType(PrintType.IMAGE); + + String param = new Gson().toJson(orderReq); + String t = System.currentTimeMillis() + ""; + + PrintReq printReq = new PrintReq(); + printReq.setT(t); + printReq.setKey(key); + printReq.setSign(SignUtils.printSign(param, t, key, secret)); + printReq.setMethod(ApiInfoConstant.ORDER); + printReq.setParam(param); + + IBaseClient baseClient = new LabelV2(); + try { + HttpResult httpResult = baseClient.execute(printReq); + System.out.println(httpResult); + if (httpResult.getStatus() == org.apache.http.HttpStatus.SC_OK && StringUtils.isNotBlank(httpResult.getBody())){ + Result result = new Gson().fromJson(httpResult.getBody(),new TypeToken>(){}.getType()); + if (result.getCode() == 200){ + // 2. 更新订单为已发货 + TradeOrderDO updateOrderObj = new TradeOrderDO(); + // 2.1 快递发货 + TradeOrderDeliveryReqVO deliveryReqVO = new TradeOrderDeliveryReqVO(); + deliveryReqVO.setId(order.getId()); + //1是申通 + deliveryReqVO.setLogisticsId(1L); + //快递单号 + deliveryReqVO.setLogisticsNo(result.getData().getKuaidinum()); + DeliveryExpressDO express = deliveryExpressService.validateDeliveryExpress(deliveryReqVO.getLogisticsId()); + updateOrderObj.setLogisticsId(deliveryReqVO.getLogisticsId()) + .setLogisticsNo(deliveryReqVO.getLogisticsNo()) + .setLogisticsLabel(result.getData().getLabel()); + + // 执行更新 + updateOrderObj.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now()); + int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), updateOrderObj); + if (updateCount == 0) { + throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); + } + + // 3. 记录订单日志 + TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.DELIVERED.getStatus(), + MapUtil.builder().put("deliveryName", express != null ? express.getName() : "") + .put("logisticsNo", express != null ? deliveryReqVO.getLogisticsNo() : "").build()); + + // 4.1 发送站内信 + tradeMessageService.sendMessageWhenDeliveryOrder(new TradeOrderMessageWhenDeliveryOrderReqBO() + .setOrderId(order.getId()).setUserId(order.getUserId()).setMessage(null)); + // 4.2 发送订阅消息 + getSelf().sendDeliveryOrderMessage(order, deliveryReqVO); + return result.getData().getLabel(); + }else { + throw exception(OMS_EXPRESS_ORDER_CREATE_ERROR, result.getMessage()); + } + }else { + throw exception(OMS_EXPRESS_ORDER_CREATE_ERROR, "接口无返回内容"); + } + } catch (Exception e) { + throw exception(OMS_EXPRESS_ORDER_CREATE_ERROR, e.getMessage()); + } + + } + + @Override + public String cancelKuaidi100(Long id) { + // 1.1 校验并获得交易订单(可发货) + TradeOrderDO order = validateOrderDeliverable(id); + // 1.2 校验 deliveryType 是否为快递,是快递才可以发货 + if (ObjectUtil.notEqual(order.getDeliveryType(), DeliveryTypeEnum.EXPRESS.getType())) { + throw exception(ORDER_DELIVERY_FAIL_DELIVERY_TYPE_NOT_EXPRESS); + } + if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.DELIVERED.getStatus())) { + throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_DELIVERED); + } + LabelCancelParam labelCancelParam = new LabelCancelParam(); + labelCancelParam.setPartnerId("314056015875"); + labelCancelParam.setPartnerKey("123456"); + labelCancelParam.setNet("314056"); + labelCancelParam.setCode("44"); + labelCancelParam.setKuaidicom(CompanyConstant.ST); + labelCancelParam.setKuaidinum(order.getLogisticsNo()); + //快递公司订单号(对应下单时返回的kdComOrderNum,如果没有可以不传,否则必传) + labelCancelParam.setOrderId("01639366271685GNkZEX"); + //业务员编码,部分快递公司必填 +// labelCancelParam.setCheckMan("123"); + //产品业务类型,部分快递公司必填 + labelCancelParam.setExpType("标准快递"); + + labelCancelParam.setReason("暂时不寄了"); + String param = new Gson().toJson(labelCancelParam); + String t = System.currentTimeMillis() + ""; + + PrintReq printReq = new PrintReq(); + printReq.setT(t); + printReq.setKey(key); + printReq.setMethod(ApiInfoConstant.CANCEL_METHOD); + printReq.setSign(SignUtils.printSign(param,t,key,secret)); + printReq.setParam(param); + + IBaseClient baseClient = new LabelV2(); + try { + HttpResult httpResult = baseClient.execute(printReq); + System.out.println(httpResult); + if (httpResult.getStatus() == org.apache.http.HttpStatus.SC_OK && StringUtils.isNotBlank(httpResult.getBody())){ + return httpResult.getBody(); + }else { + throw exception(OMS_EXPRESS_ORDER_CANCEL_ERROR, "接口无返回内容"); + } + } catch (Exception e) { + throw exception(OMS_EXPRESS_ORDER_CANCEL_ERROR, e.getMessage()); + } + } + @Async public void sendDeliveryOrderMessage(TradeOrderDO order, TradeOrderDeliveryReqVO deliveryReqVO) { // 构建并发送模版消息 @@ -505,6 +852,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { if (updateCount == 0) { throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); } + // 会员赠送积分 + if (order.getGivePoint() != null && order.getGivePoint() > 0) { + memberPointApi.addPoint(order.getUserId(), order.getGivePoint(), MemberPointBizTypeEnum.ORDER_GIVE.getType(), + String.valueOf(order.getId())); + } // 插入订单日志 TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus()); @@ -928,6 +1280,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { tradeOrderMapper.updateById(new TradeOrderDO().setId(orderId).setGiveCouponIds(giveCouponIds)); } + /** * 创建单个订单的评论 * diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/StoOrderCreateContentBo.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/StoOrderCreateContentBo.java new file mode 100644 index 0000000..d49f8ef --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/StoOrderCreateContentBo.java @@ -0,0 +1,214 @@ +package cn.iocoder.yudao.module.trade.service.order.bo; + +import lombok.Data; + +import java.util.List; + +@Data +public class StoOrderCreateContentBo { + //订单号(客户系统自己生成,唯一) + private String orderNo; + //订单来源(订阅服务时填写的来源编码) + private String orderSource; + //获取面单的类型(00-普通、03-国际、01-代收、02-到付、04-生鲜),默认普通业务,如果有其他业务先与业务方沟通清楚 + private String billType; +// 订单类型(01-普通订单、02-调度订单)默认01-普通订单,如果有散单业务需先业务方沟通清楚 + private String orderType; +// 寄件人信息 + private Sender sender; + //收件人信息 + private Receiver receiver; + //包裹信息 + private Cargo cargo; + //客户信息,在线下单取运单号必填,代单号下单不需要填写,测试账号传值如下,生产账号联系合作业务方提供 + private Customer customer; + //国际订单附属信息(国际业务订单必填,其他业务不要填写) + private InternationalAnnex internationalAnnex; + + private String waybillNo; + + private AssignAnnex assignAnnex; + + private String codValue; + + private String freightCollectValue; + + private String timelessType; + + private String productType; + + private List serviceTypeList; + + private ExtendFieldMap extendFieldMap; + + private String remark; + + private String expressDirection; + + private String createChannel; + + private String regionType; + + private InsuredAnnex insuredAnnex; + + private String expectValue; + + private String payModel; + + /** + * 发货人信息 + */ + @Data + public static class Sender + { + private String name; + + private String tel; + + private String mobile; + + private String postCode; + + private String country; + + private String province; + + private String city; + + private String area; + + private String town; + + private String address; + } + + /** + * 收货人信息 + */ + @Data + public static class Receiver + { + private String name; + + private String tel; + + private String mobile; + + private String postCode; + + private String country; + + private String province; + + private String city; + + private String area; + + private String town; + + private String address; + + private String safeNo; + + } + + @Data + public static class Cargo + { + private String battery; + + private String goodsType; + + private String goodsName; + + private Integer goodsCount; + + private Double spaceX; + + private Double spaceY; + + private Double spaceZ; + + private Double weight; + + private String goodsAmount; + + private List cargoItemList; + + } + + @Data + public static class CargoItem + { + private String serialNumber; + + private String referenceNumber; + + private String productId; + + private String name; + + private int qty; + + private int unitPrice; + + private int amount; + + private String currency; + + private int weight; + + private String remark; + } + + + @Data + public static class Customer + { + private String siteCode; + + private String customerName; + + private String sitePwd; + + private String monthCustomerCode; + } + + + @Data + public static class InternationalAnnex + { + private String internationalProductType; + + private boolean customsDeclaration; + + private String senderCountry; + + private String receiverCountry; + } + + @Data + public static class AssignAnnex + { + private String takeCompanyCode; + + private String takeUserCode; + } + + @Data + public static class ExtendFieldMap + { + private String mapValue; + } + + @Data + public static class InsuredAnnex + { + private String insuredValue; + + private String goodsValue; + + } + + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/StoRequestBo.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/StoRequestBo.java new file mode 100644 index 0000000..cc4f965 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/StoRequestBo.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.trade.service.order.bo; + +import lombok.Data; + +/** + * 申通请求公共参数 + */ +@Data +public class StoRequestBo { + // api_name:调用的目标接口ID(控制台列表中称为API,为英文、数字及下划线组成的字串,非API中文名称)。 + private String api_name; +// content:结构化的业务报文体,具体内容由订阅的接口规定(API文档中的 请求参数 表格),可以是 JSON 或 XML 格式的字串。请参考下方“请求示例”,注意:content内容中不允许有特殊字符,例如\u001b。 + private String content; +// from_appkey:订阅方appkey,即合作方应用key。 + private String from_appkey; +// from_code:订阅方资源code,即合作方应用的资源code。 + private String from_code; +// to_appkey:注册方appkey,即提供该订阅接口服务的申通应用key, + private String to_appkey; +// to_code:注册方资源code,即上述申通应用的资源code,目前值等于to_appkey。 + private String to_code; + // data_digest:报文签名,网关会统一校验。构造方法请参考下方“签名构造”。 + private String data_digest; +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/StoResponseBo.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/StoResponseBo.java new file mode 100644 index 0000000..3abb110 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/StoResponseBo.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.trade.service.order.bo; + +import lombok.Data; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@Data +@XmlRootElement(name = "response") +public class StoResponseBo { + + @XmlElement(name = "success") + private boolean success; + + @XmlElement(name = "errorCode") + private String errorCode; + + @XmlElement(name = "errorMsg") + private String errorMsg; + + @XmlElement(name = "data") + private OrderCreateResponse data; + + @Data + public static class OrderCreateResponse { + private String orderNo; + + private String waybillNo; + + private String bigWord; + + private String packagePlace; + + private String sourceOrderId; + + private String safeNo; + + private String newBlockCode; + } +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeMemberPointOrderHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeMemberPointOrderHandler.java index a9a13e3..6c94b18 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeMemberPointOrderHandler.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeMemberPointOrderHandler.java @@ -41,8 +41,8 @@ public class TradeMemberPointOrderHandler implements TradeOrderHandler { @Override public void afterPayOrder(TradeOrderDO order, List orderItems) { // 增加用户积分(订单赠送) - addPoint(order.getUserId(), order.getGivePoint(), MemberPointBizTypeEnum.ORDER_GIVE, - order.getId()); +// addPoint(order.getUserId(), order.getGivePoint(), MemberPointBizTypeEnum.ORDER_GIVE, +// order.getId()); // 增加用户经验 memberLevelApi.addExperience(order.getUserId(), order.getPayPrice(), diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/util/SignatureUtils.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/util/SignatureUtils.java new file mode 100644 index 0000000..63cd5af --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/util/SignatureUtils.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.trade.util; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.digest.DigestUtils; + +public class SignatureUtils { + + private SignatureUtils() { + throw new IllegalStateException("SignatureUtils class"); + } + + public static String getSignature(String content, String secretKey) { + String text = content + secretKey; + byte[] md5 = DigestUtils.md5(text); + return Base64.encodeBase64String(md5); + } + + public static void main(String[] args) { + String content="{\"orderNo\":\"8885452262\"}"; + String secretKey="123abc"; + System.out.println(getSignature(content,secretKey)); + } + +} \ No newline at end of file diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 4285195..7e86831 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -80,7 +80,7 @@ spring: host: 127.0.0.1 # 地址 port: 6379 # 端口 database: 0 # 数据库索引 - # password: 123456 # 密码,建议生产环境开启 + password: 123456 # 密码,建议生产环境开启 --- #################### 定时任务相关配置 #################### diff --git a/yudao-server/src/main/resources/application-prod.yaml b/yudao-server/src/main/resources/application-prod.yaml index 3c53d9a..9ef9421 100644 --- a/yudao-server/src/main/resources/application-prod.yaml +++ b/yudao-server/src/main/resources/application-prod.yaml @@ -45,7 +45,7 @@ spring: primary: master datasource: master: - url: jdbc:mysql://192.168.0.7:37897/bdgwc?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例 + url: jdbc:mysql://192.168.0.7:3306/bdgwc?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例 # url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true # MySQL Connector/J 5.X 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例 # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 @@ -63,7 +63,7 @@ spring: # password: Yudao@2024 # OpenGauss 连接的示例 slave: # 模拟从库,可根据自己需要修改 lazy: true # 开启懒加载,保证启动速度 - url: jdbc:mysql://192.168.0.7:37897/bdgwc?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true + url: jdbc:mysql://192.168.0.7:3306/bdgwc?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true username: bdgwc password: T3DrcpS6RhftmJrX @@ -71,8 +71,8 @@ spring: redis: host: 127.0.0.1 # 地址 port: 6379 # 端口 - database: 1 # 数据库索引 - password: bsd.1799 # 密码,建议生产环境开启 + database: 4 # 数据库索引 + password: 179965 # 密码,建议生产环境开启 --- #################### 定时任务相关配置 #################### diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index c5d0ae1..7a48bcf 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -3,8 +3,8 @@ spring: name: yudao-server profiles: - # active: prod - active: local + active: prod +# active: local main: allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。 @@ -362,4 +362,15 @@ yudao: debug: false # 插件配置 TODO 芋艿:【IOT】需要处理下 pf4j: - pluginsDir: /Users/anhaohao/code/gitee/ruoyi-vue-pro/plugins # 插件目录 \ No newline at end of file + pluginsDir: /Users/anhaohao/code/gitee/ruoyi-vue-pro/plugins # 插件目录 + + +sto: +# 正式环境 + api_url: 'https://cloudinter-linkgateway.sto.cn/gateway/link.do' +# 测试环境 +# api_url: 'http://cloudinter-linkgatewaytest.sto.cn/gateway/link.do' + from_appkey: 'CAKWRKlMXSPewDL' + from_code: 'CAKWRKlMXSPewDL' + to_appkey: 'sto_oms' + to_code: 'sto_oms' \ No newline at end of file