Преглед на файлове

Merge branch 'master_more_app_20251126' into master_sljx_20250813

# Conflicts:
#	deploy.sh
#	fs-admin/src/main/java/com/fs/company/controller/CompanyController.java
#	fs-admin/src/main/resources/application-dev.yml
#	fs-api/src/main/resources/application-dev.yml
#	fs-company/src/main/resources/application-dev.yml
#	fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreAfterSalesServiceImpl.java
#	fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderServiceImpl.java
#	fs-service-system/src/main/java/com/fs/store/service/impl/FsStorePaymentServiceImpl.java
#	fs-service-system/src/main/resources/application-config.yml
#	fs-sync/pom.xml
#	fs-sync/src/main/resources/application.yml
#	fs-user-app/src/main/java/com/fs/app/controller/CommonController.java
#	fs-user-app/src/main/java/com/fs/app/controller/StoreOrderController.java
#	fs-user-app/src/main/resources/application-dev.yml
yfh преди 2 седмици
родител
ревизия
68ed867295
променени са 57 файла, в които са добавени 2567 реда и са изтрити 83 реда
  1. 0 2
      .gitignore
  2. 6 2
      fs-admin/src/main/java/com/fs/store/controller/FsStoreOrderController.java
  3. 49 0
      fs-admin/src/main/java/com/fs/store/controller/FsStorePaymentController.java
  4. 6 2
      fs-admin/src/main/java/com/fs/task/StoreTask.java
  5. 117 0
      fs-admin/src/main/java/com/fs/web/controller/system/FsCoursePlaySourceConfigController.java
  6. 103 0
      fs-admin/src/main/java/com/fs/web/controller/system/WxMiniProgramConfigController.java
  7. 4 1
      fs-admin/src/main/resources/application.yml
  8. 126 0
      fs-admin/src/main/resources/logback.xml
  9. 1 1
      fs-admin/src/test/java/com/fs/store/controller/FsStorePaymentControllerTest.java
  10. 93 0
      fs-api/src/main/resources/logback.xml
  11. 5 0
      fs-company/src/main/resources/application.yml
  12. 93 0
      fs-company/src/main/resources/logback.xml
  13. 3 0
      fs-service-system/src/main/java/com/fs/company/mapper/CompanyMapper.java
  14. 3 0
      fs-service-system/src/main/java/com/fs/company/service/ICompanyService.java
  15. 7 0
      fs-service-system/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java
  16. 5 0
      fs-service-system/src/main/java/com/fs/huifuPay/domain/HuiFuCreateOrder.java
  17. 6 1
      fs-service-system/src/main/java/com/fs/huifuPay/service/impl/HuiFuServiceImpl.java
  18. 3 0
      fs-service-system/src/main/java/com/fs/store/cache/IFsWarehouseCacheService.java
  19. 18 0
      fs-service-system/src/main/java/com/fs/store/cache/impl/FsWarehouseCacheServiceImpl.java
  20. 79 0
      fs-service-system/src/main/java/com/fs/store/domain/FsCoursePlaySourceConfig.java
  21. 15 0
      fs-service-system/src/main/java/com/fs/store/domain/FsStorePayment.java
  22. 47 0
      fs-service-system/src/main/java/com/fs/store/domain/FsUserWx.java
  23. 1 1
      fs-service-system/src/main/java/com/fs/store/mapper/FsStorePaymentMapper.java
  24. 45 0
      fs-service-system/src/main/java/com/fs/store/mapper/FsUserWxMapper.java
  25. 4 0
      fs-service-system/src/main/java/com/fs/store/param/FsStoreOrderOtherPayParam.java
  26. 5 0
      fs-service-system/src/main/java/com/fs/store/param/FsStoreOrderPayParam.java
  27. 5 0
      fs-service-system/src/main/java/com/fs/store/param/FsStorePaymentParam.java
  28. 5 0
      fs-service-system/src/main/java/com/fs/store/param/FsStorePaymentPayParam.java
  29. 62 0
      fs-service-system/src/main/java/com/fs/store/param/LoginMaWxParam.java
  30. 4 1
      fs-service-system/src/main/java/com/fs/store/param/LoginMpWxParam.java
  31. 67 0
      fs-service-system/src/main/java/com/fs/store/service/IFsCoursePlaySourceConfigService.java
  32. 115 0
      fs-service-system/src/main/java/com/fs/store/service/channel/WxPaymentHandler.java
  33. 12 0
      fs-service-system/src/main/java/com/fs/store/service/channel/param/PayProcessContext.java
  34. 8 9
      fs-service-system/src/main/java/com/fs/store/service/impl/FsCityServiceImpl.java
  35. 101 0
      fs-service-system/src/main/java/com/fs/store/service/impl/FsCoursePlaySourceConfigServiceImpl.java
  36. 57 6
      fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreAfterSalesServiceImpl.java
  37. 176 25
      fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderServiceImpl.java
  38. 50 11
      fs-service-system/src/main/java/com/fs/store/service/impl/FsStorePaymentServiceImpl.java
  39. 50 10
      fs-service-system/src/main/java/com/fs/store/service/impl/FsUserServiceImpl.java
  40. 69 0
      fs-service-system/src/main/java/com/fs/system/domain/WxMiniProgramConfig.java
  41. 69 0
      fs-service-system/src/main/java/com/fs/system/mapper/FsCoursePlaySourceConfigMapper.java
  42. 61 0
      fs-service-system/src/main/java/com/fs/system/mapper/WxMiniProgramConfigMapper.java
  43. 60 0
      fs-service-system/src/main/java/com/fs/system/param/FsCoursePlaySourceConfigCreateParam.java
  44. 57 0
      fs-service-system/src/main/java/com/fs/system/param/FsCoursePlaySourceConfigEditParam.java
  45. 61 0
      fs-service-system/src/main/java/com/fs/system/service/IWxMiniProgramConfigService.java
  46. 112 0
      fs-service-system/src/main/java/com/fs/system/service/impl/WxMiniProgramConfigServiceImpl.java
  47. 5 0
      fs-service-system/src/main/java/com/fs/wx/domain/FsWxExpressTask.java
  48. 2 2
      fs-service-system/src/main/java/com/fs/wx/mapper/FsWxExpressTaskMapper.java
  49. 28 6
      fs-service-system/src/main/java/com/fs/wx/miniapp/config/WxMaConfiguration.java
  50. 1 0
      fs-service-system/src/main/resources/mapper/company/CompanyMapper.xml
  51. 6 1
      fs-service-system/src/main/resources/mapper/store/FsStorePaymentMapper.xml
  52. 44 0
      fs-service-system/src/main/resources/mapper/store/FsUserWxMapper.xml
  53. 130 0
      fs-service-system/src/main/resources/mapper/system/FsCoursePlaySourceConfigMapper.xml
  54. 122 0
      fs-service-system/src/main/resources/mapper/system/WxMiniProgramConfigMapper.xml
  55. 19 2
      fs-user-app/src/main/java/com/fs/app/controller/PaymentController.java
  56. 39 0
      fs-user-app/src/main/java/com/fs/app/controller/WxPayController.java
  57. 126 0
      fs-user-app/src/main/resources/logback.xml

+ 0 - 2
.gitignore

@@ -6,8 +6,6 @@ target/
 !**/src/main/**/target/
 !**/src/test/**/target/
 #*.yml
-logback.xml
-
 ### STS ###
 .apt_generated
 .classpath

+ 6 - 2
fs-admin/src/main/java/com/fs/store/controller/FsStoreOrderController.java

@@ -22,6 +22,7 @@ import com.fs.erp.utils.ErpContextHolder;
 import com.fs.express.FsStoreDeliversService;
 import com.fs.express.dto.DeliveryDTO;
 import com.fs.store.cache.IFsStoreProductCacheService;
+import com.fs.store.cache.IFsWarehouseCacheService;
 import com.fs.store.domain.*;
 import com.fs.store.dto.*;
 import com.fs.store.enums.ShipperCodeEnum;
@@ -87,6 +88,9 @@ public class FsStoreOrderController extends BaseController {
 
     @Autowired
     private FsStoreOrderMapper fsStoreOrderMapper;
+
+    @Autowired
+    private IFsWarehouseCacheService fsWarehouseCacheService;
     /**
      * 查询订单列表
      */
@@ -425,7 +429,7 @@ public class FsStoreOrderController extends BaseController {
 
         // 根据仓库code找erp
         if(com.fs.common.utils.StringUtils.isNotBlank(order.getStoreHouseCode())){
-            String erp = fsWarehousesMapper.selectErpByCode(order.getStoreHouseCode());
+            String erp = fsWarehouseCacheService.selectErpByCode(order.getStoreHouseCode());
             ErpContextHolder.setErpType(erp);
         }
 
@@ -524,7 +528,7 @@ public class FsStoreOrderController extends BaseController {
 
         // 根据仓库code找erp
         if(com.fs.common.utils.StringUtils.isNotBlank(order.getStoreHouseCode())){
-            String erp = fsWarehousesMapper.selectErpByCode(order.getStoreHouseCode());
+            String erp = fsWarehouseCacheService.selectErpByCode(order.getStoreHouseCode());
             ErpContextHolder.setErpType(erp);
         }
 

+ 49 - 0
fs-admin/src/main/java/com/fs/store/controller/FsStorePaymentController.java

@@ -36,8 +36,17 @@ import com.fs.store.service.impl.FsCouponScheduleServiceImpl;
 import com.fs.store.service.impl.FsStoreOrderServiceImpl;
 import com.fs.store.vo.FsStorePaymentVO;
 import com.fs.pay.service.IPayService;
+import com.fs.system.domain.WxMiniProgramConfig;
+import com.fs.system.mapper.WxMiniProgramConfigMapper;
 import com.fs.tzBank.TzBankService;
 import com.fs.tzBank.utils.TzConfigUtils;
+import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
+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.hc.openapi.tool.fastjson.JSON;
 import com.ijpay.alipay.AliPayApi;
 import com.ijpay.alipay.AliPayApiConfig;
@@ -69,8 +78,13 @@ import com.fs.common.core.page.TableDataInfo;
 @RequestMapping("/store/storePayment")
 public class FsStorePaymentController extends BaseController
 {
+    @Autowired
+    private WxPayService wxPayService;
     @Autowired
     private IFsStorePaymentService fsStorePaymentService;
+
+    @Autowired
+    private WxMiniProgramConfigMapper wxMiniProgramConfigMapper;
     @Autowired
     private IPayService payService;
     @Autowired
@@ -294,6 +308,41 @@ public class FsStorePaymentController extends BaseController
                     TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                     return R.error(result.getMessage());
                 }
+            }else if (payment.getPayMode()==null||payment.getPayMode().equals("wx")){
+                WxMiniProgramConfig wxMiniProgramConfig = new WxMiniProgramConfig();
+                wxMiniProgramConfig.setAppid(fsStorePayment.getAppId());
+                List<WxMiniProgramConfig>  wxMiniProgramConfigs = wxMiniProgramConfigMapper.selectWxMiniProgramConfigList(wxMiniProgramConfig);
+                WxMiniProgramConfig wConfig = wxMiniProgramConfigs.get(0);
+                WxPayConfig payConfig = new WxPayConfig();
+                payConfig.setAppId(wConfig.getAppid());
+                payConfig.setMchId(wConfig.getWxMerchantNo());
+                payConfig.setMchKey(wConfig.getWxKey());
+                payConfig.setKeyPath(wConfig.getWxKeyPath());
+                payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                wxPayService.setConfig(payConfig);
+                WxPayRefundRequest refundRequest = new WxPayRefundRequest();
+                refundRequest.setOutTradeNo("store-"+payment.getPayCode());
+                refundRequest.setOutRefundNo("store-"+payment.getPayCode());
+                refundRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
+                refundRequest.setRefundFee(WxPayUnifiedOrderRequest.yuanToFen(fsStorePayment.getRefundMoney().toString()));
+                try {
+                    WxPayRefundResult refundResult = wxPayService.refund(refundRequest);
+                    WxPayRefundQueryResult refundQueryResult = wxPayService.refundQuery("", refundResult.getOutTradeNo(), refundResult.getOutRefundNo(), refundResult.getRefundId());
+                    if(refundQueryResult!=null&&refundQueryResult.getResultCode().equals("SUCCESS")){
+                        FsStorePayment paymentMap=new FsStorePayment();
+                        paymentMap.setPaymentId(payment.getPaymentId());
+                        paymentMap.setStatus(-1);
+                        paymentMap.setRefundTime(DateUtils.getNowDate());
+                        paymentMap.setRefundMoney(fsStorePayment.getRefundMoney());
+                        fsStorePaymentService.updateFsStorePayment(paymentMap);
+                    }
+                    else {
+                        return R.error("退款请求失败"+refundQueryResult.getErrCodeDes());
+                    }
+                } catch (WxPayException e) {
+                    return R.error("退款请求失败"+e.getErrCodeDes());
+                }
             }else if (payment.getPayMode()!=null&&payment.getPayMode().equals("hf")){
                 V2TradePaymentScanpayRefundRequest request = new V2TradePaymentScanpayRefundRequest();
                 request.setOrdAmt(payment.getPayMoney().toString());

+ 6 - 2
fs-admin/src/main/java/com/fs/task/StoreTask.java

@@ -17,6 +17,7 @@ import com.fs.erp.service.FsJstCodPushService;
 import com.fs.erp.service.IErpGoodsService;
 import com.fs.erp.service.IErpOrderService;
 import com.fs.erp.utils.ErpContextHolder;
+import com.fs.store.cache.IFsWarehouseCacheService;
 import com.fs.store.config.StoreConfig;
 import com.fs.store.domain.*;
 import com.fs.store.dto.StoreProductGroupDTO;
@@ -128,7 +129,8 @@ public class StoreTask {
 
     @Autowired
     private FsJstCodPushService fsJstCodPushService;
-
+    @Autowired
+    private IFsWarehouseCacheService fsWarehouseCacheService;
     /**
      * 推送jst售后单
      */
@@ -144,6 +146,8 @@ public class StoreTask {
     public void jstCodPush(){
         fsJstCodPushService.jstCodPush();
     }
+
+
     /**
      * 发货任务
      */
@@ -159,7 +163,7 @@ public class StoreTask {
             try{
                 // 根据仓库code找erp
                 if(com.fs.common.utils.StringUtils.isNotBlank(order.getStoreHouseCode())){
-                    String erp = fsWarehousesMapper.selectErpByCode(order.getStoreHouseCode());
+                    String erp = fsWarehouseCacheService.selectErpByCode(order.getStoreHouseCode());
                     ErpContextHolder.setErpType(erp);
                 }
                 ErpOrderQueryResponse response = erpOrderService.getOrder(request);

+ 117 - 0
fs-admin/src/main/java/com/fs/web/controller/system/FsCoursePlaySourceConfigController.java

@@ -0,0 +1,117 @@
+package com.fs.web.controller.system;
+
+import cn.hutool.json.JSONUtil;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.bean.BeanUtils;
+import com.fs.core.security.LoginUser;
+import com.fs.core.web.service.TokenService;
+import com.fs.store.domain.FsCoursePlaySourceConfig;
+import com.fs.store.service.IFsCoursePlaySourceConfigService;
+import com.fs.system.param.FsCoursePlaySourceConfigCreateParam;
+import com.fs.system.param.FsCoursePlaySourceConfigEditParam;
+import com.fs.system.service.ISysConfigService;
+import com.github.pagehelper.PageHelper;
+import lombok.AllArgsConstructor;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.time.LocalDateTime;
+import java.util.*;
+
+@RestController
+@RequestMapping("/course/playSourceConfig")
+@AllArgsConstructor
+public class FsCoursePlaySourceConfigController extends BaseController {
+
+    private final IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService;
+    private final TokenService tokenService;
+    private final ISysConfigService configService;
+
+//    @PreAuthorize("@ss.hasPermi('course:playSourceConfig:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(@RequestParam(required = false) String name,
+                              @RequestParam(required = false) String appid,
+                              @RequestParam(required = false) Integer isMall,
+                              @RequestParam(required = false, defaultValue = "1") Integer pageNum,
+                              @RequestParam(required = false, defaultValue = "10") Integer pageSize,
+                              @RequestParam(required = false) Long companyId
+    ) {
+        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = new FsCoursePlaySourceConfig();
+        fsCoursePlaySourceConfig.setName(name);
+        fsCoursePlaySourceConfig.setAppid(appid);
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        fsCoursePlaySourceConfig.setCreateUserId(loginUser.getUser().getUserId());
+        fsCoursePlaySourceConfig.setCreateDeptId(loginUser.getUser().getDeptId());
+
+        PageHelper.startPage(pageNum, pageSize);
+        List<FsCoursePlaySourceConfig> list = fsCoursePlaySourceConfigService.selectFsCoursePlaySourceConfigList(fsCoursePlaySourceConfig);
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('course:playSourceConfig:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable Long id) {
+        FsCoursePlaySourceConfig config = fsCoursePlaySourceConfigService.selectFsCoursePlaySourceConfigById(id);
+        if (Objects.isNull(config)) {
+            return AjaxResult.success(null);
+        }
+        return AjaxResult.success(config);
+    }
+
+    @PreAuthorize("@ss.hasPermi('course:playSourceConfig:add')")
+    @Log(title = "点播播放源配置", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@Valid @RequestBody FsCoursePlaySourceConfigCreateParam param) {
+        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = new FsCoursePlaySourceConfig();
+        fsCoursePlaySourceConfig.setAppid(param.getAppid());
+        fsCoursePlaySourceConfig.setIsDel(0);
+        List<FsCoursePlaySourceConfig> list = fsCoursePlaySourceConfigService.selectFsCoursePlaySourceConfigList(fsCoursePlaySourceConfig);
+        if (CollectionUtils.isNotEmpty(list) && !list.get(0).getAppid().equals(param.getAppid())) {
+            return AjaxResult.error("appid已存在");
+        }
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        FsCoursePlaySourceConfig config = new FsCoursePlaySourceConfig();
+        BeanUtils.copyProperties(param, config);
+        config.setCreateUserId(loginUser.getUser().getUserId());
+        config.setCreateDeptId(loginUser.getUser().getDeptId());
+        config.setIsDel(0);
+        config.setCreateTime(new Date());
+        fsCoursePlaySourceConfigService.insertFsCoursePlaySourceConfig(config);
+        return AjaxResult.success();
+    }
+
+    @PreAuthorize("@ss.hasPermi('course:playSourceConfig:edit')")
+    @Log(title = "点播播放源配置", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@Valid @RequestBody FsCoursePlaySourceConfigEditParam param) {
+        FsCoursePlaySourceConfig config = fsCoursePlaySourceConfigService.selectFsCoursePlaySourceConfigById(param.getId());
+        if (Objects.isNull(config)) {
+            return AjaxResult.error("点播播放源配置不存在");
+        }
+        BeanUtils.copyProperties(param, config);
+        fsCoursePlaySourceConfigService.updateFsCoursePlaySourceConfig(config);
+        return AjaxResult.success();
+    }
+
+    @PreAuthorize("@ss.hasPermi('course:playSourceConfig:remove')")
+    @Log(title = "点播播放源配置", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids) {
+
+        fsCoursePlaySourceConfigService.deleteFsCoursePlaySourceConfigByIds(ids);
+        return AjaxResult.success();
+    }
+
+    @GetMapping("/listAll")
+    public R listAll() {
+        return R.ok().put("data", fsCoursePlaySourceConfigService.selectFsCoursePlaySourceConfigAll());
+    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/web/controller/system/WxMiniProgramConfigController.java

@@ -0,0 +1,103 @@
+package com.fs.web.controller.system;
+
+import java.util.List;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.system.domain.WxMiniProgramConfig;
+import com.fs.system.service.IWxMiniProgramConfigService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 微信小程序支付配置Controller
+ *
+ * @author fs
+ * @date 2025-12-01
+ */
+@RestController
+@RequestMapping("/system/wxMiniProgramConfig")
+public class WxMiniProgramConfigController extends BaseController
+{
+    @Autowired
+    private IWxMiniProgramConfigService wxMiniProgramConfigService;
+
+    /**
+     * 查询微信小程序支付配置列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:wxMiniProgramConfig:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(WxMiniProgramConfig wxMiniProgramConfig)
+    {
+        startPage();
+        List<WxMiniProgramConfig> list = wxMiniProgramConfigService.selectWxMiniProgramConfigList(wxMiniProgramConfig);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出微信小程序支付配置列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:wxMiniProgramConfig:export')")
+    @Log(title = "微信小程序支付配置", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(WxMiniProgramConfig wxMiniProgramConfig)
+    {
+        List<WxMiniProgramConfig> list = wxMiniProgramConfigService.selectWxMiniProgramConfigList(wxMiniProgramConfig);
+        ExcelUtil<WxMiniProgramConfig> util = new ExcelUtil<WxMiniProgramConfig>(WxMiniProgramConfig.class);
+        return util.exportExcel(list, "wxMiniProgramConfig");
+    }
+
+    /**
+     * 获取微信小程序支付配置详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:wxMiniProgramConfig:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(wxMiniProgramConfigService.selectWxMiniProgramConfigById(id));
+    }
+
+    /**
+     * 新增微信小程序支付配置
+     */
+    @PreAuthorize("@ss.hasPermi('system:wxMiniProgramConfig:add')")
+    @Log(title = "微信小程序支付配置", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody WxMiniProgramConfig wxMiniProgramConfig)
+    {
+        return toAjax(wxMiniProgramConfigService.insertWxMiniProgramConfig(wxMiniProgramConfig));
+    }
+
+    /**
+     * 修改微信小程序支付配置
+     */
+    @PreAuthorize("@ss.hasPermi('system:wxMiniProgramConfig:edit')")
+    @Log(title = "微信小程序支付配置", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody WxMiniProgramConfig wxMiniProgramConfig)
+    {
+        return toAjax(wxMiniProgramConfigService.updateWxMiniProgramConfig(wxMiniProgramConfig));
+    }
+
+    /**
+     * 删除微信小程序支付配置
+     */
+    @PreAuthorize("@ss.hasPermi('system:wxMiniProgramConfig:remove')")
+    @Log(title = "微信小程序支付配置", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(wxMiniProgramConfigService.deleteWxMiniProgramConfigByIds(ids));
+    }
+}

+ 4 - 1
fs-admin/src/main/resources/application.yml

@@ -63,7 +63,10 @@ spring:
       # 热部署开关
       enabled: true
 
-
+  datasource:
+    druid:
+      stat-view-servlet:
+        enabled: false
 # token配置
 token:
     # 令牌自定义标识

+ 126 - 0
fs-admin/src/main/resources/logback.xml

@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <!-- 日志存放路径 -->
+	<property name="log.path" value="/home/software/fs-admin/logs" />
+    <!-- 日志输出格式 -->
+    <property name="log.pattern" value="%replace([%X{traceId}] ){'\\[\\s*\\] ', ''}%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
+
+	<!-- 控制台输出 -->
+	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+	</appender>
+
+	<!-- 系统日志输出 -->
+	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-info.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+			<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 60天 -->
+			<maxHistory>60</maxHistory>
+		</rollingPolicy>
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>INFO</level>
+            <!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+	</appender>
+
+	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-error.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 60天 -->
+			<maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>ERROR</level>
+			<!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+			<!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+	<!-- 用户访问日志输出  -->
+    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<file>${log.path}/sys-user.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+    </appender>
+
+
+<!--    <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">-->
+<!--        &lt;!&ndash;配置logStash 服务地址&ndash;&gt;-->
+<!--        <destination>175.178.226.29:5044</destination>-->
+<!--        &lt;!&ndash; 日志输出编码 &ndash;&gt;-->
+<!--        <encoder charset="UTF-8"-->
+<!--                 class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">-->
+<!--            <providers>-->
+<!--                <timestamp>-->
+<!--                    <timeZone>UTC</timeZone>-->
+<!--                </timestamp>-->
+<!--                <pattern>-->
+<!--                    <pattern>-->
+<!--                        {-->
+<!--                        "env": "prod",-->
+<!--                        "service":"fs-admin",-->
+<!--                        "timestamp":"%d{yyyy-MM-dd HH:mm:ss.SSS}",-->
+<!--                        "date":"%d{yyyy-MM-dd HH:mm:ss.SSS}",-->
+<!--                        "level":"%level",-->
+<!--                        "thread": "%thread",-->
+<!--                        "logger": "%logger{36}",-->
+<!--                        "msg":"%msg",-->
+<!--                        "exception":"%exception",-->
+<!--                        "app_name":"fhhx-fs-admin-log",-->
+<!--                        "profiles_active":"prod"-->
+<!--                        }-->
+<!--                    </pattern>-->
+<!--                </pattern>-->
+<!--            </providers>-->
+<!--        </encoder>-->
+<!--    </appender>-->
+
+	<!-- 系统模块日志级别控制  -->
+	<logger name="com.fs" level="info" />
+	<!-- Spring日志级别控制  -->
+	<logger name="org.springframework" level="warn" />
+
+	<root level="info">
+		<appender-ref ref="console" />
+	</root>
+
+	<!--系统操作日志-->
+    <root level="info">
+        <appender-ref ref="file_info" />
+        <appender-ref ref="file_error" />
+<!--        <appender-ref ref="LOGSTASH" />-->
+    </root>
+
+	<!--系统用户操作日志-->
+    <logger name="sys-user" level="info">
+        <appender-ref ref="sys-user"/>
+    </logger>
+</configuration>

+ 1 - 1
fs-admin/src/test/java/com/fs/store/controller/FsStorePaymentControllerTest.java

@@ -115,7 +115,7 @@ public class FsStorePaymentControllerTest {
 
     @Test
     public void pushErp() throws ParseException {
-        fsStoreOrderService.createOmsOrder(1332687L);
+        fsStoreOrderService.createOmsOrder(1370120L);
     }
 
     @Test

+ 93 - 0
fs-api/src/main/resources/logback.xml

@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <!-- 日志存放路径 -->
+	<property name="log.path" value="/home/software/fs-api/logs" />
+    <!-- 日志输出格式 -->
+	<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
+
+	<!-- 控制台输出 -->
+	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+	</appender>
+
+	<!-- 系统日志输出 -->
+	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-info.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+			<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 60天 -->
+			<maxHistory>60</maxHistory>
+		</rollingPolicy>
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>INFO</level>
+            <!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+	</appender>
+
+	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-error.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 60天 -->
+			<maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>ERROR</level>
+			<!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+			<!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+	<!-- 用户访问日志输出  -->
+    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<file>${log.path}/sys-user.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+    </appender>
+
+	<!-- 系统模块日志级别控制  -->
+	<logger name="com.fs" level="info" />
+	<!-- Spring日志级别控制  -->
+	<logger name="org.springframework" level="warn" />
+
+	<root level="info">
+		<appender-ref ref="console" />
+	</root>
+
+	<!--系统操作日志-->
+    <root level="info">
+        <appender-ref ref="file_info" />
+        <appender-ref ref="file_error" />
+    </root>
+
+	<!--系统用户操作日志-->
+    <logger name="sys-user" level="info">
+        <appender-ref ref="sys-user"/>
+    </logger>
+</configuration>

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

@@ -57,6 +57,11 @@ spring:
     restart:
       # 热部署开关
       enabled: true
+
+  datasource:
+    druid:
+      stat-view-servlet:
+        enabled: false
 # token配置
 token:
     # 令牌自定义标识

+ 93 - 0
fs-company/src/main/resources/logback.xml

@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <!-- 日志存放路径 -->
+	<property name="log.path" value="/home/software/fs-company/logs" />
+    <!-- 日志输出格式 -->
+    <property name="log.pattern" value="%replace([%X{traceId}] ){'\\[\\s*\\] ', ''}%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
+
+	<!-- 控制台输出 -->
+	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+	</appender>
+
+	<!-- 系统日志输出 -->
+	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-info.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+			<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 60天 -->
+			<maxHistory>60</maxHistory>
+		</rollingPolicy>
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>INFO</level>
+            <!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+	</appender>
+
+	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-error.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 60天 -->
+			<maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>ERROR</level>
+			<!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+			<!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+	<!-- 用户访问日志输出  -->
+    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<file>${log.path}/sys-user.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+    </appender>
+
+	<!-- 系统模块日志级别控制  -->
+	<logger name="com.fs" level="info" />
+	<!-- Spring日志级别控制  -->
+	<logger name="org.springframework" level="warn" />
+
+	<root level="info">
+		<appender-ref ref="console" />
+	</root>
+
+	<!--系统操作日志-->
+    <root level="info">
+        <appender-ref ref="file_info" />
+        <appender-ref ref="file_error" />
+    </root>
+
+	<!--系统用户操作日志-->
+    <logger name="sys-user" level="info">
+        <appender-ref ref="sys-user"/>
+    </logger>
+</configuration>

+ 3 - 0
fs-service-system/src/main/java/com/fs/company/mapper/CompanyMapper.java

@@ -6,6 +6,7 @@ import com.fs.company.domain.Company;
 import com.fs.company.param.CompanyParam;
 import com.fs.company.vo.CompanyCrmVO;
 import com.fs.company.vo.CompanyVO;
+import com.fs.store.vo.OptionsVO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
@@ -122,4 +123,6 @@ public interface CompanyMapper
 
     @Select("select company_id,company_name from company where oms_code = #{omsCode}")
     List<Long> selectCompanyByOmsCode(@Param("omsCode") String omsCode);
+
+    List<OptionsVO> selectAllCompanyList(Long deptId);
 }

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

@@ -9,6 +9,7 @@ import com.fs.company.vo.CompanyCrmVO;
 import com.fs.company.vo.CompanyVO;
 import com.fs.store.domain.FsStoreOrder;
 import com.fs.store.domain.FsStorePayment;
+import com.fs.store.vo.OptionsVO;
 import org.apache.ibatis.annotations.Param;
 
 /**
@@ -96,4 +97,6 @@ public interface ICompanyService
     List<Long> selectCompanyByOmsCode(String omsCode);
 
     Company selectCompanyByIdForUpdate(Long companyId);
+
+    List<OptionsVO> selectAllCompanyList(Long deptId);
 }

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

@@ -1,6 +1,7 @@
 package com.fs.company.service.impl;
 
 import java.math.BigDecimal;
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 
@@ -17,6 +18,7 @@ import com.fs.store.config.StoreConfig;
 import com.fs.store.domain.FsStoreOrder;
 import com.fs.store.domain.FsStorePayment;
 import com.fs.store.mapper.FsStoreOrderMapper;
+import com.fs.store.vo.OptionsVO;
 import com.fs.system.service.ISysConfigService;
 import com.github.pagehelper.PageHelper;
 import lombok.Synchronized;
@@ -415,4 +417,9 @@ public class CompanyServiceImpl implements ICompanyService
     public Company selectCompanyByIdForUpdate(Long companyId) {
         return companyMapper.selectCompanyByIdForUpdate(companyId);
     }
+
+    @Override
+    public List<OptionsVO> selectAllCompanyList(Long deptId) {
+        return companyMapper.selectAllCompanyList(deptId);
+    }
 }

+ 5 - 0
fs-service-system/src/main/java/com/fs/huifuPay/domain/HuiFuCreateOrder.java

@@ -19,4 +19,9 @@ public class HuiFuCreateOrder {
     String transAmt;
     String goodsDesc;
     String openid;
+
+    /**
+     * 多小程序支付
+     */
+    String appId;
 }

+ 6 - 1
fs-service-system/src/main/java/com/fs/huifuPay/service/impl/HuiFuServiceImpl.java

@@ -3,6 +3,7 @@ package com.fs.huifuPay.service.impl;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.fs.common.exception.CustomException;
+import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.spring.SpringUtils;
 import com.fs.huifuPay.domain.*;
 import com.fs.huifuPay.sdk.opps.core.config.MerConfig;
@@ -57,10 +58,14 @@ public class HuiFuServiceImpl implements HuiFuService {
             extendInfoMap.put("pay_scene", "02");
             // 传入分帐遇到优惠的处理规则
             extendInfoMap.put("term_div_coupon_type", "0");
+            String appId = order.getAppId();
+            if (StringUtils.isBlank(appId)){
+                appId = config.getAppId();
+            }
             if (order.getTradeType().equals("T_MINIAPP")||order.getTradeType().equals("T_JSAPI")){
                 JSONObject dto = new JSONObject();
                 // 子商户公众账号id
-                dto.put("sub_appid", config.getAppId());
+                dto.put("sub_appid", appId);
                 // 用户标识
                 dto.put("openid", order.getOpenid());
                 extendInfoMap.put("wx_data", dto);

+ 3 - 0
fs-service-system/src/main/java/com/fs/store/cache/IFsWarehouseCacheService.java

@@ -1,7 +1,10 @@
 package com.fs.store.cache;
 
 import com.fs.store.domain.FsWarehouses;
+import org.apache.ibatis.annotations.Param;
 
 public interface IFsWarehouseCacheService {
     FsWarehouses selectFsWarehousesById(Long id);
+    String selectErpByCode(@Param("warehouseCode") String warehouseCode);
+
 }

+ 18 - 0
fs-service-system/src/main/java/com/fs/store/cache/impl/FsWarehouseCacheServiceImpl.java

@@ -4,6 +4,7 @@ import com.fs.store.cache.IFsStoreProductCacheService;
 import com.fs.store.cache.IFsWarehouseCacheService;
 import com.fs.store.domain.FsStoreProduct;
 import com.fs.store.domain.FsWarehouses;
+import com.fs.store.mapper.FsWarehousesMapper;
 import com.fs.store.service.IFsWarehousesService;
 import com.github.benmanes.caffeine.cache.Cache;
 import com.github.benmanes.caffeine.cache.Caffeine;
@@ -18,6 +19,7 @@ import java.util.concurrent.TimeUnit;
 @RequiredArgsConstructor
 public class FsWarehouseCacheServiceImpl implements IFsWarehouseCacheService {
     private final IFsWarehousesService fsWarehousesService;
+    private final FsWarehousesMapper fsWarehousesMapper;
     /**
      * 使用Caffeine本地缓存
      * maximumSize: 最大缓存条数
@@ -27,10 +29,26 @@ public class FsWarehouseCacheServiceImpl implements IFsWarehouseCacheService {
             .maximumSize(1000)
             .expireAfterWrite(1, TimeUnit.MINUTES)
             .build();
+    /**
+     * 使用Caffeine本地缓存
+     * maximumSize: 最大缓存条数
+     * expireAfterWrite: 写入后多久过期(分钟)
+     */
+    private static final Cache<String, String> CACHE_ERP_CODE = Caffeine.newBuilder()
+            .maximumSize(1000)
+            .expireAfterWrite(3, TimeUnit.MINUTES)
+            .build();
 
 
     @Override
     public FsWarehouses selectFsWarehousesById(Long id) {
         return CACHE.get(id, e -> fsWarehousesService.selectFsWarehousesById(id));
     }
+
+    @Override
+    public String selectErpByCode(String warehouseCode) {
+        return CACHE_ERP_CODE.get(warehouseCode,e->
+            fsWarehousesMapper.selectErpByCode(warehouseCode)
+        );
+    }
 }

+ 79 - 0
fs-service-system/src/main/java/com/fs/store/domain/FsCoursePlaySourceConfig.java

@@ -0,0 +1,79 @@
+package com.fs.store.domain;
+
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 点播播放源配置对象 fs_course_play_source_config
+ *
+ * @author fs
+ * @date 2025-11-27
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FsCoursePlaySourceConfig extends BaseEntity {
+
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 小程序/公众号名称
+     */
+    private String name;
+
+    /**
+     * 小程序/公众号appid
+     */
+    private String appid;
+
+    /**
+     * 小程序/公众号secret
+     */
+    private String secret;
+
+    /**
+     * 小程序/公众号icon图标
+     */
+    private String img;
+
+    /**
+     * 小程序/公众号原始id
+     */
+    private String originalId;
+
+    /**
+     * token
+     */
+    private String token;
+
+    /**
+     * aesKey
+     */
+    private String aesKey;
+
+    /**
+     * msgDataFormat
+     */
+    private String msgDataFormat;
+
+    /**
+     * 是否删除 0正常 1删除
+     */
+    private Integer isDel;
+    // 创建人
+    private Long createUserId;
+    // 创建部门
+    private Long createDeptId;
+
+    /**
+     * 小程序状态:0正常,1半封禁,2封禁
+     */
+    private Integer status;
+
+}

+ 15 - 0
fs-service-system/src/main/java/com/fs/store/domain/FsStorePayment.java

@@ -82,6 +82,21 @@ public class FsStorePayment extends BaseEntity
 
     private Integer isPayRemain;
 
+    /**
+     * 小程序appId
+     */
+    private String appId;
+
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public FsStorePayment setAppId(String appId) {
+        this.appId = appId;
+        return this;
+    }
+
     public String getPayMode() {
         return payMode;
     }

+ 47 - 0
fs-service-system/src/main/java/com/fs/store/domain/FsUserWx.java

@@ -0,0 +1,47 @@
+package com.fs.store.domain;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class FsUserWx {
+    /**
+     * 主键ID
+     */
+    private Long id;
+    /**
+     * 用户ID
+     */
+    private Long fsUserId;
+
+    /**
+     * 公司ID
+     */
+    private Long companyId;
+    /**
+     * 小程序/公众号appId
+     */
+    private String appId;
+    /**
+     * 微信unionId
+     */
+    private String unionId;
+    /**
+     * 微信openId
+     */
+    private String openId;
+
+    /**
+     * 1:小程序 2:服务号
+     */
+    private Integer type;
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+    /**
+     * 修改时间
+     */
+    private Date updateTime;
+}

+ 1 - 1
fs-service-system/src/main/java/com/fs/store/mapper/FsStorePaymentMapper.java

@@ -132,7 +132,7 @@ public interface FsStorePaymentMapper
             " AND date_format(p.create_time,'%y%m%d') &gt;= date_format(#{maps.createTimeList[0]},'%y%m%d') " +
             " AND date_format(p.create_time,'%y%m%d') &lt;= date_format(#{maps.createTimeList[1]},'%y%m%d') " +
             "</if>" +
-
+            "            <if test=\"maps.appId != null and maps.appId != ''\">  and sp.app_id like #{maps.appId}</if>\n" +
 //            "<if test = 'maps.refundTime != null    '> " +
 //            "and DATE_FORMAT(p.refund_time,'%Y-%m-%d') = DATE_FORMAT(#{maps.refundTime},'%Y-%m-%d')  " +
 //            "</if>" +

+ 45 - 0
fs-service-system/src/main/java/com/fs/store/mapper/FsUserWxMapper.java

@@ -0,0 +1,45 @@
+package com.fs.store.mapper;
+
+
+import com.fs.store.domain.FsUserWx;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.Date;
+import java.util.List;
+
+public interface FsUserWxMapper{
+
+    /**
+     * 根据FsUserId和AppId唯一键保存或更新
+     * @param wx    配置信息
+     */
+    void insertOrUpdateByUniqueKey(FsUserWx wx);
+
+
+    /**
+     * 根据fs_user_id、app_id、openId进行修改
+     * @param userId
+     * @param appId
+     * @param openId
+     * @param companyId
+     * @param unionId
+     * @param updateTime
+     * @return
+     */
+    int updateFsUserWx(@Param("userId") Long userId,
+                       @Param("appId") String appId,
+                       @Param("openId") String openId,
+                       @Param("companyId") Long companyId,
+                       @Param("unionId") String unionId,
+                       @Param("updateTime") Date updateTime);
+
+    /**
+     * 查询用户小程序关联信息
+     *
+     * @param userId
+     * @param appId
+     * @return
+     */
+    FsUserWx selectListByUserIdAndAppId(@Param("userId") Long userId,
+                                              @Param("appId") String appId);
+}

+ 4 - 0
fs-service-system/src/main/java/com/fs/store/param/FsStoreOrderOtherPayParam.java

@@ -18,4 +18,8 @@ public class FsStoreOrderOtherPayParam implements Serializable
     private String code;
 
 
+    /**
+     * 小程序APPID
+     */
+    private String appId;
 }

+ 5 - 0
fs-service-system/src/main/java/com/fs/store/param/FsStoreOrderPayParam.java

@@ -16,4 +16,9 @@ public class FsStoreOrderPayParam implements Serializable
     @ApiModelProperty(value = "payType")
     @NotNull(message = "支付类型不能为空")
     private Integer payType;
+
+    /**
+     * appId
+     */
+    private String appId;
 }

+ 5 - 0
fs-service-system/src/main/java/com/fs/store/param/FsStorePaymentParam.java

@@ -48,4 +48,9 @@ public class FsStorePaymentParam  extends BaseEntity implements Serializable
     private String createTimeRange;
     private String   payMode;
     private String[] createTimeList;
+
+    /**
+     * 小程序Id
+     */
+    private String appId;
 }

+ 5 - 0
fs-service-system/src/main/java/com/fs/store/param/FsStorePaymentPayParam.java

@@ -20,4 +20,9 @@ public class FsStorePaymentPayParam implements Serializable
     private Long companyUserId;
 
     private String code;
+
+    /**
+     * appId
+     */
+    private String appId;
 }

+ 62 - 0
fs-service-system/src/main/java/com/fs/store/param/LoginMaWxParam.java

@@ -0,0 +1,62 @@
+package com.fs.store.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+@Data
+public class LoginMaWxParam implements Serializable {
+
+    @NotBlank(message = "code参数缺失")
+    @ApiModelProperty(value = "小程序登陆code")
+    private String code;
+
+    @ApiModelProperty(value = "小程序完整用户信息的加密数据")
+    private String encryptedData;
+
+    @ApiModelProperty(value = "小程序加密算法的初始向量")
+    private String iv;
+
+    @NotNull(message = "公司id不能为空")
+    @ApiModelProperty(value = "公司id")
+    private Long companyId;
+
+    @NotNull(message = "销售id不能为空")
+    @ApiModelProperty(value = "销售id")
+    private Long companyUserId;
+
+    @ApiModelProperty(value = "用户昵称")
+    private String nickname;
+
+    @ApiModelProperty(value = "用户头像")
+    private String avatar;
+
+    @NotNull(message = "项目id不能为空")
+    @ApiModelProperty(value = "课程归属项目id")
+    private Long projectId;
+
+//    @ApiModelProperty(value = "公司id,如果不是第一位销售,都需要传")
+//    private Long companyId;
+
+//    @ApiModelProperty(value = "电话号码")
+//    private String phoneNumber;
+
+//    @ApiModelProperty(value = "上级销售id,如果没有则不传")
+//    private Long parentCompanyUseId;
+//
+//    @ApiModelProperty(value = "用户密码")
+//    private String password;
+
+    /**
+     * 0:静默授权  1:手机号授权
+     */
+    @NotNull(message = "授权类型缺失")
+    @ApiModelProperty(value = "小程序授权类型")
+    private Integer authType;
+
+    private String appId;
+
+}

+ 4 - 1
fs-service-system/src/main/java/com/fs/store/param/LoginMpWxParam.java

@@ -24,5 +24,8 @@ public class LoginMpWxParam implements Serializable {
 
     private String userCode;
 
-
+    /**
+     * 小程序APPID
+     */
+    private String appId;
 }

+ 67 - 0
fs-service-system/src/main/java/com/fs/store/service/IFsCoursePlaySourceConfigService.java

@@ -0,0 +1,67 @@
+package com.fs.store.service;
+
+
+import java.util.List;
+import com.fs.store.domain.FsCoursePlaySourceConfig;
+
+/**
+ * 点播播放源配置Service接口
+ *
+ * @author fs
+ * @date 2025-11-27
+ */
+public interface IFsCoursePlaySourceConfigService {
+    /**
+     * 查询点播播放源配置
+     *
+     * @param id 点播播放源配置主键
+     * @return 点播播放源配置
+     */
+    FsCoursePlaySourceConfig selectFsCoursePlaySourceConfigById(Long id);
+
+    /**
+     * 查询点播播放源配置列表
+     *
+     * @param fsCoursePlaySourceConfig 点播播放源配置
+     * @return 点播播放源配置集合
+     */
+    List<FsCoursePlaySourceConfig> selectFsCoursePlaySourceConfigList(FsCoursePlaySourceConfig fsCoursePlaySourceConfig);
+
+    /**
+     * 新增点播播放源配置
+     *
+     * @param fsCoursePlaySourceConfig 点播播放源配置
+     * @return 结果
+     */
+    int insertFsCoursePlaySourceConfig(FsCoursePlaySourceConfig fsCoursePlaySourceConfig);
+
+    /**
+     * 修改点播播放源配置
+     *
+     * @param fsCoursePlaySourceConfig 点播播放源配置
+     * @return 结果
+     */
+    int updateFsCoursePlaySourceConfig(FsCoursePlaySourceConfig fsCoursePlaySourceConfig);
+
+    /**
+     * 批量删除点播播放源配置
+     *
+     * @param ids 需要删除的点播播放源配置主键集合
+     * @return 结果
+     */
+    int deleteFsCoursePlaySourceConfigByIds(Long[] ids);
+
+    /**
+     * 删除点播播放源配置信息
+     *
+     * @param id 点播播放源配置主键
+     * @return 结果
+     */
+    int deleteFsCoursePlaySourceConfigById(Long id);
+
+    /**
+     * 查询小程序所有数据
+     * @return
+     */
+    List<FsCoursePlaySourceConfig> selectFsCoursePlaySourceConfigAll();
+}

+ 115 - 0
fs-service-system/src/main/java/com/fs/store/service/channel/WxPaymentHandler.java

@@ -0,0 +1,115 @@
+package com.fs.store.service.channel;
+
+import com.alibaba.fastjson.JSON;
+import com.fs.common.core.domain.R;
+import com.fs.common.exception.CustomException;
+import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.ip.IpUtils;
+import com.fs.huifuPay.domain.HuiFuCreateOrder;
+import com.fs.huifuPay.domain.HuiFuRefundResult;
+import com.fs.huifuPay.domain.HuifuCreateOrderResult;
+import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
+import com.fs.huifuPay.service.HuiFuService;
+import com.fs.store.domain.FsStorePayment;
+import com.fs.store.service.channel.param.PayProcessContext;
+import com.fs.system.domain.WxMiniProgramConfig;
+import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
+import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
+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 lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Service;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE;
+
+/**
+ * hf支付处理
+ */
+@Service
+@Scope(value = SCOPE_PROTOTYPE)
+@Slf4j
+public class WxPaymentHandler extends PaymentHandler{
+    @Autowired
+    private WxPayService wxPayService;
+
+    @Override
+    protected R doCreateOrder(PayProcessContext context) {
+        WxMiniProgramConfig wxMiniProgramConfig = context.getWxMiniProgramConfig();
+        WxPayConfig payConfig = new WxPayConfig();
+        payConfig.setAppId(wxMiniProgramConfig.getAppid());
+        payConfig.setMchId(wxMiniProgramConfig.getWxMerchantNo());
+        payConfig.setMchKey(wxMiniProgramConfig.getWxKey());
+        payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+        payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+        payConfig.setKeyPath(wxMiniProgramConfig.getWxKeyPath());
+        payConfig.setNotifyUrl(wxMiniProgramConfig.getWxNotifyUrl());
+        wxPayService.setConfig(payConfig);
+        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
+        orderRequest.setOpenid(user.getMaOpenId());//公众号支付提供用户openid
+        orderRequest.setBody("商城订单支付");
+        orderRequest.setOutTradeNo("store-" + context.getPayCode());
+        orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(context.getStorePayment().getPayMoney().toString()));//测试
+        orderRequest.setTradeType("JSAPI");
+        orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
+        //调用统一下单接口,获取"预支付交易会话标识"
+        try {
+            WxPayMpOrderResult orderResult = wxPayService.createOrder(orderRequest);
+            String resultJson = JSON.toJSONString(orderResult);
+            return R.ok().put("result", resultJson).put("type", "wx").put("isPay", 0).put("payType",context.getPayType());
+        } catch (WxPayException e) {
+            e.printStackTrace();
+            throw new CustomException("支付失败" + e.getMessage());
+        }
+    }
+
+    @Override
+    protected void doRefundOrder(PayProcessContext context) {
+        WxMiniProgramConfig wxMiniProgramConfig = context.getWxMiniProgramConfig();
+        WxPayConfig payConfig = new WxPayConfig();
+        payConfig.setAppId(wxMiniProgramConfig.getAppid());
+        payConfig.setMchId(wxMiniProgramConfig.getWxMerchantNo());
+        payConfig.setMchKey(wxMiniProgramConfig.getWxKey());
+        payConfig.setKeyPath(wxMiniProgramConfig.getWxKeyPath());
+        payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+        payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+        wxPayService.setConfig(payConfig);
+        WxPayRefundRequest refundRequest = new WxPayRefundRequest();
+        refundRequest.setOutTradeNo("store-" + context.getPayCode());
+        refundRequest.setOutRefundNo("store-" + context.getPayCode());
+        refundRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(context.getStorePayment().getPayMoney().toString()));
+        refundRequest.setRefundFee(WxPayUnifiedOrderRequest.yuanToFen(context.getStorePayment().getPayMoney().toString()));
+        try {
+            WxPayRefundResult refundResult = wxPayService.refund(refundRequest);
+            WxPayRefundQueryResult refundQueryResult = wxPayService.refundQuery("", refundResult.getOutTradeNo(), refundResult.getOutRefundNo(), refundResult.getRefundId());
+            if (refundQueryResult != null && refundQueryResult.getResultCode().equals("SUCCESS")) {
+                FsStorePayment paymentMap = new FsStorePayment();
+                paymentMap.setPaymentId(context.getPaymentId());
+                paymentMap.setStatus(-1);
+                paymentMap.setRefundTime(DateUtils.getNowDate());
+                paymentMap.setRefundMoney(context.getStorePayment().getPayMoney());
+                fsStorePaymentService.updateFsStorePayment(paymentMap);
+            } else {
+                log.error("退款请求失败:{}",refundQueryResult.getErrCodeDes());
+            }
+        } catch (WxPayException e) {
+           log.error("退款请求失败", e.getErrCodeDes());
+        }
+    }
+
+    @Override
+    public boolean support(String code) {
+        return "wx".equals(code);
+    }
+}

+ 12 - 0
fs-service-system/src/main/java/com/fs/store/service/channel/param/PayProcessContext.java

@@ -1,6 +1,8 @@
 package com.fs.store.service.channel.param;
 
 import com.fs.store.domain.FsPayConfig;
+import com.fs.store.domain.FsStorePayment;
+import com.fs.system.domain.WxMiniProgramConfig;
 import lombok.Data;
 
 @Data
@@ -29,11 +31,21 @@ public class PayProcessContext {
      */
     private String payCode;
 
+    /**
+     * 支付详情
+     */
+    private FsStorePayment storePayment;
+
     /**
      * 支付配置信息
      */
     private FsPayConfig fsPayConfig;
 
+    /**
+     * 微信支付配置信息
+     */
+    private WxMiniProgramConfig wxMiniProgramConfig;
+
     /**
      * 订单前缀
      */

+ 8 - 9
fs-service-system/src/main/java/com/fs/store/service/impl/FsCityServiceImpl.java

@@ -10,19 +10,19 @@ import com.fs.store.service.IFsCityService;
 
 /**
  * 城市Service业务层处理
- * 
+ *
  * @author fs
  * @date 2022-03-15
  */
 @Service
-public class FsCityServiceImpl implements IFsCityService 
+public class FsCityServiceImpl implements IFsCityService
 {
     @Autowired
     private FsCityMapper fsCityMapper;
 
     /**
      * 查询城市
-     * 
+     *
      * @param id 城市ID
      * @return 城市
      */
@@ -34,7 +34,7 @@ public class FsCityServiceImpl implements IFsCityService
 
     /**
      * 查询城市列表
-     * 
+     *
      * @param fsCity 城市
      * @return 城市
      */
@@ -46,7 +46,7 @@ public class FsCityServiceImpl implements IFsCityService
 
     /**
      * 新增城市
-     * 
+     *
      * @param fsCity 城市
      * @return 结果
      */
@@ -58,7 +58,7 @@ public class FsCityServiceImpl implements IFsCityService
 
     /**
      * 修改城市
-     * 
+     *
      * @param fsCity 城市
      * @return 结果
      */
@@ -70,7 +70,7 @@ public class FsCityServiceImpl implements IFsCityService
 
     /**
      * 批量删除城市
-     * 
+     *
      * @param ids 需要删除的城市ID
      * @return 结果
      */
@@ -82,7 +82,7 @@ public class FsCityServiceImpl implements IFsCityService
 
     /**
      * 删除城市信息
-     * 
+     *
      * @param id 城市ID
      * @return 结果
      */
@@ -93,7 +93,6 @@ public class FsCityServiceImpl implements IFsCityService
     }
 
     @Override
-    @Cacheable(cacheNames = "citys")
     public List<FsCity> selectFsCitys() {
         return fsCityMapper.selectFsCitys();
     }

+ 101 - 0
fs-service-system/src/main/java/com/fs/store/service/impl/FsCoursePlaySourceConfigServiceImpl.java

@@ -0,0 +1,101 @@
+package com.fs.store.service.impl;
+
+import com.fs.store.domain.FsCoursePlaySourceConfig;
+import com.fs.system.mapper.FsCoursePlaySourceConfigMapper;
+import com.fs.store.service.IFsCoursePlaySourceConfigService;
+
+import java.util.List;
+import com.fs.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 点播播放源配置Service业务层处理
+ *
+ * @author fs
+ * @date 2025-11-27
+ */
+@Service
+public class FsCoursePlaySourceConfigServiceImpl  implements IFsCoursePlaySourceConfigService {
+
+    @Autowired
+    private FsCoursePlaySourceConfigMapper baseMapper;
+    /**
+     * 查询点播播放源配置
+     *
+     * @param id 点播播放源配置主键
+     * @return 点播播放源配置
+     */
+    @Override
+    public FsCoursePlaySourceConfig selectFsCoursePlaySourceConfigById(Long id)
+    {
+        return baseMapper.selectFsCoursePlaySourceConfigById(id);
+    }
+
+    /**
+     * 查询点播播放源配置列表
+     *
+     * @param fsCoursePlaySourceConfig 点播播放源配置
+     * @return 点播播放源配置
+     */
+    @Override
+    public List<FsCoursePlaySourceConfig> selectFsCoursePlaySourceConfigList(FsCoursePlaySourceConfig fsCoursePlaySourceConfig)
+    {
+        return baseMapper.selectFsCoursePlaySourceConfigList(fsCoursePlaySourceConfig);
+    }
+
+    /**
+     * 新增点播播放源配置
+     *
+     * @param fsCoursePlaySourceConfig 点播播放源配置
+     * @return 结果
+     */
+    @Override
+    public int insertFsCoursePlaySourceConfig(FsCoursePlaySourceConfig fsCoursePlaySourceConfig)
+    {
+        fsCoursePlaySourceConfig.setCreateTime(DateUtils.getNowDate());
+        return baseMapper.insertFsCoursePlaySourceConfig(fsCoursePlaySourceConfig);
+    }
+
+    /**
+     * 修改点播播放源配置
+     *
+     * @param fsCoursePlaySourceConfig 点播播放源配置
+     * @return 结果
+     */
+    @Override
+    public int updateFsCoursePlaySourceConfig(FsCoursePlaySourceConfig fsCoursePlaySourceConfig)
+    {
+        fsCoursePlaySourceConfig.setUpdateTime(DateUtils.getNowDate());
+        return baseMapper.updateFsCoursePlaySourceConfig(fsCoursePlaySourceConfig);
+    }
+
+    /**
+     * 批量删除点播播放源配置
+     *
+     * @param ids 需要删除的点播播放源配置主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsCoursePlaySourceConfigByIds(Long[] ids)
+    {
+        return baseMapper.deleteFsCoursePlaySourceConfigByIds(ids);
+    }
+
+    /**
+     * 删除点播播放源配置信息
+     *
+     * @param id 点播播放源配置主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsCoursePlaySourceConfigById(Long id)
+    {
+        return baseMapper.deleteFsCoursePlaySourceConfigById(id);
+    }
+
+    @Override
+    public List<FsCoursePlaySourceConfig> selectFsCoursePlaySourceConfigAll() {
+        return baseMapper.selectFsCoursePlaySourceConfigAll();
+    }
+}

+ 57 - 6
fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreAfterSalesServiceImpl.java

@@ -33,6 +33,7 @@ import com.fs.huifuPay.domain.HuiFuRefundResult;
 import com.fs.huifuPay.dto.*;
 import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
 import com.fs.huifuPay.service.HuiFuService;
+import com.fs.store.cache.IFsWarehouseCacheService;
 import com.fs.store.mapper.FsStoreDeliversMapper;
 import com.fs.store.mapper.FsWarehousesMapper;
 import com.fs.system.config.SnowflakeUtils;
@@ -54,6 +55,13 @@ import com.fs.store.vo.FsStoreOrderItemVO;
 import com.fs.pay.service.IPayService;
 import com.fs.system.service.ISysConfigService;
 import com.fs.tzBank.utils.TzConfigUtils;
+import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
+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.hc.openapi.tool.fastjson.JSON;
 import lombok.Synchronized;
 import org.slf4j.Logger;
@@ -78,9 +86,12 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport;
 public class FsStoreAfterSalesServiceImpl implements IFsStoreAfterSalesService
 {
     Logger logger= LoggerFactory.getLogger(getClass());
-
     @Autowired
-    IFsStorePaymentService paymentService;
+    private WxMiniProgramConfigMapper wxMiniProgramConfigMapper;
+    @Autowired
+    private WxPayService wxPayService;
+    @Autowired
+    private IFsStorePaymentService paymentService;
     @Autowired
     private ICompanyService companyService;
     @Autowired
@@ -100,20 +111,20 @@ public class FsStoreAfterSalesServiceImpl implements IFsStoreAfterSalesService
     @Autowired
     private IFsStoreProductService productService;
     @Autowired
-    IErpOrderService erpOrderService;
+    private IErpOrderService erpOrderService;
     @Autowired
     private ISysConfigService configService;
     @Autowired
     private HuiFuService huiFuService;
 
     @Autowired
-    IFsUserService userService;
+    private IFsUserService userService;
 
     @Autowired
-    PayService ybPayService;
+    private PayService ybPayService;
 
     @Autowired
-    TzBankService tzBankService;
+    private TzBankService tzBankService;
     @Autowired
     private IFsStoreOrderService fsStoreOrderService;
     @Autowired
@@ -126,6 +137,11 @@ public class FsStoreAfterSalesServiceImpl implements IFsStoreAfterSalesService
     @Autowired
     private FsStoreAfterSalesMapper afterSalesMapper;
 
+    @Autowired
+    private IFsWarehouseCacheService fsWarehouseCacheService;
+    @Autowired
+    private IFsStorePaymentService fsStorePaymentService;
+
     /**
      * 查询售后记录
      *
@@ -690,6 +706,41 @@ public class FsStoreAfterSalesServiceImpl implements IFsStoreAfterSalesService
                             TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                             return R.error(result.getMessage());
                         }
+                    }else if (payment.getPayMode()==null||payment.getPayMode().equals("wx")){
+                        WxMiniProgramConfig wxMiniProgramConfig = new WxMiniProgramConfig();
+                        wxMiniProgramConfig.setAppid(payment.getAppId());
+                        List<WxMiniProgramConfig>  wxMiniProgramConfigs = wxMiniProgramConfigMapper.selectWxMiniProgramConfigList(wxMiniProgramConfig);
+                        WxMiniProgramConfig wConfig = wxMiniProgramConfigs.get(0);
+                        WxPayConfig payConfig = new WxPayConfig();
+                        payConfig.setAppId(wConfig.getAppid());
+                        payConfig.setMchId(wConfig.getWxMerchantNo());
+                        payConfig.setMchKey(wConfig.getWxKey());
+                        payConfig.setKeyPath(wConfig.getWxKeyPath());
+                        payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                        payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                        wxPayService.setConfig(payConfig);
+                        WxPayRefundRequest refundRequest = new WxPayRefundRequest();
+                        refundRequest.setOutTradeNo("store-"+payment.getPayCode());
+                        refundRequest.setOutRefundNo("store-"+payment.getPayCode());
+                        refundRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
+                        refundRequest.setRefundFee(WxPayUnifiedOrderRequest.yuanToFen(param.getRefundAmount().toString()));
+                        try {
+                            WxPayRefundResult refundResult = wxPayService.refund(refundRequest);
+                            WxPayRefundQueryResult refundQueryResult = wxPayService.refundQuery("", refundResult.getOutTradeNo(), refundResult.getOutRefundNo(), refundResult.getRefundId());
+                            if(refundQueryResult!=null&&refundQueryResult.getResultCode().equals("SUCCESS")){
+                                FsStorePayment paymentMap=new FsStorePayment();
+                                paymentMap.setPaymentId(payment.getPaymentId());
+                                paymentMap.setStatus(-1);
+                                paymentMap.setRefundTime(DateUtils.getNowDate());
+                                paymentMap.setRefundMoney(payment.getRefundMoney());
+                                fsStorePaymentService.updateFsStorePayment(paymentMap);
+                            }
+                            else {
+                                return R.error("退款请求失败"+refundQueryResult.getErrCodeDes());
+                            }
+                        } catch (WxPayException e) {
+                            return R.error("退款请求失败"+e.getErrCodeDes());
+                        }
                     }else if (payment.getPayMode()!=null&&payment.getPayMode().equals("hf")){
                         V2TradePaymentScanpayRefundRequest request = new V2TradePaymentScanpayRefundRequest();
                         request.setOrdAmt(payment.getPayMoney().toString());

+ 176 - 25
fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderServiceImpl.java

@@ -63,6 +63,7 @@ import com.fs.pay.pay.dto.RefundDTO;
 import com.fs.pay.pay.dto.WxJspayDTO;
 import com.fs.pay.pay.service.PayService;
 import com.fs.store.cache.IFsUserCacheService;
+import com.fs.store.cache.IFsWarehouseCacheService;
 import com.fs.store.cache.impl.IFsStoreProductCacheServiceImpl;
 import com.fs.store.config.StoreConfig;
 import com.fs.store.config.StoreIntegralConfig;
@@ -80,6 +81,9 @@ import com.fs.store.strategy.ShippingOrder;
 import com.fs.store.strategy.ShippingTemplateManager;
 import com.fs.store.vo.*;
 import com.fs.system.config.SnowflakeUtils;
+import com.fs.system.domain.WxMiniProgramConfig;
+import com.fs.system.mapper.FsCoursePlaySourceConfigMapper;
+import com.fs.system.mapper.WxMiniProgramConfigMapper;
 import com.fs.system.service.ISysConfigService;
 import com.fs.tzBank.TzBankService;
 import com.fs.tzBank.utils.TzConfigUtils;
@@ -90,6 +94,12 @@ import com.fs.wx.miniapp.config.WxMaConfiguration;
 import com.fs.wx.miniapp.config.WxMaProperties;
 import com.fs.wx.service.OrderQueryService;
 import com.fs.wx.service.ShippingService;
+import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.exception.WxPayException;
 import lombok.Synchronized;
 import me.chanjar.weixin.common.error.WxErrorException;
 import org.apache.commons.collections4.CollectionUtils;
@@ -125,6 +135,13 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
     @Autowired
     private CompanyMoneyLogsMapper moneyLogsMapper;
     @Autowired
+    private FsUserWxMapper fsUserWxMapper;
+    @Autowired
+    private FsCoursePlaySourceConfigMapper fsCoursePlaySourceConfigMapper;
+
+    @Autowired
+    private WxMiniProgramConfigMapper wxMiniProgramConfigMapper;
+    @Autowired
     private IFsStoreOrderStatusService orderStatusService;
     @Autowired
     private FsStoreCartMapper cartMapper;
@@ -415,7 +432,35 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
         }
 
         FsUser user=userService.selectFsUserById(order.getUserId());
-        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())){
+//        String json = configService.selectConfigByKey("store.pay");
+//        FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
+        WxMiniProgramConfig wxMiniProgramConfig = new WxMiniProgramConfig();
+        wxMiniProgramConfig.setAppid(param.getAppId());
+        List<WxMiniProgramConfig>  wxMiniProgramConfigs = wxMiniProgramConfigMapper.selectWxMiniProgramConfigList(wxMiniProgramConfig);
+        WxMiniProgramConfig wConfig = wxMiniProgramConfigs.get(0);
+        String openId = null;
+        String appId = param.getAppId();
+        if (StringUtils.isNotBlank(appId)) {
+            //查询fs_user_wx的openId
+            FsUserWx fsUserWx = fsUserWxMapper.selectListByUserIdAndAppId(user.getUserId(),appId);
+            logger.info("用户微信信息==============={}",fsUserWx);
+            if (fsUserWx != null) {
+                openId = fsUserWx.getOpenId();
+            }
+        } else {
+            appId = fsCoursePlaySourceConfigMapper.selectFsCoursePlaySourceConfigByAppId(param.getAppId()).getAppid();
+            openId = Objects.isNull(user) ? "" : user.getMaOpenId();
+            if (StringUtils.isBlank(openId)){
+                FsUserWx fsUserWx = fsUserWxMapper.selectListByUserIdAndAppId(user.getUserId(),appId);
+                logger.info("用户微信信息==============={}",fsUserWx);
+                if (Objects.nonNull(fsUserWx)){
+                    openId = fsUserWx.getOpenId();
+                }
+            }
+        }
+
+
+        if(user!=null&& StringUtils.isNotEmpty(openId)){
             //已改价处理
             if(order.getIsEditMoney()!=null&&order.getIsEditMoney()==1){
                 //改过价不做处理
@@ -446,15 +491,14 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
             String payCode = SnowflakeUtils.nextId();
 
             if(order.getPayType().equals("1")||order.getPayType().equals("2")){
-                String json = configService.selectConfigByKey("store.pay");
-                FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
+
                 List<FsStorePayment> fsStorePayments = fsStorePaymentMapper.selectFsStorePaymentByOrderIdNew(order.getId());
                 FsStorePayment storePayment;
                 if(CollectionUtils.isEmpty(fsStorePayments)){
                     storePayment=new FsStorePayment();
                     storePayment.setCompanyId(order.getCompanyId());
                     storePayment.setCompanyUserId(order.getCompanyUserId());
-                    storePayment.setPayMode(fsPayConfig.getType());
+                    storePayment.setPayMode("wx");
                     storePayment.setStatus(0);
                     storePayment.setPayCode(payCode);
                     storePayment.setPayMoney(order.getPayMoney());
@@ -462,14 +506,15 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
                     storePayment.setPayTypeCode("weixin");
                     storePayment.setBusinessType(2);
                     storePayment.setRemark("商城订单支付");
-                    storePayment.setOpenId(user.getRealName());
+                    storePayment.setOpenId(openId);
                     storePayment.setUserId(user.getUserId());
+                    storePayment.setAppId(appId);
                     storePayment.setBusinessOrderId(order.getId().toString());
                     storePayment.setOrderId(order.getId());
                     fsStorePaymentMapper.insertFsStorePayment(storePayment);
                 } else {
                     storePayment = fsStorePayments.get(0);
-                    storePayment.setPayMode(fsPayConfig.getType());
+                    storePayment.setPayMode("wx");
                     storePayment.setStatus(0);
                     storePayment.setPayMoney(order.getPayMoney());
                     storePayment.setCreateTime(new Date());
@@ -477,8 +522,9 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
                     storePayment.setBusinessType(2);
                     storePayment.setRemark("商城订单支付");
                     storePayment.setPayCode(payCode);
-                    storePayment.setOpenId(user.getRealName());
+                    storePayment.setOpenId(openId);
                     storePayment.setUserId(user.getUserId());
+                    storePayment.setAppId(appId);
                     storePayment.setBusinessOrderId(order.getId().toString());
                     storePayment.setOrderId(order.getId());
                     fsStorePaymentMapper.updateFsStorePayment(storePayment);
@@ -489,11 +535,12 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
                 processContext.setPayType(param.getPayType());
                 processContext.setPaymentId(storePayment.getPaymentId());
                 processContext.setPayCode(storePayment.getPayCode());
-                processContext.setFsPayConfig(fsPayConfig);
+                processContext.setWxMiniProgramConfig(wConfig);
+                processContext.setStorePayment(storePayment);
                 processContext.setUserId(order.getUserId());
                 processContext.setGoodsInfo("商城订单支付");
                 processContext.setOrderPrefix("store-");
-                PaymentHandler payment = PaymentHandlerHolder.findBest(fsPayConfig.getType());
+                PaymentHandler payment = PaymentHandlerHolder.findBest("wx");
                 if(ObjectUtil.isNull(payment)){
                     throw new CustomException("支付方式不存在");
                 }
@@ -1191,6 +1238,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
             List<FsStorePayment> fsStorePayments = fsStorePaymentService.selectFsStorePaymentByOrderIdNew(order.getId());
             if(CollectionUtils.isNotEmpty(fsStorePayments)){
                 FsStorePayment fsStorePayment = fsStorePayments.get(0);
+                fsWxExpressTask.setAppid(fsStorePayment.getAppId());
                 fsWxExpressTask.setPayCode(fsStorePayment.getPayCode());
             }
             fsWxExpressTaskMapper.insert(fsWxExpressTask);
@@ -2444,6 +2492,12 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
                     payProcessContext.setPayCode(payment.getPayCode());
                     payProcessContext.setUserId(order.getUserId());
                     payProcessContext.setOrderPrefix("refund-");
+                    WxMiniProgramConfig wxMiniProgramConfig = new WxMiniProgramConfig();
+                    wxMiniProgramConfig.setAppid(payment.getAppId());
+                    List<WxMiniProgramConfig>  wxMiniProgramConfigs = wxMiniProgramConfigMapper.selectWxMiniProgramConfigList(wxMiniProgramConfig);
+                    WxMiniProgramConfig wConfig = wxMiniProgramConfigs.get(0);
+                    payProcessContext.setWxMiniProgramConfig(wConfig);
+                    payProcessContext.setStorePayment(payment);
                     best.refundOrder(payProcessContext);
                 }
             }
@@ -3144,7 +3198,25 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
     @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
     public R otherPayment(FsStoreOrderOtherPayParam param) {
 
-        final WxMaService wxService = WxMaConfiguration.getMaService(properties.getConfigs().get(0).getAppid());
+        String courseMa_appId;
+
+        System.out.println("appid"+param.getCode());
+        logger.info("appid"+param.getCode());
+        if(org.apache.commons.lang3.StringUtils.isNotEmpty(param.getAppId())){
+            try {
+                courseMa_appId = fsCoursePlaySourceConfigMapper.selectFsCoursePlaySourceConfigByAppId(param.getAppId()).getAppid();
+            } catch (Exception e) {
+                courseMa_appId = param.getAppId();
+            }
+        }else{
+            courseMa_appId = properties.getConfigs().get(0).getAppid();
+        }
+        WxMiniProgramConfig wxMiniProgramConfig = new WxMiniProgramConfig();
+        wxMiniProgramConfig.setAppid(param.getAppId());
+        List<WxMiniProgramConfig>  wxMiniProgramConfigs = wxMiniProgramConfigMapper.selectWxMiniProgramConfigList(wxMiniProgramConfig);
+        WxMiniProgramConfig wConfig = wxMiniProgramConfigs.get(0);
+
+        final WxMaService wxService = WxMaConfiguration.getMaService(courseMa_appId);
         try {
             String ip = IpUtil.getRequestIp();
             WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
@@ -3180,8 +3252,8 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
 
             String payCode = SnowflakeUtils.nextId();
-            String json = configService.selectConfigByKey("store.pay");
-            FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
+           /* String json = configService.selectConfigByKey("store.pay");
+            FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);*/
             List<FsStorePayment> fsStorePayments = fsStorePaymentMapper.selectFsStorePaymentByOrderIdNew(order.getId());
 
             FsStorePayment storePayment;
@@ -3190,7 +3262,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
                 storePayment.setCompanyId(order.getCompanyId());
                 storePayment.setCompanyUserId(order.getCompanyUserId());
                 storePayment.setStatus(0);
-                storePayment.setPayMode(fsPayConfig.getType());
+                storePayment.setPayMode("wx");
                 storePayment.setPayCode(payCode);
                 storePayment.setPayMoney(order.getPayMoney());
                 storePayment.setCreateTime(new Date());
@@ -3198,6 +3270,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
                 storePayment.setBusinessType(2);
                 storePayment.setRemark("商城订单支付");
                 storePayment.setOpenId(session.getOpenid());
+                storePayment.setAppId(courseMa_appId);
                 storePayment.setUserId(user.getUserId());
                 storePayment.setBusinessOrderId(order.getId().toString());
                 storePayment.setOrderId(order.getId());
@@ -3209,6 +3282,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
                 storePayment.setCreateTime(new Date());
                 storePayment.setPayTypeCode("weixin");
                 storePayment.setBusinessType(2);
+                storePayment.setAppId(courseMa_appId);
                 storePayment.setRemark("商城订单支付");
                 storePayment.setOpenId(session.getOpenid());
                 storePayment.setUserId(user.getUserId());
@@ -3217,7 +3291,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
                 fsStorePaymentMapper.updateFsStorePayment(storePayment);
             }
 
-            PaymentHandler payment = PaymentHandlerHolder.findBest(fsPayConfig.getType());
+            PaymentHandler payment = PaymentHandlerHolder.findBest("wx");
             if(ObjectUtil.isNull(payment)){
                 throw new CustomException("支付方式不存在");
             }
@@ -3226,7 +3300,8 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
             processContext.setPayType(null);
             processContext.setPaymentId(storePayment.getPaymentId());
             processContext.setPayCode(storePayment.getPayCode());
-            processContext.setFsPayConfig(fsPayConfig);
+            processContext.setWxMiniProgramConfig(wConfig);
+            processContext.setStorePayment(storePayment);
             processContext.setUserId(order.getUserId());
             processContext.setGoodsInfo("商城订单支付");
             processContext.setOrderPrefix("store-");
@@ -3246,7 +3321,22 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
     @Override
     @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
     public R otherPaymentRemain(FsStoreOrderOtherPayParam param) {
-        final WxMaService wxService = WxMaConfiguration.getMaService(properties.getConfigs().get(0).getAppid());
+        String courseMa_appId;
+
+        System.out.println("appid"+param.getCode());
+        logger.info("appid"+param.getCode());
+        if(org.apache.commons.lang3.StringUtils.isNotEmpty(param.getAppId())){
+            try {
+                courseMa_appId = fsCoursePlaySourceConfigMapper.selectFsCoursePlaySourceConfigByAppId(param.getAppId()).getAppid();
+            } catch (Exception e) {
+                courseMa_appId = param.getAppId();
+            }
+        }else{
+            courseMa_appId = properties.getConfigs().get(0).getAppid();
+        }
+
+
+        final WxMaService wxService = WxMaConfiguration.getMaService(courseMa_appId);
         try {
             String ip = IpUtil.getRequestIp();
             WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
@@ -3286,6 +3376,33 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
             //易宝支付
             String json = configService.selectConfigByKey("store.pay");
             FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
+            WxMiniProgramConfig wxMiniProgramConfig = new WxMiniProgramConfig();
+            wxMiniProgramConfig.setAppid(param.getAppId());
+            List<WxMiniProgramConfig>  wxMiniProgramConfigs = wxMiniProgramConfigMapper.selectWxMiniProgramConfigList(wxMiniProgramConfig);
+            WxMiniProgramConfig wConfig = wxMiniProgramConfigs.get(0);
+            String openId = null;
+            String appId = param.getAppId();
+            if (StringUtils.isNotBlank(appId)) {
+                //查询fs_user_wx的openId
+                FsUserWx fsUserWx = fsUserWxMapper.selectListByUserIdAndAppId(user.getUserId(),appId);
+                logger.info("用户微信信息==============={}",fsUserWx);
+                if (fsUserWx != null) {
+                    openId = fsUserWx.getOpenId();
+                }
+            } else {
+                appId = fsCoursePlaySourceConfigMapper.selectFsCoursePlaySourceConfigByAppId(param.getAppId()).getAppid();
+                openId = Objects.isNull(user) ? "" : user.getMaOpenId();
+                if (StringUtils.isBlank(openId)){
+                    FsUserWx fsUserWx = fsUserWxMapper.selectListByUserIdAndAppId(user.getUserId(),appId);
+                    logger.info("用户微信信息==============={}",fsUserWx);
+                    if (Objects.nonNull(fsUserWx)){
+                        openId = fsUserWx.getOpenId();
+                    }
+                }
+            }
+
+
+
             FsStorePayment storePayment=new FsStorePayment();
             storePayment.setCompanyId(order.getCompanyId());
             storePayment.setCompanyUserId(order.getCompanyUserId());
@@ -3296,7 +3413,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
             storePayment.setPayTypeCode("weixin");
             storePayment.setBusinessType(2);
             storePayment.setRemark("商城订单尾款支付");
-            storePayment.setOpenId(user.getRealName());
+            storePayment.setOpenId(openId);
             storePayment.setUserId(user.getUserId());
             storePayment.setBusinessOrderId(order.getId().toString());
             storePayment.setOrderId(order.getId());
@@ -3306,7 +3423,8 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
             if (fsPayConfig.getType().equals("hf")){
                 HuiFuCreateOrder o = new HuiFuCreateOrder();
                 o.setTradeType("T_MINIAPP");
-                o.setOpenid(user.getMaOpenId());
+                o.setOpenid(openId);
+                o.setAppId(appId);
                 o.setReqSeqId("store_remain-"+storePayment.getPayCode());
                 o.setTransAmt(storePayment.getPayMoney().toString());
                 o.setGoodsDesc("支付订单尾款");
@@ -3315,12 +3433,15 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
                     FsStorePayment mt=new FsStorePayment();
                     mt.setPaymentId(storePayment.getPaymentId());
                     mt.setTradeNo(result.getHf_seq_id());
+                    mt.setAppId(appId);
                     fsStorePaymentMapper.updateFsStorePayment(mt);
                     redisCache.setCacheObject("isPaying:"+order.getId(),order.getId().toString(),1, TimeUnit.MINUTES);
                     return R.ok().put("result",result.getPay_info());
                 }else{
                     return R.error(result.getResp_desc());
                 }
+            }else if (fsPayConfig.getType().equals("wx")){
+                return orderService.otherPayment(param);
             }else if (fsPayConfig.getType().equals("yb")){
                 WxJspayDTO p = new WxJspayDTO();
                 // 使用setter方法为对象赋值
@@ -3329,7 +3450,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
                 p.setBody("支付订单尾款");
                 p.setIsMinipg("1");
                 p.setReturnUrl(fsPayConfig.getYbNotifyUrl());
-                p.setOpenId(user.getMaOpenId());
+                p.setOpenId(openId);
                 p.setAttach("");
                 p.setStoreid("0");
                 CreateWxOrderResult wxOrder = ybPayService.createWxOrder(p);
@@ -3686,10 +3807,36 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
             return R.error("此订单已支付");
         }
         FsUser user=userService.selectFsUserById(order.getUserId());
-        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())){
+        String json = configService.selectConfigByKey("store.pay");
+        FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
+        WxMiniProgramConfig wxMiniProgramConfig = new WxMiniProgramConfig();
+        wxMiniProgramConfig.setAppid(param.getAppId());
+        List<WxMiniProgramConfig>  wxMiniProgramConfigs = wxMiniProgramConfigMapper.selectWxMiniProgramConfigList(wxMiniProgramConfig);
+        WxMiniProgramConfig wConfig = wxMiniProgramConfigs.get(0);
+        String openId = null;
+        String appId = param.getAppId();
+        if (StringUtils.isNotBlank(appId)) {
+            //查询fs_user_wx的openId
+            FsUserWx fsUserWx = fsUserWxMapper.selectListByUserIdAndAppId(user.getUserId(),appId);
+            logger.info("用户微信信息==============={}",fsUserWx);
+            if (fsUserWx != null) {
+                openId = fsUserWx.getOpenId();
+            }
+        } else {
+            appId = fsCoursePlaySourceConfigMapper.selectFsCoursePlaySourceConfigByAppId(param.getAppId()).getAppid();
+            openId = Objects.isNull(user) ? "" : user.getMaOpenId();
+            if (StringUtils.isBlank(openId)){
+                FsUserWx fsUserWx = fsUserWxMapper.selectListByUserIdAndAppId(user.getUserId(),appId);
+                logger.info("用户微信信息==============={}",fsUserWx);
+                if (Objects.nonNull(fsUserWx)){
+                    openId = fsUserWx.getOpenId();
+                }
+            }
+        }
+
+        if(user!=null&& StringUtils.isNotEmpty(openId)){
             String payCode = SnowflakeUtils.nextId();
-            String json = configService.selectConfigByKey("store.pay");
-            FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
+
 
             FsStorePayment storePayment=new FsStorePayment();
             storePayment.setCompanyId(order.getCompanyId());
@@ -3702,7 +3849,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
             storePayment.setPayTypeCode("weixin");
             storePayment.setBusinessType(2);
             storePayment.setRemark("商城订单尾款支付");
-            storePayment.setOpenId(user.getRealName());
+            storePayment.setOpenId(openId);
             storePayment.setUserId(user.getUserId());
             storePayment.setBusinessOrderId(order.getId().toString());
             storePayment.setOrderId(order.getId());
@@ -3711,7 +3858,8 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
             if (fsPayConfig.getType().equals("hf")){
                 HuiFuCreateOrder o = new HuiFuCreateOrder();
                 o.setTradeType("T_MINIAPP");
-                o.setOpenid(user.getMaOpenId());
+                o.setOpenid(openId);
+                o.setAppId(appId);
                 o.setReqSeqId("store_remain-"+storePayment.getPayCode());
                 o.setTransAmt(storePayment.getPayMoney().toString());
                 o.setGoodsDesc("商城订单尾款支付");
@@ -3721,6 +3869,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
                     FsStorePayment mt=new FsStorePayment();
                     mt.setPaymentId(storePayment.getPaymentId());
                     mt.setTradeNo(result.getHf_seq_id());
+                    mt.setAppId(appId);
                     fsStorePaymentMapper.updateFsStorePayment(mt);
                     redisCache.setCacheObject("isPaying:"+order.getId(),order.getId().toString(),1, TimeUnit.MINUTES);
                     return R.ok().put("result",result.getPay_info());
@@ -3728,6 +3877,8 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
                 else{
                     return R.error(result.getResp_desc());
                 }
+            }else if (fsPayConfig.getType().equals("wx")){
+                return orderService.pay(param);
             }else if(fsPayConfig.getType().equals("yb")){
                 WxJspayDTO p = new WxJspayDTO();
                 // 使用setter方法为对象赋值
@@ -3736,7 +3887,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
                 p.setBody("商城订单尾款支付");
                 p.setIsMinipg("1");
                 p.setReturnUrl(fsPayConfig.getYbNotifyUrl());
-                p.setOpenId(user.getMaOpenId());
+                p.setOpenId(openId);
                 p.setAttach("");
                 p.setStoreid("0");
                 CreateWxOrderResult wxOrder = ybPayService.createWxOrder(p);

+ 50 - 11
fs-service-system/src/main/java/com/fs/store/service/impl/FsStorePaymentServiceImpl.java

@@ -1,10 +1,7 @@
 package com.fs.store.service.impl;
 
 import java.math.BigDecimal;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.TimeUnit;
 
 import cn.hutool.core.util.IdUtil;
@@ -15,6 +12,7 @@ import com.fs.common.annotation.DataScope;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyUserService;
@@ -24,11 +22,15 @@ import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayQueryRequest;
 import com.fs.huifuPay.service.HuiFuService;
 import com.fs.pay.pay.util.PayUtil;
 import com.fs.store.domain.*;
+import com.fs.store.mapper.FsUserWxMapper;
 import com.fs.store.service.IFsStoreOrderService;
 import com.fs.store.service.channel.PaymentHandler;
 import com.fs.store.service.channel.PaymentHandlerHolder;
 import com.fs.store.service.channel.param.PayProcessContext;
 import com.fs.system.config.SnowflakeUtils;
+import com.fs.system.domain.WxMiniProgramConfig;
+import com.fs.system.mapper.FsCoursePlaySourceConfigMapper;
+import com.fs.system.mapper.WxMiniProgramConfigMapper;
 import com.fs.tzBank.TzBankService;
 import com.fs.store.param.FsStoreStatisticsParam;
 import com.fs.store.service.IFsCouponScheduleService;
@@ -66,6 +68,10 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService
     @Autowired
     private FsStorePaymentMapper fsStorePaymentMapper;
     @Autowired
+    private FsCoursePlaySourceConfigMapper fsCoursePlaySourceConfigMapper;
+    @Autowired
+    private WxMiniProgramConfigMapper wxMiniProgramConfigMapper;
+    @Autowired
     private IFsUserService userService;
 
     @Autowired
@@ -87,6 +93,9 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService
     @Autowired
     private OrderQueryService orderQueryService;
 
+    @Autowired
+    private FsUserWxMapper fsUserWxMapper;
+
     @Value("${wx.miniapp.configs[0].account}")
     private String account;
 
@@ -176,37 +185,67 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService
         FsUser user=userService.selectFsUserById(payment.getUserId());
 
 
-        String json = configService.selectConfigByKey("store.pay");
-        FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
+/*        String json = configService.selectConfigByKey("store.pay");
+        FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);*/
+        WxMiniProgramConfig wxMiniProgramConfig = new WxMiniProgramConfig();
+        wxMiniProgramConfig.setAppid(payment.getAppId());
+        List<WxMiniProgramConfig>  wxMiniProgramConfigs = wxMiniProgramConfigMapper.selectWxMiniProgramConfigList(wxMiniProgramConfig);
+        WxMiniProgramConfig wConfig = wxMiniProgramConfigs.get(0);
+        String openId = null;
+        String appId = payment.getAppId();
+        if (StringUtils.isNotBlank(appId)) {
+            //查询fs_user_wx的openId
+            FsUserWx fsUserWx = fsUserWxMapper.selectListByUserIdAndAppId(user.getUserId(),appId);
+            logger.info("用户微信信息==============={}",fsUserWx);
+            if (fsUserWx != null) {
+                openId = fsUserWx.getOpenId();
+            }
+        } else {
+            appId = fsCoursePlaySourceConfigMapper.selectFsCoursePlaySourceConfigByAppId(payment.getAppId()).getAppid();
+            openId = Objects.isNull(user) ? "" : user.getMaOpenId();
+            if (StringUtils.isBlank(openId)){
+                FsUserWx fsUserWx = fsUserWxMapper.selectListByUserIdAndAppId(user.getUserId(),appId);
+                logger.info("用户微信信息==============={}",fsUserWx);
+                if (Objects.nonNull(fsUserWx)){
+                    openId = fsUserWx.getOpenId();
+                }
+            }
+        }
+
+
+
+
         FsStorePayment storePayment=new FsStorePayment();
         storePayment.setCompanyId(payment.getCompanyId());
         storePayment.setCompanyUserId(payment.getCompanyUserId());
         storePayment.setStatus(0);
-        storePayment.setPayMode(fsPayConfig.getType());
+        storePayment.setPayMode("wx");
         storePayment.setPayCode(orderSn);
         storePayment.setPayMoney(payment.getPayMoney());
         storePayment.setCreateTime(new Date());
         storePayment.setPayTypeCode("weixin");
         storePayment.setBusinessType(1);
+        storePayment.setAppId(appId);
         storePayment.setRemark(payment.getRemark());
-        storePayment.setOpenId(user.getMaOpenId());
+        storePayment.setOpenId(openId);
         storePayment.setUserId(user.getUserId());
         if(companyUser==null){
             return R.error("销售帐号不存在");
         }
         storePayment.setDeptId(companyUser.getDeptId());
-        //易宝支付
         fsStorePaymentMapper.insertFsStorePayment(storePayment);
+
         PayProcessContext processContext = new PayProcessContext();
         processContext.setOrderId(null);
         processContext.setPayType(null);
         processContext.setPaymentId(storePayment.getPaymentId());
         processContext.setPayCode(orderSn);
-        processContext.setFsPayConfig(fsPayConfig);
+        processContext.setWxMiniProgramConfig(wConfig);
         processContext.setUserId(user.getUserId());
+        processContext.setStorePayment(storePayment);
         processContext.setGoodsInfo("医学管理方案服务");
         processContext.setOrderPrefix("payment-");
-        PaymentHandler paymentHandler = PaymentHandlerHolder.findBest(fsPayConfig.getType());
+        PaymentHandler paymentHandler = PaymentHandlerHolder.findBest("wx");
         if(ObjectUtil.isNull(payment)){
             throw new CustomException("支付方式不存在");
         }

+ 50 - 10
fs-service-system/src/main/java/com/fs/store/service/impl/FsUserServiceImpl.java

@@ -14,14 +14,11 @@ import cn.hutool.json.JSONUtil;
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.IpUtil;
-import com.fs.store.domain.FsStoreOrder;
-import com.fs.store.domain.FsStoreOrderItem;
-import com.fs.store.domain.FsUserBill;
+import com.fs.store.domain.*;
 import com.fs.store.dto.FsStoreCartDTO;
 import com.fs.store.enums.BillDetailEnum;
-import com.fs.store.mapper.FsStoreOrderMapper;
-import com.fs.store.mapper.FsStoreProductAttrValueMapper;
-import com.fs.store.mapper.FsUserTuiMoneyRankMapper;
+import com.fs.store.mapper.*;
+import com.fs.store.param.LoginMaWxParam;
 import com.fs.store.param.LoginMpWxParam;
 import com.fs.store.service.IFsUserBillService;
 import com.fs.store.utils.JwtUtils;
@@ -30,6 +27,7 @@ import com.fs.store.vo.FsUserVO;
 import com.fs.store.vo.FsCompanyUserListQueryVO;
 import com.fs.store.vo.FsUserShareVO;
 import com.fs.store.vo.FsUserTuiVO;
+import com.fs.system.mapper.FsCoursePlaySourceConfigMapper;
 import com.fs.wx.miniapp.config.WxMaConfiguration;
 import com.fs.wx.miniapp.config.WxMaProperties;
 import me.chanjar.weixin.common.error.WxErrorException;
@@ -42,8 +40,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.EnableAspectJAutoProxy;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
-import com.fs.store.mapper.FsUserMapper;
-import com.fs.store.domain.FsUser;
 import com.fs.store.service.IFsUserService;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -65,6 +61,8 @@ public class FsUserServiceImpl implements IFsUserService
     @Autowired
     private FsUserMapper fsUserMapper;
 
+    @Autowired
+    private FsUserWxMapper fsUserWxMapper;
     @Autowired
     private FsStoreProductAttrValueMapper storeProductAttrValueMapper;
 
@@ -73,6 +71,9 @@ public class FsUserServiceImpl implements IFsUserService
     @Autowired
     private FsStoreOrderMapper storeOrderMapper;
 
+    @Autowired
+    private FsCoursePlaySourceConfigMapper fsCoursePlaySourceConfigMapper;
+
     @Autowired
     private WxMaProperties maProperties;
 
@@ -387,8 +388,25 @@ public class FsUserServiceImpl implements IFsUserService
         if (StringUtils.isBlank(param.getCode())) {
             return R.error("code不存在");
         }
+
+        String courseMa_appId;
+
+        System.out.println("appid"+param.getCode());
+        logger.info("appid"+param.getCode());
+        if(StringUtils.isNotEmpty(param.getAppId())){
+            try {
+                courseMa_appId = fsCoursePlaySourceConfigMapper.selectFsCoursePlaySourceConfigByAppId(param.getAppId()).getAppid();
+            } catch (Exception e) {
+                courseMa_appId = param.getAppId();
+            }
+        }else{
+            courseMa_appId = maProperties.getConfigs().get(0).getAppid();
+        }
+
+
+
         try {
-            WxMaService wxService = WxMaConfiguration.getMaService(maProperties.getConfigs().get(0).getAppid());
+            WxMaService wxService = WxMaConfiguration.getMaService(courseMa_appId);
 
             WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
             FsUser user=fsUserMapper.selectFsUserByMaOpenIdOrUnionId(session.getOpenid(),session.getUnionid());
@@ -408,13 +426,35 @@ public class FsUserServiceImpl implements IFsUserService
                     }
                 });
             }
+            LoginMaWxParam loginMaWxParam = new LoginMaWxParam();
+            loginMaWxParam.setAppId(param.getAppId());
+            loginMaWxParam.setCompanyId(user.getCompanyId());
+
+            handleFsUserWx(user,loginMaWxParam,session);
             String token = jwtUtils.generateToken(user.getUserId());
             return R.ok("登录成功").put("token",token).put("user", user);
         } catch (WxErrorException e) {
             return R.error("授权失败,"+e.getMessage());
         }
     }
-
+    public void handleFsUserWx(FsUser user, LoginMaWxParam param, WxMaJscode2SessionResult session) {
+        if (user == null) return;
+        // 尝试更新
+        boolean updated = fsUserWxMapper.updateFsUserWx(user.getUserId(),param.getAppId(),session.getOpenid(),param.getCompanyId(),session.getUnionid() == null ? "" : session.getUnionid(),new Date())> 0;
+        // 如果更新失败(记录不存在),则插入
+        if (!updated) {
+            FsUserWx fsUserWx = new FsUserWx();
+            fsUserWx.setType(1);
+            fsUserWx.setFsUserId(user.getUserId());
+            fsUserWx.setCompanyId(param.getCompanyId());
+            fsUserWx.setAppId(param.getAppId());
+            fsUserWx.setOpenId(session.getOpenid());
+            fsUserWx.setUnionId(session.getUnionid() == null ? "" : session.getUnionid());
+            fsUserWx.setCreateTime(new Date());
+            fsUserWx.setUpdateTime(new Date());
+            fsUserWxMapper.insertOrUpdateByUniqueKey(fsUserWx);
+        }
+    }
     private FsUser saveUser(LoginMpWxParam param, WxMaService wxService, WxMaJscode2SessionResult session, String ip) {
         FsUser user;
         // 解密

+ 69 - 0
fs-service-system/src/main/java/com/fs/system/domain/WxMiniProgramConfig.java

@@ -0,0 +1,69 @@
+package com.fs.system.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+/**
+ * 微信小程序支付配置对象 wx_mini_program_config
+ *
+ * @author fs
+ * @date 2025-12-01
+ */
+@Data
+public class WxMiniProgramConfig extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 主键ID */
+    private Long id;
+
+    /** 小程序名称 */
+    @Excel(name = "小程序名称")
+    private String appName;
+
+    /** 小程序appid */
+    @Excel(name = "小程序appid")
+    private String appid;
+
+    /** 小程序密钥 */
+    @Excel(name = "小程序密钥")
+    private String appSecret;
+
+    /** 微信商户号 */
+    @Excel(name = "微信商户号")
+    private String wxMerchantNo;
+
+    /** 微信API密钥 */
+    @Excel(name = "微信API密钥")
+    private String wxKey;
+
+    @Excel(name = "微信V3 API密钥")
+    private String wxV3Key;
+
+    /** 微信证书路径 */
+    @Excel(name = "微信证书路径")
+    private String wxKeyPath;
+
+    /** 微信支付回调地址 */
+    @Excel(name = "微信支付回调地址")
+    private String wxNotifyUrl;
+
+    /** 状态 */
+    @Excel(name = "状态")
+    private Long status;
+
+    @Excel(name = "商户简称")
+    private String merchantShortName;
+
+    @Excel(name = "管理员")
+    private String adminName;
+
+    @Excel(name = "签约时间")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date signingTime;
+}

+ 69 - 0
fs-service-system/src/main/java/com/fs/system/mapper/FsCoursePlaySourceConfigMapper.java

@@ -0,0 +1,69 @@
+package com.fs.system.mapper;
+
+import com.fs.store.domain.FsCoursePlaySourceConfig;
+
+import java.util.List;
+
+/**
+ * 点播播放源配置Mapper接口
+ *
+ * @author fs
+ * @date 2025-11-27
+ */
+public interface FsCoursePlaySourceConfigMapper {
+    /**
+     * 查询点播播放源配置
+     *
+     * @param id 点播播放源配置主键
+     * @return 点播播放源配置
+     */
+    FsCoursePlaySourceConfig selectFsCoursePlaySourceConfigById(Long id);
+    FsCoursePlaySourceConfig selectFsCoursePlaySourceConfigByAppId(String appId);
+
+    /**
+     * 查询点播播放源配置列表
+     *
+     * @param fsCoursePlaySourceConfig 点播播放源配置
+     * @return 点播播放源配置集合
+     */
+    List<FsCoursePlaySourceConfig> selectFsCoursePlaySourceConfigList(FsCoursePlaySourceConfig fsCoursePlaySourceConfig);
+
+    /**
+     * 新增点播播放源配置
+     *
+     * @param fsCoursePlaySourceConfig 点播播放源配置
+     * @return 结果
+     */
+    int insertFsCoursePlaySourceConfig(FsCoursePlaySourceConfig fsCoursePlaySourceConfig);
+
+    /**
+     * 修改点播播放源配置
+     *
+     * @param fsCoursePlaySourceConfig 点播播放源配置
+     * @return 结果
+     */
+    int updateFsCoursePlaySourceConfig(FsCoursePlaySourceConfig fsCoursePlaySourceConfig);
+
+    /**
+     * 删除点播播放源配置
+     *
+     * @param id 点播播放源配置主键
+     * @return 结果
+     */
+    int deleteFsCoursePlaySourceConfigById(Long id);
+
+    /**
+     * 批量删除点播播放源配置
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsCoursePlaySourceConfigByIds(Long[] ids);
+
+    /**
+     * 查询所有小程序数据
+     *
+     * @return
+     */
+    List<FsCoursePlaySourceConfig> selectFsCoursePlaySourceConfigAll();
+}

+ 61 - 0
fs-service-system/src/main/java/com/fs/system/mapper/WxMiniProgramConfigMapper.java

@@ -0,0 +1,61 @@
+package com.fs.system.mapper;
+
+import java.util.List;
+import com.fs.system.domain.WxMiniProgramConfig;
+
+/**
+ * 微信小程序支付配置Mapper接口
+ * 
+ * @author fs
+ * @date 2025-12-01
+ */
+public interface WxMiniProgramConfigMapper 
+{
+    /**
+     * 查询微信小程序支付配置
+     * 
+     * @param id 微信小程序支付配置ID
+     * @return 微信小程序支付配置
+     */
+    public WxMiniProgramConfig selectWxMiniProgramConfigById(Long id);
+
+    /**
+     * 查询微信小程序支付配置列表
+     * 
+     * @param wxMiniProgramConfig 微信小程序支付配置
+     * @return 微信小程序支付配置集合
+     */
+    public List<WxMiniProgramConfig> selectWxMiniProgramConfigList(WxMiniProgramConfig wxMiniProgramConfig);
+
+    /**
+     * 新增微信小程序支付配置
+     * 
+     * @param wxMiniProgramConfig 微信小程序支付配置
+     * @return 结果
+     */
+    public int insertWxMiniProgramConfig(WxMiniProgramConfig wxMiniProgramConfig);
+
+    /**
+     * 修改微信小程序支付配置
+     * 
+     * @param wxMiniProgramConfig 微信小程序支付配置
+     * @return 结果
+     */
+    public int updateWxMiniProgramConfig(WxMiniProgramConfig wxMiniProgramConfig);
+
+    /**
+     * 删除微信小程序支付配置
+     * 
+     * @param id 微信小程序支付配置ID
+     * @return 结果
+     */
+    public int deleteWxMiniProgramConfigById(Long id);
+
+    /**
+     * 批量删除微信小程序支付配置
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteWxMiniProgramConfigByIds(Long[] ids);
+}

+ 60 - 0
fs-service-system/src/main/java/com/fs/system/param/FsCoursePlaySourceConfigCreateParam.java

@@ -0,0 +1,60 @@
+package com.fs.system.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+@Data
+public class FsCoursePlaySourceConfigCreateParam {
+
+    @NotBlank(message = "名称不能为空")
+    @ApiModelProperty("小程序/公众号名称")
+    private String name;
+
+    @NotBlank(message = "appid不能为空")
+    @ApiModelProperty("小程序/公众号appid")
+    private String appid;
+
+    @NotBlank(message = "secret不能为空")
+    @ApiModelProperty("小程序/公众号secret")
+    private String secret;
+
+    @ApiModelProperty("小程序/公众号icon图标")
+    private String img;
+
+    @ApiModelProperty("小程序/公众号原始id")
+    private String originalId;
+
+    @NotBlank(message = "token不能为空")
+    @ApiModelProperty("token")
+    private String token;
+
+    @NotBlank(message = "aesKey不能为空")
+    @ApiModelProperty("aesKey")
+    private String aesKey;
+
+    @NotBlank(message = "msgDataFormat不能为空")
+    @ApiModelProperty("msgDataFormat")
+    private String msgDataFormat;
+
+    @NotNull(message = "类型不能为空")
+    @ApiModelProperty("类型 1主要小程序 2公众号 3炮灰小程序")
+    private Integer type;
+
+    @ApiModelProperty("所属公司")
+    private Long companyId;
+    /**
+     * 销售公司ids 用于判定销售公司可见编辑列表
+     */
+    @ApiModelProperty("销售公司ids 用于判定销售公司可见编辑列表")
+    private String setCompanyIds;
+
+    @ApiModelProperty("是否是互医/商城小程序")
+    private Integer isMall;
+    private Long createDeptId;
+
+    @ApiModelProperty("小程序状态:0正常,1半封禁,2封禁")
+    private Integer status;
+}

+ 57 - 0
fs-service-system/src/main/java/com/fs/system/param/FsCoursePlaySourceConfigEditParam.java

@@ -0,0 +1,57 @@
+package com.fs.system.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+@Data
+public class FsCoursePlaySourceConfigEditParam {
+
+    @NotNull(message = "主键ID不能为空")
+    @ApiModelProperty("主键ID")
+    private Long id;
+
+    @ApiModelProperty("小程序/公众号名称")
+    private String name;
+
+    @ApiModelProperty("小程序/公众号appid")
+    private String appid;
+
+    @ApiModelProperty("小程序/公众号secret")
+    private String secret;
+
+    @ApiModelProperty("小程序/公众号icon图标")
+    private String img;
+
+    @ApiModelProperty("小程序/公众号原始id")
+    private String originalId;
+
+    @ApiModelProperty("token")
+    private String token;
+
+    @ApiModelProperty("aesKey")
+    private String aesKey;
+
+    @ApiModelProperty("msgDataFormat")
+    private String msgDataFormat;
+
+    @ApiModelProperty("类型 1小程序 2公众号")
+    private Integer type;
+
+    @ApiModelProperty("所属公司")
+    private Long companyId;
+
+    /**
+     * 销售公司ids 用于判定销售公司可见编辑列表
+     */
+    @ApiModelProperty("销售公司ids 用于判定销售公司可见编辑列表")
+    private String setCompanyIds;
+
+    @ApiModelProperty("是否是互医/商城小程序")
+    private Integer isMall;
+    private Long createDeptId;
+
+    @ApiModelProperty("小程序状态:0正常,1半封禁,2封禁")
+    private Integer status;
+}

+ 61 - 0
fs-service-system/src/main/java/com/fs/system/service/IWxMiniProgramConfigService.java

@@ -0,0 +1,61 @@
+package com.fs.system.service;
+
+import java.util.List;
+import com.fs.system.domain.WxMiniProgramConfig;
+
+/**
+ * 微信小程序支付配置Service接口
+ * 
+ * @author fs
+ * @date 2025-12-01
+ */
+public interface IWxMiniProgramConfigService 
+{
+    /**
+     * 查询微信小程序支付配置
+     * 
+     * @param id 微信小程序支付配置ID
+     * @return 微信小程序支付配置
+     */
+    public WxMiniProgramConfig selectWxMiniProgramConfigById(Long id);
+
+    /**
+     * 查询微信小程序支付配置列表
+     * 
+     * @param wxMiniProgramConfig 微信小程序支付配置
+     * @return 微信小程序支付配置集合
+     */
+    public List<WxMiniProgramConfig> selectWxMiniProgramConfigList(WxMiniProgramConfig wxMiniProgramConfig);
+
+    /**
+     * 新增微信小程序支付配置
+     * 
+     * @param wxMiniProgramConfig 微信小程序支付配置
+     * @return 结果
+     */
+    public int insertWxMiniProgramConfig(WxMiniProgramConfig wxMiniProgramConfig);
+
+    /**
+     * 修改微信小程序支付配置
+     * 
+     * @param wxMiniProgramConfig 微信小程序支付配置
+     * @return 结果
+     */
+    public int updateWxMiniProgramConfig(WxMiniProgramConfig wxMiniProgramConfig);
+
+    /**
+     * 批量删除微信小程序支付配置
+     * 
+     * @param ids 需要删除的微信小程序支付配置ID
+     * @return 结果
+     */
+    public int deleteWxMiniProgramConfigByIds(Long[] ids);
+
+    /**
+     * 删除微信小程序支付配置信息
+     * 
+     * @param id 微信小程序支付配置ID
+     * @return 结果
+     */
+    public int deleteWxMiniProgramConfigById(Long id);
+}

+ 112 - 0
fs-service-system/src/main/java/com/fs/system/service/impl/WxMiniProgramConfigServiceImpl.java

@@ -0,0 +1,112 @@
+package com.fs.system.service.impl;
+
+import java.util.List;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.fs.common.utils.DateUtils;
+import com.fs.store.domain.FsCoursePlaySourceConfig;
+import com.fs.system.mapper.FsCoursePlaySourceConfigMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.fs.system.mapper.WxMiniProgramConfigMapper;
+import com.fs.system.domain.WxMiniProgramConfig;
+import com.fs.system.service.IWxMiniProgramConfigService;
+
+/**
+ * 微信小程序支付配置Service业务层处理
+ *
+ * @author fs
+ * @date 2025-12-01
+ */
+@Service
+public class WxMiniProgramConfigServiceImpl implements IWxMiniProgramConfigService
+{
+    @Autowired
+    private WxMiniProgramConfigMapper wxMiniProgramConfigMapper;
+    @Autowired
+    private FsCoursePlaySourceConfigMapper fsCoursePlaySourceConfigMapper;
+
+    /**
+     * 查询微信小程序支付配置
+     *
+     * @param id 微信小程序支付配置ID
+     * @return 微信小程序支付配置
+     */
+    @Override
+    public WxMiniProgramConfig selectWxMiniProgramConfigById(Long id)
+    {
+        return wxMiniProgramConfigMapper.selectWxMiniProgramConfigById(id);
+    }
+
+    /**
+     * 查询微信小程序支付配置列表
+     *
+     * @param wxMiniProgramConfig 微信小程序支付配置
+     * @return 微信小程序支付配置
+     */
+    @Override
+    public List<WxMiniProgramConfig> selectWxMiniProgramConfigList(WxMiniProgramConfig wxMiniProgramConfig)
+    {
+        return wxMiniProgramConfigMapper.selectWxMiniProgramConfigList(wxMiniProgramConfig);
+    }
+
+    /**
+     * 新增微信小程序支付配置
+     *
+     * @param wxMiniProgramConfig 微信小程序支付配置
+     * @return 结果
+     */
+    @Override
+    public int insertWxMiniProgramConfig(WxMiniProgramConfig wxMiniProgramConfig)
+    {
+        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectFsCoursePlaySourceConfigByAppId(wxMiniProgramConfig.getAppid());
+        if (ObjectUtil.isNotEmpty(fsCoursePlaySourceConfig)){
+            wxMiniProgramConfig.setAppName(fsCoursePlaySourceConfig.getName());
+            wxMiniProgramConfig.setAppSecret(fsCoursePlaySourceConfig.getSecret());
+        }
+        wxMiniProgramConfig.setCreateTime(DateUtils.getNowDate());
+        return wxMiniProgramConfigMapper.insertWxMiniProgramConfig(wxMiniProgramConfig);
+    }
+
+    /**
+     * 修改微信小程序支付配置
+     *
+     * @param wxMiniProgramConfig 微信小程序支付配置
+     * @return 结果
+     */
+    @Override
+    public int updateWxMiniProgramConfig(WxMiniProgramConfig wxMiniProgramConfig)
+    {
+        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectFsCoursePlaySourceConfigByAppId(wxMiniProgramConfig.getAppid());
+        if (ObjectUtil.isNotEmpty(fsCoursePlaySourceConfig)){
+            wxMiniProgramConfig.setAppName(fsCoursePlaySourceConfig.getName());
+            wxMiniProgramConfig.setAppSecret(fsCoursePlaySourceConfig.getSecret());
+        }
+        wxMiniProgramConfig.setUpdateTime(DateUtils.getNowDate());
+        return wxMiniProgramConfigMapper.updateWxMiniProgramConfig(wxMiniProgramConfig);
+    }
+
+    /**
+     * 批量删除微信小程序支付配置
+     *
+     * @param ids 需要删除的微信小程序支付配置ID
+     * @return 结果
+     */
+    @Override
+    public int deleteWxMiniProgramConfigByIds(Long[] ids)
+    {
+        return wxMiniProgramConfigMapper.deleteWxMiniProgramConfigByIds(ids);
+    }
+
+    /**
+     * 删除微信小程序支付配置信息
+     *
+     * @param id 微信小程序支付配置ID
+     * @return 结果
+     */
+    @Override
+    public int deleteWxMiniProgramConfigById(Long id)
+    {
+        return wxMiniProgramConfigMapper.deleteWxMiniProgramConfigById(id);
+    }
+}

+ 5 - 0
fs-service-system/src/main/java/com/fs/wx/domain/FsWxExpressTask.java

@@ -93,4 +93,9 @@ public class FsWxExpressTask {
      * 快递编号
      */
     private String expressNo;
+
+    /**
+     * 小程序ID
+     */
+    private String appid;
 }

+ 2 - 2
fs-service-system/src/main/java/com/fs/wx/mapper/FsWxExpressTaskMapper.java

@@ -23,8 +23,8 @@ public interface FsWxExpressTaskMapper {
      * @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) " +
-            "VALUES (#{orderCode}, #{userId}, #{data}, #{status}, #{retryCount}, #{maxRetries}, #{requestParams}, #{requestBody}, #{responseBody}, #{errorMessage}, #{createTime}, #{updateTime},#{expressCompany},#{expressNo})")
+    @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);
 

+ 28 - 6
fs-service-system/src/main/java/com/fs/wx/miniapp/config/WxMaConfiguration.java

@@ -7,6 +7,9 @@ import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
 import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
 import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;
 import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
+import com.fs.common.utils.spring.SpringUtils;
+import com.fs.store.domain.FsCoursePlaySourceConfig;
+import com.fs.system.mapper.FsCoursePlaySourceConfigMapper;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
@@ -37,14 +40,33 @@ public class WxMaConfiguration {
     }
 
     public static WxMaService getMaService(String appid) {
-        WxMaService wxService = maServices.get(appid);
-        if (wxService == null) {
-            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
-        }
+        return maServices.computeIfAbsent(appid,e->{
+            // 查询数据库
+            FsCoursePlaySourceConfigMapper configMapper = SpringUtils.getBean(FsCoursePlaySourceConfigMapper.class);
 
-        return wxService;
-    }
+            FsCoursePlaySourceConfig config = configMapper.selectFsCoursePlaySourceConfigByAppId(appid);
+            if (config == null) {
+                throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
+            }
 
+            return getWxMaService(config.getAppid(), config.getSecret(), config.getToken(), config.getAesKey(), config.getMsgDataFormat());
+        });
+    }
+    /**
+     * 初始化WxMaService
+     */
+    private static WxMaService getWxMaService(String appid, String secret, String token, String aesKey, String msgDataFormat) {
+        WxMaDefaultConfigImpl maConfig = new WxMaDefaultConfigImpl();
+        maConfig.setAppid(appid);
+        maConfig.setSecret(secret);
+        maConfig.setToken(token);
+        maConfig.setAesKey(aesKey);
+        maConfig.setMsgDataFormat(msgDataFormat);
+
+        WxMaService service = new WxMaServiceImpl();
+        service.setWxMaConfig(maConfig);
+        return service;
+    }
     public static WxMaMessageRouter getRouter(String appid) {
         return routers.get(appid);
     }

+ 1 - 0
fs-service-system/src/main/resources/mapper/company/CompanyMapper.xml

@@ -50,6 +50,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectCompanyVo"/>
         where company_id = #{companyId}
     </select>
+    <select id="selectAllCompanyList" resultType="com.fs.store.vo.OptionsVO"></select>
 
     <insert id="insertCompany" parameterType="Company" useGeneratedKeys="true" keyProperty="companyId">
         insert into company

+ 6 - 1
fs-service-system/src/main/resources/mapper/store/FsStorePaymentMapper.xml

@@ -28,10 +28,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="orderId"    column="order_id"    />
         <result property="isPayRemain"    column="is_pay_remain"    />
         <result property="payMode"    column="pay_mode"    />
+        <result property="appId"    column="app_id"    />
     </resultMap>
 
     <sql id="selectFsStorePaymentVo">
-        select payment_id,pay_mode, pay_code, pay_type_code, pay_money, pay_time, create_time, trade_no, user_id, open_id, business_type, business_order_id, status,remark,company_id,company_user_id,dept_id,bank_transaction_id,bank_serial_no,refund_money,refund_time,order_id,is_pay_remain from fs_store_payment
+        select payment_id,pay_mode,app_id, pay_code, pay_type_code, pay_money, pay_time, create_time, trade_no, user_id, open_id, business_type, business_order_id, status,remark,company_id,company_user_id,dept_id,bank_transaction_id,bank_serial_no,refund_money,refund_time,order_id,is_pay_remain from fs_store_payment
 
     </sql>
 
@@ -55,6 +56,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="bankTransactionId != null "> and bank_transaction_id = #{bankTransactionId}</if>
             <if test="bankSerialNo != null "> and bank_serial_no = #{bankSerialNo}</if>
             <if test="orderId != null "> and order_id = #{orderId}</if>
+            <if test="appId != null and appId !=''"> and app_id = #{appId}</if>
         </where>
     </select>
 
@@ -88,6 +90,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="orderId != null">order_id,</if>
             <if test="isPayRemain != null">is_pay_remain,</if>
             <if test="payMode != null">pay_mode,</if>
+            <if test="appId != null">app_id,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="payCode != null">#{payCode},</if>
@@ -112,6 +115,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="orderId != null">#{orderId},</if>
             <if test="isPayRemain != null">#{isPayRemain},</if>
             <if test="payMode != null">#{payMode},</if>
+            <if test="appId != null">#{appId},</if>
          </trim>
     </insert>
 
@@ -140,6 +144,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="orderId != null">order_id = #{orderId},</if>
             <if test="isPayRemain != null">is_pay_remain = #{isPayRemain},</if>
             <if test="payMode != null">pay_mode = #{payMode},</if>
+            <if test="appId != null">app_id = #{appId},</if>
         </trim>
         where payment_id = #{paymentId}
     </update>

+ 44 - 0
fs-service-system/src/main/resources/mapper/store/FsUserWxMapper.xml

@@ -0,0 +1,44 @@
+<?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.store.mapper.FsUserWxMapper">
+
+    <insert id="insertOrUpdateByUniqueKey">
+        insert into fs_user_wx
+            (fs_user_id, app_id, union_id, open_id, create_time, update_time)
+        values
+            (#{fsUserId}, #{appId}, #{unionId}, #{openId}, #{createTime, jdbcType=TIMESTAMP}, #{updateTime, jdbcType=TIMESTAMP})
+        ON DUPLICATE KEY UPDATE
+        <if test="unionId != null">
+            union_id = VALUES(union_id),
+        </if>
+            open_id     = VALUES(open_id),
+            update_time = VALUES(update_time)
+    </insert>
+
+
+    <update id="updateFsUserWx">
+        UPDATE fs_user_wx
+        <set>
+            <if test="companyId != null and companyId != ''">
+                company_id = #{companyId},
+            </if>
+            <if test="unionId != null">
+                union_id = #{unionId},
+            </if>
+            update_time = #{updateTime}
+        </set>
+        WHERE
+        fs_user_id = #{userId}
+        AND app_id = #{appId}
+        AND open_id = #{openId}
+    </update>
+
+    <select id="selectListByUserIdAndAppId" resultType="com.fs.store.domain.FsUserWx">
+        SELECT * FROM fs_user_wx
+        WHERE fs_user_id = #{userId}
+          AND app_id = #{appId} limit 1
+    </select>
+
+</mapper>

+ 130 - 0
fs-service-system/src/main/resources/mapper/system/FsCoursePlaySourceConfigMapper.xml

@@ -0,0 +1,130 @@
+<?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.system.mapper.FsCoursePlaySourceConfigMapper">
+
+    <resultMap type="FsCoursePlaySourceConfig" id="FsCoursePlaySourceConfigResult">
+        <result property="id"    column="id"    />
+        <result property="name"    column="name"    />
+        <result property="appid"    column="appid"    />
+        <result property="secret"    column="secret"    />
+        <result property="img"    column="img"    />
+        <result property="originalId"    column="original_id"    />
+        <result property="token"    column="token"    />
+        <result property="aesKey"    column="aes_key"    />
+        <result property="msgDataFormat"    column="msg_data_format"    />
+        <result property="isDel"    column="is_del"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="createUserId"    column="create_user_id"    />
+        <result property="createDeptId"    column="create_dept_id"    />
+        <result property="status"    column="status"    />
+    </resultMap>
+
+    <sql id="selectFsCoursePlaySourceConfigVo">
+        select id, name, appid,status, secret, img, original_id, token, aes_key, msg_data_format,is_del, create_time, update_time, create_user_id, create_dept_id from fs_course_play_source_config
+    </sql>
+
+    <select id="selectFsCoursePlaySourceConfigList" parameterType="FsCoursePlaySourceConfig" resultMap="FsCoursePlaySourceConfigResult">
+        <include refid="selectFsCoursePlaySourceConfigVo"/>
+        <where>
+            is_del = 0
+            <if test="name != null  and name != ''"> and name like concat('%', #{name}, '%')</if>
+            <if test="appid != null  and appid != ''"> and appid = #{appid}</if>
+            <if test="secret != null  and secret != ''"> and secret = #{secret}</if>
+            <if test="img != null  and img != ''"> and img = #{img}</if>
+            <if test="originalId != null  and originalId != ''"> and original_id = #{originalId}</if>
+            <if test="token != null  and token != ''"> and token = #{token}</if>
+            <if test="aesKey != null  and aesKey != ''"> and aes_key = #{aesKey}</if>
+            <if test="msgDataFormat != null  and msgDataFormat != ''"> and msg_data_format = #{msgDataFormat}</if>
+            <if test="isDel != null "> and is_del = #{isDel}</if>
+            <if test="createUserId != null "> and create_user_id = #{createUserId}</if>
+            <if test="createDeptId != null "> and create_dept_id = #{createDeptId}</if>
+        </where>
+    </select>
+
+    <select id="selectFsCoursePlaySourceConfigById" parameterType="Long" resultMap="FsCoursePlaySourceConfigResult">
+        <include refid="selectFsCoursePlaySourceConfigVo"/>
+        where id = #{id}
+    </select>
+    <select id="selectFsCoursePlaySourceConfigByAppId" parameterType="String" resultMap="FsCoursePlaySourceConfigResult">
+        <include refid="selectFsCoursePlaySourceConfigVo"/>
+        where appid = #{appid} and is_del = 0 limit 1
+    </select>
+    <insert id="insertFsCoursePlaySourceConfig" parameterType="FsCoursePlaySourceConfig" useGeneratedKeys="true" keyProperty="id">
+        insert into fs_course_play_source_config
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="name != null and name != ''">name,</if>
+            <if test="appid != null and appid != ''">appid,</if>
+            <if test="secret != null and secret != ''">secret,</if>
+            <if test="img != null">img,</if>
+            <if test="originalId != null">original_id,</if>
+            <if test="token != null and token != ''">token,</if>
+            <if test="aesKey != null and aesKey != ''">aes_key,</if>
+            <if test="msgDataFormat != null and msgDataFormat != ''">msg_data_format,</if>
+            <if test="isDel != null">is_del,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="createUserId != null">create_user_id,</if>
+            <if test="createDeptId != null">create_dept_id,</if>
+            <if test="status != null">`status`,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="name != null and name != ''">#{name},</if>
+            <if test="appid != null and appid != ''">#{appid},</if>
+            <if test="secret != null and secret != ''">#{secret},</if>
+            <if test="img != null">#{img},</if>
+            <if test="originalId != null">#{originalId},</if>
+            <if test="token != null and token != ''">#{token},</if>
+            <if test="aesKey != null and aesKey != ''">#{aesKey},</if>
+            <if test="msgDataFormat != null and msgDataFormat != ''">#{msgDataFormat},</if>
+            <if test="isDel != null">#{isDel},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="createUserId != null">#{createUserId},</if>
+            <if test="createDeptId != null">#{createDeptId},</if>
+            <if test="status != null">#{status},</if>
+        </trim>
+    </insert>
+
+    <update id="updateFsCoursePlaySourceConfig" parameterType="FsCoursePlaySourceConfig">
+        update fs_course_play_source_config
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="name != null and name != ''">name = #{name},</if>
+            <if test="appid != null and appid != ''">appid = #{appid},</if>
+            <if test="secret != null and secret != ''">secret = #{secret},</if>
+            <if test="img != null">img = #{img},</if>
+            <if test="originalId != null">original_id = #{originalId},</if>
+            <if test="token != null and token != ''">token = #{token},</if>
+            <if test="aesKey != null and aesKey != ''">aes_key = #{aesKey},</if>
+            <if test="msgDataFormat != null and msgDataFormat != ''">msg_data_format = #{msgDataFormat},</if>
+            <if test="isDel != null">is_del = #{isDel},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="createUserId != null">create_user_id = #{createUserId},</if>
+            <if test="createDeptId != null">create_dept_id = #{createDeptId},</if>
+            <if test="status != null">`status` = #{status},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteFsCoursePlaySourceConfigById" parameterType="Long">
+        delete from fs_course_play_source_config where id = #{id}
+    </delete>
+
+    <update id="deleteFsCoursePlaySourceConfigByIds" parameterType="String">
+        update fs_course_play_source_config
+        set is_del = 1
+        where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
+
+
+    <select id="selectFsCoursePlaySourceConfigAll"  resultMap="FsCoursePlaySourceConfigResult">
+        <include refid="selectFsCoursePlaySourceConfigVo"/>
+        where is_del = 0 and `status` = 0
+    </select>
+</mapper>

+ 122 - 0
fs-service-system/src/main/resources/mapper/system/WxMiniProgramConfigMapper.xml

@@ -0,0 +1,122 @@
+<?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.system.mapper.WxMiniProgramConfigMapper">
+
+    <resultMap type="WxMiniProgramConfig" id="WxMiniProgramConfigResult">
+        <result property="id"    column="id"    />
+        <result property="appName"    column="app_name"    />
+        <result property="appid"    column="appid"    />
+        <result property="appSecret"    column="app_secret"    />
+        <result property="wxMerchantNo"    column="wx_merchant_no"    />
+        <result property="wxKey"    column="wx_key"    />
+        <result property="wxV3Key"    column="wx_v3_key"    />
+        <result property="wxKeyPath"    column="wx_key_path"    />
+        <result property="wxNotifyUrl"    column="wx_notify_url"    />
+        <result property="status"    column="status"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="createBy"    column="create_by"    />
+        <result property="updateBy"    column="update_by"    />
+        <result property="remark"    column="remark"    />
+        <result property="merchantShortName"    column="merchant_short_name"    />
+        <result property="adminName"    column="admin_name"    />
+        <result property="signingTime"    column="signing_time"    />
+    </resultMap>
+
+    <sql id="selectWxMiniProgramConfigVo">
+        select id, app_name,wx_v3_key,merchant_short_name,admin_name,signing_time, appid, app_secret, wx_merchant_no, wx_key, wx_key_path, wx_notify_url, status, create_time, update_time, create_by, update_by, remark from wx_mini_program_config
+    </sql>
+
+    <select id="selectWxMiniProgramConfigList" parameterType="WxMiniProgramConfig" resultMap="WxMiniProgramConfigResult">
+        <include refid="selectWxMiniProgramConfigVo"/>
+        <where>
+            <if test="appName != null  and appName != ''"> and app_name like concat('%', #{appName}, '%')</if>
+            <if test="appid != null  and appid != ''"> and appid = #{appid}</if>
+        </where>
+    </select>
+
+    <select id="selectWxMiniProgramConfigById" parameterType="Long" resultMap="WxMiniProgramConfigResult">
+        <include refid="selectWxMiniProgramConfigVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertWxMiniProgramConfig" parameterType="WxMiniProgramConfig" useGeneratedKeys="true" keyProperty="id">
+        insert into wx_mini_program_config
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="appName != null">app_name,</if>
+            <if test="appid != null and appid != ''">appid,</if>
+            <if test="appSecret != null and appSecret != ''">app_secret,</if>
+            <if test="wxMerchantNo != null and wxMerchantNo != ''">wx_merchant_no,</if>
+            <if test="wxKey != null and wxKey != ''">wx_key,</if>
+            <if test="wxV3Key != null and wxV3Key != ''">wx_v3_key,</if>
+            <if test="wxKeyPath != null">wx_key_path,</if>
+            <if test="wxNotifyUrl != null and wxNotifyUrl != ''">wx_notify_url,</if>
+            <if test="status != null">status,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="updateBy != null">update_by,</if>
+            <if test="remark != null">remark,</if>
+            <if test="merchantShortName != null">merchant_short_name,</if>
+            <if test="adminName != null">admin_name,</if>
+            <if test="signingTime != null">signing_time,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="appName != null">#{appName},</if>
+            <if test="appid != null and appid != ''">#{appid},</if>
+            <if test="appSecret != null and appSecret != ''">#{appSecret},</if>
+            <if test="wxMerchantNo != null and wxMerchantNo != ''">#{wxMerchantNo},</if>
+            <if test="wxKey != null and wxKey != ''">#{wxKey},</if>
+            <if test="wxV3Key != null and wxV3Key != ''">#{wxV3Key},</if>
+            <if test="wxKeyPath != null">#{wxKeyPath},</if>
+            <if test="wxNotifyUrl != null and wxNotifyUrl != ''">#{wxNotifyUrl},</if>
+            <if test="status != null">#{status},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+            <if test="remark != null">#{remark},</if>
+            <if test="merchantShortName != null">#{merchantShortName},</if>
+            <if test="adminName != null">#{adminName},</if>
+            <if test="signingTime != null">#{signingTime},</if>
+         </trim>
+    </insert>
+
+    <update id="updateWxMiniProgramConfig" parameterType="WxMiniProgramConfig">
+        update wx_mini_program_config
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="appName != null">app_name = #{appName},</if>
+            <if test="appid != null and appid != ''">appid = #{appid},</if>
+            <if test="appSecret != null and appSecret != ''">app_secret = #{appSecret},</if>
+            <if test="wxMerchantNo != null and wxMerchantNo != ''">wx_merchant_no = #{wxMerchantNo},</if>
+            <if test="wxKey != null and wxKey != ''">wx_key = #{wxKey},</if>
+            <if test="wxV3Key != null and wxV3Key != ''">wx_v3_key = #{wxV3Key},</if>
+            <if test="wxKeyPath != null">wx_key_path = #{wxKeyPath},</if>
+            <if test="wxNotifyUrl != null and wxNotifyUrl != ''">wx_notify_url = #{wxNotifyUrl},</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="createBy != null">create_by = #{createBy},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            <if test="merchantShortName != null">merchant_short_name = #{merchantShortName},</if>
+            <if test="adminName != null">admin_name = #{adminName},</if>
+            <if test="signingTime != null">signing_time = #{signingTime},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteWxMiniProgramConfigById" parameterType="Long">
+        delete from wx_mini_program_config where id = #{id}
+    </delete>
+
+    <delete id="deleteWxMiniProgramConfigByIds" parameterType="String">
+        delete from wx_mini_program_config where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+</mapper>

+ 19 - 2
fs-user-app/src/main/java/com/fs/app/controller/PaymentController.java

@@ -9,6 +9,7 @@ import com.fs.common.core.domain.R;
 import com.fs.common.utils.IpUtil;
 import com.fs.huifuPay.dto.TzMiniProgramCodeRespDTO;
 import com.fs.store.domain.FsStorePayment;
+import com.fs.system.mapper.FsCoursePlaySourceConfigMapper;
 import com.fs.wx.miniapp.config.WxMaConfiguration;
 import com.fs.wx.miniapp.config.WxMaProperties;
 import com.fs.store.domain.FsUser;
@@ -17,6 +18,7 @@ import com.fs.store.service.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import me.chanjar.weixin.common.error.WxErrorException;
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -37,7 +39,8 @@ public class PaymentController extends AppBaseController {
     @Autowired
     private WxMaProperties properties;
     protected final Logger logger = LoggerFactory.getLogger(PaymentController.class);
-
+    @Autowired
+    private FsCoursePlaySourceConfigMapper fsCoursePlaySourceConfigMapper;
     @Autowired
     private IFsStorePaymentService paymentService;
     @Autowired
@@ -47,7 +50,21 @@ public class PaymentController extends AppBaseController {
     @PostMapping("/payment")
     @RepeatSubmit
     public R payment(@Validated @RequestBody FsStorePaymentPayParam payment, HttpServletRequest request){
-        final WxMaService wxService = WxMaConfiguration.getMaService(properties.getConfigs().get(0).getAppid());
+        String courseMa_appId;
+
+        System.out.println("appid"+payment.getCode());
+        logger.info("appid"+payment.getCode());
+        if(StringUtils.isNotEmpty(payment.getAppId())){
+            try {
+                courseMa_appId = fsCoursePlaySourceConfigMapper.selectFsCoursePlaySourceConfigByAppId(payment.getAppId()).getAppid();
+            } catch (Exception e) {
+                courseMa_appId = payment.getAppId();
+            }
+        }else{
+            courseMa_appId = properties.getConfigs().get(0).getAppid();
+        }
+
+        final WxMaService wxService = WxMaConfiguration.getMaService(courseMa_appId);
         try {
             String ip = IpUtil.getRequestIp();
             WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(payment.getCode());

+ 39 - 0
fs-user-app/src/main/java/com/fs/app/controller/WxPayController.java

@@ -39,6 +39,9 @@ public class WxPayController {
     private IFsStoreOrderService orderService;
     @Autowired
     private IFsStoreOrderStatusService orderStatusService;
+
+    @Autowired
+    private IFsStorePaymentService storePaymentService;
     @Autowired
     private IFsUserService userService;
     /**
@@ -81,7 +84,43 @@ public class WxPayController {
     }
 
 
+    @ApiOperation("微信回调")
+    @PostMapping("/wxPayNotifyNew")
+    @Transactional
+    public String wxPayNotifyNew(HttpServletRequest request) throws Exception {
+        logger.info("====================进入微信回调接口===================");
+        try {
+            String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
+            WxPayOrderNotifyResult result = wxPayService.parseOrderNotifyResult(xmlResult,"MD5");
+            System.out.println(result.getReturnCode());
+            if("SUCCESS".equals(result.getReturnCode())){
+                //订单号
+                String outtradeno = result.getOutTradeNo();
+                String tradeNo = result.getTransactionId();
+                System.out.println(outtradeno);
+                System.out.println(tradeNo);
+                String[] orderId=outtradeno.split("-");
+                switch (orderId[0]){
+                    case "store":
+                        orderService.payConfirm(1,null,orderId[1], outtradeno,tradeNo,null);
+                        break;
+                    case "store_remain":
+                        orderService.payRemainConfirm( orderId[1], outtradeno,tradeNo,null);
+                        break;
+                    case "payment":
+                        storePaymentService.payConfirm(orderId[1], outtradeno,tradeNo,null);
+                        break;
+                }
+                return WxPayNotifyResponse.success("");
+            }else{
+                return WxPayNotifyResponse.fail("");
+            }
 
+        } catch (Exception e) {
+            logger.error("微信回调结果异常,异常原因{}", e.getMessage());
+            return WxPayNotifyResponse.fail(e.getMessage());
+        }
+    }
 
     //处理订单
     @Synchronized

+ 126 - 0
fs-user-app/src/main/resources/logback.xml

@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <!-- 日志存放路径 -->
+	<property name="log.path" value="/home/software/fs-user-app/logs" />
+    <!-- 日志输出格式 -->
+	<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
+
+	<!-- 控制台输出 -->
+	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+	</appender>
+
+	<!-- 系统日志输出 -->
+	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-info.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+			<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 60天 -->
+			<maxHistory>60</maxHistory>
+		</rollingPolicy>
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>INFO</level>
+            <!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+	</appender>
+
+	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/sys-error.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 60天 -->
+			<maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>ERROR</level>
+			<!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+			<!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+	<!-- 用户访问日志输出  -->
+    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
+		<file>${log.path}/sys-user.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 按天回滚 daily -->
+            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <!-- 日志最大的历史 60天 -->
+            <maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+    </appender>
+
+
+<!--    <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">-->
+<!--        &lt;!&ndash;配置logStash 服务地址&ndash;&gt;-->
+<!--        <destination>175.178.226.29:5044</destination>-->
+<!--        &lt;!&ndash; 日志输出编码 &ndash;&gt;-->
+<!--        <encoder charset="UTF-8"-->
+<!--                 class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">-->
+<!--            <providers>-->
+<!--                <timestamp>-->
+<!--                    <timeZone>UTC</timeZone>-->
+<!--                </timestamp>-->
+<!--                <pattern>-->
+<!--                    <pattern>-->
+<!--                        {-->
+<!--                        "env": "prod",-->
+<!--                        "service":"fs-user-app",-->
+<!--                        "timestamp":"%d{yyyy-MM-dd HH:mm:ss.SSS}",-->
+<!--                        "date":"%d{yyyy-MM-dd HH:mm:ss.SSS}",-->
+<!--                        "level":"%level",-->
+<!--                        "thread": "%thread",-->
+<!--                        "logger": "%logger{36}",-->
+<!--                        "msg":"%msg",-->
+<!--                        "exception":"%exception",-->
+<!--                        "app_name":"fhhx-fs-user-app",-->
+<!--                        "profiles_active":"prod"-->
+<!--                        }-->
+<!--                    </pattern>-->
+<!--                </pattern>-->
+<!--            </providers>-->
+<!--        </encoder>-->
+<!--    </appender>-->
+
+	<!-- 系统模块日志级别控制  -->
+	<logger name="com.fs" level="info" />
+	<!-- Spring日志级别控制  -->
+	<logger name="org.springframework" level="warn" />
+
+	<root level="info">
+		<appender-ref ref="console" />
+	</root>
+
+	<!--系统操作日志-->
+    <root level="info">
+        <appender-ref ref="file_info" />
+        <appender-ref ref="file_error" />
+<!--        <appender-ref ref="LOGSTASH" />-->
+    </root>
+
+	<!--系统用户操作日志-->
+    <logger name="sys-user" level="info">
+        <appender-ref ref="sys-user"/>
+    </logger>
+</configuration>