Browse Source

红德堂-同步部分master代码

Long 2 days ago
parent
commit
f2c717cf1f
88 changed files with 6385 additions and 390 deletions
  1. 4 0
      fs-service/src/main/java/com/fs/company/service/ICompanyService.java
  2. 49 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java
  3. 4 1
      fs-service/src/main/java/com/fs/course/dto/FsOrderDeliveryNoteDTO.java
  4. 18 0
      fs-service/src/main/java/com/fs/course/dto/OrderOpenIdTransDTO.java
  5. 1 0
      fs-service/src/main/java/com/fs/erp/domain/ErpOrder.java
  6. 7 0
      fs-service/src/main/java/com/fs/erp/service/IErpOrderService.java
  7. 763 26
      fs-service/src/main/java/com/fs/erp/service/impl/DfOrderServiceImpl.java
  8. 29 0
      fs-service/src/main/java/com/fs/erp/service/impl/ErpOrderServiceImpl.java
  9. 163 0
      fs-service/src/main/java/com/fs/erp/service/impl/HzOMSErpOrderServiceImpl.java
  10. 282 4
      fs-service/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java
  11. 176 0
      fs-service/src/main/java/com/fs/erp/service/impl/K9OrderScrmServiceImpl.java
  12. 206 0
      fs-service/src/main/java/com/fs/erp/service/impl/WdtErpOrderServiceImpl.java
  13. 17 3
      fs-service/src/main/java/com/fs/his/domain/FsIntegralOrder.java
  14. 73 0
      fs-service/src/main/java/com/fs/his/domain/FsIntegralOrderDf.java
  15. 47 0
      fs-service/src/main/java/com/fs/his/domain/FsIntegralOrderLogs.java
  16. 64 0
      fs-service/src/main/java/com/fs/his/mapper/FsIntegralOrderDfMapper.java
  17. 62 0
      fs-service/src/main/java/com/fs/his/mapper/FsIntegralOrderLogsMapper.java
  18. 7 1
      fs-service/src/main/java/com/fs/his/mapper/FsIntegralOrderMapper.java
  19. 13 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java
  20. 62 0
      fs-service/src/main/java/com/fs/his/service/IFsIntegralOrderDfService.java
  21. 62 0
      fs-service/src/main/java/com/fs/his/service/IFsIntegralOrderLogsService.java
  22. 3 0
      fs-service/src/main/java/com/fs/his/service/IFsUserService.java
  23. 93 0
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderDfServiceImpl.java
  24. 92 0
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderLogsServiceImpl.java
  25. 10 4
      fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java
  26. 32 0
      fs-service/src/main/java/com/fs/his/vo/FsIntegralOrderExcelVO.java
  27. 3 0
      fs-service/src/main/java/com/fs/hisStore/config/StoreConfig.java
  28. 2 0
      fs-service/src/main/java/com/fs/hisStore/domain/FsStoreOrderScrm.java
  29. 27 12
      fs-service/src/main/java/com/fs/hisStore/domain/FsUserBillScrm.java
  30. 36 0
      fs-service/src/main/java/com/fs/hisStore/domain/FsUserScrm.java
  31. 1 0
      fs-service/src/main/java/com/fs/hisStore/enums/OrderInfoEnum.java
  32. 2 1
      fs-service/src/main/java/com/fs/hisStore/enums/ShipperCodeEnum.java
  33. 19 2
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreOrderScrmMapper.java
  34. 28 1
      fs-service/src/main/java/com/fs/hisStore/mapper/FsUserScrmMapper.java
  35. 1 0
      fs-service/src/main/java/com/fs/hisStore/param/FsStoreConfirmPackageIdOrderParam.java
  36. 6 0
      fs-service/src/main/java/com/fs/hisStore/param/FsStorePackageOrderCreateParam.java
  37. 24 0
      fs-service/src/main/java/com/fs/hisStore/param/FsUserCouponScrmSendParam.java
  38. 26 1
      fs-service/src/main/java/com/fs/hisStore/service/IFsStoreOrderScrmService.java
  39. 8 8
      fs-service/src/main/java/com/fs/hisStore/service/IFsUserBillScrmService.java
  40. 27 0
      fs-service/src/main/java/com/fs/hisStore/service/IFsUserScrmService.java
  41. 539 49
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java
  42. 9 3
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsUserBillScrmServiceImpl.java
  43. 1 1
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsUserExtractScrmServiceImpl.java
  44. 120 14
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsUserScrmServiceImpl.java
  45. 38 0
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderCodeOpenIdVo.java
  46. 84 0
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderDeliveryNoteExportVO.java
  47. 2 0
      fs-service/src/main/java/com/fs/hisStore/vo/FsStoreProductListQueryVO.java
  48. 11 0
      fs-service/src/main/java/com/fs/hisStore/vo/UserScrmVo.java
  49. 2 1
      fs-service/src/main/java/com/fs/live/domain/LiveOrderPayment.java
  50. 85 0
      fs-service/src/main/java/com/fs/live/dto/LiveOrderCustomerExportDTO.java
  51. 4 1
      fs-service/src/main/java/com/fs/live/dto/LiveOrderDeliveryNoteDTO.java
  52. 7 4
      fs-service/src/main/java/com/fs/live/mapper/LiveAfterSalesMapper.java
  53. 64 6
      fs-service/src/main/java/com/fs/live/mapper/LiveOrderMapper.java
  54. 1 0
      fs-service/src/main/java/com/fs/live/param/LiveOrderComputedParam.java
  55. 33 1
      fs-service/src/main/java/com/fs/live/service/ILiveOrderService.java
  56. 653 233
      fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java
  57. 141 0
      fs-service/src/main/java/com/fs/pay/domain/PaymentMiniProgramConfig.java
  58. 70 0
      fs-service/src/main/java/com/fs/pay/mapper/PaymentMiniProgramConfigMapper.java
  59. 1 0
      fs-service/src/main/java/com/fs/store/config/StoreConfig.java
  60. 104 0
      fs-service/src/main/java/com/fs/wx/order/domain/FsWxExpressTask.java
  61. 21 0
      fs-service/src/main/java/com/fs/wx/order/dto/Contact.java
  62. 27 0
      fs-service/src/main/java/com/fs/wx/order/dto/OrderKey.java
  63. 77 0
      fs-service/src/main/java/com/fs/wx/order/dto/OrderQueryRequest.java
  64. 236 0
      fs-service/src/main/java/com/fs/wx/order/dto/OrderQueryResponse.java
  65. 17 0
      fs-service/src/main/java/com/fs/wx/order/dto/Payer.java
  66. 26 0
      fs-service/src/main/java/com/fs/wx/order/dto/ShippingItem.java
  67. 42 0
      fs-service/src/main/java/com/fs/wx/order/dto/UploadShippingInfoRequest.java
  68. 21 0
      fs-service/src/main/java/com/fs/wx/order/dto/WeChatApiConfig.java
  69. 20 0
      fs-service/src/main/java/com/fs/wx/order/dto/WeChatApiResponse.java
  70. 117 0
      fs-service/src/main/java/com/fs/wx/order/mapper/FsWxExpressTaskMapper.java
  71. 30 0
      fs-service/src/main/java/com/fs/wx/order/service/ExpressToWxHolder.java
  72. 27 0
      fs-service/src/main/java/com/fs/wx/order/service/ExpressToWxService.java
  73. 20 0
      fs-service/src/main/java/com/fs/wx/order/service/OrderQueryService.java
  74. 128 0
      fs-service/src/main/java/com/fs/wx/order/service/ShippingService.java
  75. 46 0
      fs-service/src/main/java/com/fs/wx/order/service/WeChatAuthFactory.java
  76. 22 0
      fs-service/src/main/java/com/fs/wx/order/service/WeChatAuthService.java
  77. 114 0
      fs-service/src/main/java/com/fs/wx/order/service/impl/InMemoryWeChatAuthServiceImpl.java
  78. 107 0
      fs-service/src/main/java/com/fs/wx/order/service/impl/LiveExpressToWxService.java
  79. 107 0
      fs-service/src/main/java/com/fs/wx/order/service/impl/ShopExpressToWxService.java
  80. 5 0
      fs-service/src/main/resources/application-common.yml
  81. 127 0
      fs-service/src/main/resources/mapper/his/FsIntegralOrderDfMapper.xml
  82. 76 0
      fs-service/src/main/resources/mapper/his/FsIntegralOrderLogsMapper.xml
  83. 38 1
      fs-service/src/main/resources/mapper/his/FsUserMapper.xml
  84. 193 7
      fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml
  85. 2 1
      fs-service/src/main/resources/mapper/live/LiveAfterSalesMapper.xml
  86. 195 0
      fs-service/src/main/resources/mapper/pay/PaymentMiniProgramConfigMapper.xml
  87. 4 0
      fs-user-app/pom.xml
  88. 22 4
      fs-user-app/src/main/java/com/fs/app/controller/store/CompanyOrderScrmController.java

+ 4 - 0
fs-service/src/main/java/com/fs/company/service/ICompanyService.java

@@ -214,4 +214,8 @@ public interface ICompanyService
      * 根据扣减记录扣减红包余额
      */
     void subDbRedPacketBalance(Long companyId, List<CompanyRedPacketBalanceDeductionRecord> records);
+
+    void addCompanyTuiLiveMoney(LiveOrder order);
+
+    void subLiveCompanyMoney(LiveOrder order);
 }

+ 49 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java

@@ -34,6 +34,7 @@ import com.fs.hisStore.domain.FsStoreOrderScrm;
 import com.fs.hisStore.domain.FsStorePaymentScrm;
 import com.fs.hisStore.mapper.FsStoreOrderScrmMapper;
 import com.fs.live.domain.LiveOrder;
+import com.fs.live.mapper.LiveOrderMapper;
 import com.fs.live.service.ILiveService;
 import com.fs.store.config.CompanyMenuConfig;
 import com.fs.system.domain.SysConfig;
@@ -50,6 +51,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.support.TransactionTemplate;
 
@@ -124,6 +126,8 @@ public class CompanyServiceImpl implements ICompanyService
     private ICompanyRedPacketBalanceDeductionRecordService deductionRecordService;
     @Autowired
     private CompanyRedPacketBalanceUtil companyRedPacketBalanceUtil;
+    @Autowired
+    private LiveOrderMapper liveOrderMapper;
 
 
     @Override
@@ -137,6 +141,51 @@ public class CompanyServiceImpl implements ICompanyService
         liveService.asyncToCache();
     }
 
+    @Override
+    @Transactional
+    public void addCompanyTuiLiveMoney(LiveOrder order) {
+        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
+            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
+            if(company!=null){
+                String json =configService.selectConfigByKey("store.config");
+                com.fs.store.config.StoreConfig config= JSONUtil.toBean(json, com.fs.store.config.StoreConfig.class);
+                //支付金额-(订单金额*rate%)
+                Double rate=config.getTuiMoneyRate()/100d;
+                BigDecimal tuiMoney=order.getPayPrice().subtract(order.getTotalPrice().multiply(new BigDecimal(rate)));
+                logger.info("写入公司推广佣金:"+tuiMoney);
+                company.setTuiMoney(company.getTuiMoney().add(tuiMoney));
+                companyMapper.updateCompany(company);
+                LiveOrder storeOrderMap=new LiveOrder();
+                storeOrderMap.setOrderId(order.getOrderId());
+                storeOrderMap.setTuiMoney(tuiMoney);
+                liveOrderMapper.updateLiveOrder(storeOrderMap);
+            }
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
+    public void subLiveCompanyMoney(LiveOrder order) {
+        if(order.getCompanyId()>0){
+            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
+            if(company!=null){
+                company.setMoney(company.getMoney().subtract(order.getTuiMoney()));
+                company.setTuiMoney(company.getTuiMoney().subtract(order.getTuiMoney()));
+                companyMapper.updateCompany(company);
+                //写入日志
+                CompanyMoneyLogs log=new CompanyMoneyLogs();
+                log.setCompanyId(order.getCompanyId());
+                log.setRemark("订单佣金退款");
+                log.setMoney(order.getTuiMoney().multiply(new BigDecimal(-1)));
+                log.setLogsType(5);
+                log.setBalance(company.getMoney());
+                log.setCreateTime(new Date());
+                log.setBusinessId(order.getOrderId().toString());
+                moneyLogsMapper.insertCompanyMoneyLogs(log);
+            }
+        }
+    }
+
     /**
      * 根据扣减记录扣减红包余额
      */

+ 4 - 1
fs-service/src/main/java/com/fs/course/dto/FsOrderDeliveryNoteDTO.java

@@ -16,9 +16,12 @@ public class FsOrderDeliveryNoteDTO {
     @Excel(name = "系统订单号(必填)",width = 20,sort = 1)
     private String orderNumber;
 
-    @Excel(name = "物流公司编号(必填)(SF:顺丰、EMS:邮政、ZTO:中通、JD:京东、DBL:德邦)",width = 30,sort = 2)
+    @Excel(name = "物流公司编号(必填)(SF:顺丰、EMS:邮政、ZTO:中通、JD:京东、DBL:德邦、YTO:圆通)",width = 30,sort = 2)
     private String deliverySn;
 
+    @Excel(name = "物流公司",width = 10,sort = 10)
+    private String logisticsCompany;
+
     private String deliveryName;
 
     @Excel(name = "快递单号(必填)",width = 20,sort = 3)

+ 18 - 0
fs-service/src/main/java/com/fs/course/dto/OrderOpenIdTransDTO.java

@@ -0,0 +1,18 @@
+package com.fs.course.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class OrderOpenIdTransDTO implements Serializable {
+    /**
+     * 用户微信openId
+     * **/
+    private String openId;
+
+    /**
+     * 交易单号
+     * **/
+    private String transactionId;
+}

+ 1 - 0
fs-service/src/main/java/com/fs/erp/domain/ErpOrder.java

@@ -34,4 +34,5 @@ public class ErpOrder {
     List<ErpOrderPayment> payments;
 
     String buyer_account;
+    Boolean isIntegralOrder;
 }

+ 7 - 0
fs-service/src/main/java/com/fs/erp/service/IErpOrderService.java

@@ -5,6 +5,7 @@ import com.fs.erp.domain.ErpRefundOrder;
 import com.fs.erp.dto.*;
 import com.fs.his.domain.FsStoreOrder;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
+import com.fs.live.domain.LiveOrder;
 
 public interface IErpOrderService
 {
@@ -13,19 +14,25 @@ public interface IErpOrderService
 
     ErpOrderResponse addOrderScrm(ErpOrder order);
 
+    ErpOrderResponse addLiveOrder(ErpOrder order);
+
     //用户发起退款,然后后台审核通过后,提交退款单
     ErpOrderResponse refundOrder(ErpRefundOrder order);
     ErpOrderResponse refundOrderScrm(ErpRefundOrder order);
+    ErpOrderResponse refundLiveOrder(ErpRefundOrder order);
     ErpDeliverysResponse getDeliver(ErpDeliverysRequest param);
     ErpOrderQueryResponse getOrder(ErpOrderQueryRequert param);
     ErpOrderQueryResponse getScrmOrder(ErpOrderQueryRequert param);
+    ErpOrderQueryResponse getLiveOrder(ErpOrderQueryRequert param);
     BaseResponse refundUpdate(ErpRefundUpdateRequest param);
     BaseResponse refundUpdateScrm(ErpRefundUpdateRequest param);
+    BaseResponse refundUpdateLive(ErpRefundUpdateRequest param);
 
     ErpOrderResponse finishOrder(ErpOrder order);
     //代服管家查物流状态
     void getOrderDeliveryStatus(FsStoreOrder order);
 
     void getOrderScrmDeliveryStatus(FsStoreOrderScrm order);
+    void getOrderLiveDeliveryStatus(LiveOrder order);
 }
 

File diff suppressed because it is too large
+ 763 - 26
fs-service/src/main/java/com/fs/erp/service/impl/DfOrderServiceImpl.java


+ 29 - 0
fs-service/src/main/java/com/fs/erp/service/impl/ErpOrderServiceImpl.java

@@ -12,6 +12,8 @@ import com.fs.his.config.FsSysConfig;
 import com.fs.his.domain.FsStoreOrder;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
+import com.fs.live.domain.LiveOrder;
+import com.fs.live.mapper.LiveOrderMapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -23,6 +25,8 @@ public class ErpOrderServiceImpl implements IErpOrderService
     public final static Logger LOGGER = LoggerFactory.getLogger(ErpOrderServiceImpl.class);
     @Autowired
     ConfigUtil configUtil;
+    @Autowired
+    private LiveOrderMapper liveOrderMapper;
     @Override
     public ErpOrderResponse addOrder(ErpOrder order) {
         FsSysConfig sysConfig = configUtil.getSysConfig();
@@ -65,6 +69,11 @@ public class ErpOrderServiceImpl implements IErpOrderService
         return addOrder( order);
     }
 
+    @Override
+    public ErpOrderResponse addLiveOrder(ErpOrder order) {
+        return addOrder(order);
+    }
+
     @Override
     public ErpOrderResponse refundOrder(ErpRefundOrder order) {
         FsSysConfig sysConfig = configUtil.getSysConfig();
@@ -89,6 +98,11 @@ public class ErpOrderServiceImpl implements IErpOrderService
         return null;
     }
 
+    @Override
+    public ErpOrderResponse refundLiveOrder(ErpRefundOrder order) {
+        return null;
+    }
+
     @Override
     public ErpDeliverysResponse getDeliver(ErpDeliverysRequest request) {
         FsSysConfig sysConfig = configUtil.getSysConfig();
@@ -129,6 +143,11 @@ public class ErpOrderServiceImpl implements IErpOrderService
         return null;
     }
 
+    @Override
+    public ErpOrderQueryResponse getLiveOrder(ErpOrderQueryRequert param) {
+        return null;
+    }
+
     @Override
     public BaseResponse refundUpdate(ErpRefundUpdateRequest request) {
         FsSysConfig sysConfig = configUtil.getSysConfig();
@@ -150,6 +169,11 @@ public class ErpOrderServiceImpl implements IErpOrderService
         return null;
     }
 
+    @Override
+    public BaseResponse refundUpdateLive(ErpRefundUpdateRequest param) {
+        return null;
+    }
+
     @Override
     public ErpOrderResponse finishOrder(ErpOrder order) {
         return null;
@@ -164,4 +188,9 @@ public class ErpOrderServiceImpl implements IErpOrderService
     public void getOrderScrmDeliveryStatus(FsStoreOrderScrm order) {
 
     }
+
+    @Override
+    public void getOrderLiveDeliveryStatus(LiveOrder order) {
+
+    }
 }

+ 163 - 0
fs-service/src/main/java/com/fs/erp/service/impl/HzOMSErpOrderServiceImpl.java

@@ -14,6 +14,14 @@ import com.fs.his.domain.*;
 import com.fs.his.service.*;
 import com.fs.his.utils.PhoneUtil;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
+import com.fs.hisStore.domain.FsStoreProductAttrValueScrm;
+import com.fs.hisStore.domain.FsStoreProductScrm;
+import com.fs.hisStore.service.IFsStoreProductAttrValueScrmService;
+import com.fs.hisStore.service.IFsStoreProductScrmService;
+import com.fs.live.domain.LiveOrder;
+import com.fs.live.domain.LiveOrderItem;
+import com.fs.live.mapper.LiveOrderItemMapper;
+import com.fs.live.mapper.LiveOrderMapper;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -49,6 +57,18 @@ public class HzOMSErpOrderServiceImpl implements IErpOrderService {
     @Autowired
     HzOMSClient hzOMSClient;
 
+    @Autowired
+    private LiveOrderMapper liveOrderMapper;
+
+    @Autowired
+    private LiveOrderItemMapper liveOrderItemMapper;
+
+    @Autowired
+    private IFsStoreProductScrmService fsStoreProductScrmService;
+
+    @Autowired
+    private IFsStoreProductAttrValueScrmService fsStoreProductAttrValueScrmService;
+
     @Override
     public ErpOrderResponse addOrder(ErpOrder order) {
         try {
@@ -69,6 +89,129 @@ public class HzOMSErpOrderServiceImpl implements IErpOrderService {
         return addOrder( order);
     }
 
+    @Override
+    public ErpOrderResponse addLiveOrder(ErpOrder order) {
+        try {
+            JSONObject hzOrder = buildHzOMSOrderLive(order.getPlatform_code());
+
+            JSONObject omsOpenPtorderCreate = hzOMSClient.send("oms_open_ptorder_create", hzOrder);
+            ErpOrderResponse res = new ErpOrderResponse();
+            res.setCode("hzomssuccess");
+            return res;
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return null;
+    }
+
+    private JSONObject buildHzOMSOrderLive(String orderCode) {
+        //通过订单号查询更多订单信息
+        LiveOrder liveOrder = liveOrderMapper.selectLiveOrderByOrderCode(orderCode);
+        FsStore fsStore = fsStoreService.selectFsStoreByStoreId(liveOrder.getStoreId());
+
+        JSONObject obj = new JSONObject();
+        String iordertype = "2"; // 直播订单默认B2C快递配送
+        //订单类型 0 O2O配送订单; 1 O2O 自提订单; 2 B2C 快递配送
+        obj.put("iordertype", iordertype);
+        //订单单号
+        obj.put("cptordercode", liveOrder.getOrderCode());
+        //平台店铺编码 todo 测试环境只能写死 110111 用于联调测试 liveOrder.getStoreId()
+        obj.put("cptshopcode", 110111);
+        //平台店铺名称
+        obj.put("cptshopname", fsStore.getStoreName());
+        Integer iorderstatus = null;
+        //自提且已经支付
+        if ("1".equals(iordertype) && Integer.valueOf(1).equals(liveOrder.getIsPay())) {
+            iorderstatus = 30;
+        } else {
+            if (Integer.valueOf(1).equals(liveOrder.getStatus())) {
+                iorderstatus = 0;
+            } else if (Integer.valueOf(2).equals(liveOrder.getStatus())) {
+                iorderstatus = 5;
+            }
+        }
+        //订单状态 0待接单 5待拣货 10待配送 15配送中 20已完成 25已取消 30待自提
+        obj.put("iorderstatus", iorderstatus);
+
+        String userAddress = liveOrder.getUserAddress();
+        String[] s = null;
+        if (StringUtils.isNotBlank(userAddress)) {
+            s = userAddress.split(" ");
+        } else {
+            throw new RuntimeException("用户收货地址有问题");
+        }
+
+        //收货省
+        obj.put("cprovince", s[0]);
+        //收货市
+        obj.put("ccity", s[1]);
+        //收货区
+        obj.put("carea", s[2]);
+        //收货人密文 无密文填写明文
+        obj.put("creceivers", liveOrder.getRealName());
+        //收货人联系电话密文 无密文填写明文
+        obj.put("creceiversphone", liveOrder.getUserPhone());
+        //收货人详细地址密文 无密文填写明文
+        obj.put("creceiversaddress", userAddress);
+        //收货人脱敏信息
+        obj.put("cdesenreceivers", liveOrder.getRealName());
+        //收货联系电话脱敏信息
+        obj.put("cdesenreceiversphone", PhoneUtil.decryptPhone(liveOrder.getUserPhone()));
+        //收货联系地址脱敏信息
+        obj.put("cdesenreceiversaddress", userAddress);
+        //订单总金额 单位元
+        obj.put("forderamount", liveOrder.getTotalPrice());
+        //支付金额 单位元
+        obj.put("fpayamount", liveOrder.getPayPrice());
+        //订单总优惠 单位元
+        obj.put("fdiscamount", liveOrder.getDiscountMoney());
+        //运费
+        obj.put("ffreight", liveOrder.getPayDelivery());
+        //下单时间 格式 yyyy-MM-dd hh:mm:ss 如:2025-01-01 00:11:22
+        obj.put("dorderstarttime", liveOrder.getCreateTime());
+        //是否处方 0 否 1 是 可选
+        obj.put("iisprescription", 0);
+        //买家备注
+        obj.put("corderremark", liveOrder.getRemark());
+        //支付时间  格式 yyyy-MM-dd hh:mm:ss 如:2025-01-01 00:11:22
+        obj.put("dpurchasetime", liveOrder.getPayTime());
+        List<LiveOrderItem> liveOrderItems = liveOrderItemMapper.selectLiveOrderItemByOrderId(liveOrder.getOrderId());
+        int totalOrderItemCount = liveOrderItems.size();
+        BigDecimal divide = liveOrder.getDiscountMoney().divide(BigDecimal.valueOf(totalOrderItemCount), 2, BigDecimal.ROUND_HALF_UP);
+        JSONArray goodArr = new JSONArray();
+
+        liveOrderItems.forEach(liveOrderItem -> {
+            JSONObject goodItem = new JSONObject();
+            //商品编码
+            goodItem.put("cptgoodsid", liveOrderItem.getProductId());
+            //商品规格编码
+            goodItem.put("cptspeccode", liveOrderItem.getProductAttrValueId());
+
+            FsStoreProductScrm fsStoreProduct = fsStoreProductScrmService.selectFsStoreProductById(liveOrderItem.getProductId());
+            FsStoreProductAttrValueScrm fsStoreProductAttrValue = new FsStoreProductAttrValueScrm();
+            //判断是否含有商品规格信息 有则查询商品规格信息 没有取商品的价格
+            if(null != liveOrderItem.getProductAttrValueId()){
+                fsStoreProductAttrValue = fsStoreProductAttrValueScrmService.selectFsStoreProductAttrValueById(liveOrderItem.getProductAttrValueId());
+            }else{
+                fsStoreProductAttrValue.setPrice(fsStoreProduct.getPrice());
+            }
+            //商品名称
+            goodItem.put("cgoodsname", fsStoreProduct.getProductName());
+            //购买数量
+            goodItem.put("fqty", liveOrderItem.getNum());
+            //原单价
+            goodItem.put("fnormprice", fsStoreProductAttrValue.getPrice());
+
+            //实售单价 优惠后的单价 单位元
+            goodItem.put("fprice", fsStoreProductAttrValue.getPrice().subtract(divide));
+            goodArr.add(goodItem);
+        });
+        //订单商品信息
+        obj.put("ptorder_goods_list", goodArr);
+
+        return obj;
+    }
+
     @Override
     public ErpOrderResponse refundOrder(ErpRefundOrder order) {
         String orderCode = order.getOrderCode();
@@ -83,6 +226,11 @@ public class HzOMSErpOrderServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public ErpOrderResponse refundLiveOrder(ErpRefundOrder order) {
+        return null;
+    }
+
     @Override
     public ErpDeliverysResponse getDeliver(ErpDeliverysRequest param) {
         return null;
@@ -98,6 +246,11 @@ public class HzOMSErpOrderServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public ErpOrderQueryResponse getLiveOrder(ErpOrderQueryRequert param) {
+        return null;
+    }
+
     @Override
     public BaseResponse refundUpdate(ErpRefundUpdateRequest param) {
 
@@ -167,6 +320,11 @@ public class HzOMSErpOrderServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public BaseResponse refundUpdateLive(ErpRefundUpdateRequest param) {
+        return null;
+    }
+
     @Override
     public ErpOrderResponse finishOrder(ErpOrder order) {
         return null;
@@ -182,6 +340,11 @@ public class HzOMSErpOrderServiceImpl implements IErpOrderService {
 
     }
 
+    @Override
+    public void getOrderLiveDeliveryStatus(LiveOrder order) {
+
+    }
+
     /**
      * 构建瀚智创建订单参数
      *

+ 282 - 4
fs-service/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.fs.common.utils.StringUtils;
 import com.fs.erp.constant.AfterSalesOrderStatusEnum;
 import com.fs.erp.constant.ErpQueryOrderStatusEnum;
 import com.fs.erp.constant.OrderStatusEnum;
@@ -31,6 +32,10 @@ import com.fs.hisStore.service.IFsStoreOrderScrmService;
 import com.fs.hisStore.service.IFsStoreProductScrmService;
 import com.fs.hisStore.service.impl.FsStoreProductScrmServiceImpl;
 import com.fs.hisStore.vo.FsStoreOrderItemVO;
+import com.fs.live.domain.LiveOrder;
+import com.fs.live.domain.LiveOrderItem;
+import com.fs.live.mapper.LiveOrderItemMapper;
+import com.fs.live.mapper.LiveOrderMapper;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.http.util.Asserts;
@@ -40,10 +45,7 @@ import org.springframework.util.CollectionUtils;
 
 import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Slf4j
@@ -76,6 +78,12 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
     @Autowired
     private IFsStoreProductScrmService fsStoreProductScrmService;
 
+    @Autowired
+    private LiveOrderMapper liveOrderMapper;
+
+    @Autowired
+    private LiveOrderItemMapper liveOrderItemMapper;
+
     @Override
     public ErpOrderResponse addOrder(ErpOrder order) {
         FsStoreOrder fsStoreOrder = fsStoreOrderService.selectFsStoreOrderByOrderCode(order.getPlatform_code());
@@ -327,7 +335,127 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
         return erpOrderResponse;
     }
 
+    @Override
+    public ErpOrderResponse addLiveOrder(ErpOrder order) {
+        LiveOrder liveOrder = liveOrderMapper.selectLiveOrderByOrderCode(order.getPlatform_code());
+        log.info("ERP订单号: {}, 订单信息: {}",order.getPlatform_code(), JSON.toJSONString(liveOrder));
+
+        ErpOrderPayment erpOrderPayment = order.getPayments().get(0);
 
+        ShopOrderDTO shopOrderDTO = new ShopOrderDTO();
+
+        shopOrderDTO.setShopId(Long.valueOf(order.getShop_code()));
+        shopOrderDTO.setSoId(order.getPlatform_code());
+        shopOrderDTO.setOrderDate(order.getDeal_datetime());
+        // 待发货
+        shopOrderDTO.setShopStatus(OrderStatusEnum.WAIT_SELLER_SEND_GOODS.name());
+        // 买家账号
+        shopOrderDTO.setShopBuyerId(order.getBuyer_account());
+        // 收货人省份
+        shopOrderDTO.setReceiverState(order.getReceiver_province());
+        // 收货人城市
+        shopOrderDTO.setReceiverCity(order.getReceiver_city());
+        // 收货人区域
+        shopOrderDTO.setReceiverDistrict(order.getReceiver_district());
+        // 收货人详细地址
+        shopOrderDTO.setReceiverAddress(order.getReceiver_address());
+        // 收货人详细地址
+        shopOrderDTO.setReceiverName(order.getReceiver_name());
+        // 收货人电话
+        shopOrderDTO.setReceiverPhone(order.getReceiver_mobile());
+        // 支付金额
+        shopOrderDTO.setPayAmount(erpOrderPayment.getPayment());
+        // 运费 改
+        if (ObjectUtil.isNull(liveOrder.getPayDelivery())) {
+            shopOrderDTO.setFreight(Double.valueOf("0.00"));
+        } else {
+            shopOrderDTO.setFreight(liveOrder.getPayDelivery().doubleValue());
+        }
+        // 备注
+        shopOrderDTO.setRemark(DateUtil.format(new Date(), "dd"));
+        // 买家留言
+        shopOrderDTO.setBuyerMessage(order.getBuyer_memo());
+
+        // 订单商品项列表
+        List<OrderItemDTO> itemDTOList = new ArrayList<>();
+
+        List<LiveOrderItem> liveOrderItems = liveOrderItemMapper.selectLiveOrderItemByOrderId(liveOrder.getOrderId());
+        log.info("liveOrderItems==========>{}",liveOrderItems);
+        for (LiveOrderItem item : liveOrderItems) {
+            OrderItemDTO orderItemDTO = new OrderItemDTO();
+            JSONObject jsonObject = JSON.parseObject(item.getJsonInfo());
+
+            String barCode = jsonObject.getString("barCode");
+            String productName = jsonObject.getString("productName");
+            String sku=jsonObject.getString("sku");
+
+            orderItemDTO.setSkuId(barCode);
+            orderItemDTO.setShopSkuId(barCode);
+            orderItemDTO.setName(productName);
+            orderItemDTO.setShopIId(orderItemDTO.getSkuId());//款式编码ID,当前没有这个目前就与SKU ID一致
+            orderItemDTO.setPropertiesValue(sku);//商品属性
+
+            FsStoreProductScrm fsStoreProduct = fsStoreProductScrmService.selectFsStoreProductById(item.getProductId());
+
+            orderItemDTO.setAmount(fsStoreProduct.getPrice().multiply(new BigDecimal(item.getNum())));
+            orderItemDTO.setPic(fsStoreProduct.getImage());
+            orderItemDTO.setPrice(fsStoreProduct.getPrice());
+            orderItemDTO.setQty(item.getNum().intValue());
+            orderItemDTO.setOuterOiId(String.format("%s%s",liveOrder.getOrderCode(),item.getItemId()));
+            itemDTOList.add(orderItemDTO);
+        }
+        shopOrderDTO.setItems(itemDTOList);
+
+        // 实际支付金额
+        PaymentDTO paymentDTO = new PaymentDTO();
+        paymentDTO.setAmount(liveOrder.getPayMoney().doubleValue());
+        paymentDTO.setOuterPayId(order.getPlatform_code());
+        paymentDTO.setPayDate(order.getDeal_datetime());
+        paymentDTO.setPayment("微信支付");
+        paymentDTO.setBuyerAccount(order.getBuyer_account());
+        paymentDTO.setSellerAccount("平台销售");
+        shopOrderDTO.setPay(paymentDTO);
+
+        // 如果是货到付款
+        if("2".equals(liveOrder.getPayType()) || "3".equals(liveOrder.getPayType())){
+            shopOrderDTO.setIsCod(true);
+            // 货到付款金额 = 物流代收金额-优惠金额
+            //应付金额(货到付款= 订单总金额 - 已付金额)
+            shopOrderDTO.setPayAmount(liveOrder.getTotalPrice().subtract(liveOrder.getPayPrice()).doubleValue());
+
+            // 货到付款要推两次
+            PaymentDTO paymentDTO2 = new PaymentDTO();
+            // 物流代收金额
+            paymentDTO2.setAmount(liveOrder.getTotalPrice().subtract(liveOrder.getPayPrice()).doubleValue());
+            paymentDTO2.setOuterPayId(String.format("%s%d",order.getPlatform_code(),1));
+            paymentDTO2.setPayDate(order.getDeal_datetime());
+            paymentDTO2.setPayment("货到付款");
+            paymentDTO2.setBuyerAccount(order.getBuyer_account());
+            paymentDTO2.setSellerAccount("平台销售");
+            shopOrderDTO.setPay(paymentDTO2);
+
+            FsJstCodPush fsJstCodPush = new FsJstCodPush();
+            fsJstCodPush.setOrderId(liveOrder.getOrderCode());
+            fsJstCodPush.setType("0");
+            fsJstCodPush.setParams(JSON.toJSONString(shopOrderDTO));
+            fsJstCodPush.setRetryCount(0);
+            fsJstCodPush.setTaskStatus(TaskStatusEnum.PENDING.getCode());
+            fsJstCodPushScrmMapper.insert(fsJstCodPush);
+        }
+
+        ErpOrderResponseDTO upload = jstErpHttpService.upload(shopOrderDTO);
+
+        if(CollectionUtils.isEmpty(upload.getDatas())) {
+            log.info("推送ERP返回结果: {}",upload);
+            throw new IllegalArgumentException("推送ERP返回数不应该为0");
+        }
+        ErpOrderResponseDTO.OrderData orderData = upload.getDatas().get(0);
+
+        ErpOrderResponse erpOrderResponse = new ErpOrderResponse();
+        erpOrderResponse.setSuccess(true);
+        erpOrderResponse.setCode(String.valueOf(orderData.getOId()));
+        return erpOrderResponse;
+    }
 
     @Override
     public ErpOrderResponse refundOrder(ErpRefundOrder order) {
@@ -339,6 +467,11 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public ErpOrderResponse refundLiveOrder(ErpRefundOrder order) {
+        return null;
+    }
+
     @Override
     public ErpDeliverysResponse getDeliver(ErpDeliverysRequest param) {
         return null;
@@ -402,6 +535,36 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
 
         return response;
     }
+
+    @Override
+    public ErpOrderQueryResponse getLiveOrder(ErpOrderQueryRequert param) {
+        // 1. 构建查询请求DTO
+        OrderQueryRequestDTO requestDTO = new OrderQueryRequestDTO();
+        requestDTO.setOIds(Collections.singletonList(Long.valueOf(param.getCode())));
+        requestDTO.setOrderItemFlds(Arrays.asList("status"));
+
+        // 2. 调用ERP服务查询订单
+        OrderQueryResponseDTO query = jstErpHttpService.query(requestDTO);
+
+        // 3. 构建响应对象
+        ErpOrderQueryResponse response = new ErpOrderQueryResponse();
+
+        // 4. 设置基本响应信息
+
+        // 5. 转换订单数据
+        if (query.getOrders() != null && !query.getOrders().isEmpty()) {
+            List<ErpOrderQuery> erpOrders = query.getOrders().stream()
+                    .map(this::convertToErpOrderQueryLive)
+                    .collect(Collectors.toList());
+
+            response.setOrders(erpOrders);
+        } else {
+            response.setOrders(Collections.emptyList());
+        }
+
+        return response;
+    }
+
     /**
      * 将OrderQueryResponseDTO.Order转换为ErpOrderQuery
      *
@@ -562,6 +725,83 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
         return erpOrder;
     }
 
+    private ErpOrderQuery convertToErpOrderQueryLive(OrderQueryResponseDTO.Order order) {
+        ErpOrderQuery erpOrder = new ErpOrderQuery();
+
+        LiveOrder liveOrder = liveOrderMapper.selectLiveOrderByOrderCode(order.getSoId());
+        Asserts.notNull(liveOrder,"该订单号没有找到!");
+
+        // 设置基本订单信息
+        erpOrder.setCode(order.getSoId());
+
+        // 计算订单总数量
+        if (order.getItems() != null && !order.getItems().isEmpty()) {
+            int totalQty = order.getItems().stream()
+                    .mapToInt(OrderQueryResponseDTO.OrderItem::getQty)
+                    .sum();
+            erpOrder.setQty(totalQty);
+        }
+        if (StringUtils.isNotEmpty(order.getStatus()) && "Cancelled".equals(order.getStatus())) {
+            erpOrder.setCancle(true);
+        }
+
+        // 设置金额相关信息
+        erpOrder.setAmount(order.getAmount() != null ? order.getAmount().doubleValue() : null);
+        erpOrder.setPayment(order.getPaidAmount() != null ? order.getPaidAmount().doubleValue() : null);
+
+        // 设置其他订单属性
+        erpOrder.setCod(order.getIsCod());
+        erpOrder.setPlatform_code(order.getOrderFrom());
+
+        // 尝试解析创建时间
+        try {
+            if (order.getCreated() != null) {
+                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                erpOrder.setCreatetime(formatter.parse(order.getCreated()));
+            }
+        } catch (Exception e) {
+            // 日期解析异常处理
+            // 可以记录日志或保持为null
+        }
+
+        // 设置店铺信息
+        erpOrder.setShop_name(order.getShopName());
+        erpOrder.setShop_code(String.valueOf(order.getShopId()));
+
+        // 设置物流信息
+        erpOrder.setExpress_name(order.getLogisticsCompany());
+        erpOrder.setExpress_code(order.getLId());
+
+        // 设置收件人信息
+        erpOrder.setReceiver_name(liveOrder.getUserName());
+        erpOrder.setReceiver_phone(liveOrder.getUserPhone());
+        erpOrder.setReceiver_mobile(liveOrder.getUserPhone());
+
+        // 构建完整地址
+        erpOrder.setReceiver_address(liveOrder.getUserAddress());
+
+        // 如果是已发货
+        if(ObjectUtil.equal(order.getStatus(), ErpQueryOrderStatusEnum.SENT.getCode())){
+            List<ErpDeliverys> deliverysList = new ArrayList<>();
+
+            ErpDeliverys delivery = new ErpDeliverys();
+            delivery.setMail_no(order.getLId());
+            delivery.setExpress_code(order.getLcId());
+            delivery.setExpress_name(order.getLogisticsCompany());
+            delivery.setDelivery(true);
+            delivery.setCode(order.getSoId());
+
+            deliverysList.add(delivery);
+            erpOrder.setDeliverys(deliverysList);
+
+            // 设置发货状态,假设有物流单号就是已发货状态
+            erpOrder.setDelivery_state(1);
+        } else {
+            erpOrder.setDelivery_state(0);
+        }
+
+        return erpOrder;
+    }
 
     @Override
     public BaseResponse refundUpdate(ErpRefundUpdateRequest param) {
@@ -632,6 +872,39 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
         return baseResponse;
     }
 
+    @Override
+    public BaseResponse refundUpdateLive(ErpRefundUpdateRequest param) {
+        LiveOrder liveOrder = liveOrderMapper.selectLiveOrderByOrderCode(param.getTid());
+        log.info("订单号: {},发货状态: {},是否发货后: {}",liveOrder.getOrderCode(),liveOrder.getStatus(),ObjectUtils.equals(liveOrder.getStatus(),2));
+
+        // 发货后退款
+        if(ObjectUtils.equals(param.getOrderStatus(),2)){
+
+            FsJstAftersalePush fsJstAftersalePush = new FsJstAftersalePush();
+            fsJstAftersalePush.setOrderId(liveOrder.getOrderCode());
+            fsJstAftersalePush.setTaskStatus(com.fs.hisStore.enums.TaskStatusEnum.PENDING.getCode());
+            fsJstAftersalePush.setType(String.valueOf(AfterSalesOrderStatusEnum.WAIT_SELLER_AGREE.getIndex()));
+            fsJstAftersalePush.setRetryCount(0);
+            fsJstAftersalePush.setAfterSaleId(String.valueOf(param.getStoreAfterSalesId()));
+            fsJstAftersalePushScrmMapper.insert(fsJstAftersalePush);
+
+        } else {
+            // 如果是发货前退款,直接走取消订单流程
+            // 如果是发货后退款,走售后流程
+            OrderCancelRequestDTO requestDTO = new OrderCancelRequestDTO();
+            requestDTO.setOIds(Collections.singletonList(Integer.valueOf(liveOrder.getExtendOrderId())));
+            requestDTO.setCancelType("用户退款");
+            requestDTO.setRemark("用户退款");
+
+            jstErpHttpService.cancel(requestDTO);
+        }
+
+        BaseResponse baseResponse = new BaseResponse();
+        baseResponse.setSuccess(true);
+
+        return baseResponse;
+    }
+
     @Override
     public ErpOrderResponse finishOrder(ErpOrder order) {
         return null;
@@ -646,5 +919,10 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
     public void getOrderScrmDeliveryStatus(FsStoreOrderScrm order) {
 
     }
+
+    @Override
+    public void getOrderLiveDeliveryStatus(LiveOrder order) {
+
+    }
 }
 

+ 176 - 0
fs-service/src/main/java/com/fs/erp/service/impl/K9OrderScrmServiceImpl.java

@@ -22,6 +22,10 @@ import com.fs.hisStore.mapper.FsStoreOrderScrmMapper;
 import com.fs.hisStore.mapper.FsStoreProductScrmMapper;
 import com.fs.hisStore.service.IFsStoreOrderItemScrmService;
 import com.fs.hisStore.vo.FsStoreOrderItemVO;
+import com.fs.live.domain.LiveOrder;
+import com.fs.live.domain.LiveOrderItem;
+import com.fs.live.mapper.LiveOrderItemMapper;
+import com.fs.live.mapper.LiveOrderMapper;
 import lombok.extern.slf4j.Slf4j;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -51,6 +55,13 @@ public class K9OrderScrmServiceImpl implements IErpOrderService {
     private IFsStoreOrderItemScrmService storeOrderItemService;
     @Autowired
     private FsStoreProductScrmMapper productMapper;
+
+    @Autowired
+    private LiveOrderMapper liveOrderMapper;
+
+    @Autowired
+    private LiveOrderItemMapper liveOrderItemMapper;
+
     @Override
     /**
      * 推送erp订单
@@ -64,6 +75,151 @@ public class K9OrderScrmServiceImpl implements IErpOrderService {
         return addOmsOrder(order.getPlatform_code());
     }
 
+    @Override
+    public ErpOrderResponse addLiveOrder(ErpOrder order) {
+        return addOmsOrderLive(order.getPlatform_code());
+    }
+
+    private ErpOrderResponse addOmsOrderLive(String orderCode) {
+        try {
+            KingbosOrderResponse response = this.createOmsOrderLive(orderCode, NO_DELIVERED.getCode());
+            if (response.getIsSuccess()){
+                log.info("订单推送成功: {}", response);
+                ErpOrderResponse erpOrderResponse = new ErpOrderResponse();
+                erpOrderResponse.setCode(response.getCbilid());
+                return erpOrderResponse;
+            }else {
+                throw new RuntimeException(String.format("订单推送失败,原因: %s",response.getErrmsg()));
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return new ErpOrderResponse();
+    }
+
+    private KingbosOrderResponse createOmsOrderLive(String orderCode, String orderStatus){
+        logger.info("【金博网络订单】开始创建订单,订单Code: {}", orderCode);
+        try {
+            LiveOrder order = liveOrderMapper.selectLiveOrderByOrderCode(orderCode);
+            logger.info("【金博网络订单】订单信息获取成功,订单id: {}", order.getOrderId());
+            logger.info("【金博网络订单】订单信息获取成功,订单号: {}", order.getOrderCode());
+
+            KingbosOrderData data = buildKingbosOrderDataLive(order, orderStatus);
+            logger.info("【金博网络订单】订单数据构建完成,金博订单号: {}", data.getCo_id());
+
+            List<KingbosOrderD1Data> d1Datas = buildOrderDetailDataLive(order, data.getCdo_id());
+            logger.info("【金博网络订单】订单明细数据构建完成,明细数量: {}", d1Datas.size());
+
+            KingbosOrderResponse response = sendOrderRequest(data, d1Datas);
+            if (response.getCbilid()==null){
+                response.setCbilid(order.getExtendOrderId());
+            }
+            return response;
+        } catch (Exception e) {
+            logger.error("【金博网络订单】创建订单失败,订单Code: {}, 错误信息: {}", orderCode, e.getMessage(), e);
+            throw e;
+        }
+    }
+
+    private KingbosOrderData buildKingbosOrderDataLive(LiveOrder order, String orderStatus) {
+        FsErpConfig erpConfig = configUtil.getErpConfig();
+        logger.debug("【金博网络订单】开始构建订单数据,订单号: {}", order.getOrderCode());
+        KingbosOrderData data = new KingbosOrderData();
+        data.setCordersource("MALL");
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        data.setDorder_date(sdf.format(order.getCreateTime()));
+        data.setCplatformtype("99");
+        data.setCshop_id("zk2025");
+        data.setCshop_name("自建商城");
+        String orderSn = "";
+        if (orderStatus.equals(NO_DELIVERED.getCode())){
+            orderSn= IdUtil.getSnowflake(0, 0).nextIdStr();
+        }else if (orderStatus.equals(CANCELLED.getCode())){
+            orderSn = order.getExtendOrderId();
+        }
+
+        data.setCso_id(order.getOrderCode());
+        data.setCo_id(orderSn);
+        data.setCdo_id(orderSn);
+        order.setExtendOrderId(orderSn);
+
+        data.setFpay_amount(order.getPayPrice());
+        data.setFpaid_amount(order.getPayMoney());
+        data.setFfreight(order.getTotalPostage());
+        data.setFfree_amount(order.getCouponPrice());
+        data.setFpostcost(BigDecimal.ZERO);
+
+        data.setCstatus(orderStatus);
+        data.setDmodified(sdf.format(order.getUpdateTime()));
+
+        setReceiverInfoLive(data, order);
+
+        data.setCwarehouse_code(erpConfig.getCwarehouseCode());
+        data.setCwarehouse_name(erpConfig.getCwarehouseName());
+
+        if (!order.getPayType().equals("1")) {
+            data.setBis_cod(1);
+            data.setFshouldpaymoney(order.getDeliveryPayMoney());
+        }
+
+        return data;
+    }
+
+    private void setReceiverInfoLive(KingbosOrderData data, LiveOrder order) {
+        logger.debug("【金博网络订单】开始处理收货信息,订单号: {}", order.getOrderCode());
+        String[] address = order.getUserAddress().split(" ");
+        if (address.length < 3) {
+            logger.error("【金博网络订单】收货地址格式不正确,订单号: {}, 地址: {}", order.getOrderCode(), order.getUserAddress());
+            throw new ServiceException("收货地址格式不正确");
+        }
+
+        data.setCreceiver_state(address[0]);
+        data.setCreceiver_city(address[1]);
+        data.setCreceiver_district(address[2]);
+
+        String detailAddress = address.length > 3 ?
+            String.join("", Arrays.copyOfRange(address, 3, address.length)) :
+            address[2];
+
+        detailAddress = detailAddress.replace("+", "加")
+                                   .replace("\n", "");
+
+        data.setCreceiver_address(detailAddress);
+        data.setCreceiver_name(order.getRealName());
+        data.setCreceiver_mobile(order.getUserPhone());
+    }
+
+    private List<KingbosOrderD1Data> buildOrderDetailDataLive(LiveOrder order, String orderId) {
+        logger.debug("【金博网络订单】开始构建订单明细,订单号: {}", order.getOrderCode());
+        List<LiveOrderItem> orderItems = liveOrderItemMapper.selectLiveOrderItemByOrderId(order.getOrderId());
+        List<KingbosOrderD1Data> d1Datas = orderItems.stream()
+                .map(item -> buildOrderDetailItemLive(item, orderId))
+                .collect(Collectors.toList());
+
+        logger.debug("【金博网络订单】订单明细构建完成,订单号: {}, 明细数量: {}", order.getOrderCode(), d1Datas.size());
+        return d1Datas;
+    }
+
+    private KingbosOrderD1Data buildOrderDetailItemLive(LiveOrderItem orderItem, String orderId) {
+        FsStoreCartDTO cartDTO = JSONUtil.toBean(orderItem.getJsonInfo(), FsStoreCartDTO.class);
+        BigDecimal quantity = new BigDecimal(orderItem.getNum());
+
+        KingbosOrderD1Data item = new KingbosOrderD1Data();
+        item.setCdo_id(orderId);
+        item.setCo_id(orderId);
+        item.setCsku_id(cartDTO.getBarCode());
+        item.setCgoodsid(cartDTO.getBarCode());
+        item.setCname(cartDTO.getProductName());
+        item.setCshop_sku_id(cartDTO.getSku());
+        item.setIqty(quantity);
+        item.setFprice(cartDTO.getPrice());
+        item.setFamount(quantity.multiply(cartDTO.getPrice()));
+        item.setCordersource("MALL");
+        item.setFpromoamount(BigDecimal.ZERO);
+
+        return item;
+    }
+
 
     /**
      * 退款
@@ -93,6 +249,11 @@ public class K9OrderScrmServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public ErpOrderResponse refundLiveOrder(ErpRefundOrder order) {
+        return null;
+    }
+
     private KingbosRefundOrderRequest getKingbosRefundOrderRequest(String orderCode) {
         FsStoreOrderScrm order = fsStoreOrderMapper.selectFsStoreOrderByOrderCode(orderCode);
         if (order != null){
@@ -138,6 +299,11 @@ public class K9OrderScrmServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public ErpOrderQueryResponse getLiveOrder(ErpOrderQueryRequert param) {
+        return null;
+    }
+
     @Override
     public BaseResponse refundUpdate(ErpRefundUpdateRequest param) {
         return null;
@@ -148,6 +314,11 @@ public class K9OrderScrmServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public BaseResponse refundUpdateLive(ErpRefundUpdateRequest param) {
+        return null;
+    }
+
 
     /**
      * 退款 运单号已获取到
@@ -460,4 +631,9 @@ public class K9OrderScrmServiceImpl implements IErpOrderService {
     public void getOrderScrmDeliveryStatus(FsStoreOrderScrm order) {
 
     }
+
+    @Override
+    public void getOrderLiveDeliveryStatus(LiveOrder order) {
+
+    }
 }

+ 206 - 0
fs-service/src/main/java/com/fs/erp/service/impl/WdtErpOrderServiceImpl.java

@@ -32,6 +32,10 @@ import com.fs.hisStore.domain.FsStoreProductScrm;
 import com.fs.hisStore.service.IFsStoreOrderItemScrmService;
 import com.fs.hisStore.service.IFsStoreOrderScrmService;
 import com.fs.hisStore.service.IFsStoreProductScrmService;
+import com.fs.live.domain.LiveOrder;
+import com.fs.live.domain.LiveOrderItem;
+import com.fs.live.mapper.LiveOrderItemMapper;
+import com.fs.live.mapper.LiveOrderMapper;
 import com.hc.openapi.tool.util.StringUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
@@ -70,6 +74,12 @@ public class WdtErpOrderServiceImpl implements IErpOrderService {
     @Autowired
     private IFsStoreProductScrmService fsStoreProductScrmService;
 
+    @Autowired
+    private LiveOrderMapper liveOrderMapper;
+
+    @Autowired
+    private LiveOrderItemMapper liveOrderItemMapper;
+
 //    @Value("${fsConfig.erpWdShopCode}")
 //    private String shopCode;
 
@@ -103,6 +113,182 @@ public class WdtErpOrderServiceImpl implements IErpOrderService {
         return getErpOrderResponseScrm(order);
     }
 
+    @Override
+    public ErpOrderResponse addLiveOrder(ErpOrder order) {
+        return getErpOrderResponseLive(order);
+    }
+
+    private ErpOrderResponse getErpOrderResponseLive(ErpOrder order) {
+        FsSysConfig sysConfig = configUtil.getSysConfig();
+        String shopCode = sysConfig.getErpWdShopCode();
+
+        ErpWdtBusinessRequestParams erpWdtBusinessRequestParams = new ErpWdtBusinessRequestParams();
+        erpWdtBusinessRequestParams.setShopNo(shopCode);
+        erpWdtBusinessRequestParams.setSwitchMode(0);
+        ErpWdtTrade erpWdtTrade = new ErpWdtTrade();
+        LiveOrder liveOrder = liveOrderMapper.selectLiveOrderByOrderCode(order.getPlatform_code());
+        BigDecimal couponPrice = liveOrder.getCouponPrice();
+        if (couponPrice == null) {
+            couponPrice = BigDecimal.ZERO;
+        }
+
+        // 平台状态
+        erpWdtTrade.setTradeStatus(TradeStatus.PAID_WAITING_FOR_SHIPMENT.getValue());
+
+        // 订单id
+        erpWdtTrade.setTid(order.getPlatform_code());
+
+        // 如果是货到付款
+        if("2".equals(liveOrder.getPayType())){
+            // 支付状态
+            erpWdtTrade.setPayStatus(PaymentStatus.PARTIALLY_PAID.getValue());
+            // 发货条件
+            erpWdtTrade.setDeliveryTerm(DeliveryTerm.CASH_ON_DELIVERY.getValue());
+            // 货到付款金额 = 物流代收金额-优惠金额
+            erpWdtTrade.setCodAmount(liveOrder.getPayDelivery().subtract(couponPrice));
+
+        } else if("3".equals(liveOrder.getPayType())){
+            // 支付状态
+            erpWdtTrade.setPayStatus(PaymentStatus.UNPAID.getValue());
+            // 发货条件
+            erpWdtTrade.setDeliveryTerm(DeliveryTerm.CASH_ON_DELIVERY.getValue());
+            // 货到付款金额 = 物流代收金额-优惠金额
+            erpWdtTrade.setCodAmount(liveOrder.getPayDelivery().subtract(couponPrice));
+        } else { // 如果是线上付款
+            // 支付状态
+            erpWdtTrade.setPayStatus(PaymentStatus.FULLY_PAID.getValue());
+            // 发货条件
+            erpWdtTrade.setDeliveryTerm(DeliveryTerm.PAYMENT_BEFORE_DELIVERY.getValue());
+        }
+
+        // 下单时间
+        erpWdtTrade.setTradeTime(order.getDeal_datetime());
+        // 支付时间
+        erpWdtTrade.setPayTime(order.getDeal_datetime());
+        // 分销类别
+        erpWdtTrade.setFenxiaoType(FenxiaoType.JINGXIAO.getValue());
+        // 客户网名
+        erpWdtTrade.setBuyerNick(order.getReceiver_name());
+        // 收件人姓名
+        erpWdtTrade.setReceiverName(order.getReceiver_name());
+        // 省份
+        erpWdtTrade.setReceiverProvince(order.getReceiver_province());
+        // 市
+        erpWdtTrade.setReceiverCity(order.getReceiver_city());
+        // 区
+        erpWdtTrade.setReceiverDistrict(order.getReceiver_district());
+        // 详细地址
+        erpWdtTrade.setReceiverAddress(order.getReceiver_address());
+        // 手机
+        erpWdtTrade.setReceiverMobile(order.getReceiver_mobile());
+        // 固定电话
+        erpWdtTrade.setReceiverTelno(order.getReceiver_mobile());
+        // 买家备注
+        erpWdtTrade.setBuyerMessage(order.getBuyer_memo());
+        // 卖家备注
+        erpWdtTrade.setSellerMemo(order.getSeller_memo());
+        erpWdtTrade.setWarehouseNo(order.getWarehouse_code());
+
+        // 运费金额
+        erpWdtTrade.setPostAmount(liveOrder.getPayDelivery());
+        // 已付金额
+        if(ObjectUtils.isNotNull(liveOrder)){
+            erpWdtTrade.setPaid(liveOrder.getPayMoney());
+        }
+
+        List<LiveOrderItem> liveOrderItems = liveOrderItemMapper.selectLiveOrderItemByOrderId(liveOrder.getOrderId());
+        List<ErpWdtOrder> erpWdtOrderList = new ArrayList<>();
+        // 商品总价
+        BigDecimal totalPrice = liveOrder.getTotalPrice();
+
+        // 总折扣金额 = 优惠券金额 + 折扣金额
+        BigDecimal totalDiscountPrice = BigDecimal.ZERO;
+        // 折扣金额
+        BigDecimal discountPrice = totalPrice.subtract(liveOrder.getPayPrice());
+        totalDiscountPrice = couponPrice.add(discountPrice);
+
+        // 防止除零错误
+        if (totalPrice.compareTo(BigDecimal.ZERO) == 0) {
+            totalPrice = BigDecimal.ONE;
+        }
+
+        for (LiveOrderItem liveOrderItem : liveOrderItems) {
+            ErpWdtOrder erpWdtOrder = new ErpWdtOrder();
+            //平台订单货品表主键
+            erpWdtOrder.setOid(String.format("%s%s",liveOrder.getOrderCode(),liveOrderItem.getItemId()));
+            erpWdtOrder.setNum(BigDecimal.valueOf(liveOrderItem.getNum()));
+            FsStoreProductScrm fsStoreProduct = fsStoreProductScrmService.selectFsStoreProductById(liveOrderItem.getProductId());
+            Asserts.check(ObjectUtils.isNotNull(fsStoreProduct),"该产品不存在! 产品id: {} ",liveOrderItem.getProductId());
+            // 单价
+            erpWdtOrder.setPrice(fsStoreProduct.getPrice());
+            // 状态
+            erpWdtOrder.setStatus(TradeStatus.PAID_WAITING_FOR_SHIPMENT.getValue());
+            // 退款状态
+            erpWdtOrder.setRefundStatus(RefundStatus.NO_REFUND.getValue());
+
+            // 平台货品ID
+            erpWdtOrder.setGoodsId(String.valueOf(fsStoreProduct.getProductId()));
+            JSONObject jsonObject = JSON.parseObject(liveOrderItem.getJsonInfo());
+            erpWdtOrder.setSpecId(jsonObject.getString("sku"));
+            erpWdtOrder.setGoodsNo(jsonObject.getString("barCode"));
+            erpWdtOrder.setSpecNo(jsonObject.getString("sku"));
+            // 货品名称
+            erpWdtOrder.setGoodsName(fsStoreProduct.getProductName());
+            // 调整
+            erpWdtOrder.setAdjustAmount(BigDecimal.ZERO);
+            // 优惠
+            erpWdtOrder.setDiscount(BigDecimal.ZERO);
+            // 分摊优惠
+            // 分摊比例
+            BigDecimal price = fsStoreProduct.getPrice().multiply(BigDecimal.valueOf(liveOrderItem.getNum()));
+            BigDecimal divide = price.divide(totalPrice, RoundingMode.HALF_UP);
+            erpWdtOrder.setShareDiscount(divide.multiply(totalDiscountPrice));
+
+            erpWdtOrderList.add(erpWdtOrder);
+        }
+
+        // 最后一个商品的分摊优惠等于总优惠减去前面分摊优惠之和
+        Asserts.check(CollectionUtils.isNotEmpty(erpWdtOrderList),"订单 {} 商品不能为空!", order.getPlatform_code());
+        long size = erpWdtOrderList.size();
+        if(size > 1) {
+            ErpWdtOrder erpWdtOrder = erpWdtOrderList.get(erpWdtOrderList.size() - 1);
+            erpWdtOrder.setShareDiscount(totalDiscountPrice.subtract(erpWdtOrderList.stream()
+                    .limit(size - 1L)
+                    .map(item -> Optional.ofNullable(item.getShareDiscount()).orElse(BigDecimal.ZERO))
+                    .reduce(BigDecimal.ZERO, BigDecimal::add)));
+        }
+
+        erpWdtTrade.setOrderList(erpWdtOrderList);
+        erpWdtBusinessRequestParams.setTradeList(new ArrayList<>(Arrays.asList(erpWdtTrade)));
+
+        Map<String,String> map = new HashMap<>();
+        map.put("shop_no",erpWdtBusinessRequestParams.getShopNo());
+        map.put("switch_mode", String.valueOf(erpWdtBusinessRequestParams.getSwitchMode()));
+        map.put("trade_list", convertToSnakeCase(erpWdtBusinessRequestParams.getTradeList()));
+
+
+        try {
+            String response = client.execute("trade_push.php", map);
+            ParserConfig config = new ParserConfig();
+            config.propertyNamingStrategy = PropertyNamingStrategy.CamelCase;
+            ErpWdtApiResponse erpWdtApiResponse = JSON.parseObject(response, ErpWdtApiResponse.class,config);
+            if(ObjectUtil.equal(0,erpWdtApiResponse.getCode())){
+                log.info("订单推送成功: {}", response);
+                ErpOrderResponse erpOrderResponse = new ErpOrderResponse();
+                erpOrderResponse.setCode(order.getPlatform_code());
+                erpOrderResponse.setSuccess(true);
+                erpOrderResponse.setRequestRawData(JSON.toJSONString(map));
+                erpOrderResponse.setResponseRawData(response);
+                return erpOrderResponse;
+            } else {
+                throw new RuntimeException(String.format("订单推送失败,原因: %s",erpWdtApiResponse.getMessage()));
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return new ErpOrderResponse();
+    }
+
     /**
      * 获取erp推送参数
      * @param order 订单参数
@@ -800,6 +986,11 @@ public class WdtErpOrderServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public ErpOrderResponse refundLiveOrder(ErpRefundOrder order) {
+        return null;
+    }
+
     @Override
     public ErpDeliverysResponse getDeliver(ErpDeliverysRequest param) {
         return null;
@@ -837,6 +1028,11 @@ public class WdtErpOrderServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public ErpOrderQueryResponse getLiveOrder(ErpOrderQueryRequert param) {
+        return null;
+    }
+
     @Override
     public BaseResponse refundUpdate(ErpRefundUpdateRequest param) {
         FsSysConfig sysConfig = configUtil.getSysConfig();
@@ -921,6 +1117,11 @@ public class WdtErpOrderServiceImpl implements IErpOrderService {
         return null;
     }
 
+    @Override
+    public BaseResponse refundUpdateLive(ErpRefundUpdateRequest param) {
+        return null;
+    }
+
     @Override
     public ErpOrderResponse finishOrder(ErpOrder order) {
         FsSysConfig sysConfig = configUtil.getSysConfig();
@@ -1103,6 +1304,11 @@ public class WdtErpOrderServiceImpl implements IErpOrderService {
 
     }
 
+    @Override
+    public void getOrderLiveDeliveryStatus(LiveOrder order) {
+
+    }
+
     public static String convertToSnakeCase(Object obj) {
         SerializeConfig config = new SerializeConfig();
         config.propertyNamingStrategy = PropertyNamingStrategy.SnakeCase;

+ 17 - 3
fs-service/src/main/java/com/fs/his/domain/FsIntegralOrder.java

@@ -1,5 +1,8 @@
 package com.fs.his.domain;
 
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
@@ -16,11 +19,12 @@ import java.util.Date;
  * @date 2023-11-02
  */
 @Data
-public class FsIntegralOrder extends BaseEntity
+public class FsIntegralOrder
 {
     private static final long serialVersionUID = 1L;
 
     /** id */
+    @TableId
     private Long orderId;
 
     /** 订单编号 */
@@ -47,9 +51,10 @@ public class FsIntegralOrder extends BaseEntity
     @Excel(name = "商品信息")
     private String itemJson;
 
+    @TableField(exist = false)
     @Excel(name = "商品名称")
     private String goodsName;
-
+    @TableField(exist = false)
     @Excel(name = "原价")
     private BigDecimal otPrice;
 
@@ -73,7 +78,7 @@ public class FsIntegralOrder extends BaseEntity
     @Excel(name = "支付类型 1积分 2现金 3积分+现金")
     private Integer payType;
 
-    /** 1:待发货;2:待收货;3:已完成 4待支付 5取消 */
+    /** 1:待发货;2:待收货;3:已完成 4待支付 -1取消 */
     @Excel(name = "状态",dictType="sys_integral_order_status")
     private Integer status;
     @Excel(name = "商品编号")
@@ -116,4 +121,13 @@ public class FsIntegralOrder extends BaseEntity
 
     private String loginAccount;
 
+    private String remark;
+
+    private Date createTime;
+    @TableField(exist = false)
+    private Date updateTime;
+
+    private Integer deliveryStatus;
+
+    private String deliveryType;
 }

+ 73 - 0
fs-service/src/main/java/com/fs/his/domain/FsIntegralOrderDf.java

@@ -0,0 +1,73 @@
+package com.fs.his.domain;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 【请填写功能名称】对象 fs_integral_order_df
+ *
+ * @author fs
+ * @date 2025-11-11
+ */
+@Data
+public class FsIntegralOrderDf{
+
+    @TableId
+    /** 订单id */
+    private Long orderId;
+
+    /** 订单编号 */
+    @Excel(name = "订单编号")
+    private String orderCode;
+
+    /** $column.columnComment */
+    @Excel(name = "订单编号")
+    private String appKey;
+
+    /** $column.columnComment */
+    @Excel(name = "订单编号")
+    private String appSecret;
+
+    /** $column.columnComment */
+    @Excel(name = "订单编号")
+    private String loginAccount;
+
+    /** 顺丰月结账户 */
+    @Excel(name = "顺丰月结账户")
+    private String monthlyCard;
+
+    /** 物流产品编码:1-顺丰标快,2-顺丰标快(陆运),204-陆运微小件,231-陆运包裹,208-特惠专配 */
+    @Excel(name = "物流产品编码:1-顺丰标快,2-顺丰标快", readConverterExp = "陆=运")
+    private String expressProductCode;
+
+    /** 订单总价 */
+    @Excel(name = "订单总价")
+    private BigDecimal totalPrice;
+
+    /** 平台收款 */
+    @Excel(name = "平台收款")
+    private BigDecimal platformPrice;
+
+    /** 0:默认 1下单 2取消订单 */
+    @Excel(name = "0:默认 1下单 2取消订单")
+    private Integer status;
+
+    /** 失败原因 */
+    @Excel(name = "失败原因")
+    private String failMsg;
+
+    /** 包裹数量 */
+    @Excel(name = "包裹数量")
+    private Integer parcelQuantity;
+
+    private LocalDateTime updateTime;
+    private LocalDateTime createTime;
+    private String erpPhone;
+    private Integer isPush;
+}

+ 47 - 0
fs-service/src/main/java/com/fs/his/domain/FsIntegralOrderLogs.java

@@ -0,0 +1,47 @@
+package com.fs.his.domain;
+
+import com.fs.common.annotation.Excel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+/**
+ * 订单操作记录对象 fs_integral_order_logs
+ *
+ * @author fs
+ * @date 2025-11-25
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class FsIntegralOrderLogs{
+
+    /** $column.columnComment */
+    private String logsId;
+
+    /** 订单id */
+    @Excel(name = "订单id")
+    private Long orderId;
+
+    /** 操作类型 */
+    @Excel(name = "操作类型")
+    private String changeType;
+
+    /** 操作备注 */
+    @Excel(name = "操作备注")
+    private String changeMessage;
+
+    /** 操作时间 */
+    private LocalDateTime changeTime;
+
+    /** 操作员 */
+    @Excel(name = "操作员")
+    private String operator;
+
+
+}

+ 64 - 0
fs-service/src/main/java/com/fs/his/mapper/FsIntegralOrderDfMapper.java

@@ -0,0 +1,64 @@
+package com.fs.his.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsIntegralOrderDf;
+
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Mapper接口
+ *
+ * @author fs
+ * @date 2025-11-11
+ */
+public interface FsIntegralOrderDfMapper extends BaseMapper<FsIntegralOrderDf> {
+    /**
+     * 查询【请填写功能名称】
+     *
+     * @param orderId 【请填写功能名称】主键
+     * @return 【请填写功能名称】
+     */
+    FsIntegralOrderDf selectFsIntegralOrderDfByOrderId(Long orderId);
+
+    /**
+     * 查询【请填写功能名称】列表
+     *
+     * @param fsIntegralOrderDf 【请填写功能名称】
+     * @return 【请填写功能名称】集合
+     */
+    List<FsIntegralOrderDf> selectFsIntegralOrderDfList(FsIntegralOrderDf fsIntegralOrderDf);
+
+    /**
+     * 新增【请填写功能名称】
+     *
+     * @param fsIntegralOrderDf 【请填写功能名称】
+     * @return 结果
+     */
+    int insertFsIntegralOrderDf(FsIntegralOrderDf fsIntegralOrderDf);
+
+    /**
+     * 修改【请填写功能名称】
+     *
+     * @param fsIntegralOrderDf 【请填写功能名称】
+     * @return 结果
+     */
+    int updateFsIntegralOrderDf(FsIntegralOrderDf fsIntegralOrderDf);
+
+    /**
+     * 删除【请填写功能名称】
+     *
+     * @param orderId 【请填写功能名称】主键
+     * @return 结果
+     */
+    int deleteFsIntegralOrderDfByOrderId(Long orderId);
+
+    /**
+     * 批量删除【请填写功能名称】
+     *
+     * @param orderIds 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsIntegralOrderDfByOrderIds(Long[] orderIds);
+
+    List<FsIntegralOrderDf> selectByIsPush();
+}

+ 62 - 0
fs-service/src/main/java/com/fs/his/mapper/FsIntegralOrderLogsMapper.java

@@ -0,0 +1,62 @@
+package com.fs.his.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsIntegralOrderLogs;
+
+import java.util.List;
+
+/**
+ * 订单操作记录Mapper接口
+ *
+ * @author fs
+ * @date 2025-11-25
+ */
+public interface FsIntegralOrderLogsMapper extends BaseMapper<FsIntegralOrderLogs> {
+    /**
+     * 查询订单操作记录
+     *
+     * @param logsId 订单操作记录主键
+     * @return 订单操作记录
+     */
+    FsIntegralOrderLogs selectFsIntegralOrderLogsByLogsId(String logsId);
+
+    /**
+     * 查询订单操作记录列表
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 订单操作记录集合
+     */
+    List<FsIntegralOrderLogs> selectFsIntegralOrderLogsList(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 新增订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    int insertFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 修改订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    int updateFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 删除订单操作记录
+     *
+     * @param logsId 订单操作记录主键
+     * @return 结果
+     */
+    int deleteFsIntegralOrderLogsByLogsId(String logsId);
+
+    /**
+     * 批量删除订单操作记录
+     *
+     * @param logsIds 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsIntegralOrderLogsByLogsIds(String[] logsIds);
+}

+ 7 - 1
fs-service/src/main/java/com/fs/his/mapper/FsIntegralOrderMapper.java

@@ -1,6 +1,8 @@
 package com.fs.his.mapper;
 
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.his.domain.FsIntegralOrder;
+import com.fs.his.domain.FsIntegralOrderDf;
 import com.fs.his.param.FsIntegralOrderListUParam;
 import com.fs.his.param.FsIntegralOrderParam;
 import com.fs.his.vo.FsIntegralOrderListUVO;
@@ -17,7 +19,7 @@ import java.util.List;
  * @author fs
  * @date 2023-11-02
  */
-public interface FsIntegralOrderMapper
+public interface FsIntegralOrderMapper extends BaseMapper<FsIntegralOrder>
 {
     /**
      * 查询积分商品订单
@@ -110,4 +112,8 @@ public interface FsIntegralOrderMapper
     int cancelOrder(@Param("orderId") Long orderId);
 
     int finishOrder(@Param("orderId") Long orderId,@Param("oldStatus") Integer status);
+
+    List<FsIntegralOrder> findOrderByIds(@Param("orderIds") List<Long> orderIds);
+
+    List<FsIntegralOrderListVO> selectFsIntegralOrderListJn(FsIntegralOrderParam fsIntegralOrder);
 }

+ 13 - 0
fs-service/src/main/java/com/fs/his/mapper/FsUserMapper.java

@@ -1,5 +1,6 @@
 package com.fs.his.mapper;
 
+import java.math.BigDecimal;
 import java.util.List;
 import java.util.Map;
 
@@ -35,6 +36,8 @@ import org.apache.ibatis.annotations.Param;
  */
 public interface FsUserMapper
 {
+    @Select("select * from fs_user where phone=#{phone}")
+    List<FsUser> selectFsUsersByPhoneLimitOne(String phone);
     /**
      * 查询用户
      *
@@ -463,4 +466,14 @@ public interface FsUserMapper
      * 查询会员列表
      */
     List<FsUser> findUsersByIdsV2(@Param("userIds") List<Long> userIds);
+
+    /**
+     * 更新用户下单次数和累计成交总额
+     * @param userId 用户ID
+     * @param amount 成交金额
+     */
+    @Update("update fs_user set order_count = order_count + 1, total_amount = IFNULL(total_amount, 0) + #{amount} where user_id = #{userId}")
+    void updateUserOrderCountAndAmount(@Param("userId") Long userId, @Param("amount") BigDecimal amount);
+
+    List<FsUser> selectFsUserListByPhone(String phone);
 }

+ 62 - 0
fs-service/src/main/java/com/fs/his/service/IFsIntegralOrderDfService.java

@@ -0,0 +1,62 @@
+package com.fs.his.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.his.domain.FsIntegralOrderDf;
+
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Service接口
+ *
+ * @author fs
+ * @date 2025-11-11
+ */
+public interface IFsIntegralOrderDfService extends IService<FsIntegralOrderDf> {
+    /**
+     * 查询【请填写功能名称】
+     *
+     * @param orderId 【请填写功能名称】主键
+     * @return 【请填写功能名称】
+     */
+    FsIntegralOrderDf selectFsIntegralOrderDfByOrderId(Long orderId);
+
+    /**
+     * 查询【请填写功能名称】列表
+     *
+     * @param fsIntegralOrderDf 【请填写功能名称】
+     * @return 【请填写功能名称】集合
+     */
+    List<FsIntegralOrderDf> selectFsIntegralOrderDfList(FsIntegralOrderDf fsIntegralOrderDf);
+
+    /**
+     * 新增【请填写功能名称】
+     *
+     * @param fsIntegralOrderDf 【请填写功能名称】
+     * @return 结果
+     */
+    int insertFsIntegralOrderDf(FsIntegralOrderDf fsIntegralOrderDf);
+
+    /**
+     * 修改【请填写功能名称】
+     *
+     * @param fsIntegralOrderDf 【请填写功能名称】
+     * @return 结果
+     */
+    int updateFsIntegralOrderDf(FsIntegralOrderDf fsIntegralOrderDf);
+
+    /**
+     * 批量删除【请填写功能名称】
+     *
+     * @param orderIds 需要删除的【请填写功能名称】主键集合
+     * @return 结果
+     */
+    int deleteFsIntegralOrderDfByOrderIds(Long[] orderIds);
+
+    /**
+     * 删除【请填写功能名称】信息
+     *
+     * @param orderId 【请填写功能名称】主键
+     * @return 结果
+     */
+    int deleteFsIntegralOrderDfByOrderId(Long orderId);
+}

+ 62 - 0
fs-service/src/main/java/com/fs/his/service/IFsIntegralOrderLogsService.java

@@ -0,0 +1,62 @@
+package com.fs.his.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.his.domain.FsIntegralOrderLogs;
+
+import java.util.List;
+
+/**
+ * 订单操作记录Service接口
+ *
+ * @author fs
+ * @date 2025-11-25
+ */
+public interface IFsIntegralOrderLogsService extends IService<FsIntegralOrderLogs> {
+    /**
+     * 查询订单操作记录
+     *
+     * @param logsId 订单操作记录主键
+     * @return 订单操作记录
+     */
+    FsIntegralOrderLogs selectFsIntegralOrderLogsByLogsId(String logsId);
+
+    /**
+     * 查询订单操作记录列表
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 订单操作记录集合
+     */
+    List<FsIntegralOrderLogs> selectFsIntegralOrderLogsList(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 新增订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    int insertFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 修改订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    int updateFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 批量删除订单操作记录
+     *
+     * @param logsIds 需要删除的订单操作记录主键集合
+     * @return 结果
+     */
+    int deleteFsIntegralOrderLogsByLogsIds(String[] logsIds);
+
+    /**
+     * 删除订单操作记录信息
+     *
+     * @param logsId 订单操作记录主键
+     * @return 结果
+     */
+    int deleteFsIntegralOrderLogsByLogsId(String logsId);
+}

+ 3 - 0
fs-service/src/main/java/com/fs/his/service/IFsUserService.java

@@ -22,6 +22,7 @@ import com.fs.his.vo.FsUserExportListVO;
 import com.fs.his.vo.FsUserFollowDoctorVO;
 import com.fs.his.vo.UserVo;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
+import com.fs.hisStore.domain.FsUserScrm;
 import com.fs.hisStore.vo.FsCompanyUserListQueryVO;
 import com.fs.live.vo.HisFsUserVO;
 import com.fs.qw.dto.FsUserTransferParamDTO;
@@ -237,4 +238,6 @@ public interface IFsUserService
     void increaseIntegral(List<Long> longs, Long integral);
 
     HisFsUserVO getHisUserIntegralWithLogs(FsUser fsUser);
+
+    List<FsUser> selectFsUserListByPhone(String phone);
 }

+ 93 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderDfServiceImpl.java

@@ -0,0 +1,93 @@
+package com.fs.his.service.impl;
+
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.utils.DateUtils;
+import com.fs.his.domain.FsIntegralOrderDf;
+import com.fs.his.mapper.FsIntegralOrderDfMapper;
+import com.fs.his.service.IFsIntegralOrderDfService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 【请填写功能名称】Service业务层处理
+ *
+ * @author fs
+ * @date 2025-11-11
+ */
+@Service
+public class FsIntegralOrderDfServiceImpl extends ServiceImpl<FsIntegralOrderDfMapper, FsIntegralOrderDf> implements IFsIntegralOrderDfService {
+
+    /**
+     * 查询【请填写功能名称】
+     *
+     * @param orderId 【请填写功能名称】主键
+     * @return 【请填写功能名称】
+     */
+    @Override
+    public FsIntegralOrderDf selectFsIntegralOrderDfByOrderId(Long orderId)
+    {
+        return baseMapper.selectFsIntegralOrderDfByOrderId(orderId);
+    }
+
+    /**
+     * 查询【请填写功能名称】列表
+     *
+     * @param fsIntegralOrderDf 【请填写功能名称】
+     * @return 【请填写功能名称】
+     */
+    @Override
+    public List<FsIntegralOrderDf> selectFsIntegralOrderDfList(FsIntegralOrderDf fsIntegralOrderDf)
+    {
+        return baseMapper.selectFsIntegralOrderDfList(fsIntegralOrderDf);
+    }
+
+    /**
+     * 新增【请填写功能名称】
+     *
+     * @param fsIntegralOrderDf 【请填写功能名称】
+     * @return 结果
+     */
+    @Override
+    public int insertFsIntegralOrderDf(FsIntegralOrderDf fsIntegralOrderDf)
+    {
+        return baseMapper.insertFsIntegralOrderDf(fsIntegralOrderDf);
+    }
+
+    /**
+     * 修改【请填写功能名称】
+     *
+     * @param fsIntegralOrderDf 【请填写功能名称】
+     * @return 结果
+     */
+    @Override
+    public int updateFsIntegralOrderDf(FsIntegralOrderDf fsIntegralOrderDf)
+    {
+        return baseMapper.updateFsIntegralOrderDf(fsIntegralOrderDf);
+    }
+
+    /**
+     * 批量删除【请填写功能名称】
+     *
+     * @param orderIds 需要删除的【请填写功能名称】主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsIntegralOrderDfByOrderIds(Long[] orderIds)
+    {
+        return baseMapper.deleteFsIntegralOrderDfByOrderIds(orderIds);
+    }
+
+    /**
+     * 删除【请填写功能名称】信息
+     *
+     * @param orderId 【请填写功能名称】主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsIntegralOrderDfByOrderId(Long orderId)
+    {
+        return baseMapper.deleteFsIntegralOrderDfByOrderId(orderId);
+    }
+}

+ 92 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderLogsServiceImpl.java

@@ -0,0 +1,92 @@
+package com.fs.his.service.impl;
+
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.his.domain.FsIntegralOrderLogs;
+import com.fs.his.mapper.FsIntegralOrderLogsMapper;
+import com.fs.his.service.IFsIntegralOrderLogsService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 订单操作记录Service业务层处理
+ *
+ * @author fs
+ * @date 2025-11-25
+ */
+@Service
+public class FsIntegralOrderLogsServiceImpl extends ServiceImpl<FsIntegralOrderLogsMapper, FsIntegralOrderLogs> implements IFsIntegralOrderLogsService {
+
+    /**
+     * 查询订单操作记录
+     *
+     * @param logsId 订单操作记录主键
+     * @return 订单操作记录
+     */
+    @Override
+    public FsIntegralOrderLogs selectFsIntegralOrderLogsByLogsId(String logsId)
+    {
+        return baseMapper.selectFsIntegralOrderLogsByLogsId(logsId);
+    }
+
+    /**
+     * 查询订单操作记录列表
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 订单操作记录
+     */
+    @Override
+    public List<FsIntegralOrderLogs> selectFsIntegralOrderLogsList(FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        return baseMapper.selectFsIntegralOrderLogsList(fsIntegralOrderLogs);
+    }
+
+    /**
+     * 新增订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    @Override
+    public int insertFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        return baseMapper.insertFsIntegralOrderLogs(fsIntegralOrderLogs);
+    }
+
+    /**
+     * 修改订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    @Override
+    public int updateFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        return baseMapper.updateFsIntegralOrderLogs(fsIntegralOrderLogs);
+    }
+
+    /**
+     * 批量删除订单操作记录
+     *
+     * @param logsIds 需要删除的订单操作记录主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsIntegralOrderLogsByLogsIds(String[] logsIds)
+    {
+        return baseMapper.deleteFsIntegralOrderLogsByLogsIds(logsIds);
+    }
+
+    /**
+     * 删除订单操作记录信息
+     *
+     * @param logsId 订单操作记录主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsIntegralOrderLogsByLogsId(String logsId)
+    {
+        return baseMapper.deleteFsIntegralOrderLogsByLogsId(logsId);
+    }
+}

+ 10 - 4
fs-service/src/main/java/com/fs/his/service/impl/FsUserServiceImpl.java

@@ -68,6 +68,7 @@ import com.fs.im.config.ImTypeConfig;
 import com.fs.im.service.OpenIMService;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
 import com.fs.hisStore.domain.FsUserBillScrm;
+import com.fs.hisStore.domain.FsUserScrm;
 import com.fs.hisStore.enums.BillDetailEnum;
 import com.fs.hisStore.mapper.FsStoreOrderScrmMapper;
 import com.fs.hisStore.service.IFsUserBillScrmService;
@@ -1244,11 +1245,11 @@ public class FsUserServiceImpl implements IFsUserService {
                 if (tuiUser != null) {
                     FsUser tuiUserMap = new FsUser();
                     tuiUserMap.setUserId(tuiUser.getUserId());
-                    tuiUserMap.setNowMoney(tuiUser.getNowMoney().add(new BigDecimal(bill.getNumber())));
-                    tuiUserMap.setBrokeragePrice(tuiUser.getBrokeragePrice().subtract(new BigDecimal(bill.getNumber())));
+                    tuiUserMap.setNowMoney(tuiUser.getNowMoney().add(bill.getMoney()));
+                    tuiUserMap.setBrokeragePrice(tuiUser.getBrokeragePrice().subtract(bill.getMoney()));
                     fsUserMapper.updateFsUser(tuiUserMap);
-                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_3.getValue(), 0, BillDetailEnum.TYPE_6.getDesc(), bill.getNumber().doubleValue(), tuiUserMap.getBrokeragePrice().doubleValue(), "订单分佣金", order.getId().toString(), bill.getTuiUserId());
-                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_1.getValue(), 1, BillDetailEnum.TYPE_5.getDesc(), bill.getNumber().doubleValue(), tuiUserMap.getNowMoney().doubleValue(), "订单分佣金", order.getId().toString(), bill.getTuiUserId());
+                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_3.getValue(), 0, BillDetailEnum.TYPE_6.getDesc(), bill.getMoney(), tuiUserMap.getBrokeragePrice(), "订单分佣金", order.getId().toString(), bill.getTuiUserId());
+                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_1.getValue(), 1, BillDetailEnum.TYPE_5.getDesc(), bill.getMoney(), tuiUserMap.getNowMoney(), "订单分佣金", order.getId().toString(), bill.getTuiUserId());
                 }
             }
         }
@@ -1613,4 +1614,9 @@ public class FsUserServiceImpl implements IFsUserService {
         return new HisFsUserVO();
     }
 
+    @Override
+    public List<FsUser> selectFsUserListByPhone(String phone) {
+        return fsUserMapper.selectFsUserListByPhone(phone);
+    }
+
 }

+ 32 - 0
fs-service/src/main/java/com/fs/his/vo/FsIntegralOrderExcelVO.java

@@ -0,0 +1,32 @@
+package com.fs.his.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class FsIntegralOrderExcelVO {
+    @Excel(name = "药品订单号",required = true)
+    private String orderCode;
+
+    @Excel(name = "订单状态",dictType = "sys_integral_order_status")
+    private String status;
+
+//    @Excel(name = "物流代收金额")
+//    private BigDecimal payRemain;
+
+    /** 物流状态 */
+    @Excel(name = "物流状态",dictType = "sys_store_order_delivery_status")
+    private String deliveryStatus;
+
+    /** 物流跟踪状态 */
+    @Excel(name = "物流跟踪状态",dictType = "sys_delivery_type")
+    private String deliveryType;
+
+    /** shou */
+    @Excel(name = "收货人电话")
+    private String userPhone;
+    /** 详情地址 */
+    @Excel(name = "详情地址(例:广东省 韶关市 仁化县 亨特中心22楼)使用空格分割")
+    private String userAddress;
+
+}

+ 3 - 0
fs-service/src/main/java/com/fs/hisStore/config/StoreConfig.java

@@ -25,4 +25,7 @@ public class StoreConfig implements Serializable {
     private Integer createSalesOrderType; // 订单改价方式 1 商品改价 2总价改价
     private Boolean isBrushOrders;//是否开启刷单按钮
     private Integer orderAttribution; // 下单归属 1 多销售 2单销售
+    private Boolean isWeChatShipping;//是否开启微信发货
+    private Boolean scanCodeDiscountEnabled;//是否开启扫码立减金
+    private BigDecimal scanCodeDiscountAmount;//扫码立减金额
 }

+ 2 - 0
fs-service/src/main/java/com/fs/hisStore/domain/FsStoreOrderScrm.java

@@ -351,4 +351,6 @@ public class FsStoreOrderScrm extends BaseEntity
     private BigDecimal billPrice;
     private String erpPhone;
 
+    @TableField(exist = false)
+    private String bankTransactionId;
 }

+ 27 - 12
fs-service/src/main/java/com/fs/hisStore/domain/FsUserBillScrm.java

@@ -4,9 +4,11 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import com.fs.common.annotation.Excel;
 import com.fs.common.core.domain.BaseEntity;
 
+import java.math.BigDecimal;
+
 /**
  * 用户账单对象 fs_user_bill
- * 
+ *
  * @author fs
  * @date 2022-04-30
  */
@@ -16,7 +18,7 @@ public class FsUserBillScrm extends BaseEntity
     private static final long serialVersionUID = 1L;
 
     /** 用户账单id */
-    private Long id;
+    private Long billId;
 
     /** 用户uid */
     @Excel(name = "用户uid")
@@ -44,11 +46,14 @@ public class FsUserBillScrm extends BaseEntity
 
     /** 明细数字 */
     @Excel(name = "明细数字")
-    private Double number;
+    private BigDecimal number;
+
+    @Excel(name = "金额")
+    private BigDecimal money;
 
     /** 剩余 */
     @Excel(name = "剩余")
-    private Double balance;
+    private BigDecimal balance;
 
     /** 0 = 带确定 1 = 有效 -1 = 无效 */
     @Excel(name = "0 = 带确定 1 = 有效 -1 = 无效")
@@ -56,6 +61,15 @@ public class FsUserBillScrm extends BaseEntity
 
     private Long tuiUserId;
 
+
+    public BigDecimal getMoney() {
+        return money;
+    }
+
+    public void setMoney(BigDecimal money) {
+        this.money = money;
+    }
+
     public Long getTuiUserId() {
         return tuiUserId;
     }
@@ -68,12 +82,13 @@ public class FsUserBillScrm extends BaseEntity
         return serialVersionUID;
     }
 
-    public Long getId() {
-        return id;
+    public Long getBillId() {
+        return billId;
     }
 
-    public void setId(Long id) {
-        this.id = id;
+    public FsUserBillScrm setBillId(Long billId) {
+        this.billId = billId;
+        return this;
     }
 
     public Long getUserId() {
@@ -124,19 +139,19 @@ public class FsUserBillScrm extends BaseEntity
         this.title = title;
     }
 
-    public Double getNumber() {
+    public BigDecimal getNumber() {
         return number;
     }
 
-    public void setNumber(Double number) {
+    public void setNumber(BigDecimal number) {
         this.number = number;
     }
 
-    public Double getBalance() {
+    public BigDecimal getBalance() {
         return balance;
     }
 
-    public void setBalance(Double balance) {
+    public void setBalance(BigDecimal balance) {
         this.balance = balance;
     }
 

+ 36 - 0
fs-service/src/main/java/com/fs/hisStore/domain/FsUserScrm.java

@@ -171,6 +171,10 @@ public class FsUserScrm extends BaseEntity
 
     private String courseMaOpenId; //看课小程序openid
 
+
+
+    private String historyApp; //app登录后不为null(表示是否下载app)
+
     private Long qwExtId;
 
     /**
@@ -178,6 +182,19 @@ public class FsUserScrm extends BaseEntity
      * **/
     private Long qwUserId;
 
+    /**
+     * 小程序appId,多个用逗号分隔
+     */
+    private String appId;
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
     public void setNickName(String nickname)
     {
         if(StringUtils.isNotEmpty(nickname)){
@@ -215,6 +232,16 @@ public class FsUserScrm extends BaseEntity
     private String companyName;
     private String rank;
     private String react;
+    /** 绑定的公司用户ID */
+    private Long bindCompanyUserId;
+
+    public Long getBindCompanyUserId() {
+        return bindCompanyUserId;
+    }
+
+    public void setBindCompanyUserId(Long bindCompanyUserId) {
+        this.bindCompanyUserId = bindCompanyUserId;
+    }
 
     /**
      * 项目ID
@@ -816,4 +843,13 @@ public class FsUserScrm extends BaseEntity
     public void setOrderCount(Integer orderCount) {
         this.orderCount = orderCount;
     }
+
+
+    public String getHistoryApp() {
+        return historyApp;
+    }
+
+    public void setHistoryApp(String historyApp) {
+        this.historyApp = historyApp;
+    }
 }

+ 1 - 0
fs-service/src/main/java/com/fs/hisStore/enums/OrderInfoEnum.java

@@ -15,6 +15,7 @@ public enum OrderInfoEnum {
     STATUS_1(1,"待发货"),
     STATUS_2(2,"待收货"),
     STATUS_3(3,"已完成"),
+    STATUS_4(4,"待评价"),
 
     PAY_STATUS_0(0,"未支付"),
     PAY_STATUS_1(1,"已支付"),

+ 2 - 1
fs-service/src/main/java/com/fs/hisStore/enums/ShipperCodeEnum.java

@@ -6,7 +6,8 @@ import lombok.Getter;
 @Getter
 @AllArgsConstructor
 public enum  ShipperCodeEnum {
-    SF("SF","顺丰速运");
+    SF("SF","顺丰速运"),
+    ZTO("ZTO","中通快递");
 
     private String value;
     private String desc;

+ 19 - 2
fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreOrderScrmMapper.java

@@ -509,9 +509,9 @@ public interface FsStoreOrderScrmMapper
     @Select("select * from fs_store_order_scrm where extend_order_id=#{extendOrderId}")
     FsStoreOrderScrm selectFsStoreOrderByExtendOrderId(String extendOrderId);
     @Select({"<script> " +
-            "select b.number as tui_price,b.bill_type,b.create_time,o.id as order_id,o.order_code,o.pay_price,u.nickname,u.avatar from fs_user_bill b inner join  fs_store_order_scrm o on b.business_id=o.id left join fs_user u on u.user_id=o.user_id  " +
+            "select b.money as tui_price,b.bill_type,b.create_time,o.id as order_id,o.order_code,o.pay_price,u.nickname,u.avatar from fs_user_bill b inner join  fs_store_order_scrm o on b.business_id=o.id left join fs_user u on u.user_id=o.user_id  " +
             "where b.user_id=#{userId} and b.category='brokerage_price'   " +
-            " order by b.id desc"+
+            " order by b.bill_id desc"+
             "</script>"})
     List<FsStoreOrderTuiVO> selectFsStoreOrderTuiListVO(String userId);
     @Select({"<script> " +
@@ -1378,4 +1378,21 @@ public interface FsStoreOrderScrmMapper
 
     @Select("select * from fs_store_order_scrm where  `status`=2 and (extend_order_id is not null and extend_order_id != '') and (delivery_id is not null and delivery_id != '')")
     List<FsStoreOrderScrm> selectShippedOrder();
+    /**
+     * 获取发货单数据
+     * @param maps 查询参数
+     * @return list
+     * **/
+    List<FsStoreOrderDeliveryNoteExportVO> getDeliveryNote(@Param("maps") FsStoreOrderParam maps);
+    /**
+     * 获取订单用户信息
+     * @param list 订单号
+     * @return lsit
+     * **/
+    List<FsStoreOrderCodeOpenIdVo> selectOrderCodeOpenIdInOrderCode(@Param("list") List<String> list);
+    /**
+     * 获取未结算订单
+     * **/
+    List<FsStoreOrderScrm> getUnsettledOrder();
+
 }

+ 28 - 1
fs-service/src/main/java/com/fs/hisStore/mapper/FsUserScrmMapper.java

@@ -3,6 +3,7 @@ package com.fs.hisStore.mapper;
 import com.fs.course.vo.newfs.FsCourseAnalysisCountVO;
 import com.fs.his.domain.FsUser;
 import com.fs.his.vo.OptionsVO;
+import com.fs.hisStore.vo.UserScrmVo;
 import com.fs.qw.param.QwFsUserParam;
 import com.fs.qw.vo.QwFsUserVO;
 import com.fs.hisStore.domain.FsUserScrm;
@@ -20,7 +21,9 @@ import com.fs.hisStore.domain.FsUserWatchStatisticsScrm;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
+import org.springframework.security.core.parameters.P;
 
+import java.math.BigDecimal;
 import java.util.List;
 import java.util.Map;
 
@@ -124,6 +127,13 @@ public interface FsUserScrmMapper
     @Select("select * from fs_user where phone=#{phone}")
     FsUserScrm selectFsUserByPhone(String phone);
 
+    /**
+     * 根据手机号码精确查询用户列表(完全匹配)
+     * @param phone 手机号码
+     * @return 用户列表
+     */
+    List<FsUserScrm> selectFsUserListByPhoneExact(String phone);
+
 
     @Select("select  b.total_amount,b.last_buy_time,p.pay_money as number,p.payment_id,p.pay_time," +
             " u.* FROM fs_user u LEFT JOIN  (" +
@@ -158,7 +168,7 @@ public interface FsUserScrmMapper
             "</script>"})
     List<FsCompanyUserListQueryVO> selectFsCompanyUserListQuery(@Param("maps") FsUserScrm fsUser);
     @Select({"<script> " +
-            "select u.user_id,u.phone,u.avatar,u.nickname,ifnull((select sum(b.number) from fs_user_bill b where b.category='brokerage_price' and b.bill_type=1  and b.tui_user_id=u.user_id and b.user_id=#{userId} ),0)-ifnull((select sum(b.number) from fs_user_bill b where b.category='brokerage_price' and b.bill_type=0 and b.tui_user_id=u.user_id and b.user_id=#{userId}  ),0) as tui_money ,u.create_time from fs_user u " +
+            "select u.user_id,u.phone,u.avatar,u.nickname,ifnull((select sum(b.money) from fs_user_bill b where b.category='brokerage_price' and b.bill_type=1  and b.tui_user_id=u.user_id and b.user_id=#{userId} ),0)-ifnull((select sum(b.money) from fs_user_bill b where b.category='brokerage_price' and b.bill_type=0 and b.tui_user_id=u.user_id and b.user_id=#{userId}  ),0) as tui_money ,u.create_time from fs_user u " +
             "where u.spread_user_id=#{userId} " +
             "order by tui_money desc " +
             "</script>"})
@@ -319,4 +329,21 @@ public interface FsUserScrmMapper
     Map<String, Long> countCourseDetailsNew(UserStatisticsCommonParam param);
     @Select("select * from fs_user where mp_open_id=#{openId}")
     FsUserScrm selectFsUserByOpenId(String openId);
+
+    /**
+     * 更新用户下单次数和累计成交总额
+     * @param userId 用户ID
+     * @param amount 成交金额
+     */
+    @Update("update fs_user set order_count = order_count + 1, total_amount = IFNULL(total_amount, 0) + #{amount} where user_id = #{userId}")
+    void updateUserOrderCountAndAmount(@Param("userId") Long userId, @Param("amount") BigDecimal amount);
+
+    /**
+     * 累计成交总额
+     * @param payMoney 成交金额
+     */
+    @Update("update fs_user set total_amount = IFNULL(total_amount, 0) + #{payMoney} where user_id = #{userId}")
+    void incPayMoney(@Param("payMoney") BigDecimal payMoney, @Param("userId") Long userId);
+
+    List<UserScrmVo> selectUserVOList(@Param("phone") String phone);
 }

+ 1 - 0
fs-service/src/main/java/com/fs/hisStore/param/FsStoreConfirmPackageIdOrderParam.java

@@ -8,4 +8,5 @@ import lombok.Setter;
 public class FsStoreConfirmPackageIdOrderParam {
     private Long packageId;
     private Long couponUserId;
+    private String createOrderKey;
 }

+ 6 - 0
fs-service/src/main/java/com/fs/hisStore/param/FsStorePackageOrderCreateParam.java

@@ -6,6 +6,7 @@ import lombok.Data;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
 import java.io.Serializable;
+import java.math.BigDecimal;
 
 @Data
 public class FsStorePackageOrderCreateParam implements Serializable
@@ -22,5 +23,10 @@ public class FsStorePackageOrderCreateParam implements Serializable
     private Long packageId;
     private Long companyUserId;
     private Long couponUserId;
+    @ApiModelProperty(value = "修改后的价格")
+    private BigDecimal payAmount;
+
+    @ApiModelProperty(value = "是否是套餐包制单",example  = "0")
+    private Integer isPackage;
 
 }

+ 24 - 0
fs-service/src/main/java/com/fs/hisStore/param/FsUserCouponScrmSendParam.java

@@ -0,0 +1,24 @@
+package com.fs.hisStore.param;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+@Data
+public class FsUserCouponScrmSendParam {
+
+    /** 优惠劵id */
+    @Excel(name = "优惠劵id")
+    private Long id;
+
+    @Excel(name = "会员ID")
+    private Long userId;
+
+    // 发送人id
+    private Long setSendUserId;
+
+    //发送销售id
+    private Long companyUserId;
+
+    //发送销售公司id
+    private Long companyId;
+}

+ 26 - 1
fs-service/src/main/java/com/fs/hisStore/service/IFsStoreOrderScrmService.java

@@ -39,6 +39,10 @@ import com.fs.his.vo.FsPrescribeVO;
 public interface IFsStoreOrderScrmService
 {
 
+    /**
+     * 同步物流信息到微信
+     */
+    void syncExpressToWx();
     /**
      * 查询订单
      *
@@ -181,7 +185,7 @@ public interface IFsStoreOrderScrmService
 
     R addUserCart(long userId, String createOrderKey);
 
-    R updateSalseOrderMoney(String createOrderKey, BigDecimal money,BigDecimal payAmount,Integer payType);
+    R updateSalseOrderMoney(String createOrderKey, BigDecimal money,BigDecimal payAmount,Integer payType, Integer isPackage);
 
     Integer selectFsStoreOrderCountByType(Long companyId, long userId, int type);
 
@@ -320,4 +324,25 @@ public interface IFsStoreOrderScrmService
     R dfOrderResult(String body);
 
     R receiveWaybillPush(String body);
+
+    /**
+     * 获取发货单数据
+     * @param param 查询条件
+     * @return list
+     * **/
+    List<FsStoreOrderDeliveryNoteExportVO> getDeliveryNote(FsStoreOrderParam param);
+
+    R importDeliveryNoteExpress(List<FsOrderDeliveryNoteDTO> dtoList, String miniAppId);
+
+    void refreshOrderSettlementStatus();
+
+    /**
+     * 套餐包制单
+     * @param companyUser 销售
+     * @param packageId 套餐包id
+     * @param orderType 订单类型
+     * @param orderMedium 媒体类型
+     * @return
+     */
+    R createPackageSalesOrder(CompanyUser companyUser, String packageId, Integer orderType, Integer orderMedium);
 }

+ 8 - 8
fs-service/src/main/java/com/fs/hisStore/service/IFsUserBillScrmService.java

@@ -9,7 +9,7 @@ import com.fs.hisStore.vo.FsUserBillVO;
 
 /**
  * 用户账单Service接口
- * 
+ *
  * @author fs
  * @date 2022-04-03
  */
@@ -17,7 +17,7 @@ public interface IFsUserBillScrmService
 {
     /**
      * 查询用户账单
-     * 
+     *
      * @param id 用户账单ID
      * @return 用户账单
      */
@@ -25,7 +25,7 @@ public interface IFsUserBillScrmService
 
     /**
      * 查询用户账单列表
-     * 
+     *
      * @param fsUserBill 用户账单
      * @return 用户账单集合
      */
@@ -33,7 +33,7 @@ public interface IFsUserBillScrmService
 
     /**
      * 新增用户账单
-     * 
+     *
      * @param fsUserBill 用户账单
      * @return 结果
      */
@@ -41,7 +41,7 @@ public interface IFsUserBillScrmService
 
     /**
      * 修改用户账单
-     * 
+     *
      * @param fsUserBill 用户账单
      * @return 结果
      */
@@ -49,7 +49,7 @@ public interface IFsUserBillScrmService
 
     /**
      * 批量删除用户账单
-     * 
+     *
      * @param ids 需要删除的用户账单ID
      * @return 结果
      */
@@ -57,13 +57,13 @@ public interface IFsUserBillScrmService
 
     /**
      * 删除用户账单信息
-     * 
+     *
      * @param id 用户账单ID
      * @return 结果
      */
     public int deleteFsUserBillById(Long id);
 
-    void addBill(Long uid,String cate,Integer billType, String title, double number, double balance, String remark,String busId,Long tuiUserId);
+    void addBill(Long uid,String cate,Integer billType, String title, BigDecimal number, BigDecimal balance, String remark,String busId,Long tuiUserId);
 
 
     List<FsUserBillScrm> selectFsUserBillListQuery(FsUserBillQueryParam param);

+ 27 - 0
fs-service/src/main/java/com/fs/hisStore/service/IFsUserScrmService.java

@@ -1,11 +1,18 @@
 package com.fs.hisStore.service;
 
+import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.param.LoginMaWxParam;
 import com.fs.course.param.newfs.FsUserCourseBeMemberParam;
 import com.fs.course.vo.newfs.FsCourseAnalysisVO;
+import com.fs.his.domain.FsStoreProductAttrValue;
+import com.fs.his.domain.FsUser;
 import com.fs.his.vo.OptionsVO;
+import com.fs.hisStore.domain.FsStoreProductAttrValueScrm;
+import com.fs.hisStore.vo.UserScrmVo;
+import com.fs.live.domain.LiveOrder;
 import com.fs.qw.param.QwFsUserParam;
 import com.fs.qw.vo.QwFsUserVO;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
@@ -22,6 +29,7 @@ import com.fs.hisStore.vo.FsUserTuiVO;
 import com.fs.hisStore.vo.h5.*;
 import com.github.pagehelper.PageInfo;
 
+import java.math.BigDecimal;
 import java.util.List;
 import java.util.Map;
 
@@ -104,6 +112,13 @@ public interface IFsUserScrmService
 
     FsUserScrm selectFsUserByPhone(String phone);
 
+    /**
+     * 根据手机号码精确查询用户列表(完全匹配)
+     * @param phone 手机号码
+     * @return 用户列表
+     */
+    List<FsUserScrm> selectFsUserListByPhoneExact(String phone);
+
     TableDataInfo selectCusListPage(SelectCusListPageParam param);
 
     List<FsCompanyUserListQueryVO> selectFsCompanyUserListQuery(FsUserScrm fsUser);
@@ -147,6 +162,8 @@ public interface IFsUserScrmService
 
     UserListPageVO getUserNumber(Long userId);
 
+    UserDetailsVO getUserDetails(Long userId, Long fsUserId, String dateTag, Long userCompanyId);
+
     /**
      * 查询重粉用户是否存在
      * @param userIds
@@ -270,4 +287,14 @@ public interface IFsUserScrmService
     List<FSUserVO> selectFsUserVOListByProject(FsUserScrm fsUser);
 
     FsUserScrm selectFsUserByOpenId(String openid);
+
+    void addTuiLiveMoney(LiveOrder order, List<FsStoreProductAttrValueScrm> productAttrValues);
+
+    void subLiveTuiMoney(LiveOrder liveOrder);
+
+    void handleFsUserWx(FsUserScrm user, LoginMaWxParam param, WxMaJscode2SessionResult session);
+
+    void incPayMoney(BigDecimal payMoney, Long userId);
+
+    List<UserScrmVo> selectUserVOList(String phone);
 }

+ 539 - 49
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java

@@ -1,6 +1,8 @@
 package com.fs.hisStore.service.impl;
 
 import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
+import cn.binarywang.wx.miniapp.bean.shop.request.shipping.*;
+import cn.binarywang.wx.miniapp.bean.shop.response.WxMaOrderShippingInfoGetResponse;
 import cn.hutool.core.date.DateTime;
 import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.hutool.core.net.URLDecoder;
@@ -46,6 +48,7 @@ import com.fs.core.config.WxMaConfiguration;
 import com.fs.core.config.WxPayProperties;
 import com.fs.core.utils.OrderCodeUtils;
 import com.fs.course.dto.FsOrderDeliveryNoteDTO;
+import com.fs.course.dto.OrderOpenIdTransDTO;
 import com.fs.erp.domain.*;
 import com.fs.erp.dto.*;
 import com.fs.erp.dto.df.*;
@@ -102,6 +105,12 @@ import com.fs.hisStore.enums.*;
 import com.fs.hisStore.service.*;
 import com.fs.system.service.ISysConfigService;
 import com.fs.wx.miniapp.config.WxMaProperties;
+import com.fs.wx.order.domain.FsWxExpressTask;
+import com.fs.wx.order.dto.*;
+import com.fs.wx.order.mapper.FsWxExpressTaskMapper;
+import com.fs.wx.order.service.ExpressToWxHolder;
+import com.fs.wx.order.service.ExpressToWxService;
+import com.fs.wx.order.service.ShippingService;
 import com.fs.ybPay.domain.OrderResult;
 import com.fs.ybPay.domain.RefundResult;
 import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
@@ -112,6 +121,7 @@ import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
 import com.github.binarywang.wxpay.config.WxPayConfig;
 import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.binarywang.wxpay.service.WxPayService;
+import com.google.common.base.Joiner;
 import lombok.Synchronized;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
@@ -141,6 +151,7 @@ import java.sql.Timestamp;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
@@ -360,6 +371,13 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
 
     @Autowired
     private FsStoreOrderDfMapper fsStoreOrderDfMapper;
+    @Autowired
+    private ShippingService shippingService;
+    @Autowired
+    private FsWxExpressTaskMapper fsWxExpressTaskMapper;
+
+    @Autowired
+    private IFsStoreCartScrmService fsStoreCartScrmService;
 
     @PostConstruct
     public void initErpServiceMap() {
@@ -371,6 +389,82 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         erpServiceMap.put(5, jSTOrderService);     // 聚水潭
         erpServiceMap.put(6, k9OrderService);      // K9
     }
+    @Override
+    public void syncExpressToWx() {
+        List<FsWxExpressTask> fsWxExpressTasks = fsWxExpressTaskMapper.selectPendingData();
+        if (CollectionUtils.isEmpty(fsWxExpressTasks)) {
+            logger.info("当前没有待同步的数据!已取消");
+            return;
+        }
+
+        for (FsWxExpressTask fsWxExpressTask : fsWxExpressTasks) {
+
+            try{
+                UploadShippingInfoRequest request = new UploadShippingInfoRequest();
+
+                OrderKey orderKey = new OrderKey();
+                orderKey.setOrderNumberType(2);
+
+
+                FsUserScrm fsUser = userService.selectFsUserByUserId(fsWxExpressTask.getUserId());
+
+                // 目前支持商城订单和直播订单
+                ExpressToWxService service = ExpressToWxHolder.findBest(fsWxExpressTask.getType(),fsWxExpressTask.getOrderCode());
+                Asserts.notNull(service,"订单类型不被支持!");
+
+
+                orderKey.setTransactionId(service.getTransactionId());
+
+
+                String userPhone = service.getUserPhone();
+                String orderGoodsInfo = service.getOrderGoodsInfo();
+
+
+                Payer payer = new Payer();
+                if(StringUtils.isNotBlank(fsUser.getMaOpenId())){
+                    payer.setOpenid(fsUser.getMaOpenId());
+                }
+                request.setPayer(payer);
+                request.setOrderKey(orderKey);
+
+                request.setLogisticsType(1);
+                request.setDeliveryMode(1);
+
+                request.setShippingList(Collections.singletonList(ShippingItem.builder()
+                        .itemDesc(orderGoodsInfo)
+                        .expressCompany(service.getExpressCompany())
+                        .trackingNo(service.getExpressNo())
+                        .contact(Contact.builder().consignorContact(userPhone).build())
+                        .build()));
+
+                OffsetDateTime now = OffsetDateTime.now();
+                DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
+                String formattedTimestamp = now.format(formatter);
+                request.setUploadTime(formattedTimestamp);
+
+
+                request.setAppid(fsWxExpressTask.getAppid());
+                WeChatApiResponse response = shippingService.uploadShippingInfo(request);
+                if(ObjectUtil.equal(response.getErrcode(),0)){
+                    fsWxExpressTask.setStatus(2);
+                } else {
+                    fsWxExpressTask.setRetryCount(fsWxExpressTask.getRetryCount() +1);
+                    fsWxExpressTask.setStatus(3);
+                    fsWxExpressTask.setData(JSON.toJSONString(request));
+                    fsWxExpressTask.setRequestBody(JSON.toJSONString(request));
+                    fsWxExpressTask.setResponseBody(JSON.toJSONString(response));
+                }
+            }catch (Exception e){
+                logger.info("该单 {} 推送到物流失败!",fsWxExpressTask);
+                fsWxExpressTask.setRetryCount(fsWxExpressTask.getRetryCount() +1);
+                fsWxExpressTask.setStatus(3);
+
+
+            }
+        }
+        fsWxExpressTaskMapper.batchUpdate(fsWxExpressTasks);
+
+    }
     /**
      * 查询订单
      *
@@ -905,7 +999,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             }
             //使用了积分扣积分
             if (dto.getUsedIntegral() > 0) {
-                this.decIntegral(userId, dto.getUsedIntegral(), dto.getDeductionPrice().doubleValue(), storeOrder.getId().toString());
+                this.decIntegral(userId, dto.getUsedIntegral(), dto.getDeductionPrice(), storeOrder.getId().toString());
             }
             //减库存加销量
             this.deStockIncSale(carts);
@@ -1109,11 +1203,11 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     /**
      * 积分抵扣
      */
-    private void decIntegral(Long uid, double usedIntegral, double deductionPrice, String busId) {
+    private void decIntegral(Long uid, double usedIntegral, BigDecimal deductionPrice, String busId) {
         userService.decIntegral(uid, usedIntegral);
         FsUserScrm user = userService.selectFsUserById(uid);
         //积分记录
-        billService.addBill(uid, BillDetailEnum.CATEGORY_2.getValue(), 0, BillDetailEnum.TYPE_1.getDesc(), usedIntegral, user.getIntegral().doubleValue(),
+        billService.addBill(uid, BillDetailEnum.CATEGORY_2.getValue(), 0, BillDetailEnum.TYPE_1.getDesc(), new BigDecimal(usedIntegral) ,new BigDecimal(user.getIntegral()),
                 "购买商品使用" + usedIntegral + "积分抵扣" + deductionPrice + "元", busId, 0l);
 
     }
@@ -1266,7 +1360,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                     OrderLogEnum.DELIVERY_GOODS.getDesc());
             //订阅物流回调
             String lastFourNumber = "";
-            if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())) {
+            if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())  || order.getDeliverySn().equals(ShipperCodeEnum.ZTO.getValue())) {
                 lastFourNumber = order.getUserPhone();
                 if (lastFourNumber.length() == 11) {
                     lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
@@ -1283,6 +1377,20 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                     .templateType(TemplateListenEnum.TYPE_2.getValue())
                     .build();
             publisher.publishEvent(new TemplateEvent(this, templateBean));
+
+            List<FsStorePaymentScrm> fsStorePayments = fsStorePaymentMapper.selectFsStorePaymentByOrderId(order.getId());
+            FsStorePaymentScrm fsStorePayment = fsStorePayments.get(0);
+            FsWxExpressTask fsWxExpressTask = new FsWxExpressTask();
+            fsWxExpressTask.setUserId(order.getUserId());
+            fsWxExpressTask.setStatus(0);
+            fsWxExpressTask.setRetryCount(0);
+            fsWxExpressTask.setCreateTime(LocalDateTime.now());
+            fsWxExpressTask.setUpdateTime(LocalDateTime.now());
+            fsWxExpressTask.setOrderCode(order.getOrderCode());
+            fsWxExpressTask.setExpressCompany(express.getCode());
+            fsWxExpressTask.setExpressNo(deliveryId);
+            fsWxExpressTask.setAppid(fsStorePayment.getAppId());
+            fsWxExpressTaskMapper.insert(fsWxExpressTask);
         }
     }
 
@@ -1301,7 +1409,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                         OrderLogEnum.DELIVERY_GOODS.getDesc());
                 //订阅物流回调
                 String lastFourNumber = "";
-                if (express.getCode().equals(ShipperCodeEnum.SF.getValue())) {
+                if (express.getCode().equals(ShipperCodeEnum.SF.getValue())  || express.getCode().equals(ShipperCodeEnum.ZTO.getValue())) {
                     lastFourNumber = order.getUserPhone();
                     if (lastFourNumber.length() == 11) {
                         lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
@@ -1360,7 +1468,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     public R getExpress(FsStoreOrderScrm order) {
         //顺丰轨迹查询处理
         String lastFourNumber = "";
-        if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())) {
+        if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue()) || order.getDeliverySn().equals(ShipperCodeEnum.ZTO.getValue())) {
             lastFourNumber = order.getUserPhone();
             if (lastFourNumber.length() == 11) {
                 lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
@@ -1450,14 +1558,24 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     public R confirmPackageOrder(long uid, FsStoreConfirmPackageIdOrderParam param) {
         FsUserAddressScrm address = userAddressMapper.selectFsUserAddressByDefaultAddress(uid);
         FsStoreProductPackageScrm storeProductPackage = productPackageService.selectFsStoreProductPackageById(param.getPackageId());
-        String uuid = IdUtil.randomUUID();
-        BigDecimal totalMoney = storeProductPackage.getPayMoney();
+        // 由于套餐制单前面有生成oderkey,并且要取修改的价格,所以这里判断,如果有传就用传的orderkey,如果没有就生成(代表走的是直接购买)
+        String uuid;
+        BigDecimal totalMoney;
+        if(StringUtils.isEmpty(param.getCreateOrderKey())){
+            //直接购买
+            uuid = IdUtil.randomUUID();
+            totalMoney = storeProductPackage.getPayMoney();
+        } else {
+            // 套餐制单
+            uuid = param.getCreateOrderKey();
+            totalMoney = redisCache.getCacheObject("createOrderMoney:" + param.getCreateOrderKey());
+        }
+
         if (param.getCouponUserId() != null) {
             FsStoreCouponUserScrm couponUser = couponUserService.selectFsStoreCouponUserById(param.getCouponUserId());
             if (couponUser != null && couponUser.getStatus() == 0) {
                 if (couponUser.getUseMinPrice().compareTo(storeProductPackage.getPayMoney()) == -1) {
-                    //
-                    totalMoney = totalMoney.subtract(couponUser.getCouponPrice());
+                    totalMoney = totalMoney != null ? totalMoney.subtract(couponUser.getCouponPrice()) : BigDecimal.ZERO.subtract(couponUser.getCouponPrice());
                 }
             }
         }
@@ -1493,29 +1611,37 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             List<StorePackageProductDTO> goodsList = JSONUtil.toList(jsonArray, StorePackageProductDTO.class);
             //检测库存
             Integer totalNum = 0;
-            List<FsStoreCartQueryVO> carts = new ArrayList<>();
-            for (StorePackageProductDTO goods : goodsList) {
-                FsStoreProductAttrValueScrm attrValue = attrValueService.selectFsStoreProductAttrValueById(goods.getId());
-                if (attrValue != null && attrValue.getProductId() != null) {
-                    FsStoreProductScrm product = storeProductService.selectFsStoreProductById(attrValue.getProductId());
-                    if (product != null) {
-                        totalNum += goods.getCount();
-                        FsStoreCartQueryVO vo = new FsStoreCartQueryVO();
-                        vo.setProductId(attrValue.getProductId());
-                        vo.setProductAttrValueId(goods.getId());
-                        vo.setCartNum(goods.getCount());
-                        vo.setProductName(product.getProductName());
-                        vo.setProductAttrName(attrValue.getSku());
-                        vo.setProductImage(product.getImage());
-                        vo.setBarCode(attrValue.getBarCode());
-                        vo.setGroupBarCode(attrValue.getGroupBarCode());
-                        vo.setPrice(product.getPrice());
-                        vo.setProductType(product.getProductType());
-                        carts.add(vo);
+            List<FsStoreCartQueryVO> carts = redisCache.getCacheObject("orderCarts:" + param.getOrderKey());
+            String joinCartIds = null;
+            if(carts == null || carts.isEmpty()){
+                carts = new ArrayList<>();
+                for (StorePackageProductDTO goods : goodsList) {
+                    FsStoreProductAttrValueScrm attrValue = attrValueService.selectFsStoreProductAttrValueById(goods.getId());
+                    if (attrValue != null && attrValue.getProductId() != null) {
+                        FsStoreProductScrm product = storeProductService.selectFsStoreProductById(attrValue.getProductId());
+                        if (product != null) {
+                            totalNum += goods.getCount();
+                            FsStoreCartQueryVO vo = new FsStoreCartQueryVO();
+                            vo.setProductId(attrValue.getProductId());
+                            vo.setProductAttrValueId(goods.getId());
+                            vo.setCartNum(goods.getCount());
+                            vo.setProductName(product.getProductName());
+                            vo.setProductAttrName(attrValue.getSku());
+                            vo.setProductImage(product.getImage());
+                            vo.setBarCode(attrValue.getBarCode());
+                            vo.setGroupBarCode(attrValue.getGroupBarCode());
+                            vo.setPrice(product.getPrice());
+                            vo.setProductType(product.getProductType());
+                            carts.add(vo);
 
+                        }
                     }
+                    cartService.checkProductStock(attrValue.getProductId(), attrValue.getId());
                 }
-                cartService.checkProductStock(attrValue.getProductId(), attrValue.getId());
+            } else {
+                // 如果cartIds不为空,则表示是套餐制单购买,非套餐制单是没有购物车信息的。
+                List<Long> cartIds = carts.stream().map(FsStoreCartQueryVO::getId).collect(Collectors.toList());
+                joinCartIds = Joiner.on(",").join(cartIds);
             }
             //生成分布式唯一值
             String orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();
@@ -1524,6 +1650,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             //组合数据
             CompanyUser user = companyUserService.selectCompanyUserById(param.getCompanyUserId());
             FsStoreOrderScrm storeOrder = new FsStoreOrderScrm();
+            storeOrder.setCartId(joinCartIds);
             //修改默认仓库
 
             storeOrder.setStoreHouseCode("CK01");
@@ -1532,7 +1659,13 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 storeOrder.setCompanyId(user.getCompanyId());
                 storeOrder.setDeptId(user.getDeptId());
             }
-            BigDecimal totalMoney = storeProductPackage.getPayMoney();
+            BigDecimal totalMoney;
+            if(param.getIsPackage() != null && param.getIsPackage() == 1){
+                totalMoney = redisCache.getCacheObject("createOrderMoney:" + param.getOrderKey());
+            } else {
+                totalMoney = storeProductPackage.getPayMoney();
+            }
+
             //优惠券处理
             if (param.getCouponUserId() != null) {
                 FsStoreCouponUserScrm couponUser = couponUserService.selectFsStoreCouponUserById(param.getCouponUserId());
@@ -1597,6 +1730,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             //减库存加销量
             this.deStockIncSale(carts);
             //保存购物车商品信息
+            List<FsStoreOrderItemScrm> listOrderItem = new ArrayList<>();
             for (FsStoreCartQueryVO vo : carts) {
                 FsStoreCartDTO fsStoreCartDTO = new FsStoreCartDTO();
                 fsStoreCartDTO.setProductId(vo.getProductId());
@@ -1624,7 +1758,13 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                     item.setIsPrescribe(1);
                 }
                 fsStoreOrderItemMapper.insertFsStoreOrderItem(item);
+                listOrderItem.add(item);
+            }
+            if (!listOrderItem.isEmpty()) {
+                storeOrder.setItemJson(JSONUtil.toJsonStr(listOrderItem));
             }
+            fsStoreOrderMapper.updateFsStoreOrder(storeOrder);
+
             //删除缓存
             redisCache.deleteObject("orderKey:" + param.getOrderKey());
             //添加记录
@@ -1867,6 +2007,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
 
 
     @Override
+    @Transactional
     public R createOmsOrder(Long orderId) throws ParseException {
         FsStoreOrderScrm order = fsStoreOrderMapper.selectFsStoreOrderById(orderId);
         FsSysConfig erpConfig = configUtil.generateStructConfigByKey(SysConfigEnum.HIS_CONFIG.getKey(), FsSysConfig.class);
@@ -2266,7 +2407,11 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                         FsHfpayConfigMapper fsHfpayConfigMapper = SpringUtils.getBean(FsHfpayConfigMapper.class);
                         if (payment.getAppId() != null) {
                             FsHfpayConfig fsHfpayConfig = fsHfpayConfigMapper.selectByAppId(payment.getAppId());
-                            huifuId = fsHfpayConfig.getHuifuId();
+                            if (fsHfpayConfig == null){
+                                huifuId = fsPayConfig.getHuifuId();
+                            }else {
+                                huifuId = fsHfpayConfig.getHuifuId();
+                            }
                         } else {
                             if (("益善缘".equals(cloudHostProper.getCompanyName()))) {
 
@@ -2378,7 +2523,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     public R syncExpress(FsStoreOrderExpressEditParam param) {
         FsStoreOrderScrm order = fsStoreOrderMapper.selectFsStoreOrderById(param.getOrderId());
         String lastFourNumber = "";
-        if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())) {
+        if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue()) || order.getDeliverySn().equals(ShipperCodeEnum.ZTO.getValue())) {
             lastFourNumber = order.getUserPhone();
             if (lastFourNumber.length() == 11) {
                 lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
@@ -2489,7 +2634,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     }
 
     @Override
-    public R updateSalseOrderMoney(String createOrderKey, BigDecimal money, BigDecimal payAmount,Integer payType) {
+    public R updateSalseOrderMoney(String createOrderKey, BigDecimal money, BigDecimal payAmount,Integer payType, Integer isPackage) {
         //货到付款自定义金额
         if (payAmount == null) {
             String configJson = configService.selectConfigByKey("store.config");
@@ -2513,8 +2658,13 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         }
         List<FsStoreCartQueryVO> carts = redisCache.getCacheObject("orderCarts:" + createOrderKey);
         BigDecimal totalMoney = BigDecimal.ZERO;
-        for (FsStoreCartQueryVO vo : carts) {
-            totalMoney = totalMoney.add(vo.getPrice().multiply(new BigDecimal(vo.getCartNum().toString())));
+        if(isPackage == 0){
+            for (FsStoreCartQueryVO vo : carts) {
+                totalMoney = totalMoney.add(vo.getPrice().multiply(new BigDecimal(vo.getCartNum().toString())));
+            }
+        } else {
+            //套餐制单
+            totalMoney = carts.get(0).getPrice();
         }
         if (money.compareTo(totalMoney) == 1) {
             throw new CustomException("价格不能大于商品总价", 501);
@@ -2782,8 +2932,8 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         userService.updateFsUser(user);
         //增加流水
         billService.addBill(user.getUserId(), BillDetailEnum.CATEGORY_2.getValue(), 1, BillDetailEnum.TYPE_5.getDesc(),
-                order.getUseIntegral().doubleValue(),
-                newIntegral.doubleValue(),
+                order.getUseIntegral(),
+                newIntegral,
                 "购买商品失败,回退积分" + order.getUseIntegral(), order.getId().toString(), 0l);
         //更新订单回退积分
         FsStoreOrderScrm storeOrder = new FsStoreOrderScrm();
@@ -2821,9 +2971,8 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         BigDecimal payIntegral = this.getOrderSumPrice(cartInfo, "payIntegral");//获取订单需要的积分
 
         //如果设置满包邮0 表示全局包邮,如果设置大于0表示满这价格包邮,否则走运费模板算法
-        if (storeFreePostage.compareTo(BigDecimal.ZERO) != 0 && totalPrice.compareTo(storeFreePostage) <= 0) {
-            storePostage = this.handlePostage(cartInfo, userAddress);
-        }
+        storePostage = this.handlePostage(cartInfo, userAddress);
+
 
         FsStoreOrderPriceDTO priceGroupDTO = new FsStoreOrderPriceDTO();
         priceGroupDTO.setStorePostage(storePostage);
@@ -2897,10 +3046,10 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                     TemplateDTO templateDTO = TemplateDTO.builder()
                             .number(num)
                             .price(price)
-                            .first(shippingTemplatesRegion.getFirst().doubleValue())
-                            .firstPrice(shippingTemplatesRegion.getFirstPrice())
-                            .continues(shippingTemplatesRegion.getContinues().doubleValue())
-                            .continuePrice(shippingTemplatesRegion.getContinuePrice())
+                            .first(ObjectUtil.isNotEmpty(shippingTemplatesRegion)?shippingTemplatesRegion.getFirst().doubleValue():0.0)
+                            .firstPrice(ObjectUtil.isNotEmpty(shippingTemplatesRegion)?shippingTemplatesRegion.getFirstPrice():new BigDecimal(0.0))
+                            .continues(ObjectUtil.isNotEmpty(shippingTemplatesRegion)?shippingTemplatesRegion.getContinues().doubleValue():0.0)
+                            .continuePrice(ObjectUtil.isNotEmpty(shippingTemplatesRegion)?shippingTemplatesRegion.getContinuePrice():new BigDecimal(0.0))
                             .tempId(tempId)
                             .cityId(cityId)
                             .build();
@@ -3070,7 +3219,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                             if ((!dto.isSuccess() && dto.getReason().equals("三天无轨迹")) || (!dto.isSuccess() && dto.getReason().equals("七天内无轨迹变化"))) {
                                 //订阅物流回调
                                 String lastFourNumber = "";
-                                if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())) {
+                                if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())  || order.getDeliverySn().equals(ShipperCodeEnum.ZTO.getValue())) {
                                     lastFourNumber = order.getUserPhone();
                                     if (lastFourNumber.length() == 11) {
                                         lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
@@ -3426,7 +3575,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 FsStoreScrm store = fsStoreMapper.selectFsStoreByStoreId(o.getStoreId());
                 int i = fsStoreOrderMapper.updateFsStoreOrderByOrderCode(fsStoreOrder);
                 String lastFourNumber = "";
-                if (fsStoreOrder.getDeliveryCode().equals(com.fs.his.enums.ShipperCodeEnum.SF.getValue())) {
+                if (fsStoreOrder.getDeliveryCode().equals(com.fs.his.enums.ShipperCodeEnum.SF.getValue())  || fsStoreOrder.getDeliveryCode().equals(ShipperCodeEnum.ZTO.getValue())) {
                     if (store.getSendPhone() != null) {
                         lastFourNumber = store.getSendPhone();
                     } else {
@@ -3526,7 +3675,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         fsStoreOrderLogsMapper.insertFsStoreOrderLogs(Logs);
 
         String lastFourNumber = "";
-        if (order.getDeliveryCode().equals(com.fs.his.enums.ShipperCodeEnum.SF.getValue())) {
+        if (order.getDeliveryCode().equals(com.fs.his.enums.ShipperCodeEnum.SF.getValue())  || order.getDeliveryCode().equals(ShipperCodeEnum.ZTO.getValue())) {
             lastFourNumber = order.getUserPhone();
             if (lastFourNumber.length() == 11) {
                 lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
@@ -3854,7 +4003,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                     FsStoreOrderScrm order = fsStoreOrderMapper.selectFsStoreOrderByOrderCode(dto.getOrderNumber());
                     //订阅物流回调
                     String lastFourNumber = "";
-                    if (dto.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())) {
+                    if (dto.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())  || order.getDeliverySn().equals(ShipperCodeEnum.ZTO.getValue())) {
                         lastFourNumber = order.getUserPhone();
                         if (lastFourNumber.length() == 11) {
                             lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
@@ -3944,6 +4093,17 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                     if (amount != null){
                         payMoney=amount;
                     }
+                    //运费
+                    BigDecimal payPostage = order.getPayPostage();
+                    if (payPostage == null || payPostage.compareTo(BigDecimal.ZERO) <= 0){
+                        payPostage = storeConfig.getPayPostage();
+                        if (payPostage == null){
+                            payPostage = BigDecimal.ZERO;
+                        }
+                        order.setPayPrice(order.getPayPrice().add(payPostage));
+                    }
+                    order.setPayPostage(payPostage);
+                    payMoney = payMoney.add(payPostage);
                     order.setPayMoney(payMoney);
                     order.setPayDelivery(order.getPayPrice().subtract(payMoney) );
                 }
@@ -3968,6 +4128,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 storePayment.setUserId(user.getUserId());
                 storePayment.setBusinessOrderId(order.getId().toString());
                 storePayment.setOrderId(order.getId());
+                storePayment.setAppId(fsPayConfig.getAppId() == null ? "" : fsPayConfig.getAppId());
                 fsStorePaymentMapper.insertFsStorePayment(storePayment);
 
                 if (fsPayConfig.getType().equals("hf")){
@@ -4063,6 +4224,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 user.setStatus(1);
                 user.setMaOpenId(session.getOpenid());
                 user.setUnionId(session.getUnionid());
+                user.setAppId(properties.getConfigs().get(0).getAppid());
                 user.setIsWeixinAuth(0);
                 user.setLastIp(ip);
                 user.setCreateTime(new Date());
@@ -4181,6 +4343,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 user.setStatus(1);
                 user.setMaOpenId(session.getOpenid());
                 user.setUnionId(session.getUnionid());
+                user.setAppId(properties.getConfigs().get(0).getAppid());
                 user.setIsWeixinAuth(0);
                 user.setLastIp(ip);
                 user.setCreateTime(new Date());
@@ -4440,6 +4603,17 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                     if (amount != null){
                         payMoney=amount;
                     }
+                    //运费
+                    BigDecimal payPostage = order.getPayPostage();
+                    if (payPostage == null || payPostage.compareTo(BigDecimal.ZERO) <= 0){
+                        payPostage = storeConfig.getPayPostage();
+                        if (payPostage == null){
+                            payPostage = BigDecimal.ZERO;
+                        }
+                        order.setPayPrice(order.getPayPrice().add(payPostage));
+                    }
+                    order.setPayPostage(payPostage);
+                    payMoney = payMoney.add(payPostage);
                     order.setPayMoney(payMoney);
                     order.setPayDelivery(order.getPayPrice().subtract(payMoney) );
                 }
@@ -4710,6 +4884,308 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         return null;
     }
 
+    @Override
+    public List<FsStoreOrderDeliveryNoteExportVO> getDeliveryNote(FsStoreOrderParam param) {
+        return fsStoreOrderMapper.getDeliveryNote(param);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public R importDeliveryNoteExpress(List<FsOrderDeliveryNoteDTO> dtoList, String appId) {
+        try {
+            StringBuilder builder = new StringBuilder();
+            //获取商城配置
+            String json = configService.selectConfigByKey("store.config");
+            StoreConfig config = JSONUtil.toBean(json, StoreConfig.class);
+
+            List<FsOrderDeliveryNoteDTO> successList = new ArrayList<>(dtoList.size());
+            //提前获取所有必要数据
+            Map<String, String> expressDeliveryMap = buildExpressDeliveryMap();
+            //提取所有有效订单号
+            List<String> orderCodeList = new ArrayList<>(dtoList.size());
+            for (int i = 0; i < dtoList.size(); i++) {
+                FsOrderDeliveryNoteDTO dto = dtoList.get(i);
+                if (StringUtils.isEmpty(dto.getOrderNumber())) {
+                    builder.append("数据第").append(i + 2).append("行系统订单为空!").append(System.lineSeparator());
+                }
+                if (StringUtils.isEmpty(dto.getLogisticsCompany())) {
+                    builder.append("数据第").append(i + 2).append("行物流公司为空!").append(System.lineSeparator());
+                }
+                if (StringUtils.isEmpty(dto.getDeliveryId())) {
+                    builder.append("数据第").append(i + 2).append("行快递单号为空!").append(System.lineSeparator());
+                } else {
+                    //处理订单ID信息
+                    String originalOrderNumber = dto.getOrderNumber();
+                    String processedOrderNumber = extractNumbers(originalOrderNumber);
+                    dto.setOrderNumber(processedOrderNumber);
+                    orderCodeList.add(dto.getOrderNumber());
+                }
+            }
+
+            //批量查询订单信息
+            if (orderCodeList.isEmpty()) {
+                return R.ok(builder.toString());
+            }
+            List<FsStoreOrderCodeOpenIdVo> orderCodeOpenIdVoList = fsStoreOrderMapper.selectOrderCodeOpenIdInOrderCode(orderCodeList);
+            Map<String, OrderOpenIdTransDTO> orderMap = new HashMap<>(orderCodeOpenIdVoList.size());
+            Map<String, List<FsStoreOrderCodeOpenIdVo>> orderDetailsMap = new HashMap<>(orderCodeOpenIdVoList.size());
+
+            for (FsStoreOrderCodeOpenIdVo vo : orderCodeOpenIdVoList) {
+                orderMap.computeIfAbsent(vo.getId(), k -> {
+                    OrderOpenIdTransDTO dto = new OrderOpenIdTransDTO();
+                    dto.setOpenId(vo.getOpenId());
+                    dto.setTransactionId(vo.getOutTransId());
+                    return dto;
+                });
+
+                orderDetailsMap
+                        .computeIfAbsent(vo.getId(), k -> new ArrayList<>())
+                        .add(vo);
+            }
+            final WxMaService wxService = WxMaConfiguration.getMaService(appId);
+            String uploadTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"))
+                    .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+
+            for (int i = 0; i < dtoList.size(); i++) {
+                FsOrderDeliveryNoteDTO dto = dtoList.get(i);
+                int rowNum = i + 2;
+                if (StringUtils.isEmpty(dto.getOrderNumber())) {
+                    continue;
+                }
+                if (StringUtils.isEmpty(dto.getDeliveryId())) {
+                    builder.append("数据第").append(rowNum).append("行快递单号为空!")
+                            .append(System.lineSeparator());
+                    continue;
+                }
+
+                if (StringUtils.isEmpty(dto.getLogisticsCompany())) {
+                    builder.append("数据第").append(rowNum).append("行快递公司编号为空!")
+                            .append(System.lineSeparator());
+                    continue;
+                }
+//                if (dto.getDeliveryStatus() == null) {
+//                    dto.setDeliveryStatus(0);
+//                }
+//                if (ObjectUtil.isNotNull(dto.getDeliveryTime())) {
+//                    dto.setDeliveryTime(parseCstToDateOnlyString(dto.getDeliveryTime()));
+//                }
+//
+//                if (ObjectUtil.isNotNull(dto.getDeliveryPayTime()) &&
+//                        !dto.getDeliveryPayTime().isEmpty()) {
+//                    dto.setDeliveryPayTime(parseCstToDateOnlyString(dto.getDeliveryPayTime()));
+//                }
+                // 验证快递公司
+                String deliverySn = expressDeliveryMap.get(dto.getLogisticsCompany());
+                if (deliverySn == null) {
+                    builder.append("数据第").append(rowNum).append("行订单号为")
+                            .append(dto.getOrderNumber()).append("物流公司名称异常")
+                            .append(System.lineSeparator());
+                    continue;
+                }
+                dto.setDeliverySn(deliverySn);
+
+                // 检查订单是否存在
+                String orderNumber = dto.getOrderNumber();
+                OrderOpenIdTransDTO orderInfo = orderMap.get(orderNumber);
+                if (orderInfo == null) {
+                    builder.append("数据第").append(rowNum).append("行订单号")
+                            .append(orderNumber).append("不存在").append(System.lineSeparator());
+                    continue;
+                }
+                //验证是否开启微信发货
+                if (config.getIsWeChatShipping() != null && config.getIsWeChatShipping()) {
+                    // 上传物流信息到微信
+                    List<FsStoreOrderCodeOpenIdVo> orderDetails = orderDetailsMap.get(orderNumber);
+                    if (uploadShippingInfoToWechat(wxService, orderInfo, orderDetails, dto, uploadTime)) {
+                        successList.add(dto);
+                    } else {
+                        builder.append("数据第").append(rowNum).append("行订单号为")
+                                .append(orderNumber).append("上传微信失败").append(System.lineSeparator());
+                    }
+                } else {
+                    successList.add(dto);
+                }
+            }
+
+            //批量更新数据
+            if (!successList.isEmpty()) {
+                batchUpdateDeliveryNotes(successList);
+            }
+
+            return R.ok(builder.toString().equals("") ? "操作成功!" : builder.toString());
+        } catch (Exception e) {
+            log.error("导入发货单快递信息失败", e);
+            return R.error("导入失败:" + e.getMessage());
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
+    public void refreshOrderSettlementStatus() {
+        try {
+            // 判断是否对接微信发货
+            String json = configService.selectConfigByKey("store.config");
+            StoreConfig config = JSONUtil.toBean(json, StoreConfig.class);
+            logger.info("进入微信结算订单定时任务--------------->{}", "start");
+            if (config != null && config.getIsWeChatShipping() != null && config.getIsWeChatShipping()) {
+                // 获取未结算订单
+                List<FsStoreOrderScrm> orderScrmList = fsStoreOrderMapper.getUnsettledOrder();
+
+//                String payConfig = configService.selectConfigByKey("store.pay");
+                String payConfig = configService.selectConfigByKey("his.pay");
+                JSONObject js = JSON.parseObject(payConfig);
+                String appId = js.getString("appId");
+
+                if (ObjectUtil.isNotNull(appId) && !appId.isEmpty()) {
+                    final WxMaService wxService = WxMaConfiguration.getMaService(appId);
+
+                    if (!orderScrmList.isEmpty()) {
+                        for (FsStoreOrderScrm order : orderScrmList) {
+                            WxMaOrderShippingInfoGetRequest request = new WxMaOrderShippingInfoGetRequest();
+                            request.setTransactionId(order.getBankTransactionId());
+                            WxMaOrderShippingInfoGetResponse response;
+
+                            try {
+                                response = wxService.getWxMaOrderShippingService().get(request);
+
+                                if (response.getErrCode().equals(0)) {
+                                    // 订单状态枚举:(1) 待发货;(2) 已发货;(3) 确认收货;(4) 交易完成;(5) 已退款
+                                    if (response.getOrder().getOrderState().equals(3) || response.getOrder().getOrderState().equals(4)) {
+                                        if (order.getStatus() == OrderInfoEnum.STATUS_2.getValue()) {
+                                            this.finishOrder(order.getId());
+                                        }
+                                    }
+                                    logger.info("请求信息------------------------》{}", response);
+                                }
+
+                            } catch (WxErrorException e) {
+                                logger.info("异常信息------------------------》{}", e.getMessage());
+                                continue;
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.getStackTrace();
+        } finally {
+            logger.info("进入微信结算订单定时任务--------------->{}", "end");
+        }
+    }
+
+    private void batchUpdateDeliveryNotes(List<FsOrderDeliveryNoteDTO> list) {
+        int batchSize = 500;
+        int total = list.size();
+        int batches = (total + batchSize - 1) / batchSize;
+        for (int i = 0; i < batches; i++) {
+            int start = i * batchSize;
+            int end = Math.min(start + batchSize, total);
+            List<FsOrderDeliveryNoteDTO> subList = list.subList(start, end);
+            fsStoreOrderMapper.batchUpdateInOrderCode(subList);
+        }
+    }
+
+    private boolean uploadShippingInfoToWechat(WxMaService wxService,
+                                               OrderOpenIdTransDTO orderInfo,
+                                               List<FsStoreOrderCodeOpenIdVo> orderDetails,
+                                               FsOrderDeliveryNoteDTO dto,
+                                               String uploadTime) {
+        try {
+            WxMaOrderShippingInfoUploadRequest request = new WxMaOrderShippingInfoUploadRequest();
+            OrderKeyBean orderKeyBean = new OrderKeyBean();
+            orderKeyBean.setOrderNumberType(2);
+            orderKeyBean.setTransactionId(orderInfo.getTransactionId());
+            request.setOrderKey(orderKeyBean);
+            request.setDeliveryMode(1);
+            request.setLogisticsType(1);
+            List<ShippingListBean> shippingList = new ArrayList<>(orderDetails.size());
+            ShippingListBean shippingListBean = null;
+            for (FsStoreOrderCodeOpenIdVo detail : orderDetails) {
+                if (shippingListBean == null) {
+                    shippingListBean = new ShippingListBean();
+                    shippingListBean.setTrackingNo(dto.getDeliveryId());
+                    shippingListBean.setExpressCompany(dto.getDeliverySn());
+                    JSONObject js = JSON.parseObject(detail.getJsonInfo());
+                    shippingListBean.setItemDesc(js.getString("productName"));
+                    ContactBean contactBean = new ContactBean();
+                    contactBean.setReceiverContact(detail.getPhone());
+                    shippingListBean.setContact(contactBean);
+                } else {
+                    //拼接
+//                    JSONObject js = JSON.parseObject(detail.getJsonInfo());
+//                    shippingListBean.setItemDesc(shippingListBean.getItemDesc()+"-"+js.getString("productName"));
+                    break;
+                }
+            }
+            shippingList.add(shippingListBean);
+            request.setShippingList(shippingList);
+            request.setUploadTime(uploadTime);
+            // 设置支付者信息
+            PayerBean payerBean = new PayerBean();
+            payerBean.setOpenid(orderInfo.getOpenId());
+            request.setPayer(payerBean);
+
+            // 上传物流信息
+            return wxService.getWxMaOrderShippingService().upload(request).getErrCode() == 0;
+        } catch (Exception e) {
+            log.error("上传物流信息到微信失败,订单号: {}", dto.getOrderNumber(), e);
+            return false;
+        }
+    }
+
+    @Override
+    public R createPackageSalesOrder(CompanyUser companyUser, String packageId, Integer orderType, Integer orderMedium) {
+        FsStoreProductPackageScrm storeProductPackage = productPackageService.selectFsStoreProductPackageById(Long.parseLong(packageId));
+        if(storeProductPackage == null){
+            return R.error("商品套餐不存在");
+        }
+
+        /**
+         * 由于套餐包制单前端页面没有走购物车,因为为了保证后续可以使用之前商品制单的改价接口、创建订单接口、支付等接口,
+         * 也为了保持结构一致,因此这里手动添加购物车
+         */
+        // 获取套餐包的商品信息,然后添加购物车
+        JSONArray jsonArray = JSONUtil.parseArray(storeProductPackage.getProducts());
+        List<StorePackageProductDTO> goodsList = JSONUtil.toList(jsonArray, StorePackageProductDTO.class);
+        String cartIds = "";
+        for (StorePackageProductDTO goods : goodsList) {
+            FsStoreCartParam fsStoreCartParam = new FsStoreCartParam();
+            FsStoreProductAttrValueScrm attrValue = attrValueService.selectFsStoreProductAttrValueById(goods.getId());
+            if (attrValue != null && attrValue.getProductId() != null) {
+                    fsStoreCartParam.setProductId(attrValue.getProductId());
+                    fsStoreCartParam.setCartNum(goods.getCount());
+                    fsStoreCartParam.setIsBuy(1);
+                    fsStoreCartParam.setAttrValueId(goods.getId());
+                R r = fsStoreCartScrmService.addCart(companyUser.getUserId(), fsStoreCartParam);
+                Object id = r.get("id");
+                if(id != null){
+                    cartIds += id + ",";
+                }
+            }
+
+        }
+
+        List<FsStoreCartQueryVO> carts = cartMapper.selectFsStoreCartListByIds(cartIds);
+        String uuid = IdUtil.randomUUID();
+        redisCache.setCacheObject("createOrderKey:" + uuid, companyUser.getCompanyId() + "-" + companyUser.getUserId(), 24, TimeUnit.HOURS);
+
+        // 这里的carts是购物车信息,价格取的套餐包价格
+        for (FsStoreCartQueryVO vo : carts) {
+            vo.setPrice(storeProductPackage.getPayMoney());
+        }
+        redisCache.setCacheObject("orderCarts:" + uuid, carts, 24, TimeUnit.HOURS);
+        if (orderType != null || orderMedium != null) {
+            FsStoreOrderScrm fsStoreOrder = new FsStoreOrderScrm();
+            fsStoreOrder.setOrderMedium(orderMedium);
+            fsStoreOrder.setOrderType(orderType);
+            redisCache.setCacheObject("orderInfo:" + uuid, fsStoreOrder, 24, TimeUnit.HOURS);
+        }
+
+        redisCache.setCacheObject("createOrderMoney:" + uuid, storeProductPackage.getPayMoney(), 24, TimeUnit.HOURS);
+        // 根据前端要求,为了前端方便取值,所以返回的参数key与商品制单的接口保持一致
+        return R.ok().put("orderKey", uuid);
+    }
+
     private static final DateTimeFormatter CST_FORMATTER = DateTimeFormatter
             .ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US)
             .withZone(ZoneId.of("Asia/Shanghai"));
@@ -4746,9 +5222,23 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         map.put("ZTO", "中通");
         map.put("JD", "京东");
         map.put("DBL", "德邦");
+        map.put("YTO", "圆通");
         return map;
     }
 
+    //高性能截取订单ID
+    private static String extractNumbers(String str) {
+        if (str == null || str.isEmpty()) {
+            return "";
+        }
+        int start = 0;
+        int len = str.length();
+        while (start < len && !Character.isDigit(str.charAt(start))) {
+            start++;
+        }
+        return start < len ? str.substring(start) : "";
+    }
+
 
     @Override
     public FsStoreOrderAmountScrmStatsVo selectFsStoreOrderAmountScrmStats(FsStoreOrderAmountScrmStatsQueryDto queryDto) {

+ 9 - 3
fs-service/src/main/java/com/fs/hisStore/service/impl/FsUserBillScrmServiceImpl.java

@@ -3,6 +3,7 @@ package com.fs.hisStore.service.impl;
 import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
+import java.util.Optional;
 
 import cn.hutool.json.JSONUtil;
 import com.fs.common.utils.DateUtils;
@@ -55,7 +56,11 @@ public class FsUserBillScrmServiceImpl implements IFsUserBillScrmService
     @Override
     public List<FsUserBillScrm> selectFsUserBillList(FsUserBillScrm fsUserBill)
     {
-        return fsUserBillMapper.selectFsUserBillList(fsUserBill);
+        List<FsUserBillScrm> bills=fsUserBillMapper.selectFsUserBillList(fsUserBill);
+        Optional.ofNullable( bills).ifPresent(list -> list.forEach(bill -> {
+            bill.setNumber(bill.getMoney());
+        }));
+        return bills;
     }
 
     /**
@@ -109,13 +114,14 @@ public class FsUserBillScrmServiceImpl implements IFsUserBillScrmService
     }
 
     @Override
-    public void addBill(Long uid, String cate,Integer billType,String title, double number, double balance, String renark,String busId,Long tuiUserId) {
+    public void addBill(Long uid, String cate,Integer billType,String title, BigDecimal money, BigDecimal balance, String renark,String busId,Long tuiUserId) {
         FsUserBillScrm bill=new FsUserBillScrm();
         bill.setCategory(cate);
         bill.setBillType(billType);
         bill.setUserId(uid);
         bill.setTitle(title);
-        bill.setNumber(number);
+//        bill.setNumber(number);
+        bill.setMoney(money);
         bill.setBalance(balance);
         bill.setRemark(renark);
         bill.setBusinessId(busId);

+ 1 - 1
fs-service/src/main/java/com/fs/hisStore/service/impl/FsUserExtractScrmServiceImpl.java

@@ -139,7 +139,7 @@ public class FsUserExtractScrmServiceImpl implements IFsUserExtractScrmService
         fsUserExtractMapper.insertFsUserExtract(extract);
         userMapper.updateFsUser(user);
         //插入流水
-        billService.addBill(user.getUserId(), BillDetailEnum.CATEGORY_1.getValue(),0,BillDetailEnum.TYPE_6.getDesc(),param.getExtractPrice().doubleValue(),user.getNowMoney().doubleValue(),"提现申请",extract.getId().toString(),0l);
+        billService.addBill(user.getUserId(), BillDetailEnum.CATEGORY_1.getValue(),0,BillDetailEnum.TYPE_6.getDesc(),param.getExtractPrice(),user.getNowMoney(),"提现申请",extract.getId().toString(),0l);
 
         return R.ok("提交成功,等待后台审核");
     }

+ 120 - 14
fs-service/src/main/java/com/fs/hisStore/service/impl/FsUserScrmServiceImpl.java

@@ -1,5 +1,6 @@
 package com.fs.hisStore.service.impl;
 
+import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
@@ -8,6 +9,7 @@ import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.core.domain.entity.SysDictData;
 import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.param.LoginMaWxParam;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.DictUtils;
 import com.fs.common.utils.ParseUtils;
@@ -30,7 +32,13 @@ import com.fs.course.param.newfs.UserCourseVideoPageParam;
 import com.fs.course.vo.newfs.FsCourseAnalysisCountVO;
 import com.fs.course.vo.newfs.FsCourseAnalysisVO;
 import com.fs.course.vo.newfs.FsUserCourseVideoPageListVO;
+import com.fs.his.domain.FsUser;
+import com.fs.his.domain.FsUserBill;
+import com.fs.his.domain.FsUserWx;
+import com.fs.his.service.IFsUserWxService;
 import com.fs.his.vo.OptionsVO;
+import com.fs.hisStore.vo.*;
+import com.fs.live.domain.LiveOrder;
 import com.fs.qw.param.QwFsUserParam;
 import com.fs.qw.vo.QwFsUserVO;
 import com.fs.hisStore.domain.*;
@@ -50,10 +58,6 @@ import com.fs.hisStore.service.IFsUserCompanyUserScrmService;
 import com.fs.hisStore.service.IFsUserProjectTagScrmService;
 import com.fs.hisStore.service.IFsUserScrmService;
 import com.fs.hisStore.service.cache.IFsUserCourseCountCacheService;
-import com.fs.hisStore.vo.FSUserVO;
-import com.fs.hisStore.vo.FsCompanyUserListQueryVO;
-import com.fs.hisStore.vo.FsUserLastCount;
-import com.fs.hisStore.vo.FsUserTuiVO;
 import com.fs.hisStore.vo.h5.*;
 import com.fs.system.mapper.SysDictDataMapper;
 import com.github.pagehelper.PageHelper;
@@ -245,6 +249,11 @@ public class FsUserScrmServiceImpl implements IFsUserScrmService
         return fsUserMapper.selectFsUserByPhone(phone);
     }
 
+    @Override
+    public List<FsUserScrm> selectFsUserListByPhoneExact(String phone) {
+        return fsUserMapper.selectFsUserListByPhoneExact(phone);
+    }
+
     @Override
     public TableDataInfo selectCusListPage(SelectCusListPageParam param) {
         Asserts.check(ObjectUtils.isNotNull(param.getPageNum()), "页数不能为空");
@@ -328,7 +337,7 @@ public class FsUserScrmServiceImpl implements IFsUserScrmService
                     tuiUserMap.setUserId(tuiUser.getUserId());
                     tuiUserMap.setBrokeragePrice(tuiUser.getBrokeragePrice().add(brokerage));
                     fsUserMapper.updateFsUser(tuiUserMap);
-                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_3.getValue(),1,BillDetailEnum.TYPE_5.getDesc(),brokerage.doubleValue(),tuiUserMap.getBrokeragePrice().doubleValue(),"订单返佣金",order.getId().toString(),order.getUserId());
+                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_3.getValue(),1,BillDetailEnum.TYPE_5.getDesc(),brokerage,tuiUserMap.getBrokeragePrice(),"订单返佣金",order.getId().toString(),order.getUserId());
                 }
             }
             //二级返
@@ -340,7 +349,7 @@ public class FsUserScrmServiceImpl implements IFsUserScrmService
                         tuiUserTwoMap.setUserId(tuiUserTwo.getUserId());
                         tuiUserTwoMap.setBrokeragePrice(tuiUserTwo.getBrokeragePrice().add(brokerageTwo));
                         fsUserMapper.updateFsUser(tuiUserTwoMap);
-                        billService.addBill(tuiUserTwoMap.getUserId(), CATEGORY_3.getValue(),1,BillDetailEnum.TYPE_5.getDesc(),brokerageTwo.doubleValue(),tuiUserTwoMap.getBrokeragePrice().doubleValue(),"订单返佣金",order.getId().toString(),tuiUser.getUserId());
+                        billService.addBill(tuiUserTwoMap.getUserId(), CATEGORY_3.getValue(),1,BillDetailEnum.TYPE_5.getDesc(),brokerageTwo,tuiUserTwoMap.getBrokeragePrice(),"订单返佣金",order.getId().toString(),tuiUser.getUserId());
                     }
                     //三级
                     FsUserScrm tuiUserThree= fsUserMapper.selectFsUserById(tuiUserTwo.getSpreadUserId());
@@ -350,7 +359,7 @@ public class FsUserScrmServiceImpl implements IFsUserScrmService
                             tuiUserThreeMap.setUserId(tuiUserThree.getUserId());
                             tuiUserThreeMap.setBrokeragePrice(tuiUserThree.getBrokeragePrice().add(brokerageThree));
                             fsUserMapper.updateFsUser(tuiUserThreeMap);
-                            billService.addBill(tuiUserThreeMap.getUserId(), CATEGORY_3.getValue(),1,BillDetailEnum.TYPE_5.getDesc(),brokerageThree.doubleValue(),tuiUserThreeMap.getBrokeragePrice().doubleValue(),"订单返佣金",order.getId().toString(),tuiUser.getUserId());
+                            billService.addBill(tuiUserThreeMap.getUserId(), CATEGORY_3.getValue(),1,BillDetailEnum.TYPE_5.getDesc(),brokerageThree,tuiUserThreeMap.getBrokeragePrice(),"订单返佣金",order.getId().toString(),tuiUser.getUserId());
                         }
 
                     }
@@ -359,7 +368,7 @@ public class FsUserScrmServiceImpl implements IFsUserScrmService
             }
         }
         catch (Exception e){
-
+            log.error("分佣异常",e);
         }
     }
 
@@ -377,9 +386,9 @@ public class FsUserScrmServiceImpl implements IFsUserScrmService
                 if(tuiUser!=null){
                     FsUserScrm tuiUserMap=new FsUserScrm();
                     tuiUserMap.setUserId(tuiUser.getUserId());
-                    tuiUserMap.setBrokeragePrice(tuiUser.getBrokeragePrice().subtract(new BigDecimal(bill.getNumber())));
+                    tuiUserMap.setBrokeragePrice(tuiUser.getBrokeragePrice().subtract(bill.getMoney()));
                     fsUserMapper.updateFsUser(tuiUserMap);
-                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_3.getValue(),0,BillDetailEnum.TYPE_6.getDesc(),bill.getNumber().doubleValue(),tuiUserMap.getBrokeragePrice().doubleValue(),"订单退佣金",order.getId().toString(),bill.getTuiUserId());
+                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_3.getValue(),0,BillDetailEnum.TYPE_6.getDesc(),bill.getMoney(),tuiUserMap.getBrokeragePrice(),"订单退佣金",order.getId().toString(),bill.getTuiUserId());
                 }
             }
         }
@@ -400,11 +409,11 @@ public class FsUserScrmServiceImpl implements IFsUserScrmService
                 if(tuiUser!=null){
                     FsUserScrm tuiUserMap=new FsUserScrm();
                     tuiUserMap.setUserId(tuiUser.getUserId());
-                    tuiUserMap.setNowMoney(tuiUser.getNowMoney().add(new BigDecimal(bill.getNumber())));
-                    tuiUserMap.setBrokeragePrice(tuiUser.getBrokeragePrice().subtract(new BigDecimal(bill.getNumber())));
+                    tuiUserMap.setNowMoney(tuiUser.getNowMoney().add(bill.getMoney()));
+                    tuiUserMap.setBrokeragePrice(tuiUser.getBrokeragePrice().subtract(bill.getMoney()));
                     fsUserMapper.updateFsUser(tuiUserMap);
-                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_3.getValue(),0,BillDetailEnum.TYPE_6.getDesc(),bill.getNumber().doubleValue(),tuiUserMap.getBrokeragePrice().doubleValue(),"订单分佣金",order.getId().toString(),bill.getTuiUserId());
-                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_1.getValue(),1,BillDetailEnum.TYPE_5.getDesc(),bill.getNumber().doubleValue(),tuiUserMap.getNowMoney().doubleValue(),"订单分佣金",order.getId().toString(),bill.getTuiUserId());
+                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_3.getValue(),0,BillDetailEnum.TYPE_6.getDesc(),bill.getMoney(),tuiUserMap.getBrokeragePrice(),"订单分佣金",order.getId().toString(),bill.getTuiUserId());
+                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_1.getValue(),1,BillDetailEnum.TYPE_5.getDesc(),bill.getMoney(),tuiUserMap.getNowMoney(),"订单分佣金",order.getId().toString(),bill.getTuiUserId());
                 }
             }
         }
@@ -653,6 +662,30 @@ public class FsUserScrmServiceImpl implements IFsUserScrmService
         return pageVO;
     }
 
+    @Override
+    public UserDetailsVO getUserDetails(Long userId, Long fsUserId, String dateTag, Long userCompanyId) {
+        UserDetailsVO countWatchCourse = fsUserMapper.getCountWatchCourse(userId, fsUserId, dateTag,userCompanyId);
+        FsUserCompanyUserScrm fsUserCompanyUser = userCompanyUserService.selectFsUserCompanyUserById(userCompanyId);
+
+        UserDetailsVO countAnswer = fsUserMapper.getCountAnswer(fsUserCompanyUser.getCompanyUserId(), fsUserId, dateTag);
+        UserDetailsVO countRedPacket = fsUserMapper.getCountRedPacket(fsUserCompanyUser.getCompanyUserId(), fsUserId, dateTag);
+        UserDetailsVO vo = new UserDetailsVO();
+        if (countWatchCourse != null){
+            BeanUtils.copyProperties(countWatchCourse, vo);
+        }
+        if (countRedPacket != null) {
+            vo.setAnswerRedPacketTime(countRedPacket.getAnswerRedPacketTime());
+            vo.setAnswerRedPacketAmount(countRedPacket.getAnswerRedPacketAmount());
+        } else {
+            vo.setAnswerRedPacketAmount(BigDecimal.ZERO);
+        }
+        if (countAnswer != null) {
+            vo.setAnswerTime(countAnswer.getAnswerTime());
+            vo.setAnswerRightTime(countAnswer.getAnswerRightTime());
+        }
+        return vo;
+    }
+
     @Override
     public Integer selectFsUserByUserIds(String[] userIds, Long companyUserId) {
         return fsUserMapper.selectFsUserByUserIds(userIds, companyUserId);
@@ -970,6 +1003,7 @@ public class FsUserScrmServiceImpl implements IFsUserScrmService
         // 逻辑调整:会员与销售的绑定关系通过中间表关联 /20250625 17:13
         FsUserCompanyUserScrm userCompanyUser = userCompanyUserService.selectByUserIdAndProjectId(fsUser.getUserId(), param.getProjectId());
         if (Objects.nonNull(userCompanyUser) && !userCompanyUser.getCompanyUserId().equals(param.getCompanyUserId())){
+            log.error("进入::FsUserCompanyUserScrm 该用户fsUser={},companyUser={},param={}",fsUser,userCompanyUser,param);
             return ResponseResult.fail(500,"该用户("+fsUser.getUserId() + ")已成为其他销售会员");
         }
 
@@ -1049,6 +1083,46 @@ public class FsUserScrmServiceImpl implements IFsUserScrmService
         return fsUserMapper.selectFsUserByOpenId(openid);
     }
 
+    @Override
+    @Transactional
+    public void addTuiLiveMoney(LiveOrder order, List<FsStoreProductAttrValueScrm> productAttrValues) {
+        BigDecimal brokerage=BigDecimal.ZERO;
+        //返佣金
+        FsUserScrm user= fsUserMapper.selectFsUserById(order.getCompanyUserId());
+        for (FsStoreProductAttrValueScrm productAttrValue : productAttrValues) {
+            brokerage=brokerage.add(productAttrValue.getBrokerage().multiply(new BigDecimal(order.getTotalNum())));
+        }
+        if(brokerage.compareTo(BigDecimal.ZERO)==1){
+            FsUserScrm tuiUserMap=new FsUserScrm();
+            tuiUserMap.setUserId(user.getUserId());
+            tuiUserMap.setBrokeragePrice(user.getBrokeragePrice().add(brokerage));
+            fsUserMapper.updateFsUser(tuiUserMap);
+            billService.addBill(tuiUserMap.getUserId(), CATEGORY_3.getValue(),1,BillDetailEnum.TYPE_5.getDesc(),brokerage,tuiUserMap.getBrokeragePrice(),"订单返佣金",order.getOrderId().toString(),order.getCompanyUserId());
+        }
+    }
+
+    @Override
+    @Transactional
+    public void subLiveTuiMoney(LiveOrder liveOrder) {
+        FsUserBillScrm map=new FsUserBillScrm();
+        map.setCategory(CATEGORY_3.getValue());
+        map.setBusinessId(liveOrder.getOrderId().toString());
+        map.setBillType(1);
+        List<FsUserBillScrm> list=billService.selectFsUserBillList(map);
+        if(list!=null&&list.size()>0){
+            for(FsUserBillScrm bill:list){
+                FsUserScrm tuiUser= fsUserMapper.selectFsUserByIdForUpdate(bill.getUserId());
+                if(tuiUser!=null){
+                    FsUserScrm tuiUserMap=new FsUserScrm();
+                    tuiUserMap.setUserId(tuiUser.getUserId());
+                    tuiUserMap.setBrokeragePrice(tuiUser.getBrokeragePrice().subtract(bill.getNumber()));
+                    fsUserMapper.updateFsUser(tuiUserMap);
+                    billService.addBill(tuiUserMap.getUserId(), CATEGORY_3.getValue(),0,BillDetailEnum.TYPE_6.getDesc(),bill.getNumber(),tuiUserMap.getBrokeragePrice(),"订单退佣金",liveOrder.getOrderId().toString(),bill.getTuiUserId());
+                }
+            }
+        }
+    }
+
     /**
      * 查询会员选项列表
      * @param params    参数
@@ -1058,4 +1132,36 @@ public class FsUserScrmServiceImpl implements IFsUserScrmService
     public List<OptionsVO> selectUserListByMap(Map<String, Object> params) {
         return fsUserMapper.selectUserListByMap(params);
     }
+
+
+    @Autowired
+    private IFsUserWxService fsUserWxService;
+
+    @Override
+    public void handleFsUserWx(FsUserScrm user, LoginMaWxParam param, WxMaJscode2SessionResult session) {
+        try {
+            FsUserWx fsUserWx = new FsUserWx();
+            fsUserWx.setType(1);
+            fsUserWx.setFsUserId(user.getUserId());
+            fsUserWx.setAppId(param.getAppId());
+            fsUserWx.setOpenId(session.getOpenid());
+            fsUserWx.setUnionId(session.getUnionid() != null ? session.getUnionid() : null);
+            fsUserWx.setCreateTime(new Date());
+            fsUserWx.setUpdateTime(new Date());
+            fsUserWxService.saveOrUpdateByUniqueKey(fsUserWx);
+            log.info("zyp \n 【更新或插入用户与小程序{}的绑定关系】:{}", param.getAppId(), user.getUserId());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void incPayMoney(BigDecimal payMoney, Long userId) {
+        fsUserMapper.incPayMoney(payMoney, userId);
+    }
+
+    @Override
+    public List<UserScrmVo> selectUserVOList(String phone) {
+        return fsUserMapper.selectUserVOList(phone);
+    }
 }

+ 38 - 0
fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderCodeOpenIdVo.java

@@ -0,0 +1,38 @@
+package com.fs.hisStore.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class FsStoreOrderCodeOpenIdVo implements Serializable {
+//    /**
+//     * 订单编码
+//     * **/
+//    private String orderCode;
+
+    /**
+     * 订单id
+     * **/
+    private String id;
+
+    /**
+     * 用户openId
+     * **/
+    private String openId;
+
+    /**
+     * 用户手机号
+     * **/
+    private String phone;
+
+    /**
+     * 商品详情信息
+     * **/
+    private String jsonInfo;
+
+    /**
+     * 交易单号
+     * **/
+    private String outTransId;
+}

+ 84 - 0
fs-service/src/main/java/com/fs/hisStore/vo/FsStoreOrderDeliveryNoteExportVO.java

@@ -0,0 +1,84 @@
+package com.fs.hisStore.vo;
+
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 发货单导出(商城订单)
+ * **/
+@Data
+public class FsStoreOrderDeliveryNoteExportVO implements Serializable {
+    //系统订单号
+    @Excel(name = "原始单号",width = 20,sort = 1)
+    private String orderNumber;
+
+    @Excel(name = "收件人",width = 10,sort = 2)
+    private String recipient;
+
+    @Excel(name = "收件人手机",width = 20,sort = 3)
+    private String recipientPhone;
+
+    @Excel(name = "收件人电话",width = 20,sort = 4)
+    private String recipientTelephone;
+
+    //具体到某个街道和小区
+    @Excel(name = "收件人详细地址",width = 30,sort = 5)
+    private String recipientAddress;
+
+//    //省市区
+//    @Excel(name = "收货地址",width = 20,sort = 6)
+//    private String receivingAddress;
+
+    //编号和数量:662551*2
+    @Excel(name = "组合编号及数量",width = 20,sort = 7)
+    private String number;
+
+    //名称和数量:商品名称*2
+    @Excel(name = "组合名称及数量",width = 20,sort = 8)
+    private String nameAndNumber;
+
+    @Excel(name = "代收金额",width = 10,sort = 9)
+    private BigDecimal collectionAmount;
+
+    @Excel(name = "物流公司",width = 10,sort = 10)
+    private String logisticsCompany;
+
+    @Excel(name = "物流产品",width = 10,sort = 11)
+    private String logisticsProduct;
+
+    @Excel(name = "物流付款方式",width = 15,sort = 12)
+    private String logisticsPayMethod;
+
+    @Excel(name = "包裹数",width = 10,sort = 13)
+    private Long packageNum;
+
+    @Excel(name = "寄件人",width = 10,sort = 14)
+    private String sender;
+
+    @Excel(name = "寄件人手机",width = 20,sort = 15)
+    private String senderPhone;
+
+    @Excel(name = "寄件人电话",width = 20,sort = 16)
+    private String senderTelephone;
+
+    @Excel(name = "寄件公司",width = 10,sort = 17)
+    private String senderCompany;
+
+    //具体到某个街道和小区
+    @Excel(name = "寄件人详细地址",width = 30,sort = 18)
+    private String senderAddress;
+
+    @Excel(name = "出库仓库",width = 10,sort = 19)
+    private String outboundWarehouse;
+
+    @Excel(name = "订单付款方式",width = 10,sort = 20)
+    private String payMethod;
+
+    @Excel(name = "订单备注",width = 20,sort = 21)
+    private String orderNotes;
+
+    private String keyword;
+}

+ 2 - 0
fs-service/src/main/java/com/fs/hisStore/vo/FsStoreProductListQueryVO.java

@@ -60,6 +60,8 @@ public class FsStoreProductListQueryVO implements Serializable
     private String storeIds;
 
     private Long storeId;
+    private Long companyId;
+    private Long companyUserId;
 
 
 

+ 11 - 0
fs-service/src/main/java/com/fs/hisStore/vo/UserScrmVo.java

@@ -0,0 +1,11 @@
+package com.fs.hisStore.vo;
+
+import lombok.Data;
+
+@Data
+public class UserScrmVo {
+    Long id;
+    String name;
+    String position;
+    String certificateCode;
+}

+ 2 - 1
fs-service/src/main/java/com/fs/live/domain/LiveOrderPayment.java

@@ -116,5 +116,6 @@ public class LiveOrderPayment extends BaseEntity{
     @Excel(name = "是否分账")
     private Integer isShare;
 
-
+    //小程序appId(用于多汇付支付/退款)
+    private String appId;
 }

+ 85 - 0
fs-service/src/main/java/com/fs/live/dto/LiveOrderCustomerExportDTO.java

@@ -0,0 +1,85 @@
+package com.fs.live.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 直播订单客户导出DTO
+ * 
+ * @author fs
+ * @date 2025-11-13
+ */
+@Data
+public class LiveOrderCustomerExportDTO {
+
+    /** 销售id */
+    @Excel(name = "销售ID")
+    private Long companyUserId;
+
+    /** 绑定销售昵称 */
+    @Excel(name = "销售昵称")
+    private String companyUserNickName;
+
+    /** 客户编码 */
+    @Excel(name = "客户编码")
+    private String customerCode;
+
+    /** 会员等级 */
+    @Excel(name = "会员等级")
+    private Integer userLevel;
+
+    /** 销售绑定手机号 */
+    @Excel(name = "销售手机号")
+    private String companyUserPhone;
+
+    /** 销售创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "销售创建时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date companyUserCreateTime;
+
+    /** 客户id */
+    @Excel(name = "客户ID")
+    private Long userId;
+
+    /** 客户昵称 */
+    @Excel(name = "客户昵称")
+    private String nickName;
+
+    /** 客户绑定手机号 */
+    @Excel(name = "客户手机号")
+    private String userPhone;
+
+    /** 收货手机号 */
+    @Excel(name = "收货手机号")
+    private String receivePhone;
+
+    /** 累计成交笔数 */
+    @Excel(name = "累计成交笔数")
+    private Long totalOrderCount;
+
+    /** 累计成交总额 */
+    @Excel(name = "累计成交总额", cellType = Excel.ColumnType.NUMERIC)
+    private BigDecimal totalOrderAmount;
+
+    /** 最新绑定时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "最新绑定时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date latestBindTime;
+
+    /** 客户状态 */
+    @Excel(name = "客户状态", dictType = "user_status")
+    private Integer userStatus;
+
+    /** 所属店铺 */
+    @Excel(name = "所属店铺ID")
+    private Long storeId;
+
+    /** 所属店铺名称 */
+    @Excel(name = "所属店铺名称")
+    private String storeName;
+}
+

+ 4 - 1
fs-service/src/main/java/com/fs/live/dto/LiveOrderDeliveryNoteDTO.java

@@ -16,9 +16,12 @@ public class LiveOrderDeliveryNoteDTO {
     @Excel(name = "系统订单号(必填)",width = 20,sort = 1)
     private String orderNumber;
 
-    @Excel(name = "物流公司编号(必填)(SF:顺丰、EMS:邮政、ZTO:中通、JD:京东、DBL:德邦)",width = 30,sort = 2)
+//    @Excel(name = "物流公司编号(必填)(SF:顺丰、EMS:邮政、ZTO:中通、JD:京东、DBL:德邦)",width = 30,sort = 2)
     private String deliverySn;
 
+    @Excel(name = "物流公司(必填)(SF:顺丰、EMS:邮政、ZTO:中通、JD:京东、DBL:德邦)",width = 10,sort = 10)
+    private String logisticsCompany;
+
     private String deliveryName;
 
     @Excel(name = "快递单号(必填)",width = 20,sort = 3)

+ 7 - 4
fs-service/src/main/java/com/fs/live/mapper/LiveAfterSalesMapper.java

@@ -110,7 +110,7 @@ public interface LiveAfterSalesMapper {
     Map<Long, LiveAfterSales> findByOrderIds(@Param("orderIdList") List<Long> orderIdList);
 
     @Select({"<script> " +
-            "select *  from live_after_sales  " +
+            "select lo.order_code,las.*  from live_after_sales las left join live_order lo on lo.order_id = las.order_id " +
             "where 1=1 " +
             "<if test = 'maps.status != null and maps.status ==1   '> " +
             "and sales_status = 0 " +
@@ -119,15 +119,18 @@ public interface LiveAfterSalesMapper {
             "and sales_status = 3 " +
             "</if>" +
             "<if test = 'maps.userId != null    '> " +
-            "and user_id = #{maps.userId} " +
+            "and las.user_id = #{maps.userId} " +
             "</if>" +
-            "order by create_time desc "+
+            "order by las.create_time desc "+
             "</script>"})
-    List<LiveAfterSalesQueryVO> selectLiveAfterSalesListQuery(LiveAfterSalesQueryParam param);
+    List<LiveAfterSalesQueryVO> selectLiveAfterSalesListQuery(@Param("maps") LiveAfterSalesQueryParam param);
 
     @Select({"<script> " +
             "select ifnull(count(1),0) from live_after_sales   " +
             "where user_id=#{userId}  and sales_status =#{salesStatus} " +
             "</script>"})
     Integer selectLiveAfterSalesCount(@Param("userId")long userId,@Param("salesStatus") int salesStatus);
+
+    @Select(" select  * from  live_after_sales where order_id = #{orderId} and sales_status = 0 ")
+    LiveAfterSales getLiveAfterSalesByOrderId(@Param("orderId") Long orderId);
 }

+ 64 - 6
fs-service/src/main/java/com/fs/live/mapper/LiveOrderMapper.java

@@ -2,6 +2,7 @@ package com.fs.live.mapper;
 
 
 import com.fs.live.domain.LiveOrder;
+import com.fs.live.dto.LiveOrderDeliveryNoteDTO;
 import com.fs.live.param.FsMyLiveOrderQueryParam;
 import com.fs.live.param.LiveOrderParam;
 import com.fs.live.vo.*;
@@ -103,13 +104,13 @@ public interface LiveOrderMapper {
     @Select("select * from live_order where `status` = 3 AND TIMESTAMPDIFF(HOUR, start_time, NOW()) >= 48  ")
     List<LiveOrder> selectLiveOrderByFinish();
 
-    @Select("select * from live_order where `status` = 2 and extend_order_id is not null ")
+    @Select("select * from live_order where `status` = 1 and extend_order_id is not null and (delivery_sn is null or delivery_code = '') and refund_status = 0 and is_pay = 1 order by update_time ")
     List<LiveOrder> selectUpdateExpress();
 
-    @Select("select order_id from live_order where `status` = 2")
+    @Select("select order_id from live_order where `status` = 2 and delivery_code is not null and delivery_sn is not null and is_pay = 1")
     List<Long> selectSyncExpressIds();
 
-    @Select("select order_id from live_order where `status` = 2 and extend_order_id is null ")
+    @Select("select order_id from live_order where `status` = 1 and extend_order_id is null and is_pay='1'")
     List<Long> selectOrderIdByNoErp();
 
     @Select("select * from live_order where extend_order_id is not null and `status`=2")
@@ -368,8 +369,8 @@ public interface LiveOrderMapper {
     int batchUpdateErpByOrderIds(@Param("maps")ArrayList<Map<String, String>> maps);
 
     @Select({"<script> " +
-            "select o.order_id,o.order_code,o.item_json,o.pay_price,o.status,o.delivery_id,o.finish_time  from live_order o  " +
-            "where o.is_del=0 and o.is_sys_del=0 " +
+            "select o.order_id,o.total_num,o.create_time, o.discount_money ,o.live_id,o.order_code,o.item_json,o.pay_price,o.status,o.delivery_sn as delivery_id,o.finish_time  from live_order o  " +
+            "where o.is_del=0 " +
             "<if test = 'maps.status != null and maps.status != \"\"     '> " +
             "and o.status =#{maps.status} " +
             "</if>" +
@@ -388,7 +389,7 @@ public interface LiveOrderMapper {
 
     @Select({"<script> " +
             "select o.*  from live_order o  " +
-            "where o.is_del=0 and o.is_sys_del=0 " +
+            "where o.is_del=0 " +
             "<if test = 'maps.status != null and maps.status != \"\"     '> " +
             "and o.status =#{maps.status} " +
             "</if>" +
@@ -413,4 +414,61 @@ public interface LiveOrderMapper {
             "where o.user_id=#{userId}  and o.status =#{status} " +
             "</script>"})
     Integer selectLiveOrderCount(long userId, int status);
+
+
+    List<LiveOrderVoZm> selectLiveOrderListZm(LiveOrder liveOrder);
+
+    @Select(" SELECT * from live_order WHERE item_json is NULL ORDER BY create_time DESC  LIMIT 30")
+    List<LiveOrder> selectLiveOrderItemJson();
+
+    @Update(" UPDATE live_order SET item_json=#{itemJson} WHERE order_id=#{orderId}")
+    void updateLiveOrderItemJson(LiveOrder storeOrder);
+
+    @Select("select * from live_order where  `status`=2 and (extend_order_id is not null and extend_order_id != '') and (delivery_id is not null and delivery_id != '')")
+    List<LiveOrder> selectShippedOrder();
+
+    List<LiveOrder> getUnsettledOrder();
+
+
+    List<LiveOrderDeliveryNoteExportVO> getDeliveryNote(@Param("maps") LiveOrderParam param);
+
+    /**
+     * 根据订单号批量查询订单信息(包含openId和transactionId)
+     * @param list 订单号列表
+     * @return 订单信息列表
+     */
+    List<LiveOrderCodeOpenIdVo> selectLiveOrderCodeOpenIdInOrderCode(@Param("list") List<String> list);
+
+    /**
+     * 批量更新订单物流信息
+     * @param dtoList 物流信息列表
+     */
+    void batchUpdateInOrderCode(@Param("list") List<LiveOrderDeliveryNoteDTO> dtoList);
+
+    @Select("SELECT * FROM live_order WHERE user_id=#{userId} LIMIT 1")
+    LiveOrder selectOrderByUserIdLimit1(@Param("userId") Long userId);
+
+    @Select("SELECT * FROM live_order WHERE live_id= #{liveId}")
+    List<LiveOrder> selectOrderByLiveId(@Param("liveId") Long liveId);
+
+    /*
+    * 查询订单创建时间为最近30分钟的订单
+    * */
+    @Select("SELECT * FROM live_order WHERE create_time >= DATE_SUB(NOW(), INTERVAL 15 MINUTE) and status = 0 and refund_status = 0")
+    List<LiveOrder> selectBankOrder();
+
+
+    void batchUpdateTime(@Param("list") List<LiveOrder> list);
+
+    @Update({
+            "<script>",
+            "UPDATE live_order ",
+            "SET update_time = NOW() ",
+            "WHERE id IN ",
+            "<foreach collection='ids' item='id' open='(' separator=',' close=')'>",
+            "#{id}",
+            "</foreach>",
+            "</script>"
+    })
+    void batchUpdateTimeIds(@Param("ids") List<Long> ids);
 }

+ 1 - 0
fs-service/src/main/java/com/fs/live/param/LiveOrderComputedParam.java

@@ -17,6 +17,7 @@ public class LiveOrderComputedParam implements Serializable
     private Long productId;
     private String totalNum;
     private Long cityId;
+    private Long attrValueId;
 
 
     @ApiModelProperty(value = "使用积分 1使用")

+ 33 - 1
fs-service/src/main/java/com/fs/live/service/ILiveOrderService.java

@@ -9,8 +9,10 @@ import com.fs.hisStore.vo.FsStoreOrderVO;
 import com.fs.live.domain.LiveAfterSales;
 import com.fs.live.domain.LiveOrder;
 import com.fs.live.dto.LiveOrderComputeDTO;
+import com.fs.live.dto.LiveOrderDeliveryNoteDTO;
 import com.fs.live.param.*;
 import com.fs.live.vo.*;
+import com.fs.live.vo.LiveOrderDeliveryNoteExportVO;
 import com.fs.store.domain.FsStoreDelivers;
 import org.springframework.web.bind.annotation.RequestBody;
 
@@ -98,7 +100,7 @@ public interface ILiveOrderService {
      * @param orderId
      * @return
      */
-    int getGoods(Long orderId);
+    int finishishOrder(Long orderId);
 
     /**
      * 修改物流信息
@@ -231,4 +233,34 @@ public interface ILiveOrderService {
     Integer selectFsStoreOrderCount(long l, int i);
 
     R payConfirmReward(LiveOrder liveOrder);
+
+
+    List<LiveOrderVoZm> selectLiveOrderListZm(LiveOrder liveOrder);
+
+    R handleLiveOrderPay(LiveOrderPayParam param);
+
+    List<LiveOrder> selectLiveOrderItemJson();
+
+    void refreshOrderSettlementStatus();
+
+    /**
+     * 批量导入更新直播订单发货状态
+     * @param dtoList 订单数据
+     * **/
+    R importDeliveryNoteExpress(List<LiveOrderDeliveryNoteDTO> dtoList,String appId);
+
+    /**
+     * 获取发货单数据
+     * @param param 查询条件
+     * @return list
+     * **/
+    List<LiveOrderDeliveryNoteExportVO> getDeliveryNote(LiveOrderParam param);
+
+    LiveOrder selectOrderByUserIdLimit1(Long userId);
+
+    List<LiveOrder> selectBankOrder();
+
+    void batchUpdateTime(List<LiveOrder> list);
+
+    void batchUpdateTimeIds(List<Long> ids);
 }

File diff suppressed because it is too large
+ 653 - 233
fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java


+ 141 - 0
fs-service/src/main/java/com/fs/pay/domain/PaymentMiniProgramConfig.java

@@ -0,0 +1,141 @@
+package com.fs.pay.domain;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 多小程序支付配置对象 payment_mini_program_config
+ *
+ * @author fs
+ * @date 2025-11-05
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class PaymentMiniProgramConfig extends BaseEntity{
+
+    /** 主键ID */
+    private Long id;
+
+    /** 支付类型:YB-易宝,TZH-台州银行,WX-微信,HF-汇付 */
+    @Excel(name = "支付类型:YB-易宝,TZH-台州银行,WX-微信,HF-汇付")
+    private String payType;
+
+    /**
+     * 小程序名称
+     */
+    @Excel(name = "小程序名称")
+    private String appName;
+    /** 小程序appid */
+    @Excel(name = "小程序appid")
+    private String appid;
+    /**
+     * 小程序密钥
+     */
+    @Excel(name = "小程序密钥")
+    private String appSecret;
+
+    /** 易宝商户号 */
+    @Excel(name = "易宝商户号")
+    private String ybMerchantNo;
+
+    /** 易宝Key */
+    @Excel(name = "易宝Key")
+    private String ybKey;
+
+    /** 易宝回调地址 */
+    @Excel(name = "易宝回调地址")
+    private String ybNotifyUrl;
+
+    /** 台州银行商户号 */
+    @Excel(name = "台州银行商户号")
+    private String tzhMerchantNo;
+
+    /** 台州appSecret */
+    @Excel(name = "台州appSecret")
+    private String tzhAppsecret;
+
+    /** 台州私钥 */
+    @Excel(name = "台州私钥")
+    private String tzhPrivateKey;
+
+    /** 台州平台公钥 */
+    @Excel(name = "台州平台公钥")
+    private String tzhPublicKey;
+
+    /** 台州appKey */
+    @Excel(name = "台州appKey")
+    private String tzhAppkey;
+
+    /** 台州支付回调地址 */
+    @Excel(name = "台州支付回调地址")
+    private String tzhPayNotifyUrl;
+
+    /** 台州退款回调地址 */
+    @Excel(name = "台州退款回调地址")
+    private String tzhRefundNotifyUrl;
+
+    /** 台州分账回调地址 */
+    @Excel(name = "台州分账回调地址")
+    private String tzhSplitNotifyUrl;
+
+    /** 微信商户号 */
+    @Excel(name = "微信商户号")
+    private String wxMerchantNo;
+
+    /** 微信Key */
+    @Excel(name = "微信Key")
+    private String wxKey;
+    /**
+     *
+     */
+    private String wxKeyPath;
+    /**
+     * 微信回调url
+     */
+    @Excel(name = "微信回调url")
+    private String wxNotifyUrl;
+
+    /** 汇付产品号 */
+    @Excel(name = "汇付产品号")
+    private String hfProductNo;
+
+    /** 汇付系统号 */
+    @Excel(name = "汇付系统号")
+    private String hfSystemNo;
+
+    /** 汇付商户号 */
+    @Excel(name = "汇付商户号")
+    private String hfMerchantNo;
+
+    /** 汇付服务商私钥 */
+    @Excel(name = "汇付服务商私钥")
+    private String hfPrivateKey;
+
+    /** 汇付公钥 */
+    @Excel(name = "汇付公钥")
+    private String hfPublicKey;
+
+    /** 汇付支付回调地址 */
+    @Excel(name = "汇付支付回调地址")
+    private String hfPayNotifyUrl;
+
+    /** 汇付大额支付回调地址 */
+    @Excel(name = "汇付大额支付回调地址")
+    private String hfLargePayNotifyUrl;
+
+    /** 汇付退款回调地址 */
+    @Excel(name = "汇付退款回调地址")
+    private String hfRefundNotifyUrl;
+
+    /** 汇付大额退款回调地址 */
+    @Excel(name = "汇付大额退款回调地址")
+    private String hfLargeRefundNotifyUrl;
+
+    /** 状态,1启用,0禁用 */
+    @Excel(name = "状态,1启用,0禁用")
+    private Integer status;
+
+
+}

+ 70 - 0
fs-service/src/main/java/com/fs/pay/mapper/PaymentMiniProgramConfigMapper.java

@@ -0,0 +1,70 @@
+package com.fs.pay.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.pay.domain.PaymentMiniProgramConfig;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+/**
+ * 多小程序支付配置Mapper接口
+ *
+ * @author fs
+ * @date 2025-11-05
+ */
+public interface PaymentMiniProgramConfigMapper extends BaseMapper<PaymentMiniProgramConfig>{
+    /**
+     * 查询多小程序支付配置
+     *
+     * @param id 多小程序支付配置主键
+     * @return 多小程序支付配置
+     */
+    PaymentMiniProgramConfig selectPaymentMiniProgramConfigById(String id);
+
+    /**
+     * 查询多小程序支付配置列表
+     *
+     * @param paymentMiniProgramConfig 多小程序支付配置
+     * @return 多小程序支付配置集合
+     */
+    List<PaymentMiniProgramConfig> selectPaymentMiniProgramConfigList(PaymentMiniProgramConfig paymentMiniProgramConfig);
+
+    /**
+     * 新增多小程序支付配置
+     *
+     * @param paymentMiniProgramConfig 多小程序支付配置
+     * @return 结果
+     */
+    int insertPaymentMiniProgramConfig(PaymentMiniProgramConfig paymentMiniProgramConfig);
+
+    /**
+     * 修改多小程序支付配置
+     *
+     * @param paymentMiniProgramConfig 多小程序支付配置
+     * @return 结果
+     */
+    int updatePaymentMiniProgramConfig(PaymentMiniProgramConfig paymentMiniProgramConfig);
+
+    /**
+     * 删除多小程序支付配置
+     *
+     * @param id 多小程序支付配置主键
+     * @return 结果
+     */
+    int deletePaymentMiniProgramConfigById(String id);
+
+    /**
+     * 批量删除多小程序支付配置
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deletePaymentMiniProgramConfigByIds(String[] ids);
+
+    PaymentMiniProgramConfig selectPaymentConfigByAppId(@Param("appid") String appid);
+
+    @Select("select * from payment_mini_program_config where status = 1")
+    List<PaymentMiniProgramConfig> selectAll();
+
+}

+ 1 - 0
fs-service/src/main/java/com/fs/store/config/StoreConfig.java

@@ -22,5 +22,6 @@ public class StoreConfig implements Serializable {
     private String refundPhoneNumber;
     private String refundAddress;
     private Integer auditSwitch; // 订单审核开关
+    private BigDecimal payPostage; // 货到付款邮费
 
 }

+ 104 - 0
fs-service/src/main/java/com/fs/wx/order/domain/FsWxExpressTask.java

@@ -0,0 +1,104 @@
+package com.fs.wx.order.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+/**
+ * 微信同步发货信息定时任务表
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class FsWxExpressTask {
+
+    /**
+     * 任务ID,唯一标识
+     */
+    private Long id;
+
+    /**
+     * 订单code
+     */
+    private String orderCode;
+
+    /**
+     * 支付单号
+     */
+    private String payCode;
+
+    /**
+     * 用户id
+     */
+    private Long userId;
+
+    /**
+     * 消息内容,JSON格式。
+     */
+    private String data;
+
+    /**
+     * 任务状态:0=待执行, 1=执行中, 2=执行成功, 3=执行失败, 4=已取消
+     */
+    private Integer status;
+
+    /**
+     * 当前重试次数
+     */
+    private Integer retryCount;
+
+    /**
+     * 最大重试次数
+     */
+    private Integer maxRetries;
+
+    /**
+     * 请求参数(JSON格式,主要记录 access_token 获取方式)
+     */
+    private String requestParams;
+
+    /**
+     * 完整的请求体 (JSON格式)
+     */
+    private String requestBody;
+
+    /**
+     * API 响应结果 (JSON格式)
+     */
+    private String responseBody;
+
+    /**
+     * 错误信息 (如果执行失败)
+     */
+    private String errorMessage;
+
+    /**
+     * 任务创建时间
+     */
+    private LocalDateTime createTime; // 使用LocalDateTime对应timestamp
+
+    /**
+     * 最后更新时间
+     */
+    private LocalDateTime updateTime; // 使用LocalDateTime对应timestamp
+
+
+    /**
+     * 快递公司
+     */
+    private String expressCompany;
+
+    /**
+     * 快递编号
+     */
+    private String expressNo;
+
+    private Integer type;
+
+    /**
+     * 小程序ID
+     */
+    private String appid;
+}

+ 21 - 0
fs-service/src/main/java/com/fs/wx/order/dto/Contact.java

@@ -0,0 +1,21 @@
+package com.fs.wx.order.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class Contact {
+    // 根据实际需要添加更多联系人字段
+    @JsonProperty("consignor_contact")
+    private String consignorContact; // 发货人联系方式 (示例字段)
+
+    // 可以添加收货人联系方式等
+    // @JsonProperty("receiver_contact")
+    // private String receiverContact;
+}

+ 27 - 0
fs-service/src/main/java/com/fs/wx/order/dto/OrderKey.java

@@ -0,0 +1,27 @@
+package com.fs.wx.order.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderKey {
+
+    @JsonProperty("order_number_type")
+    private Integer orderNumberType;
+
+    @JsonProperty("transaction_id")
+    private String transactionId;
+
+    @JsonProperty("mchid")
+    private String mchId;
+
+    @JsonProperty("out_trade_no")
+    private String outTradeNo;
+}

+ 77 - 0
fs-service/src/main/java/com/fs/wx/order/dto/OrderQueryRequest.java

@@ -0,0 +1,77 @@
+package com.fs.wx.order.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderQueryRequest {
+
+    /**
+     * 聚合账户 (Required)
+     */
+    private String account;
+
+    /**
+     * 下游订单号 (Required if upOrderId is null)
+     */
+    private String lowOrderId;
+
+    /**
+     * 通莞订单号 (Required if lowOrderId is null)
+     */
+    private String upOrderId;
+
+    /**
+     * 值为"Y"时,接口返回优惠信息字段 (Optional)
+     */
+    private String extendInfo;
+
+    /**
+     * 值为"1"时,接口返回易宝专业版分账订单详情 (Optional)
+     */
+    private String isExtend;
+
+    /**
+     * 值为"1"时,接口返回SAAS分账订单详情 (Optional)
+     */
+    private String isNeedUpInfo;
+
+    /**
+     * 值为"1"时,接口返回渠道商户订单号字段 (Optional)
+     */
+    private String isNeedChannelMchOrderId;
+
+    /**
+     * 值为"1"时,返回因公付金额信息,仅支付宝服务商渠道支持 (Optional)
+     */
+    private String isNeedEnterprisePayInfo;
+
+    /**
+     * 签名 (Required)
+     * Note: This will be calculated and set by the service.
+     */
+    private String sign;
+
+    /**
+     * Helper method to get parameters for signing.
+     * Excludes the 'sign' field itself.
+     * Returns sorted map to ensure consistent order for signing.
+     *
+     * @return A map of non-null parameters sorted by key.
+     */
+    public Map<String, String> toSignMap() {
+       Map<String,String> sign = new HashMap<>();
+        sign.put("account",account);
+        sign.put("upOrderId",upOrderId);
+        sign.put("isNeedUpInfo", isNeedUpInfo);
+        return sign;
+    }
+}

+ 236 - 0
fs-service/src/main/java/com/fs/wx/order/dto/OrderQueryResponse.java

@@ -0,0 +1,236 @@
+package com.fs.wx.order.dto;
+
+import cn.hutool.core.annotation.Alias;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class OrderQueryResponse {
+
+    /**
+     * 100:成功,101:失败 (Required)
+     */
+    private Integer status;
+
+    /**
+     * 消息描述 (Required)
+     */
+    private String message;
+
+    /**
+     * 上游订单号 (Required)
+     */
+    private String channelOrderId;
+
+    /**
+     * 通莞订单号 (Required)
+     */
+    private String upOrderId;
+
+    /**
+     * 默认传null (Required) - Although API doc says required, it seems informational.
+     */
+    private String payoffType;
+
+    /**
+     * 支付时间 (Required)
+     */
+    private String payTime;
+
+    /**
+     * WX: openid; Alipay: account name (Required)
+     * Mapped from both "openId" and "openid" in JSON
+     */
+    @Alias("openid") // Instruct Hutool to map "openid" to this field as well
+    private String openId;
+
+    /**
+     * 签名 (Required) - For response validation
+     */
+    private String sign;
+
+    /**
+     * 结算渠道编号 (Required)
+     */
+    private String settlementChannel;
+
+    /**
+     * 下游订单号 (Required)
+     */
+    private String lowOrderId;
+
+    /**
+     * 支付金额,单位元 (Required)
+     */
+    private String payMoney; // Keep as String as per API doc, can be converted later
+
+    /**
+     * 支付方式 0:WX, 1:ZFB, 2:UnionPay QR, 6:LongPay, 8:BestPay, H:Digital Currency (Required)
+     */
+    private String payType;
+
+    /**
+     * 0:Success, 1:Fail, 2:Revoked, 4:Pending, 5:Refunded, 6:Partial Refund (Required)
+     */
+    private String state;
+
+    /**
+     * 订单备注 (Optional)
+     */
+    private String attach;
+
+    /**
+     * 聚合账户 (Required)
+     */
+    private String account;
+
+    /**
+     * 支付方式例:WX、ZFB、YZF、LZF、YLZF (Required)
+     */
+    private String channelId;
+
+    /**
+     * 渠道优惠金额 JSON String, e.g., {"discountAmt":"100"} (Unit: Fen) (Optional)
+     */
+    private String discountInfo;
+
+    /**
+     * 扩展信息 JSON String (Optional, if requested)
+     * Need to be parsed into an object if needed.
+     */
+    private String extendInfo; // Raw JSON string
+
+    /**
+     * 易宝/SAAS分账详情 JSON Object (Optional, if requested)
+     */
+    private JSONObject extend; // Parsed JSON Object
+
+    /**
+     * SAAS分账订单详情 JSON Object (Optional, if requested)
+     */
+    private JSONObject upInfo; // Parsed JSON Object
+
+    /**
+     * 渠道商户订单号 (Optional, if requested)
+     */
+    private String channelMchOrderId;
+
+    /**
+     * 订单管控状态 FROZEN/UN_FROZEN (Optional, if requested via isNeedUpInfo=1)
+     */
+    private String fundControlCsStatus;
+
+    /**
+     * 管控订单解冻时间 yyyy-mm-dd hh:mm:ss (Optional, if requested via isNeedUpInfo=1 and status is UN_FROZEN)
+     */
+    private String csUnFrozenCompleteDate;
+
+    /**
+     * 因公付金额信息 JSON String, e.g., {"invoiceAmount":"0.01","isUseEnterprisePay":false} (Optional, if requested)
+     */
+    private String enterprisePayInfo; // Raw JSON String
+
+    // --- Helper methods to access parsed nested JSON data ---
+
+    /**
+     * Gets parsed DiscountInfo object from discountInfo string.
+     * @return DiscountInfo object or null if parsing fails or discountInfo is null/empty.
+     */
+    public DiscountInfo getParsedDiscountInfo() {
+        if (JSONUtil.isJson(this.discountInfo)) {
+            try {
+                return JSONUtil.toBean(this.discountInfo, DiscountInfo.class);
+            } catch (Exception e) {
+                // Log parsing error if needed
+                return null;
+            }
+        }
+        return null;
+    }
+
+     /**
+     * Gets parsed EnterprisePayInfo object from enterprisePayInfo string.
+     * @return EnterprisePayInfo object or null if parsing fails or enterprisePayInfo is null/empty.
+     */
+    public EnterprisePayInfo getParsedEnterprisePayInfo() {
+         if (JSONUtil.isJson(this.enterprisePayInfo)) {
+            try {
+                return JSONUtil.toBean(this.enterprisePayInfo, EnterprisePayInfo.class);
+            } catch (Exception e) {
+                 // Log parsing error if needed
+                return null;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Gets parsed ExtendInfo object from extendInfo string.
+     * @return JSONObject or null if parsing fails or extendInfo is null/empty.
+     */
+    public JSONObject getParsedExtendInfo() {
+        if (JSONUtil.isJson(this.extendInfo)) {
+            try {
+                return JSONUtil.parseObj(this.extendInfo);
+            } catch (Exception e) {
+                 // Log parsing error if needed
+                return null;
+            }
+        }
+        return null;
+    }
+
+    // --- Nested DTOs for parsed JSON strings ---
+
+    @Data
+    public static class DiscountInfo {
+        /**
+         * Discount amount in Fen (分)
+         */
+        private String discountAmt; // Keep as String as per API, or use Integer/Long
+
+        public BigDecimal getDiscountAmtYuan() {
+            if (discountAmt != null) {
+                try {
+                    // Assuming discountAmt is in Fen (cents)
+                    return new BigDecimal(discountAmt).divide(new BigDecimal("100"));
+                } catch (NumberFormatException e) {
+                    return null; // Or handle error appropriately
+                }
+            }
+            return null;
+        }
+    }
+
+    @Data
+    public static class EnterprisePayInfo {
+        private String invoiceAmount; // Amount in Yuan (元)
+        private Boolean isUseEnterprisePay;
+
+        public BigDecimal getInvoiceAmountValue() {
+             if (invoiceAmount != null) {
+                 try {
+                     return new BigDecimal(invoiceAmount);
+                 } catch (NumberFormatException e) {
+                     return null; // Or handle error appropriately
+                 }
+             }
+             return null;
+         }
+    }
+
+    /**
+     * Validates the response signature.
+     * IMPORTANT: Implement the actual signature validation logic based on Tongguan's specification.
+     * @param secretKey The secret key.
+     * @return true if the signature is valid, false otherwise.
+     */
+    public boolean isResponseSignValid(String secretKey) {
+
+        System.err.println("WARN: Response signature validation is not implemented!");
+        return true;
+    }
+}

+ 17 - 0
fs-service/src/main/java/com/fs/wx/order/dto/Payer.java

@@ -0,0 +1,17 @@
+package com.fs.wx.order.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class Payer {
+
+    @JsonProperty("openid")
+    private String openid;
+}

+ 26 - 0
fs-service/src/main/java/com/fs/wx/order/dto/ShippingItem.java

@@ -0,0 +1,26 @@
+package com.fs.wx.order.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ShippingItem {
+
+    @JsonProperty("tracking_no")
+    private String trackingNo;
+
+    @JsonProperty("express_company")
+    private String expressCompany;
+
+    @JsonProperty("item_desc")
+    private String itemDesc;
+
+    @JsonProperty("contact")
+    private Contact contact;
+}

+ 42 - 0
fs-service/src/main/java/com/fs/wx/order/dto/UploadShippingInfoRequest.java

@@ -0,0 +1,42 @@
+package com.fs.wx.order.dto;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class UploadShippingInfoRequest {
+
+    @JsonProperty("order_key")
+    private OrderKey orderKey;
+
+    @JsonProperty("logistics_type")
+    private Integer logisticsType;
+
+    @JsonProperty("delivery_mode")
+    private Integer deliveryMode;
+
+    @JsonProperty("is_all_delivered")
+    private Boolean isAllDelivered;
+
+    @JsonProperty("shipping_list")
+    private List<ShippingItem> shippingList;
+
+    @JsonProperty("upload_time")
+    private String uploadTime;
+
+    @JsonProperty("payer")
+    private Payer payer;
+
+    @JsonIgnore
+    private String appid;
+
+}

+ 21 - 0
fs-service/src/main/java/com/fs/wx/order/dto/WeChatApiConfig.java

@@ -0,0 +1,21 @@
+package com.fs.wx.order.dto;
+
+import lombok.Getter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@Getter
+public class WeChatApiConfig {
+
+    @Value("${wechat.api.base-url}")
+    private String baseUrl;
+
+    @Value("${wechat.api.upload-shipping-info}")
+    private String uploadShippingInfoPath;
+
+
+    public String getUploadShippingInfoUrl() {
+        return baseUrl + uploadShippingInfoPath;
+    }
+}

+ 20 - 0
fs-service/src/main/java/com/fs/wx/order/dto/WeChatApiResponse.java

@@ -0,0 +1,20 @@
+package com.fs.wx.order.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+public class WeChatApiResponse {
+
+    @JsonProperty("errcode")
+    private Integer errcode;
+
+    @JsonProperty("errmsg")
+    private String errmsg;
+
+    public boolean isSuccess() {
+        return errcode != null && errcode == 0;
+    }
+}

+ 117 - 0
fs-service/src/main/java/com/fs/wx/order/mapper/FsWxExpressTaskMapper.java

@@ -0,0 +1,117 @@
+package com.fs.wx.order.mapper;
+
+import com.fs.wx.order.domain.FsWxExpressTask;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+
+/**
+ * 微信同步发货信息定时任务表 Mapper 接口
+ */
+@Mapper
+public interface FsWxExpressTaskMapper {
+
+    /**
+     * 根据ID查询任务
+     * @param id 任务ID
+     * @return FsWxExpressTask 任务实体
+     */
+    @Select("SELECT * FROM f s_wx_express_task WHERE id = #{id}")
+    FsWxExpressTask selectById(@Param("id") Long id);
+
+    /**
+     * 插入新任务
+     * @param task 任务实体
+     * @return 影响行数
+     */
+    @Insert("INSERT INTO fs_wx_express_task (order_code, user_id, data, status, retry_count, max_retries, request_params, request_body, response_body, error_message, create_time, update_time,express_company,express_no,type,appid) " +
+            "VALUES (#{orderCode}, #{userId}, #{data}, #{status}, #{retryCount}, #{maxRetries}, #{requestParams}, #{requestBody}, #{responseBody}, #{errorMessage}, #{createTime}, #{updateTime},#{expressCompany},#{expressNo},#{type},#{appid})")
+    @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
+    int insert(FsWxExpressTask task);
+
+    /**
+     * 根据ID更新任务信息
+     * @param task 任务实体
+     * @return 影响行数
+     */
+    @Update("<script>" +
+            "UPDATE fs_wx_express_task " +
+            "<set>" +
+            "  <if test='orderCode != null'>order_code = #{orderCode},</if>" +
+            "  <if test='userId != null'>user_id = #{userId},</if>" +
+            "  <if test='data != null'>data = #{data}::json,</if>" +
+            "  <if test='status != null'>status = #{status},</if>" +
+            "  <if test='retryCount != null'>retry_count = #{retryCount},</if>" +
+            "  <if test='maxRetries != null'>max_retries = #{maxRetries},</if>" +
+            "  <if test='requestParams != null'>request_params = #{requestParams},</if>" +
+            "  <if test='requestBody != null'>request_body = #{requestBody},</if>" +
+            "  <if test='responseBody != null'>response_body = #{responseBody},</if>" +
+            "  <if test='errorMessage != null'>error_message = #{errorMessage},</if>" +
+            "  <if test='type != null'>type = #{type},</if>" +
+            "</set>" +
+            "WHERE id = #{id}" +
+            "</script>")
+    int updateById(FsWxExpressTask task);
+
+    /**
+     * 根据ID删除任务
+     * @param id 任务ID
+     * @return 影响行数
+     */
+    @Delete("DELETE FROM fs_wx_express_task WHERE id = #{id}")
+    int deleteById(@Param("id") Long id);
+
+    /**
+     * 根据状态查询任务列表
+     * @param status 任务状态
+     * @return List<FsWxExpressTask> 任务列表
+     */
+    @Select("SELECT * FROM fs_wx_express_task WHERE status = #{status}")
+    List<FsWxExpressTask> selectByStatus(@Param("status") Integer status);
+
+
+    /**
+     * 查询待处理数据
+     * @return
+     */
+    @Select("SELECT * FROM fs_wx_express_task WHERE retry_count < 3 AND status in (0,3)")
+    List<FsWxExpressTask> selectPendingData();
+    @Update("<script>" +
+            "<foreach collection='list' item='task' separator=';'>" +
+            " UPDATE fs_wx_express_task" +
+            " SET" +
+            "  order_code = #{task.orderCode}," +
+            "  user_id = #{task.userId}," +
+            "  data = #{task.data}," +
+            "  status = #{task.status}," +
+            "  retry_count = #{task.retryCount}," +
+            "  max_retries = #{task.maxRetries}," +
+            "  request_params = #{task.requestParams}," +
+            "  request_body = #{task.requestBody}," +
+            "  response_body = #{task.responseBody}," +
+            "  error_message = #{task.errorMessage}," +
+            "  update_time = now()" +
+            " WHERE id = #{task.id}" +
+            "</foreach>" +
+            "</script>")
+    void batchUpdate(List<FsWxExpressTask> fsWxExpressTasks);
+
+    /**
+     * 批量插入新任务
+     * @param tasks 任务实体列表
+     * @return 影响行数 (Optional: change void to int if needed)
+     */
+    @Insert("<script>" +
+            "INSERT INTO fs_wx_express_task " +
+            "(order_code, user_id, data, status, retry_count, max_retries, request_params, request_body, response_body, error_message, create_time, update_time, pay_code,appid) " +
+            "VALUES " +
+            "<foreach collection='tasks' item='task' separator=','>" +
+            "(" +
+            "#{task.orderCode}, #{task.userId}, #{task.data}, #{task.status}, #{task.retryCount}, #{task.maxRetries}, " + // Keep ::json if PostgreSQL
+            "#{task.requestParams}, #{task.requestBody}, #{task.responseBody}, #{task.errorMessage}, " +
+            "#{task.createTime}, #{task.updateTime},#{task.payCode},#{task.appid}" +
+            ")" +
+            "</foreach>" +
+            "</script>")
+    void insertBatch(List<FsWxExpressTask> tasks);
+}

+ 30 - 0
fs-service/src/main/java/com/fs/wx/order/service/ExpressToWxHolder.java

@@ -0,0 +1,30 @@
+package com.fs.wx.order.service;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class ExpressToWxHolder {
+    private static ApplicationContext applicationContext;
+
+    @Autowired
+    public void setApplicationContext(ApplicationContext applicationContext) {
+        ExpressToWxHolder.applicationContext = applicationContext;
+    }
+
+    public static ExpressToWxService findBest(Integer type,String orderCode) {
+        String[] beanNames = applicationContext.getBeanNamesForType(ExpressToWxService.class);
+
+        for (String beanName : beanNames) {
+            ExpressToWxService handler = (ExpressToWxService) applicationContext.getBean(beanName);
+            if (handler.support(type)) {
+                handler.setOrderCode(orderCode);
+                return handler;
+            }
+        }
+        throw new IllegalArgumentException(String.format(String.format("对应类型 %d 没有被找到!",type)));
+    }
+}

+ 27 - 0
fs-service/src/main/java/com/fs/wx/order/service/ExpressToWxService.java

@@ -0,0 +1,27 @@
+package com.fs.wx.order.service;
+
+import lombok.Getter;
+
+@Getter
+public abstract class ExpressToWxService {
+
+    private String orderCode;
+
+
+    public void setOrderCode(String orderCode) {
+        this.orderCode = orderCode;
+    }
+
+    public abstract String getTransactionId();
+
+
+    public abstract String getUserPhone();
+
+
+    public abstract String getOrderGoodsInfo();
+
+    public abstract String getExpressCompany();
+    public abstract String getExpressNo();
+
+    public abstract boolean support(Integer type);
+}

+ 20 - 0
fs-service/src/main/java/com/fs/wx/order/service/OrderQueryService.java

@@ -0,0 +1,20 @@
+package com.fs.wx.order.service;
+
+
+import com.fs.wx.order.dto.OrderQueryRequest;
+import com.fs.wx.order.dto.OrderQueryResponse;
+
+public interface OrderQueryService {
+
+    /**
+     * Queries an order using either lowOrderId or upOrderId.
+     *
+     * @param request The request object containing query parameters.
+     *                The 'sign' field will be calculated internally.
+     * @return The order query response.
+     * @throws IllegalArgumentException if required parameters are missing.
+     * @throws RuntimeException if the API call fails or returns an error status.
+     */
+    OrderQueryResponse queryOrder(OrderQueryRequest request);
+
+}

+ 128 - 0
fs-service/src/main/java/com/fs/wx/order/service/ShippingService.java

@@ -0,0 +1,128 @@
+package com.fs.wx.order.service;
+
+import cn.hutool.core.exceptions.ExceptionUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.*;
+import cn.hutool.json.JSONUtil;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fs.wx.order.dto.UploadShippingInfoRequest;
+import com.fs.wx.order.dto.WeChatApiConfig;
+import com.fs.wx.order.dto.WeChatApiResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.web.util.UriComponentsBuilder;
+
+@Slf4j
+@Service
+public class ShippingService {
+
+
+    private final WeChatApiConfig weChatApiConfig;
+
+    public ShippingService(WeChatApiConfig weChatApiConfig) {
+        this.weChatApiConfig = weChatApiConfig;
+    }
+
+    /**
+     * 调用微信 API 上传发货信息 (使用 Hutool HttpUtil)
+     * @param request 发货信息请求体
+     * @return 微信 API 的响应
+     */
+    public WeChatApiResponse uploadShippingInfo(UploadShippingInfoRequest request) {
+        WeChatAuthService weChatAuthService = WeChatAuthFactory.getWeChatAuthService(request.getAppid());
+        String accessToken = weChatAuthService.getAccessToken(false);
+        if (accessToken == null) {
+            log.error("获取微信 Access Token 失败");
+            WeChatApiResponse errorResponse = new WeChatApiResponse();
+            errorResponse.setErrcode(-3); // 自定义错误码,表示获取Token失败
+            errorResponse.setErrmsg("获取微信 Access Token 失败");
+            return errorResponse;
+        }
+
+        String url = UriComponentsBuilder.fromHttpUrl(weChatApiConfig.getUploadShippingInfoUrl())
+                .queryParam("access_token", accessToken)
+                .toUriString();
+
+        log.debug("请求微信上传发货接口 Appid: {} URL: {}", request.getAppid(),url);
+
+        ObjectMapper objectMapper = new ObjectMapper();
+        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+        String requestBodyJson = null;
+        try {
+            requestBodyJson = objectMapper.writeValueAsString(request);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+
+        log.debug("请求体 JSON: {}", requestBodyJson);
+
+
+        HttpResponse httpResponse = null;
+        try {
+            HttpRequest httpRequest = HttpUtil.createPost(url)
+                    .header(Header.CONTENT_TYPE, ContentType.JSON.getValue())
+                    .body(requestBodyJson)
+                    .timeout(10000);
+
+            httpResponse = httpRequest.execute();
+
+            int statusCode = httpResponse.getStatus();
+            String responseBodyString = httpResponse.body();
+
+            log.info("微信接口响应状态: {}", statusCode);
+            log.info("微信接口响应体: {}", responseBodyString);
+
+            if (httpResponse.isOk()) {
+                WeChatApiResponse weChatApiResponse = JSONUtil.toBean(responseBodyString, WeChatApiResponse.class);
+
+                if (!weChatApiResponse.isSuccess()) {
+                    log.warn("微信接口返回业务错误: code={}, message={}", weChatApiResponse.getErrcode(), weChatApiResponse.getErrmsg());
+                    if(ObjectUtil.equal(weChatApiResponse.getErrcode(),40001)) {
+                        log.info("token缓存失效,清除token,等待下次执行...");
+                        weChatAuthService.clearToken();
+                    }
+                }
+                return weChatApiResponse;
+
+            } else {
+                log.error("调用微信接口收到非成功状态码: {}", statusCode);
+                try {
+                    WeChatApiResponse errorResponse = JSONUtil.toBean(responseBodyString, WeChatApiResponse.class);
+                    if (errorResponse.getErrcode() == null) {
+                        errorResponse.setErrcode(statusCode);
+                        errorResponse.setErrmsg("微信接口HTTP错误,状态码: " + statusCode + ", 响应体: " + responseBodyString);
+                    }
+                    return errorResponse;
+                } catch (Exception parseEx) {
+                    log.warn("无法将微信错误响应体解析为JSON: {}", responseBodyString, parseEx);
+                    WeChatApiResponse errorResponse = new WeChatApiResponse();
+                    errorResponse.setErrcode(statusCode);
+                    errorResponse.setErrmsg("调用微信接口失败,状态码: " + statusCode + ", 原始响应体: " + responseBodyString);
+                    return errorResponse;
+                }
+            }
+        } catch (HttpException e) {
+            log.error("调用微信接口发生HTTP异常: {}", e.getMessage(), e);
+            WeChatApiResponse errorResponse = new WeChatApiResponse();
+            errorResponse.setErrcode(-1);
+            String detailedMessage = ExceptionUtil.getMessage(e);
+            errorResponse.setErrmsg("调用微信接口时发生HTTP异常: " + detailedMessage);
+            if (httpResponse != null) {
+                errorResponse.setErrmsg(errorResponse.getErrmsg() + ", HTTP状态码: " + httpResponse.getStatus());
+            }
+            return errorResponse;
+        } catch (Exception e) {
+            log.error("调用微信接口时发生意外错误", e);
+            WeChatApiResponse errorResponse = new WeChatApiResponse();
+            errorResponse.setErrcode(-2);
+            errorResponse.setErrmsg("调用微信接口时发生内部服务器错误: " + e.getMessage());
+            return errorResponse;
+        }finally {
+            if(httpResponse != null) {
+                httpResponse.close();
+            }
+        }
+    }
+}

+ 46 - 0
fs-service/src/main/java/com/fs/wx/order/service/WeChatAuthFactory.java

@@ -0,0 +1,46 @@
+package com.fs.wx.order.service;
+
+import com.fs.pay.domain.PaymentMiniProgramConfig;
+import com.fs.pay.mapper.PaymentMiniProgramConfigMapper;
+import com.fs.wx.order.service.impl.InMemoryWeChatAuthServiceImpl;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.SmartInitializingSingleton;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+//@Component
+public class WeChatAuthFactory  {
+    private static ApplicationContext applicationContext;
+    private final static Map<String,WeChatAuthService> weChatAuthServices = new ConcurrentHashMap<>();
+
+
+    public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
+        WeChatAuthFactory.applicationContext = applicationContext;
+    }
+
+
+    public void afterSingletonsInstantiated() {
+        PaymentMiniProgramConfigMapper mapper = applicationContext.getBean(PaymentMiniProgramConfigMapper.class);
+        List<PaymentMiniProgramConfig> configs = mapper.selectAll();
+        for (PaymentMiniProgramConfig config : configs) {
+            WeChatAuthService weChatAuthService = new InMemoryWeChatAuthServiceImpl(config.getAppid(),config.getAppSecret());
+            weChatAuthServices.put(config.getAppid(),weChatAuthService);
+        }
+    }
+
+    /**
+     * 通过appid获取WeChatAuthService
+     * @param appid 小程序ID
+     * @return WeChatAuthService
+     */
+    public static WeChatAuthService getWeChatAuthService(String appid){
+        return weChatAuthServices.get(appid);
+    }
+
+}

+ 22 - 0
fs-service/src/main/java/com/fs/wx/order/service/WeChatAuthService.java

@@ -0,0 +1,22 @@
+package com.fs.wx.order.service;
+
+public interface WeChatAuthService {
+    void clearToken();
+
+    /**
+     * 获取有效的微信小程序 Access Token
+     * @param forceRefresh 是否强制刷新,忽略缓存
+     * @return Access Token
+     * @throws RuntimeException 如果获取失败
+     */
+    String getAccessToken(boolean forceRefresh);
+
+    /**
+     * 获取有效的微信小程序 Access Token (优先使用缓存)
+     * @return Access Token
+     * @throws RuntimeException 如果获取失败
+     */
+    default String getAccessToken() {
+        return getAccessToken(true);
+    }
+}

+ 114 - 0
fs-service/src/main/java/com/fs/wx/order/service/impl/InMemoryWeChatAuthServiceImpl.java

@@ -0,0 +1,114 @@
+package com.fs.wx.order.service.impl;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.fs.wx.order.service.WeChatAuthService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class InMemoryWeChatAuthServiceImpl implements WeChatAuthService {
+
+    private static final Logger log = LoggerFactory.getLogger(InMemoryWeChatAuthServiceImpl.class);
+    private String cachedToken = null;
+    private long expiryTime = 0; // Token 过期时间戳 (ms)
+
+    private final String appId;
+    private final String appSecret;
+
+    private final String tokenUrlFormat = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
+
+
+    public InMemoryWeChatAuthServiceImpl(String appId, String appSecret) {
+        this.appId = appId;
+        this.appSecret = appSecret;
+    }
+
+    @Override
+    public synchronized void clearToken(){
+        log.info("清除token缓存...");
+        cachedToken = null;
+        expiryTime = 0;
+    }
+
+    @Override
+    public synchronized String getAccessToken(boolean forceRefresh) {
+        long now = System.currentTimeMillis();
+        if (!forceRefresh && cachedToken != null && now < expiryTime) {
+            log.debug("Using cached access token.");
+            return cachedToken;
+        }
+
+        if (StrUtil.hasBlank(appId, appSecret)) {
+            log.error("appId或者appSecret不存在!");
+            throw new RuntimeException("appId或者appSecret不存在!");
+        }
+
+
+        String url = String.format(tokenUrlFormat, appId, appSecret);
+        log.info(url);
+        HttpResponse httpResponse = null;
+        String body = null;
+
+        try {
+            httpResponse = HttpRequest.get(url)
+                    .timeout(5000)
+                    .execute();
+
+            body = httpResponse.body();
+
+            if (!httpResponse.isOk()) {
+                log.error("获取accessToken失败!. Status: {}, Body: {}", httpResponse.getStatus(), body);
+                String errorMsg = parseErrorMsg(body);
+                throw new RuntimeException("获取accessToken失败! Status: " + httpResponse.getStatus() + ", Message: " + errorMsg);
+            }
+
+            if (StrUtil.isBlank(body)) {
+                log.error("获取accessToken失败!.  URL: {}", url);
+                throw new RuntimeException("获取accessToken失败!");
+            }
+
+            JSONObject responseJson = JSONUtil.parseObj(body);
+
+            if (responseJson.containsKey("access_token")) {
+                cachedToken = responseJson.getStr("access_token");
+                if(StrUtil.isBlank(cachedToken)){
+                    log.error("获取accessToken失败!response: {}", body);
+                    throw new RuntimeException("获取accessToken失败!");
+                }
+
+                long expiresInSeconds = responseJson.getLong("expires_in", 7200L);
+                expiryTime = now + (expiresInSeconds - 120) * 1000;
+                log.info("获取accessToken获取成功 {}",cachedToken);
+                return cachedToken;
+            } else {
+                String errorMsg = responseJson.getStr("errmsg", "Unknown error: access_token missing in response");
+                log.error("Failed to fetch access token, 'access_token' key missing. Response: {}", body);
+                throw new RuntimeException("Failed to fetch access token: " + errorMsg);
+            }
+        } catch (Exception e) {
+            cachedToken = null;
+            expiryTime = 0;
+            log.error("Error fetching access token from URL: {}", url, e);
+            throw new RuntimeException("Error fetching access token: " + e.getMessage(), e);
+        }finally {
+            if(httpResponse != null) {
+                httpResponse.close();
+            }
+        }
+    }
+
+    private String parseErrorMsg(String jsonBody) {
+        if (StrUtil.isBlank(jsonBody)) {
+            return "返回为空!";
+        }
+        try {
+            JSONObject json = JSONUtil.parseObj(jsonBody);
+            return json.getStr("errmsg", "Unknown error in response body");
+        } catch (Exception e) {
+            return "返回解析失败!";
+        }
+    }
+}

+ 107 - 0
fs-service/src/main/java/com/fs/wx/order/service/impl/LiveExpressToWxService.java

@@ -0,0 +1,107 @@
+package com.fs.wx.order.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.fs.his.domain.FsStoreOrder;
+import com.fs.his.domain.FsStorePayment;
+import com.fs.his.mapper.FsStoreOrderMapper;
+import com.fs.his.mapper.FsStorePaymentMapper;
+import com.fs.live.domain.LiveOrder;
+import com.fs.live.domain.LiveOrderPayment;
+import com.fs.live.mapper.LiveOrderMapper;
+import com.fs.live.mapper.LiveOrderPaymentMapper;
+import com.fs.live.service.ILiveOrderService;
+import com.fs.wx.order.service.ExpressToWxService;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE;
+
+@Service
+@Scope(value = SCOPE_PROTOTYPE)
+public class LiveExpressToWxService extends ExpressToWxService {
+    @Autowired
+    private LiveOrderMapper liveOrderMapper;
+    @Autowired
+    private LiveOrderPaymentMapper liveOrderPaymentMapper;
+
+    private LiveOrder liveOrder;
+    private LiveOrderPayment liveOrderPayment ;
+
+    @Override
+    public void setOrderCode(String orderCode) {
+        super.setOrderCode(orderCode);
+        this.liveOrder = liveOrderMapper.selectLiveOrderByOrderCode(getOrderCode());
+        if(ObjectUtil.isNull(liveOrder)) {
+            throw new IllegalArgumentException(String.format("该订单 %s 未找到!",getOrderCode()));
+        }
+        LiveOrderPayment fsStorePayments = liveOrderPaymentMapper.selectLiveOrderLatestPayByOrderId(liveOrder.getOrderId());
+        if(fsStorePayments == null){
+            throw new IllegalArgumentException(String.format("该订单 %s 未找到对应支付记录!", getOrderCode()));
+        }
+    }
+
+
+    @Override
+    public String getTransactionId() {
+        return liveOrderPayment.getBankTransactionId();
+    }
+
+    @Override
+    public String getUserPhone() {
+        return liveOrder.getUserPhone();
+    }
+
+    @Override
+    public String getOrderGoodsInfo() {
+        return getOrderGoodsInfo(liveOrder);
+    }
+
+    @Override
+    public String getExpressCompany() {
+
+        return liveOrder.getDeliveryCode();
+    }
+
+    @Override
+    public String getExpressNo() {
+
+        return liveOrder.getDeliverySn();
+    }
+
+    @Override
+    public boolean support(Integer type) {
+        return 1 == type;
+    }
+
+
+    /**
+     * 获取订单商品信息
+     * @return
+     */
+    private String getOrderGoodsInfo(LiveOrder order){
+        StringBuilder title = new StringBuilder();
+        // 如果是套餐
+//        if(ObjectUtil.equal(order.getIsPackage(),1)){
+//            String packageJson = order.getPackageJson();
+//            JSONObject jsonObject = JSON.parseObject(packageJson);
+//            title = new StringBuilder(jsonObject.getString("title"));
+//        } else {
+            String itemJson = order.getItemJson();
+            com.alibaba.fastjson.JSONArray arrays = JSON.parseArray(itemJson);
+            for(int i=0;i<arrays.size();i++){
+                JSONObject jsonObject = arrays.getJSONObject(i);
+                String jsonInfo = jsonObject.getString("jsonInfo");
+                JSONObject jsonObject1 = JSON.parseObject(jsonInfo);
+                String productName = jsonObject1.getString("productName");
+                title.append(productName).append("\n");
+            }
+//        }
+        return title.toString();
+    }
+}

+ 107 - 0
fs-service/src/main/java/com/fs/wx/order/service/impl/ShopExpressToWxService.java

@@ -0,0 +1,107 @@
+package com.fs.wx.order.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.fs.his.domain.FsStoreOrder;
+import com.fs.his.domain.FsStorePayment;
+import com.fs.his.mapper.FsStoreOrderMapper;
+import com.fs.his.mapper.FsStorePaymentMapper;
+import com.fs.hisStore.domain.FsStoreOrderScrm;
+import com.fs.hisStore.domain.FsStorePaymentScrm;
+import com.fs.hisStore.mapper.FsStoreOrderScrmMapper;
+import com.fs.hisStore.mapper.FsStorePaymentScrmMapper;
+import com.fs.wx.order.service.ExpressToWxService;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE;
+
+@Service
+@Scope(value = SCOPE_PROTOTYPE)
+public class ShopExpressToWxService extends ExpressToWxService {
+    @Autowired
+    private FsStoreOrderScrmMapper fsStoreOrderMapper;
+    @Autowired
+    private FsStorePaymentScrmMapper fsStorePaymentMapper;
+
+    private FsStoreOrderScrm fsStoreOrder;
+    private FsStorePaymentScrm fsStorePayment;
+
+    @Override
+    public void setOrderCode(String orderCode) {
+        super.setOrderCode(orderCode);
+        this.fsStoreOrder = fsStoreOrderMapper.selectFsStoreOrderByOrderCode(getOrderCode());
+        if(ObjectUtil.isNull(fsStoreOrder)) {
+            throw new IllegalArgumentException(String.format("该订单 %s 未找到!",getOrderCode()));
+        }
+        List<FsStorePaymentScrm> fsStorePayments = fsStorePaymentMapper.selectFsStorePaymentByOrderId(fsStoreOrder.getId());
+        if(CollectionUtils.isEmpty(fsStorePayments)){
+            throw new IllegalArgumentException(String.format("该订单 %s 未找到对应支付记录!", getOrderCode()));
+        }
+        fsStorePayment = fsStorePayments.get(0);
+    }
+
+
+    @Override
+    public String getTransactionId() {
+        return fsStorePayment.getBankTransactionId();
+    }
+
+    @Override
+    public String getUserPhone() {
+        return fsStoreOrder.getUserPhone();
+    }
+
+    @Override
+    public String getOrderGoodsInfo() {
+        return getOrderGoodsInfo(fsStoreOrder);
+    }
+
+    @Override
+    public String getExpressCompany() {
+
+        return fsStoreOrder.getDeliveryCode();
+    }
+
+    @Override
+    public String getExpressNo() {
+
+        return fsStoreOrder.getDeliverySn();
+    }
+
+    @Override
+    public boolean support(Integer type) {
+        return 0 == type;
+    }
+
+
+    /**
+     * 获取订单商品信息
+     * @return
+     */
+    private String getOrderGoodsInfo(FsStoreOrderScrm order){
+        StringBuilder title = new StringBuilder();
+        // 如果是套餐
+//        if(ObjectUtil.equal(order.getIsPackage(),1)){
+//            String packageJson = order.getPackageJson();
+//            JSONObject jsonObject = JSON.parseObject(packageJson);
+//            title = new StringBuilder(jsonObject.getString("title"));
+//        } else {
+            String itemJson = order.getItemJson();
+            com.alibaba.fastjson.JSONArray arrays = JSON.parseArray(itemJson);
+            for(int i=0;i<arrays.size();i++){
+                JSONObject jsonObject = arrays.getJSONObject(i);
+                String jsonInfo = jsonObject.getString("jsonInfo");
+                JSONObject jsonObject1 = JSON.parseObject(jsonInfo);
+                String productName = jsonObject1.getString("productName");
+                title.append(productName).append("\n");
+            }
+//        }
+        return title.toString();
+    }
+}

+ 5 - 0
fs-service/src/main/resources/application-common.yml

@@ -138,3 +138,8 @@ image:
   storage:
     local-path: C:\logoFile\logo.jpg
     server-path: C:\logoFile\logo.jpg
+# application.properties
+wechat:
+  api:
+    base-url: https://api.weixin.qq.com
+    upload-shipping-info: /wxa/sec/order/upload_shipping_info

+ 127 - 0
fs-service/src/main/resources/mapper/his/FsIntegralOrderDfMapper.xml

@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.his.mapper.FsIntegralOrderDfMapper">
+
+    <resultMap type="FsIntegralOrderDf" id="FsIntegralOrderDfResult">
+        <result property="orderId"    column="order_id"    />
+        <result property="orderCode"    column="order_code"    />
+        <result property="appKey"    column="app_key"    />
+        <result property="appSecret"    column="app_secret"    />
+        <result property="loginAccount"    column="login_account"    />
+        <result property="monthlyCard"    column="monthly_card"    />
+        <result property="expressProductCode"    column="express_product_code"    />
+        <result property="totalPrice"    column="total_price"    />
+        <result property="platformPrice"    column="platform_price"    />
+        <result property="status"    column="status"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="failMsg"    column="fail_msg"    />
+        <result property="parcelQuantity"    column="parcel_quantity"    />
+        <result property="erpPhone"    column="erp_phone"    />
+        <result property="isPush"    column="is_push"    />
+    </resultMap>
+
+    <sql id="selectFsIntegralOrderDfVo">
+        select order_id, order_code, app_key, app_secret, login_account, monthly_card, express_product_code, total_price, platform_price, status, create_time, update_time, fail_msg, parcel_quantity, is_push from fs_integral_order_df
+    </sql>
+
+    <select id="selectFsIntegralOrderDfList" parameterType="FsIntegralOrderDf" resultMap="FsIntegralOrderDfResult">
+        <include refid="selectFsIntegralOrderDfVo"/>
+        <where>
+            <if test="orderCode != null  and orderCode != ''"> and order_code = #{orderCode}</if>
+            <if test="appKey != null  and appKey != ''"> and app_key = #{appKey}</if>
+            <if test="appSecret != null  and appSecret != ''"> and app_secret = #{appSecret}</if>
+            <if test="loginAccount != null  and loginAccount != ''"> and login_account = #{loginAccount}</if>
+            <if test="monthlyCard != null  and monthlyCard != ''"> and monthly_card = #{monthlyCard}</if>
+            <if test="expressProductCode != null  and expressProductCode != ''"> and express_product_code = #{expressProductCode}</if>
+            <if test="totalPrice != null "> and total_price = #{totalPrice}</if>
+            <if test="platformPrice != null "> and platform_price = #{platformPrice}</if>
+            <if test="status != null "> and status = #{status}</if>
+            <if test="failMsg != null  and failMsg != ''"> and fail_msg = #{failMsg}</if>
+            <if test="parcelQuantity != null "> and parcel_quantity = #{parcelQuantity}</if>
+        </where>
+    </select>
+
+    <select id="selectFsIntegralOrderDfByOrderId" parameterType="Long" resultMap="FsIntegralOrderDfResult">
+        <include refid="selectFsIntegralOrderDfVo"/>
+        where order_id = #{orderId}
+    </select>
+    <select id="selectByIsPush" resultType="com.fs.his.domain.FsIntegralOrderDf">
+        SELECT fiod.*
+        FROM fs_integral_order_df fiod
+                 INNER JOIN fs_integral_order fio ON fio.order_id = fiod.order_id
+        WHERE fiod.is_push = 1
+          AND fio.delivery_sn IS NULL
+    </select>
+
+    <insert id="insertFsIntegralOrderDf" parameterType="FsIntegralOrderDf">
+        insert into fs_integral_order_df
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="orderId != null">order_id,</if>
+            <if test="orderCode != null">order_code,</if>
+            <if test="appKey != null and appKey != ''">app_key,</if>
+            <if test="appSecret != null and appSecret != ''">app_secret,</if>
+            <if test="loginAccount != null and loginAccount != ''">login_account,</if>
+            <if test="monthlyCard != null and monthlyCard != ''">monthly_card,</if>
+            <if test="expressProductCode != null">express_product_code,</if>
+            <if test="totalPrice != null">total_price,</if>
+            <if test="platformPrice != null">platform_price,</if>
+            <if test="status != null">status,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="failMsg != null">fail_msg,</if>
+            <if test="parcelQuantity != null">parcel_quantity,</if>
+            <if test="erpPhone != null">erp_phone,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="orderId != null">#{orderId},</if>
+            <if test="orderCode != null">#{orderCode},</if>
+            <if test="appKey != null and appKey != ''">#{appKey},</if>
+            <if test="appSecret != null and appSecret != ''">#{appSecret},</if>
+            <if test="loginAccount != null and loginAccount != ''">#{loginAccount},</if>
+            <if test="monthlyCard != null and monthlyCard != ''">#{monthlyCard},</if>
+            <if test="expressProductCode != null">#{expressProductCode},</if>
+            <if test="totalPrice != null">#{totalPrice},</if>
+            <if test="platformPrice != null">#{platformPrice},</if>
+            <if test="status != null">#{status},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="failMsg != null">#{failMsg},</if>
+            <if test="parcelQuantity != null">#{parcelQuantity},</if>
+            <if test="erpPhone != null">#{erpPhone},</if>
+        </trim>
+    </insert>
+
+    <update id="updateFsIntegralOrderDf" parameterType="FsIntegralOrderDf">
+        update fs_integral_order_df
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="orderCode != null">order_code = #{orderCode},</if>
+            <if test="appKey != null and appKey != ''">app_key = #{appKey},</if>
+            <if test="appSecret != null and appSecret != ''">app_secret = #{appSecret},</if>
+            <if test="loginAccount != null and loginAccount != ''">login_account = #{loginAccount},</if>
+            <if test="monthlyCard != null and monthlyCard != ''">monthly_card = #{monthlyCard},</if>
+            <if test="expressProductCode != null">express_product_code = #{expressProductCode},</if>
+            <if test="totalPrice != null">total_price = #{totalPrice},</if>
+            <if test="platformPrice != null">platform_price = #{platformPrice},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="failMsg != null">fail_msg = #{failMsg},</if>
+            <if test="parcelQuantity != null">parcel_quantity = #{parcelQuantity},</if>
+        </trim>
+        where order_id = #{orderId}
+    </update>
+
+    <delete id="deleteFsIntegralOrderDfByOrderId" parameterType="Long">
+        delete from fs_integral_order_df where order_id = #{orderId}
+    </delete>
+
+    <delete id="deleteFsIntegralOrderDfByOrderIds" parameterType="String">
+        delete from fs_integral_order_df where order_id in
+        <foreach item="orderId" collection="array" open="(" separator="," close=")">
+            #{orderId}
+        </foreach>
+    </delete>
+</mapper>

+ 76 - 0
fs-service/src/main/resources/mapper/his/FsIntegralOrderLogsMapper.xml

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.his.mapper.FsIntegralOrderLogsMapper">
+
+    <resultMap type="FsIntegralOrderLogs" id="FsIntegralOrderLogsResult">
+        <result property="logsId"    column="logs_id"    />
+        <result property="orderId"    column="order_id"    />
+        <result property="changeType"    column="change_type"    />
+        <result property="changeMessage"    column="change_message"    />
+        <result property="changeTime"    column="change_time"    />
+        <result property="operator"    column="operator"    />
+    </resultMap>
+
+    <sql id="selectFsIntegralOrderLogsVo">
+        select logs_id, order_id, change_type, change_message, change_time, operator from fs_integral_order_logs
+    </sql>
+
+    <select id="selectFsIntegralOrderLogsList" parameterType="FsIntegralOrderLogs" resultMap="FsIntegralOrderLogsResult">
+        <include refid="selectFsIntegralOrderLogsVo"/>
+        <where>
+            <if test="orderId != null  and orderId != ''"> and order_id = #{orderId}</if>
+            <if test="changeType != null  and changeType != ''"> and change_type = #{changeType}</if>
+            <if test="changeMessage != null  and changeMessage != ''"> and change_message = #{changeMessage}</if>
+            <if test="changeTime != null "> and change_time = #{changeTime}</if>
+            <if test="operator != null  and operator != ''"> and operator = #{operator}</if>
+        </where>
+    </select>
+
+    <select id="selectFsIntegralOrderLogsByLogsId" parameterType="String" resultMap="FsIntegralOrderLogsResult">
+        <include refid="selectFsIntegralOrderLogsVo"/>
+        where logs_id = #{logsId}
+    </select>
+
+    <insert id="insertFsIntegralOrderLogs" parameterType="FsIntegralOrderLogs" useGeneratedKeys="true" keyProperty="logsId">
+        insert into fs_integral_order_logs
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="orderId != null and orderId != ''">order_id,</if>
+            <if test="changeType != null and changeType != ''">change_type,</if>
+            <if test="changeMessage != null and changeMessage != ''">change_message,</if>
+            <if test="changeTime != null">change_time,</if>
+            <if test="operator != null">operator,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="orderId != null and orderId != ''">#{orderId},</if>
+            <if test="changeType != null and changeType != ''">#{changeType},</if>
+            <if test="changeMessage != null and changeMessage != ''">#{changeMessage},</if>
+            <if test="changeTime != null">#{changeTime},</if>
+            <if test="operator != null">#{operator},</if>
+        </trim>
+    </insert>
+
+    <update id="updateFsIntegralOrderLogs" parameterType="FsIntegralOrderLogs">
+        update fs_integral_order_logs
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="orderId != null and orderId != ''">order_id = #{orderId},</if>
+            <if test="changeType != null and changeType != ''">change_type = #{changeType},</if>
+            <if test="changeMessage != null and changeMessage != ''">change_message = #{changeMessage},</if>
+            <if test="changeTime != null">change_time = #{changeTime},</if>
+            <if test="operator != null">operator = #{operator},</if>
+        </trim>
+        where logs_id = #{logsId}
+    </update>
+
+    <delete id="deleteFsIntegralOrderLogsByLogsId" parameterType="String">
+        delete from fs_integral_order_logs where logs_id = #{logsId}
+    </delete>
+
+    <delete id="deleteFsIntegralOrderLogsByLogsIds" parameterType="String">
+        delete from fs_integral_order_logs where logs_id in
+        <foreach item="logsId" collection="array" open="(" separator="," close=")">
+            #{logsId}
+        </foreach>
+    </delete>
+</mapper>

+ 38 - 1
fs-service/src/main/resources/mapper/his/FsUserMapper.xml

@@ -48,11 +48,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="courseMaOpenId"    column="course_ma_open_id"    />
         <result property="qwExtId"    column="qw_ext_id"    />
         <result property="qwUserId"    column="qw_user_id"    />
+        <result property="appId"    column="app_id"    />
         <result property="level" column="level"/>
     </resultMap>
 
     <sql id="selectFsUserVo">
-        select user_id,qw_ext_id,sex,is_buy,`level`,course_ma_open_id,is_push,is_add_qw,source,login_device,is_individuation_push,store_open_id,password,jpush_id, is_vip,vip_start_date,vip_end_date,vip_level,vip_status,nick_name,integral_status, avatar, phone, integral,sign_num, status, tui_user_id, tui_time, tui_user_count, ma_open_id, mp_open_id, union_id, is_del, user_code, remark, create_time, update_time, last_ip, balance,is_weixin_auth,parent_id,qw_user_id,company_id,company_user_id from fs_user
+        select user_id,qw_ext_id,sex,is_buy,`level`,course_ma_open_id,is_push,is_add_qw,source,login_device,is_individuation_push,store_open_id,password,jpush_id, is_vip,vip_start_date,vip_end_date,vip_level,vip_status,nick_name,integral_status, avatar, phone, integral,sign_num, status, tui_user_id, tui_time, tui_user_count, ma_open_id, mp_open_id, union_id, is_del, user_code, remark, create_time, update_time, last_ip, balance,is_weixin_auth,parent_id,qw_user_id,app_id,company_id,company_user_id,is_promoter,now_money,brokerage_price,spread_user_id, spread_time,pay_count, spread_count,user_type from fs_user
     </sql>
 
     <select id="selectFsUserList" parameterType="FsUser" resultMap="FsUserResult">
@@ -75,6 +76,25 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="userCode != null  and userCode != ''"> and user_code = #{userCode}</if>
             <if test="lastIp != null  and lastIp != ''"> and last_ip = #{lastIp}</if>
             <if test="balance != null "> and balance = #{balance}</if>
+            <if test="level != null ">and level = #{level}</if>
+            <if test="spreadUserId != null ">and spread_user_id = #{spreadUserId}</if>
+            <if test="spreadTime != null ">and spread_time = #{spreadTime}</if>
+            <if test="userType != null  and userType != ''">and user_type = #{userType}</if>
+            <if test="isPromoter != null ">and is_promoter = #{isPromoter}</if>
+            <if test="payCount != null ">and pay_count = #{payCount}</if>
+            <if test="spreadCount != null ">and spread_count = #{spreadCount}</if>
+            <if test="addres != null  and addres != ''">and addres = #{addres}</if>
+            <if test="companyId != null ">and company_id = #{companyId}</if>
+            <if test="companyUserId != null ">and company_user_id = #{companyUserId}</if>
+            <if test="registerDate != null ">and DATE_FORMAT(register_date,'%Y-%m-%d') =
+                DATE_FORMAT(#{registerDate},'%Y-%m-%d')
+            </if>
+            <if test="registerCode != null   and registerCode != '' ">and register_code = #{registerCode}</if>
+            <if test="source != null  and source != '' ">and source = #{source}</if>
+            <if test="isShow != null  ">and is_show = #{isShow}</if>
+            <!--<if test="qwRepeat != null  ">and qw_repeat = #{qwRepeat}</if>
+            <if test="userRepeat != null  ">and user_repeat = #{userRepeat}</if>-->
+<!--            <if test="payOrder != null  ">and pay_order = #{payOrder}</if>-->
         </where>
     </select>
 
@@ -575,6 +595,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="companyId != null">company_id,</if>
             <if test="companyUserId != null">company_user_id,</if>
             <if test="level != null">`level`,</if>
+            <if test="spreadUserId != null">spread_user_id,</if>
+            <if test="spreadTime != null">spread_time,</if>
+            <if test="isPromoter != null">is_promoter,</if>
+            <if test="payCount != null">pay_count,</if>
+            <if test="spreadCount != null">spread_count,</if>
+            <if test="appId != null">app_id,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="nickName != null">#{nickName},</if>
@@ -619,6 +645,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="companyId != null">#{companyId},</if>
             <if test="companyUserId != null">#{companyUserId},</if>
             <if test="level != null">#{level},</if>
+            <if test="spreadUserId != null">#{spreadUserId},</if>
+            <if test="spreadTime != null">#{spreadTime},</if>
+            <if test="isPromoter != null">#{isPromoter},</if>
+            <if test="payCount != null">#{payCount},</if>
+            <if test="spreadCount != null">#{spreadCount},</if>
+            <if test="appId != null">#{appId},</if>
          </trim>
     </insert>
 
@@ -666,9 +698,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="courseMaOpenId != null">course_ma_open_id = #{courseMaOpenId},</if>
             <if test="parentId != null">parent_id = #{parentId},</if>
             <if test="qwExtId != null">qw_ext_id = #{qwExtId},</if>
+            <if test="isPromoter != null">is_promoter = #{isPromoter},</if>
             <if test="companyId != null">company_id = #{companyId},</if>
             <if test="orderCount != null">order_count = #{orderCount},</if>
             <if test="companyUserId != null">company_user_id = #{companyUserId},</if>
+            <if test="appId != null">app_id = #{appId},</if>
         </trim>
         where user_id = #{userId}
     </update>
@@ -2353,5 +2387,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </where>
     </select>
 
+    <select id="selectFsUserListByPhone" resultType="com.fs.his.domain.FsUser">
+        select * from fs_user where phone=#{phone}
+    </select>
 
 </mapper>

+ 193 - 7
fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml

@@ -985,7 +985,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </foreach>
     </select>
     <select id="selectFsStoreOrderListVOByErpAccount" resultType="com.fs.hisStore.vo.FsStoreOrderVO">
-        select o.*,u.phone,u.register_code,u.register_date,u.source, c.company_name ,cu.nick_name as company_user_nick_name ,cu.phonenumber as company_usere_phonenumber,,df.login_account as erp_account,
+        select o.*,u.phone,u.register_code,u.register_date,u.source, c.company_name ,cu.nick_name as company_user_nick_name ,cu.phonenumber as company_usere_phonenumber,df.login_account as erp_account,
+        sp_latest.bank_transaction_id as bankTransactionId
         from fs_store_order_scrm o
             left join fs_user u on o.user_id=u.user_id
             left join company c on c.company_id=o.company_id
@@ -1000,6 +1001,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         sp.*,
         ROW_NUMBER() OVER (PARTITION BY sp.business_code ORDER BY sp.create_time DESC) as rn
         FROM fs_store_payment_scrm sp
+        WHERE sp.business_code IS NOT NULL
         ) sp_latest ON sp_latest.business_code = o.order_code AND sp_latest.rn = 1
         LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id
         <where>
@@ -1015,6 +1017,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.orderCode != null and  maps.orderCode !=''">
                 and o.order_code like CONCAT('%',#{maps.orderCode},'%')
             </if>
+            <if test="maps.bankTransactionId != null and  maps.bankTransactionId !=''">
+                and sp_latest.bank_transaction_id like CONCAT('%',#{maps.bankTransactionId},'%')
+            </if>
             <if test="maps.isPayRemain != null">
                 and o.is_pay_remain =#{maps.isPayRemain}
             </if>
@@ -1181,6 +1186,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.orderCode != null and  maps.orderCode !=''">
                 and o.order_code like CONCAT('%',#{maps.orderCode},'%')
             </if>
+            <if test="maps.bankTransactionId != null and  maps.bankTransactionId !=''">
+                and sp_latest.bank_transaction_id like CONCAT('%',#{maps.bankTransactionId},'%')
+            </if>
             <if test="maps.isPayRemain != null">
                 and o.is_pay_remain =#{maps.isPayRemain}
             </if>
@@ -1324,6 +1332,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.orderCode != null and  maps.orderCode !=''">
                 and o.order_code like CONCAT('%',#{maps.orderCode},'%')
             </if>
+            <if test="maps.bankTransactionId != null and  maps.bankTransactionId !=''">
+                and sp_latest.bank_transaction_id like CONCAT('%',#{maps.bankTransactionId},'%')
+            </if>
             <if test="maps.isPayRemain != null">
                 and o.is_pay_remain =#{maps.isPayRemain}
             </if>
@@ -1468,6 +1479,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.orderCode != null and  maps.orderCode !=''">
                 and o.order_code like CONCAT('%',#{maps.orderCode},'%')
             </if>
+            <if test="maps.bankTransactionId != null and  maps.bankTransactionId !=''">
+                and sp_latest.bank_transaction_id like CONCAT('%',#{maps.bankTransactionId},'%')
+            </if>
             <if test="maps.isPayRemain != null">
                 and o.is_pay_remain =#{maps.isPayRemain}
             </if>
@@ -1572,9 +1586,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         ${maps.params.dataScope} GROUP BY sp.product_id
         ) AS t
     </select>
+<!--    商城订单查询接口-->
     <select id="selectFsStoreOrderListVO" resultType="com.fs.hisStore.vo.FsStoreOrderVO">
-        select o.*,u.phone,u.register_code,u.register_date,u.source, c.company_name ,cu.nick_name as company_user_nick_name ,cu.phonenumber as company_usere_phonenumber
-        , csc.name miniProgramName
+        select o.id,o.order_code,o.extend_order_id,o.pay_order_id,o.bank_order_id,o.user_id,o.real_name,o.user_phone,o.user_address,o.cart_id,o.freight_price,o.total_num,o.total_price,o.total_postage,o.pay_price,o.pay_postage,o.pay_delivery,o.pay_money,o.deduction_price,o.coupon_id,o.coupon_price,o.paid,o.pay_time,o.pay_type,o.create_time,o.update_time,o.status,o.refund_status,o.refund_reason_wap_img,o.refund_reason_wap_explain,o.refund_reason_time,o.refund_reason_wap,o.refund_reason,o.refund_price,o.delivery_sn,o.delivery_name,o.delivery_type,o.delivery_id,o.gain_integral,o.use_integral,o.pay_integral,o.back_integral,o.mark,o.is_del,o.remark,o.verify_code,o.store_id,o.shipping_type,o.is_channel,o.is_remind,o.is_sys_del,o.is_prescribe,o.prescribe_id,o.company_id,o.company_user_id,o.is_package,o.package_json,o.order_type,o.package_id,o.finish_time,o.delivery_status,o.delivery_pay_status,o.delivery_time,o.delivery_pay_time,o.delivery_pay_money,o.tui_money,o.tui_money_status,o.delivery_import_time,o.tui_user_id,o.tui_user_money_status,o.order_create_type,o.store_house_code,o.dept_id,o.is_edit_money,o.customer_id,o.is_pay_remain,o.delivery_send_time,o.certificates,o.upload_time,o.item_json,o.schedule_id,o.delivery_pay_type,o.order_visit,o.service_fee,o.cycle,o.prescribe_price,o.follow_doctor_id,o.follow_time,o.user_coupon_id,o.order_medium,o.erp_phone
+        ,u.phone,u.register_code,u.register_date,u.source, c.company_name ,cu.nick_name as company_user_nick_name ,cu.phonenumber as company_usere_phonenumber
+        , csc.name miniProgramName,fsp.cost, fspc.cate_name,spavs.bar_code, sp_latest.bank_transaction_id as bankTransactionId
         from fs_store_order_scrm o
         left join fs_user u on o.user_id=u.user_id
         left join company c on c.company_id=o.company_id
@@ -1583,10 +1599,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             LEFT JOIN fs_store_order_df df on df.order_id=o.id
 
         </if>
-        <if test = "maps.productName != null and  maps.productName !=  '' ">
-            left join fs_store_order_item_scrm oi on o.id = oi.order_id
-            left join fs_store_product_scrm fsp on fsp.product_id = oi.product_id
-        </if>
+        left join fs_store_order_item_scrm oi on o.id = oi.order_id
+        left join fs_store_product_scrm fsp on fsp.product_id = oi.product_id
+        left join fs_store_product_category_scrm fspc on fspc.cate_id = fsp.cate_id
+        left join fs_store_product_attr_value_scrm spavs on fsp.product_id = spavs.product_id
+
         LEFT JOIN (
         SELECT
         sp.*,
@@ -1608,6 +1625,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.orderCode != null and  maps.orderCode !=''">
                 and o.order_code like CONCAT('%',#{maps.orderCode},'%')
             </if>
+            <if test="maps.bankTransactionId != null and  maps.bankTransactionId !=''">
+                and sp_latest.bank_transaction_id like CONCAT('%',#{maps.bankTransactionId},'%')
+            </if>
             <if test="maps.isPayRemain != null">
                 and o.is_pay_remain =#{maps.isPayRemain}
             </if>
@@ -1763,6 +1783,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.orderCode != null and  maps.orderCode !=''">
                 and o.order_code like CONCAT('%',#{maps.orderCode},'%')
             </if>
+            <if test="maps.bankTransactionId != null and  maps.bankTransactionId !=''">
+                and sp_latest.bank_transaction_id like CONCAT('%',#{maps.bankTransactionId},'%')
+            </if>
             <if test="maps.isPayRemain != null">
                 and o.is_pay_remain =#{maps.isPayRemain}
             </if>
@@ -1896,4 +1919,167 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             AND company_user_id = #{companyUserId}
         </if>
     </select>
+
+    <select id="getDeliveryNote" resultType="com.fs.hisStore.vo.FsStoreOrderDeliveryNoteExportVO">
+        SELECT
+        CONCAT('AC', o.id) AS orderNumber,
+        o.real_name AS recipient,
+        o.user_phone AS recipientPhone,
+        o.user_address AS recipientAddress,
+        GROUP_CONCAT(
+        DISTINCT IFNULL(
+        CASE WHEN LENGTH(sps.product_name) > 0
+        THEN CONCAT(sps.product_name, '*', sois.num)
+        END, ''
+        )
+        SEPARATOR '+'
+        ) AS nameAndNumber,
+        sps.keyword
+        FROM
+        fs_store_order_scrm o
+        LEFT JOIN fs_store_order_item_scrm sois
+        ON sois.order_id = o.id
+        LEFT JOIN fs_store_product_scrm sps
+        ON sps.product_id = sois.product_id
+        LEFT JOIN fs_user u
+        ON o.user_id = u.user_id
+        LEFT JOIN company c
+        ON c.company_id = o.company_id
+        LEFT JOIN company_user cu
+        ON cu.user_id = o.company_user_id
+        LEFT JOIN (
+        SELECT DISTINCT order_id
+        FROM fs_store_payment_scrm
+        WHERE is_pay_remain != 0 AND STATUS != 0
+        ) fp
+        ON o.id = fp.order_id
+        WHERE
+        o.is_del = 0 and
+        1 = 1
+        <if test="maps.orderCode != null and maps.orderCode != ''">
+            AND o.order_code LIKE CONCAT('%', #{maps.orderCode}, '%')
+        </if>
+        <if test="maps.userId != null">
+            AND o.user_id = #{maps.userId}
+        </if>
+        <if test="maps.deliveryId != null and maps.deliveryId != ''">
+            AND o.delivery_id = #{maps.deliveryId}
+        </if>
+        <if test="maps.nickname != null and maps.nickname != ''">
+            AND u.nickname LIKE CONCAT('%', #{maps.nickname}, '%')
+        </if>
+        <if test="maps.realName != null and maps.realName != ''">
+            AND o.real_name LIKE CONCAT('%', #{maps.realName}, '%')
+        </if>
+        <if test="maps.phone != null and maps.phone != ''">
+            AND u.phone LIKE CONCAT('%', #{maps.phone}, '%')
+        </if>
+        <if test="maps.userPhone != null and maps.userPhone != ''">
+            AND o.user_phone LIKE CONCAT('%', #{maps.userPhone}, '%')
+        </if>
+        <if test="maps.status == null">
+            AND o.status = 1
+        </if>
+        <if test="maps.status != null">
+            AND o.status = #{maps.status}
+        </if>
+        <if test="maps.deliveryStatus != null">
+            AND o.delivery_status = #{maps.deliveryStatus}
+        </if>
+        <if test="maps.deliveryPayStatus != null">
+            AND o.delivery_pay_status = #{maps.deliveryPayStatus}
+        </if>
+        <if test="maps.companyId != null">
+            AND o.company_id = #{maps.companyId}
+        </if>
+        <if test="maps.isHealth != null and maps.isHealth != ''">
+            AND o.company_id IS NULL
+        </if>
+        <if test="maps.notHealth != null and maps.notHealth != ''">
+            AND o.company_id IS NOT NULL
+        </if>
+        <if test="maps.companyUserId != null">
+            AND o.company_user_id = #{maps.companyUserId}
+        </if>
+        <if test="maps.companyUserNickName != null and maps.companyUserNickName != ''">
+            AND cu.nick_name LIKE CONCAT('%', #{maps.companyUserNickName}, '%')
+        </if>
+        <if test="maps.orderType != null">
+            AND o.order_type = #{maps.orderType}
+        </if>
+        <if test="maps.payType != null">
+            AND o.pay_type = #{maps.payType}
+        </if>
+        <if test="maps.createTimeList != null">
+            AND o.create_time >= STR_TO_DATE(#{maps.createTimeList[0]}, '%Y%m%d')
+            AND o.create_time &lt; DATE_ADD(STR_TO_DATE(#{maps.createTimeList[1]}, '%Y%m%d'), INTERVAL 1 DAY)
+        </if>
+        <if test="maps.payTimeList != null">
+            AND o.pay_time >= STR_TO_DATE(#{maps.payTimeList[0]}, '%Y%m%d')
+            AND o.pay_time &lt; DATE_ADD(STR_TO_DATE(#{maps.payTimeList[1]}, '%Y%m%d'), INTERVAL 1 DAY)
+        </if>
+        <if test="maps.deliverySendTimeList != null">
+            AND o.delivery_send_time >= STR_TO_DATE(#{maps.deliverySendTimeList[0]}, '%Y%m%d')
+            AND o.delivery_send_time &lt; DATE_ADD(STR_TO_DATE(#{maps.deliverySendTimeList[1]}, '%Y%m%d'), INTERVAL 1 DAY)
+        </if>
+        <if test="maps.deliveryImportTimeList != null">
+            AND o.delivery_import_time >= STR_TO_DATE(#{maps.deliveryImportTimeList[0]}, '%Y%m%d')
+            AND o.delivery_import_time &lt; DATE_ADD(STR_TO_DATE(#{maps.deliveryImportTimeList[1]}, '%Y%m%d'), INTERVAL 1 DAY)
+        </if>
+        <if test="maps.deptId != null">
+            AND (o.dept_id = #{maps.deptId}
+            OR o.dept_id IN (SELECT t.dept_id FROM company_dept t WHERE FIND_IN_SET(#{maps.deptId}, t.ancestors)))
+        </if>
+        <if test="maps.isUpload != null and maps.isUpload == 0">
+            AND o.certificates IS NULL
+        </if>
+        <if test="maps.scheduleId != null">
+            AND o.schedule_id = #{maps.scheduleId}
+        </if>
+        <if test="maps.isUpload != null and maps.isUpload == 1">
+            AND o.certificates IS NOT NULL
+        </if>
+        ${maps.params.dataScope}
+        AND o.paid = 1
+        GROUP BY o.id
+        LIMIT 10000;
+    </select>
+
+    <select id="selectOrderCodeOpenIdInOrderCode" resultType="com.fs.hisStore.vo.FsStoreOrderCodeOpenIdVo">
+        SELECT
+        os.id,
+        fu.phone,
+        fu.ma_open_id openId,
+        ois.json_info,
+        sps.bank_transaction_id outTransId
+        FROM
+        fs_store_order_scrm os
+        INNER JOIN fs_user fu ON os.user_id = fu.user_id
+        INNER JOIN fs_store_order_item_scrm ois ON ois.order_id = os.id
+        INNER JOIN fs_store_payment_scrm sps ON os.id=sps.order_id
+        WHERE os.is_del = 0 and os.id IN <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
+        #{item}
+    </foreach>
+        AND  sps.`status` = 1
+    </select>
+
+    <select id="getUnsettledOrder" resultType="com.fs.hisStore.domain.FsStoreOrderScrm">
+        SELECT
+            sos.*,
+            sps.bank_transaction_id
+        FROM
+            fs_store_order_scrm sos
+                INNER JOIN fs_store_payment_scrm sps ON sos.id = sps.order_id
+        WHERE
+            sos.is_del = 0 and
+            sos.paid = 1
+          AND sps.business_type = 2
+          AND sos.`status` = 2
+          AND sps.`status`=1
+          AND DATEDIFF(
+                      NOW(),
+                      sos.delivery_send_time
+              ) >= 3
+    </select>
+
 </mapper>

+ 2 - 1
fs-service/src/main/resources/mapper/live/LiveAfterSalesMapper.xml

@@ -66,11 +66,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         select las.id, las.live_id, las.store_id, las.order_id, las.refund_amount,
         las.refund_type, las.reasons, las.explains, las.explain_img, las.delivery_code, las.delivery_sn, las.delivery_name, las.status, las.sales_status,
         las.order_status, las.create_time, las.is_del, las.user_id, las.consignee, las.phone_number, las.address, las.company_id, las.company_user_id, las.dept_id,
-        cu.nick_name as company_user_nick_name, c.company_name,lo.order_code,lo.user_phone,las.user_id
+        cu.nick_name as company_user_nick_name, c.company_name,lo.order_id,lo.order_code,lo.user_phone,las.user_id,lo.item_json,lo.pay_time as orderPayTime,lo.user_address,lo.user_name,lo.pay_price,lo.total_postage,lop.bank_serial_no
         from live_after_sales las
         left join live_order lo on lo.order_id = las.order_id
         left join company_user cu on cu.user_id = las.company_user_id
         left join company c on c.company_id = cu.company_id
+        left join live_order_payment lop on lop.business_id = lo.order_id and lop.status in (1,-1)
 
         <where>
             <if test="liveId != null and liveId != ''"> and las.live_id = #{liveId}</if>

+ 195 - 0
fs-service/src/main/resources/mapper/pay/PaymentMiniProgramConfigMapper.xml

@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.pay.mapper.PaymentMiniProgramConfigMapper">
+
+    <resultMap type="PaymentMiniProgramConfig" id="PaymentMiniProgramConfigResult">
+        <result property="id"    column="id"    />
+        <result property="payType"    column="pay_type"    />
+        <result property="appName"    column="appname"    />
+        <result property="appid"    column="appid"    />
+        <result property="appSecret"    column="appsecret"    />
+        <result property="ybMerchantNo"    column="yb_merchant_no"    />
+        <result property="ybKey"    column="yb_key"    />
+        <result property="ybNotifyUrl"    column="yb_notify_url"    />
+        <result property="tzhMerchantNo"    column="tzh_merchant_no"    />
+        <result property="tzhAppsecret"    column="tzh_appsecret"    />
+        <result property="tzhPrivateKey"    column="tzh_private_key"    />
+        <result property="tzhPublicKey"    column="tzh_public_key"    />
+        <result property="tzhAppkey"    column="tzh_appkey"    />
+        <result property="tzhPayNotifyUrl"    column="tzh_pay_notify_url"    />
+        <result property="tzhRefundNotifyUrl"    column="tzh_refund_notify_url"    />
+        <result property="tzhSplitNotifyUrl"    column="tzh_split_notify_url"    />
+        <result property="wxMerchantNo"    column="wx_merchant_no"    />
+        <result property="wxKey"    column="wx_key"    />
+        <result property="hfProductNo"    column="hf_product_no"    />
+        <result property="hfSystemNo"    column="hf_system_no"    />
+        <result property="hfMerchantNo"    column="hf_merchant_no"    />
+        <result property="hfPrivateKey"    column="hf_private_key"    />
+        <result property="hfPublicKey"    column="hf_public_key"    />
+        <result property="hfPayNotifyUrl"    column="hf_pay_notify_url"    />
+        <result property="hfLargePayNotifyUrl"    column="hf_large_pay_notify_url"    />
+        <result property="hfRefundNotifyUrl"    column="hf_refund_notify_url"    />
+        <result property="hfLargeRefundNotifyUrl"    column="hf_large_refund_notify_url"    />
+        <result property="status"    column="status"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+    </resultMap>
+
+    <sql id="selectPaymentMiniProgramConfigVo">
+        select id, pay_type, appid,appname,appsecret, yb_merchant_no, yb_key, yb_notify_url, tzh_merchant_no, tzh_appsecret, tzh_private_key, tzh_public_key, tzh_appkey, tzh_pay_notify_url, tzh_refund_notify_url, tzh_split_notify_url, wx_merchant_no, wx_key, hf_product_no, hf_system_no, hf_merchant_no, hf_private_key, hf_public_key, hf_pay_notify_url, hf_large_pay_notify_url, hf_refund_notify_url, hf_large_refund_notify_url, status, create_time, update_time from payment_mini_program_config
+    </sql>
+
+    <select id="selectPaymentMiniProgramConfigList" parameterType="PaymentMiniProgramConfig" resultMap="PaymentMiniProgramConfigResult">
+        <include refid="selectPaymentMiniProgramConfigVo"/>
+        <where>
+            <if test="payType != null  and payType != ''"> and pay_type = #{payType}</if>
+            <if test="appid != null  and appid != ''"> and appid = #{appid}</if>
+            <if test="ybMerchantNo != null  and ybMerchantNo != ''"> and yb_merchant_no = #{ybMerchantNo}</if>
+            <if test="ybKey != null  and ybKey != ''"> and yb_key = #{ybKey}</if>
+            <if test="ybNotifyUrl != null  and ybNotifyUrl != ''"> and yb_notify_url = #{ybNotifyUrl}</if>
+            <if test="tzhMerchantNo != null  and tzhMerchantNo != ''"> and tzh_merchant_no = #{tzhMerchantNo}</if>
+            <if test="tzhAppsecret != null  and tzhAppsecret != ''"> and tzh_appsecret = #{tzhAppsecret}</if>
+            <if test="tzhPrivateKey != null  and tzhPrivateKey != ''"> and tzh_private_key = #{tzhPrivateKey}</if>
+            <if test="tzhPublicKey != null  and tzhPublicKey != ''"> and tzh_public_key = #{tzhPublicKey}</if>
+            <if test="tzhAppkey != null  and tzhAppkey != ''"> and tzh_appkey = #{tzhAppkey}</if>
+            <if test="tzhPayNotifyUrl != null  and tzhPayNotifyUrl != ''"> and tzh_pay_notify_url = #{tzhPayNotifyUrl}</if>
+            <if test="tzhRefundNotifyUrl != null  and tzhRefundNotifyUrl != ''"> and tzh_refund_notify_url = #{tzhRefundNotifyUrl}</if>
+            <if test="tzhSplitNotifyUrl != null  and tzhSplitNotifyUrl != ''"> and tzh_split_notify_url = #{tzhSplitNotifyUrl}</if>
+            <if test="wxMerchantNo != null  and wxMerchantNo != ''"> and wx_merchant_no = #{wxMerchantNo}</if>
+            <if test="wxKey != null  and wxKey != ''"> and wx_key = #{wxKey}</if>
+            <if test="hfProductNo != null  and hfProductNo != ''"> and hf_product_no = #{hfProductNo}</if>
+            <if test="hfSystemNo != null  and hfSystemNo != ''"> and hf_system_no = #{hfSystemNo}</if>
+            <if test="hfMerchantNo != null  and hfMerchantNo != ''"> and hf_merchant_no = #{hfMerchantNo}</if>
+            <if test="hfPrivateKey != null  and hfPrivateKey != ''"> and hf_private_key = #{hfPrivateKey}</if>
+            <if test="hfPublicKey != null  and hfPublicKey != ''"> and hf_public_key = #{hfPublicKey}</if>
+            <if test="hfPayNotifyUrl != null  and hfPayNotifyUrl != ''"> and hf_pay_notify_url = #{hfPayNotifyUrl}</if>
+            <if test="hfLargePayNotifyUrl != null  and hfLargePayNotifyUrl != ''"> and hf_large_pay_notify_url = #{hfLargePayNotifyUrl}</if>
+            <if test="hfRefundNotifyUrl != null  and hfRefundNotifyUrl != ''"> and hf_refund_notify_url = #{hfRefundNotifyUrl}</if>
+            <if test="hfLargeRefundNotifyUrl != null  and hfLargeRefundNotifyUrl != ''"> and hf_large_refund_notify_url = #{hfLargeRefundNotifyUrl}</if>
+            <if test="status != null "> and status = #{status}</if>
+        </where>
+    </select>
+
+    <select id="selectPaymentMiniProgramConfigById" parameterType="String" resultMap="PaymentMiniProgramConfigResult">
+        <include refid="selectPaymentMiniProgramConfigVo"/>
+        where id = #{id}
+    </select>
+    <select id="selectPaymentConfigByAppId" resultType="com.fs.pay.domain.PaymentMiniProgramConfig">
+        select * from payment_mini_program_config where appid=#{appid} limit 1
+    </select>
+
+    <insert id="insertPaymentMiniProgramConfig" parameterType="PaymentMiniProgramConfig" useGeneratedKeys="true" keyProperty="id">
+        insert into payment_mini_program_config
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="payType != null and payType != ''">pay_type,</if>
+            <if test="appName != null and appName != ''">appname,</if>
+            <if test="appid != null and appid != ''">appid,</if>
+            <if test="appSecret != null and appSecret != ''">appsecret,</if>
+            <if test="ybMerchantNo != null">yb_merchant_no,</if>
+            <if test="ybKey != null">yb_key,</if>
+            <if test="ybNotifyUrl != null">yb_notify_url,</if>
+            <if test="tzhMerchantNo != null">tzh_merchant_no,</if>
+            <if test="tzhAppsecret != null">tzh_appsecret,</if>
+            <if test="tzhPrivateKey != null">tzh_private_key,</if>
+            <if test="tzhPublicKey != null">tzh_public_key,</if>
+            <if test="tzhAppkey != null">tzh_appkey,</if>
+            <if test="tzhPayNotifyUrl != null">tzh_pay_notify_url,</if>
+            <if test="tzhRefundNotifyUrl != null">tzh_refund_notify_url,</if>
+            <if test="tzhSplitNotifyUrl != null">tzh_split_notify_url,</if>
+            <if test="wxMerchantNo != null">wx_merchant_no,</if>
+            <if test="wxKey != null">wx_key,</if>
+            <if test="hfProductNo != null">hf_product_no,</if>
+            <if test="hfSystemNo != null">hf_system_no,</if>
+            <if test="hfMerchantNo != null">hf_merchant_no,</if>
+            <if test="hfPrivateKey != null">hf_private_key,</if>
+            <if test="hfPublicKey != null">hf_public_key,</if>
+            <if test="hfPayNotifyUrl != null">hf_pay_notify_url,</if>
+            <if test="hfLargePayNotifyUrl != null">hf_large_pay_notify_url,</if>
+            <if test="hfRefundNotifyUrl != null">hf_refund_notify_url,</if>
+            <if test="hfLargeRefundNotifyUrl != null">hf_large_refund_notify_url,</if>
+            <if test="status != null">status,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="payType != null and payType != ''">#{payType},</if>
+            <if test="appName != null and appName != ''">#{appName},</if>
+            <if test="appid != null and appid != ''">#{appid},</if>
+            <if test="appSecret != null and appSecret != ''">#{appSecret},</if>
+            <if test="ybMerchantNo != null">#{ybMerchantNo},</if>
+            <if test="ybKey != null">#{ybKey},</if>
+            <if test="ybNotifyUrl != null">#{ybNotifyUrl},</if>
+            <if test="tzhMerchantNo != null">#{tzhMerchantNo},</if>
+            <if test="tzhAppsecret != null">#{tzhAppsecret},</if>
+            <if test="tzhPrivateKey != null">#{tzhPrivateKey},</if>
+            <if test="tzhPublicKey != null">#{tzhPublicKey},</if>
+            <if test="tzhAppkey != null">#{tzhAppkey},</if>
+            <if test="tzhPayNotifyUrl != null">#{tzhPayNotifyUrl},</if>
+            <if test="tzhRefundNotifyUrl != null">#{tzhRefundNotifyUrl},</if>
+            <if test="tzhSplitNotifyUrl != null">#{tzhSplitNotifyUrl},</if>
+            <if test="wxMerchantNo != null">#{wxMerchantNo},</if>
+            <if test="wxKey != null">#{wxKey},</if>
+            <if test="hfProductNo != null">#{hfProductNo},</if>
+            <if test="hfSystemNo != null">#{hfSystemNo},</if>
+            <if test="hfMerchantNo != null">#{hfMerchantNo},</if>
+            <if test="hfPrivateKey != null">#{hfPrivateKey},</if>
+            <if test="hfPublicKey != null">#{hfPublicKey},</if>
+            <if test="hfPayNotifyUrl != null">#{hfPayNotifyUrl},</if>
+            <if test="hfLargePayNotifyUrl != null">#{hfLargePayNotifyUrl},</if>
+            <if test="hfRefundNotifyUrl != null">#{hfRefundNotifyUrl},</if>
+            <if test="hfLargeRefundNotifyUrl != null">#{hfLargeRefundNotifyUrl},</if>
+            <if test="status != null">#{status},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+        </trim>
+    </insert>
+
+    <update id="updatePaymentMiniProgramConfig" parameterType="PaymentMiniProgramConfig">
+        update payment_mini_program_config
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="payType != null and payType != ''">pay_type = #{payType},</if>
+            <if test="appName != null and appName != ''">appname = #{appName},</if>
+            <if test="appid != null and appid != ''">appid = #{appid},</if>
+            <if test="appSecret != null and appSecret != ''">appsecret = #{appSecret},</if>
+            <if test="ybMerchantNo != null">yb_merchant_no = #{ybMerchantNo},</if>
+            <if test="ybKey != null">yb_key = #{ybKey},</if>
+            <if test="ybNotifyUrl != null">yb_notify_url = #{ybNotifyUrl},</if>
+            <if test="tzhMerchantNo != null">tzh_merchant_no = #{tzhMerchantNo},</if>
+            <if test="tzhAppsecret != null">tzh_appsecret = #{tzhAppsecret},</if>
+            <if test="tzhPrivateKey != null">tzh_private_key = #{tzhPrivateKey},</if>
+            <if test="tzhPublicKey != null">tzh_public_key = #{tzhPublicKey},</if>
+            <if test="tzhAppkey != null">tzh_appkey = #{tzhAppkey},</if>
+            <if test="tzhPayNotifyUrl != null">tzh_pay_notify_url = #{tzhPayNotifyUrl},</if>
+            <if test="tzhRefundNotifyUrl != null">tzh_refund_notify_url = #{tzhRefundNotifyUrl},</if>
+            <if test="tzhSplitNotifyUrl != null">tzh_split_notify_url = #{tzhSplitNotifyUrl},</if>
+            <if test="wxMerchantNo != null">wx_merchant_no = #{wxMerchantNo},</if>
+            <if test="wxKey != null">wx_key = #{wxKey},</if>
+            <if test="hfProductNo != null">hf_product_no = #{hfProductNo},</if>
+            <if test="hfSystemNo != null">hf_system_no = #{hfSystemNo},</if>
+            <if test="hfMerchantNo != null">hf_merchant_no = #{hfMerchantNo},</if>
+            <if test="hfPrivateKey != null">hf_private_key = #{hfPrivateKey},</if>
+            <if test="hfPublicKey != null">hf_public_key = #{hfPublicKey},</if>
+            <if test="hfPayNotifyUrl != null">hf_pay_notify_url = #{hfPayNotifyUrl},</if>
+            <if test="hfLargePayNotifyUrl != null">hf_large_pay_notify_url = #{hfLargePayNotifyUrl},</if>
+            <if test="hfRefundNotifyUrl != null">hf_refund_notify_url = #{hfRefundNotifyUrl},</if>
+            <if test="hfLargeRefundNotifyUrl != null">hf_large_refund_notify_url = #{hfLargeRefundNotifyUrl},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deletePaymentMiniProgramConfigById" parameterType="String">
+        delete from payment_mini_program_config where id = #{id}
+    </delete>
+
+    <delete id="deletePaymentMiniProgramConfigByIds" parameterType="String">
+        delete from payment_mini_program_config where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>

+ 4 - 0
fs-user-app/pom.xml

@@ -108,6 +108,10 @@
             <artifactId>rocketmq-spring-boot-starter</artifactId>
             <version>2.2.3</version>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

+ 22 - 4
fs-user-app/src/main/java/com/fs/app/controller/store/CompanyOrderScrmController.java

@@ -55,7 +55,11 @@ public class CompanyOrderScrmController extends AppBaseController {
 
         PageHelper.startPage(param.getPage(), param.getPageSize());
         param.setIsDisplay(0);
-        List<FsStoreProductListQueryVO> productList=productService.selectFsStoreProductListQuery(param);
+        List<FsStoreProductListQueryVO> productList = productService.selectFsStoreProductListQuery(param);
+        for (FsStoreProductListQueryVO fsStoreProductListQueryVO : productList) {
+            fsStoreProductListQueryVO.setCompanyId(companyUser.getCompanyId());
+            fsStoreProductListQueryVO.setCompanyUserId(companyUser.getUserId());
+        }
         PageInfo<FsStoreProductListQueryVO> listPageInfo=new PageInfo<>(productList);
         return R.ok().put("data",listPageInfo);
     }
@@ -64,9 +68,11 @@ public class CompanyOrderScrmController extends AppBaseController {
     @ApiOperation("制单")
     @GetMapping("/createSalesOrder")
     public R createSalesOrder(@RequestParam("token")String token,
-                              @RequestParam("cateIds")String cateIds,
+                              @RequestParam(value = "cateIds", required = false)String cateIds,
                               @RequestParam(value = "orderType",required = false)Integer orderType,
                               @RequestParam(value = "orderMedium",required = false)Integer orderMedium,
+                              @RequestParam(value = "isPackage", required = false, defaultValue = "0")Integer isPackage,
+                              @RequestParam(value = "packageId", required = false)String packageId,
                               HttpServletRequest request){
         Long userId=redisCache.getCacheObject("company-user-token:"+token);
         if(userId==null){
@@ -79,7 +85,18 @@ public class CompanyOrderScrmController extends AppBaseController {
         if(!companyUser.getStatus().equals("0")){
             return R.error("用户已禁用");
         }
-        return orderService.createSalesOrder(companyUser,cateIds,orderType,orderMedium);
+        if(isPackage == 0){
+            return orderService.createSalesOrder(companyUser,cateIds,orderType,orderMedium);
+        } else if(isPackage == 1){
+            // 套餐包制单
+            if (packageId == null){
+                return R.error("套餐包ID不能为空");
+            }
+            return orderService.createPackageSalesOrder(companyUser,packageId,orderType,orderMedium);
+        } else {
+            return R.error("参数错误");
+        }
+
     }
 
     @ApiOperation("改价")
@@ -89,6 +106,7 @@ public class CompanyOrderScrmController extends AppBaseController {
                                    @RequestParam(value = "money",required = false) BigDecimal money,
                                    @RequestParam(value = "payAmount",required = false) BigDecimal payAmount,
                                    @RequestParam(value = "payType",required = false) Integer payType,
+                                   @RequestParam(value = "isPackage",required = false,defaultValue = "0")Integer isPackage,
                                    HttpServletRequest request){
         Long userId=redisCache.getCacheObject("company-user-token:"+token);
         if(userId==null){
@@ -100,7 +118,7 @@ public class CompanyOrderScrmController extends AppBaseController {
         if (payAmount == null){
             payAmount = BigDecimal.ZERO;
         }
-        return orderService.updateSalseOrderMoney(createOrderKey,money,payAmount,payType);
+        return orderService.updateSalseOrderMoney(createOrderKey,money,payAmount,payType, isPackage);
     }
 
     @ApiOperation("商品改价")

Some files were not shown because too many files changed in this diff