diff --git a/yshop-drink-boot3/yshop-module-mall/yshop-module-order-api/src/main/java/co/yixiang/yshop/module/order/enums/ErrorCodeConstants.java b/yshop-drink-boot3/yshop-module-mall/yshop-module-order-api/src/main/java/co/yixiang/yshop/module/order/enums/ErrorCodeConstants.java index 3258734..222c7fc 100644 --- a/yshop-drink-boot3/yshop-module-mall/yshop-module-order-api/src/main/java/co/yixiang/yshop/module/order/enums/ErrorCodeConstants.java +++ b/yshop-drink-boot3/yshop-module-mall/yshop-module-order-api/src/main/java/co/yixiang/yshop/module/order/enums/ErrorCodeConstants.java @@ -38,6 +38,8 @@ public interface ErrorCodeConstants { ErrorCode STORE_ORDER_DESK_NOT = new ErrorCode(1008007023, "当前桌号不存在"); ErrorCode STORE_ORDER_OUT_OF_DELIVERY_RANGE = new ErrorCode(1008007024, "当前收货地址不在配送范围内"); ErrorCode STORE_ORDER_MIN_PRICE_NOT_MET = new ErrorCode(1008007025, "未达到外卖起送价"); + ErrorCode WECHAT_SHIPPING_DELIVERY_NO_REQUIRED = new ErrorCode(1008007026, "请填写同城配送单号"); + ErrorCode WECHAT_SHIPPING_UPLOAD_FAILED = new ErrorCode(1008007027, "微信发货信息上报失败"); diff --git a/yshop-drink-boot3/yshop-module-mall/yshop-module-order-biz/src/main/java/co/yixiang/yshop/module/order/service/storeorder/StoreOrderServiceImpl.java b/yshop-drink-boot3/yshop-module-mall/yshop-module-order-biz/src/main/java/co/yixiang/yshop/module/order/service/storeorder/StoreOrderServiceImpl.java index 34cb62a..fd3fbd9 100644 --- a/yshop-drink-boot3/yshop-module-mall/yshop-module-order-biz/src/main/java/co/yixiang/yshop/module/order/service/storeorder/StoreOrderServiceImpl.java +++ b/yshop-drink-boot3/yshop-module-mall/yshop-module-order-biz/src/main/java/co/yixiang/yshop/module/order/service/storeorder/StoreOrderServiceImpl.java @@ -3,6 +3,11 @@ package co.yixiang.yshop.module.order.service.storeorder; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.shop.request.shipping.OrderKeyBean; +import cn.binarywang.wx.miniapp.bean.shop.request.shipping.PayerBean; +import cn.binarywang.wx.miniapp.bean.shop.request.shipping.ShippingListBean; +import cn.binarywang.wx.miniapp.bean.shop.request.shipping.WxMaOrderShippingInfoUploadRequest; import co.yixiang.yshop.framework.common.constant.ShopConstants; import co.yixiang.yshop.framework.common.enums.OrderInfoEnum; import co.yixiang.yshop.framework.common.enums.PayIdEnum; @@ -30,6 +35,8 @@ import co.yixiang.yshop.module.order.enums.OrderLogEnum; import co.yixiang.yshop.module.order.enums.PayTypeEnum; import co.yixiang.yshop.module.order.enums.UpdateOrderEnum; import co.yixiang.yshop.module.order.service.storeorderstatus.StoreOrderStatusService; +import co.yixiang.yshop.module.pay.dal.dataobject.merchantdetails.MerchantDetailsDO; +import co.yixiang.yshop.module.pay.service.merchantdetails.MerchantDetailsService; import co.yixiang.yshop.module.product.service.storeproduct.AppStoreProductService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.egzosn.pay.common.bean.RefundOrder; @@ -37,6 +44,7 @@ import com.egzosn.pay.common.bean.RefundResult; import com.egzosn.pay.spring.boot.core.PayServiceManager; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; import org.redisson.api.RBlockingDeque; import org.redisson.api.RDelayedQueue; import org.redisson.api.RedissonClient; @@ -48,6 +56,9 @@ import org.springframework.validation.annotation.Validated; import java.math.BigDecimal; import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.Collection; import java.util.List; import java.util.Map; @@ -89,6 +100,10 @@ public class StoreOrderServiceImpl implements StoreOrderService { private AppStoreProductService appStoreProductService; @Resource private PayServiceManager manager; + @Resource + private WxMaService wxMaService; + @Resource + private MerchantDetailsService merchantDetailsService; @Resource private AsyncStoreOrderService asyncStoreOrderService; @@ -119,22 +134,28 @@ public class StoreOrderServiceImpl implements StoreOrderService { //发货自取模式 直接收货 if(UpdateOrderEnum.ORDER_SEND.getValue().equals(updateReqVO.getUpdateType()) - && updateObj.getOrderType().equals(OrderLogEnum.ORDER_TAKE_IN.getValue())){ - this.takeStoreOrder(updateObj.getId()); + && updateObj2.getOrderType().equals(OrderLogEnum.ORDER_TAKE_IN.getValue())){ + uploadWechatShippingInfo(updateObj2, null); + this.takeStoreOrder(updateObj.getId()); //todo 异步打印小票 商业版本才有 官网购买:https://www.yixiang.co return; } //发货-外卖模式 if(UpdateOrderEnum.ORDER_SEND.getValue().equals(updateReqVO.getUpdateType()) - && updateObj.getOrderType().equals(OrderLogEnum.ORDER_TAKE_OUT.getValue())){ + && updateObj2.getOrderType().equals(OrderLogEnum.ORDER_TAKE_OUT.getValue())){ + if (StrUtil.isBlank(updateObj.getDeliveryId())) { + throw exception(WECHAT_SHIPPING_DELIVERY_NO_REQUIRED); + } + updateObj.setDeliveryName(StrUtil.emptyToDefault(updateObj.getDeliveryName(), "同城配送")); + uploadWechatShippingInfo(updateObj2, updateObj.getDeliveryId()); updateObj.setStatus(OrderInfoEnum.STATUS_1.getValue()); //todo 异步打印小票 商业版本才有 官网购买:https://www.yixiang.co } //堂食模式 if(UpdateOrderEnum.ORDER_SEND.getValue().equals(updateReqVO.getUpdateType()) - && updateObj.getOrderType().equals(OrderLogEnum.ORDER_TAKE_DESK.getValue())){ + && updateObj2.getOrderType().equals(OrderLogEnum.ORDER_TAKE_DESK.getValue())){ //todo 异步打印小票 商业版本才有 官网购买:https://www.yixiang.co @@ -175,6 +196,60 @@ public class StoreOrderServiceImpl implements StoreOrderService { } + private void uploadWechatShippingInfo(StoreOrderDO order, String deliveryNo) { + if (!PayTypeEnum.WEIXIN.getValue().equals(order.getPayType())) { + return; + } + boolean sameCityDelivery = OrderLogEnum.ORDER_TAKE_OUT.getValue().equals(order.getOrderType()); + if (sameCityDelivery && StrUtil.isBlank(deliveryNo)) { + throw exception(WECHAT_SHIPPING_DELIVERY_NO_REQUIRED); + } + + MemberUserDO payer = userService.getUser(order.getUid()); + if (payer == null || StrUtil.isBlank(payer.getRoutineOpenid())) { + log.warn("[uploadWechatShippingInfo][skip non-miniapp orderId={}]", order.getOrderId()); + return; + } + MerchantDetailsDO merchant = merchantDetailsService.getMerchantDetails(PayIdEnum.WX_MINIAPP.getValue()); + if (merchant == null || StrUtil.isBlank(merchant.getMchId())) { + log.warn("[uploadWechatShippingInfo][skip missing miniapp merchant config, orderId={}]", order.getOrderId()); + return; + } + + String itemDesc = buildItemDesc(order.getId()); + ShippingListBean shipping = ShippingListBean.builder().itemDesc(itemDesc).build(); + if (sameCityDelivery) { + shipping.setTrackingNo(deliveryNo); + } + WxMaOrderShippingInfoUploadRequest request = WxMaOrderShippingInfoUploadRequest.builder() + .orderKey(OrderKeyBean.builder().orderNumberType(1).mchId(merchant.getMchId()).outTradeNo(order.getOrderId()).build()) + .logisticsType(sameCityDelivery ? 2 : 4) + .deliveryMode(1) + .shippingList(List.of(shipping)) + .uploadTime(OffsetDateTime.now(ZoneId.of("Asia/Shanghai")).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)) + .payer(PayerBean.builder().openid(payer.getRoutineOpenid()).build()) + .build(); + try { + wxMaService.getWxMaOrderShippingService().upload(request); + } catch (WxErrorException e) { + log.error("[uploadWechatShippingInfo][orderId={} upload failed]", order.getOrderId(), e); + throw exception(WECHAT_SHIPPING_UPLOAD_FAILED); + } + } + + private String buildItemDesc(Long orderId) { + List items = storeOrderCartInfoMapper.selectList(new LambdaQueryWrapper() + .eq(StoreOrderCartInfoDO::getOid, orderId)); + StringBuilder desc = new StringBuilder(); + for (StoreOrderCartInfoDO item : items) { + if (desc.length() > 0) { + desc.append('、'); + } + desc.append(item.getTitle()).append('*').append(item.getNumber()); + } + return StrUtil.subPre(StrUtil.emptyToDefault(desc.toString(), "商品"), 120); + } + @Override public void deleteStoreOrder(Long id) { // 校验存在 diff --git a/yshop-drink-vue3/src/views/mall/order/storeOrder/OrderSend.vue b/yshop-drink-vue3/src/views/mall/order/storeOrder/OrderSend.vue index 1bca742..233be8d 100644 --- a/yshop-drink-vue3/src/views/mall/order/storeOrder/OrderSend.vue +++ b/yshop-drink-vue3/src/views/mall/order/storeOrder/OrderSend.vue @@ -18,7 +18,15 @@ {{ formData.realName }}{{ formData.userPhone }}{{ formData.userAddress }} - + + + +