Explorar o código

倍力优商城修改 优化

xgb hai 3 semanas
pai
achega
c09fef9a93
Modificáronse 28 ficheiros con 1741 adicións e 272 borrados
  1. 84 0
      fs-admin/src/main/java/com/fs/course/controller/FsCoursePlaySourceConfigController.java
  2. 107 0
      fs-admin/src/main/java/com/fs/his/controller/MerchantAppConfigController.java
  3. 16 0
      fs-service/src/main/java/com/fs/course/domain/FsCoursePlaySourceConfig.java
  4. 2 0
      fs-service/src/main/java/com/fs/course/mapper/FsCoursePlaySourceConfigMapper.java
  5. 12 0
      fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigEditParam.java
  6. 12 0
      fs-service/src/main/java/com/fs/course/vo/FsCoursePlaySourceConfigVO.java
  7. 7 0
      fs-service/src/main/java/com/fs/his/domain/FsPayConfig.java
  8. 9 0
      fs-service/src/main/java/com/fs/his/domain/FsStorePayment.java
  9. 66 0
      fs-service/src/main/java/com/fs/his/domain/MerchantAppConfig.java
  10. 87 0
      fs-service/src/main/java/com/fs/his/mapper/MerchantAppConfigMapper.java
  11. 61 0
      fs-service/src/main/java/com/fs/his/service/IMerchantAppConfigService.java
  12. 30 10
      fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java
  13. 272 40
      fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java
  14. 201 0
      fs-service/src/main/java/com/fs/his/service/impl/MerchantAppConfigServiceImpl.java
  15. 4 0
      fs-service/src/main/java/com/fs/hisStore/domain/FsStoreOrderScrm.java
  16. 1 1
      fs-service/src/main/java/com/fs/hisStore/mapper/FsUserScrmMapper.java
  17. 2 0
      fs-service/src/main/java/com/fs/hisStore/param/FsStoreOrderCreateParam.java
  18. 2 0
      fs-service/src/main/java/com/fs/hisStore/service/IFsStoreOrderScrmService.java
  19. 14 14
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreAfterSalesScrmServiceImpl.java
  20. 251 4
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java
  21. 12 0
      fs-service/src/main/java/com/fs/huifuPay/sdk/opps/core/request/V2TradePaymentScanpayQueryRequest.java
  22. 48 22
      fs-service/src/main/java/com/fs/huifuPay/service/impl/HuiFuServiceImpl.java
  23. 137 0
      fs-service/src/main/resources/mapper/MerchantAppConfigMapper.xml
  24. 8 0
      fs-service/src/main/resources/mapper/course/FsCoursePlaySourceConfigMapper.xml
  25. 4 0
      fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml
  26. 3 0
      fs-user-app/src/main/java/com/fs/app/controller/WxPayController.java
  27. 270 181
      fs-user-app/src/main/java/com/fs/app/controller/store/StoreOrderScrmController.java
  28. 19 0
      fs-user-app/src/main/java/com/fs/app/controller/store/UserScrmController.java

+ 84 - 0
fs-admin/src/main/java/com/fs/course/controller/FsCoursePlaySourceConfigController.java

@@ -1,10 +1,12 @@
 package com.fs.course.controller;
 
 import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.annotation.Log;
 import com.fs.common.core.controller.BaseController;
@@ -18,11 +20,15 @@ import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.bean.BeanUtils;
 import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
+//import com.fs.course.enums.MiniProgramAgreementEnum;
 import com.fs.course.param.FsCoursePlaySourceConfigCreateParam;
 import com.fs.course.param.FsCoursePlaySourceConfigEditParam;
+//import com.fs.course.param.MiniProgramAgreementParam;
 import com.fs.course.service.IFsCoursePlaySourceConfigService;
 import com.fs.course.vo.FsCoursePlaySourceConfigVO;
 import com.fs.framework.web.service.TokenService;
+//import com.fs.his.domain.MiniProgramAgreement;
+//import com.fs.his.service.MiniProgramAgreementService;
 import com.fs.system.service.ISysConfigService;
 import com.github.pagehelper.PageHelper;
 import lombok.AllArgsConstructor;
@@ -41,6 +47,7 @@ public class FsCoursePlaySourceConfigController extends BaseController {
     private final IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService;
     private final TokenService tokenService;
     private final ISysConfigService configService;
+//    private final MiniProgramAgreementService miniProgramAgreementService;
 
 //    @PreAuthorize("@ss.hasPermi('course:playSourceConfig:list')")
     @GetMapping("/list")
@@ -134,6 +141,29 @@ public class FsCoursePlaySourceConfigController extends BaseController {
         return AjaxResult.success();
     }
 
+    @PreAuthorize("@ss.hasPermi('course:playSourceConfig:bind')")
+    @Log(title = "绑定支付配置", businessType = BusinessType.UPDATE)
+    @PutMapping("/updateBindConfig")
+    public AjaxResult updateBindConfig(@RequestBody FsCoursePlaySourceConfigEditParam param) {
+
+        FsCoursePlaySourceConfig update =new FsCoursePlaySourceConfig();
+        update.setId(param.getId());
+        update.setMerchantConfigId(param.getMerchantConfigId());
+        fsCoursePlaySourceConfigService.updateById(update);
+        return AjaxResult.success();
+    }
+
+    @PreAuthorize("@ss.hasPermi('course:playSourceConfig:unbind')")
+    @Log(title = "解绑支付配置", businessType = BusinessType.UPDATE)
+    @PutMapping("/updateUnbindConfig")
+    public AjaxResult updateUnbindConfig(@RequestBody FsCoursePlaySourceConfigEditParam param) {
+        LambdaUpdateWrapper<FsCoursePlaySourceConfig> updateWrapper = Wrappers.lambdaUpdate();
+        updateWrapper.eq(FsCoursePlaySourceConfig::getId, param.getId())
+                .set(FsCoursePlaySourceConfig::getMerchantConfigId, null);
+        fsCoursePlaySourceConfigService.update(updateWrapper);
+        return AjaxResult.success();
+    }
+
     @PreAuthorize("@ss.hasPermi('course:playSourceConfig:remove')")
     @Log(title = "点播播放源配置", businessType = BusinessType.DELETE)
     @DeleteMapping("/{ids}")
@@ -159,4 +189,58 @@ public class FsCoursePlaySourceConfigController extends BaseController {
         }
         return R.ok().put("data", fsCoursePlaySourceConfigService.list(queryWrapper));
     }
+
+
+//    @PreAuthorize("@ss.hasPermi('course:playSourceConfig:agreement')")
+//    @Log(title = "小程序协议配置", businessType = BusinessType.UPDATE)
+//    @PostMapping("/updateAgreementConfig")
+//    public AjaxResult updateAgreementConfig(@RequestBody MiniProgramAgreementParam agreement) {
+//        Map<String, String> map = (Map<String, String>) JSON.parse(agreement.getAgreementData());
+//
+//        List<MiniProgramAgreement> list = new ArrayList<>();
+//        for (MiniProgramAgreementEnum agreementEnum : MiniProgramAgreementEnum.values()) {
+//            String content = map.get(agreementEnum.getCode());
+//            if (content != null) {
+//                MiniProgramAgreement update = new MiniProgramAgreement();
+//                update.setAppId(agreement.getAppId());
+//                update.setAgreementType(agreementEnum.getCode());
+//                update.setAgreementContent(content);
+//
+//                list.add(update);
+//            }
+//        }
+//
+//        if (!list.isEmpty()) {
+//            miniProgramAgreementService.batchUpsertAgreements(list);
+//        }
+//
+//        return AjaxResult.success();
+//    }
+
+
+
+//    @PreAuthorize("@ss.hasPermi('course:playSourceConfig:agreement')")
+//    @GetMapping("/queryAgreementConfig")
+//    public AjaxResult queryAgreementConfig(@RequestParam(required = true) String appid) {
+//        // 查询协议数据
+//        QueryWrapper<MiniProgramAgreement> queryWrapper = new QueryWrapper<MiniProgramAgreement>()
+//                .eq("app_id", appid);
+//        List<MiniProgramAgreement> agreements = miniProgramAgreementService.list(queryWrapper);
+//
+//        // 按agreementType分组
+//        Map<String, String> agreementMap = new HashMap<>();
+//        for (MiniProgramAgreement agreement : agreements) {
+//            agreementMap.put(agreement.getAgreementType(), agreement.getAgreementContent());
+//        }
+//
+//        // 转换为JSON串返回
+//        String agreementData = JSON.toJSONString(agreementMap);
+//
+//        Map<String, Object> result = new HashMap<>();
+//        result.put("agreementData", agreementData);
+//        result.put("appId", appid);
+//
+//        return AjaxResult.success(result);
+//    }
+
 }

+ 107 - 0
fs-admin/src/main/java/com/fs/his/controller/MerchantAppConfigController.java

@@ -0,0 +1,107 @@
+package com.fs.his.controller;
+
+import java.util.List;
+
+import com.fs.his.domain.MerchantAppConfig;
+import com.fs.his.service.IMerchantAppConfigService;
+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.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+
+/**
+ * 商户应用配置Controller
+ *
+ * @author fs
+ * @date 2025-12-05
+ */
+@RestController
+@RequestMapping("/his/merchantAppConfig")
+public class MerchantAppConfigController extends BaseController
+{
+    @Autowired
+    private IMerchantAppConfigService merchantAppConfigService;
+
+    /**
+     * 查询商户应用配置列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:merchantAppConfig:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(MerchantAppConfig merchantAppConfig)
+    {
+        startPage();
+        List<MerchantAppConfig> list = merchantAppConfigService.selectMerchantAppConfigList(merchantAppConfig);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出商户应用配置列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:merchantAppConfig:export')")
+    @Log(title = "商户应用配置", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(MerchantAppConfig merchantAppConfig)
+    {
+        List<MerchantAppConfig> list = merchantAppConfigService.selectMerchantAppConfigList(merchantAppConfig);
+        ExcelUtil<MerchantAppConfig> util = new ExcelUtil<MerchantAppConfig>(MerchantAppConfig.class);
+        return util.exportExcel(list, "商户应用配置数据");
+    }
+
+    /**
+     * 获取商户应用配置详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('his:merchantAppConfig:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(merchantAppConfigService.selectMerchantAppConfigById(id));
+    }
+
+    /**
+     * 新增商户应用配置
+     */
+    @PreAuthorize("@ss.hasPermi('his:merchantAppConfig:add')")
+    @Log(title = "商户应用配置", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody MerchantAppConfig merchantAppConfig)
+    {
+        merchantAppConfig.setCreatedBy(getUsername());
+        merchantAppConfig.setUpdatedBy(getUsername());
+        return toAjax(merchantAppConfigService.insertMerchantAppConfig(merchantAppConfig));
+    }
+
+    /**
+     * 修改商户应用配置
+     */
+    @PreAuthorize("@ss.hasPermi('his:merchantAppConfig:edit')")
+    @Log(title = "商户应用配置", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody MerchantAppConfig merchantAppConfig)
+    {
+        merchantAppConfig.setUpdatedBy(getUsername());
+        return toAjax(merchantAppConfigService.updateMerchantAppConfig(merchantAppConfig));
+    }
+
+    /**
+     * 删除商户应用配置
+     */
+    @PreAuthorize("@ss.hasPermi('his:merchantAppConfig:remove')")
+    @Log(title = "商户应用配置", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long ids)
+    {
+        return toAjax(merchantAppConfigService.deleteMerchantAppConfigById(ids));
+    }
+}

+ 16 - 0
fs-service/src/main/java/com/fs/course/domain/FsCoursePlaySourceConfig.java

@@ -82,6 +82,10 @@ public class FsCoursePlaySourceConfig {
      */
     private Long companyId;
 
+    /**
+     * 销售公司ids 用于判定销售公司可见编辑列表
+     */
+    private String setCompanyIds;
     /**
      * 销售ID
      */
@@ -95,4 +99,16 @@ public class FsCoursePlaySourceConfig {
      * 是否是互医/商城小程序
      */
     private Integer isMall;
+
+    /**
+     * 小程序状态:0正常,1半封禁,2封禁
+     */
+    private Integer status;
+
+    /**
+     * 商户支付配置id
+     */
+    private Long merchantConfigId;
+
+    private Integer mimiType;
 }

+ 2 - 0
fs-service/src/main/java/com/fs/course/mapper/FsCoursePlaySourceConfigMapper.java

@@ -14,4 +14,6 @@ public interface FsCoursePlaySourceConfigMapper extends BaseMapper<FsCoursePlayS
      * 查询点播配置列表
      */
     List<FsCoursePlaySourceConfigVO> selectCoursePlaySourceConfigVOListByMap(@Param("params") Map<String, Object> params);
+
+    FsCoursePlaySourceConfig selectCoursePlaySourceConfigByAppId(String appId);
 }

+ 12 - 0
fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigEditParam.java

@@ -43,7 +43,19 @@ public class FsCoursePlaySourceConfigEditParam {
     @ApiModelProperty("所属公司")
     private Long companyId;
 
+    /**
+     * 销售公司ids 用于判定销售公司可见编辑列表
+     */
+    @ApiModelProperty("销售公司ids 用于判定销售公司可见编辑列表")
+    private String setCompanyIds;
+
     @ApiModelProperty("是否是互医/商城小程序")
     private Integer isMall;
     private Long createDeptId;
+
+    @ApiModelProperty("小程序状态:0正常,1半封禁,2封禁")
+    private Integer status;
+
+    @ApiModelProperty("商户支付配置id")
+    private Long merchantConfigId;
 }

+ 12 - 0
fs-service/src/main/java/com/fs/course/vo/FsCoursePlaySourceConfigVO.java

@@ -42,6 +42,12 @@ public class FsCoursePlaySourceConfigVO {
     @ApiModelProperty("所属公司")
     private Long companyId;
 
+    /**
+     * 销售公司ids 用于判定销售公司可见编辑列表
+     */
+    @ApiModelProperty("销售公司ids 用于判定销售公司可见编辑列表")
+    private String setCompanyIds;
+
     @ApiModelProperty("创建时间")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime createTime;
@@ -55,4 +61,10 @@ public class FsCoursePlaySourceConfigVO {
      */
     private Integer isMall;
     private Long createDeptId;
+
+    @ApiModelProperty("小程序状态:0正常,1半封禁,2封禁")
+    private Integer status;
+
+    @ApiModelProperty("小程序支付配置id")
+    private Long merchantConfigId;
 }

+ 7 - 0
fs-service/src/main/java/com/fs/his/domain/FsPayConfig.java

@@ -15,6 +15,13 @@ public class FsPayConfig {
     private String appId;
     private String wxMchId;
     private String wxMchKey;
+    private String keyPath;
+    private String wxApiV3Key;
+
+    /**
+     * 微信回调地址
+     */
+    private String notifyUrlScrm;
 
     private String ybNotifyUrl;
     private String tzPayDecrypt;

+ 9 - 0
fs-service/src/main/java/com/fs/his/domain/FsStorePayment.java

@@ -100,6 +100,15 @@ public class FsStorePayment extends BaseEntity
     //小程序appId
     private String appId;
 
+    private Long merConfigId;
+
+    public Long getMerConfigId() {
+        return merConfigId;
+    }
+
+    public void setMerConfigId(Long merConfigId) {
+        this.merConfigId = merConfigId;
+    }
 
     public Integer getIsShare() {
         return isShare;

+ 66 - 0
fs-service/src/main/java/com/fs/his/domain/MerchantAppConfig.java

@@ -0,0 +1,66 @@
+package com.fs.his.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import lombok.Data;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 商户应用配置对象 merchant_app_config
+ *
+ * @author fs
+ * @date 2025-12-05
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class MerchantAppConfig extends BaseEntity{
+
+    /** 主键ID */
+    private Long id;
+
+    /** 商户类型 */
+    @Excel(name = "商户类型")
+    private String merchantType;
+
+    // 应用ID
+    @Excel(name = "应用ID")
+    private String appId;
+
+    /** 回调地址,用于接收支付结果等通知 */
+    @Excel(name = "回调地址,用于接收支付结果等通知")
+    private String callbackUrl;
+
+    /** 配置详情 */
+    @Excel(name = "配置详情")
+    private String dataJson;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date createdTime;
+
+    /** 修改时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "修改时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date updatedTime;
+
+    /** 删除状态:0-正常,1-已删除 */
+    @Excel(name = "删除状态:0-正常,1-已删除")
+    private Long isDeleted;
+
+    /** 创建人ID或用户名 */
+    private String createdBy;
+
+    /** 修改人ID或用户名 */
+    private String updatedBy;
+
+    /**
+     * 商户号
+     */
+    private String merchantId;
+
+
+}

+ 87 - 0
fs-service/src/main/java/com/fs/his/mapper/MerchantAppConfigMapper.java

@@ -0,0 +1,87 @@
+package com.fs.his.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.common.annotation.DataSource;
+import com.fs.common.enums.DataSourceType;
+import com.fs.his.domain.MerchantAppConfig;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 商户应用配置Mapper接口
+ *
+ * @author fs
+ * @date 2025-12-05
+ */
+public interface MerchantAppConfigMapper extends BaseMapper<MerchantAppConfig>{
+
+
+    /**
+     * 检查表是否存在
+     */
+    Integer checkTableExists();
+
+    /**
+     * 创建商户配置表
+     */
+    void createMerchantAppConfigTable();
+
+
+    /**
+     * 查询商户应用配置
+     *
+     * @param id 商户应用配置主键
+     * @return 商户应用配置
+     */
+    MerchantAppConfig selectMerchantAppConfigById(Long id);
+
+    /**
+     * 查询商户应用配置列表
+     *
+     * @param merchantAppConfig 商户应用配置
+     * @return 商户应用配置集合
+     */
+    List<MerchantAppConfig> selectMerchantAppConfigList(MerchantAppConfig merchantAppConfig);
+
+    /**
+     * 新增商户应用配置
+     *
+     * @param merchantAppConfig 商户应用配置
+     * @return 结果
+     */
+    int insertMerchantAppConfig(MerchantAppConfig merchantAppConfig);
+
+    /**
+     * 修改商户应用配置
+     *
+     * @param merchantAppConfig 商户应用配置
+     * @return 结果
+     */
+    int updateMerchantAppConfig(MerchantAppConfig merchantAppConfig);
+
+    /**
+     * 删除商户应用配置
+     *
+     * @param id 商户应用配置主键
+     * @return 结果
+     */
+    int deleteMerchantAppConfigById(Long id);
+
+    /**
+     * 批量删除商户应用配置
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteMerchantAppConfigByIds(Long[] ids);
+
+
+    /**
+     * 根据appId和支付类型查询商户信息
+     *
+     * @param appId
+     * @param payType
+     * @return
+     */
+    MerchantAppConfig selectMerchantAppConfigByAppId(@Param("appId") String appId, @Param("payType") String payType);
+}

+ 61 - 0
fs-service/src/main/java/com/fs/his/service/IMerchantAppConfigService.java

@@ -0,0 +1,61 @@
+package com.fs.his.service;
+
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.his.domain.MerchantAppConfig;
+
+/**
+ * 商户应用配置Service接口
+ *
+ * @author fs
+ * @date 2025-12-05
+ */
+public interface IMerchantAppConfigService extends IService<MerchantAppConfig>{
+    /**
+     * 查询商户应用配置
+     *
+     * @param id 商户应用配置主键
+     * @return 商户应用配置
+     */
+    MerchantAppConfig selectMerchantAppConfigById(Long id);
+
+    /**
+     * 查询商户应用配置列表
+     *
+     * @param merchantAppConfig 商户应用配置
+     * @return 商户应用配置集合
+     */
+    List<MerchantAppConfig> selectMerchantAppConfigList(MerchantAppConfig merchantAppConfig);
+
+    /**
+     * 新增商户应用配置
+     *
+     * @param merchantAppConfig 商户应用配置
+     * @return 结果
+     */
+    int insertMerchantAppConfig(MerchantAppConfig merchantAppConfig);
+
+    /**
+     * 修改商户应用配置
+     *
+     * @param merchantAppConfig 商户应用配置
+     * @return 结果
+     */
+    int updateMerchantAppConfig(MerchantAppConfig merchantAppConfig);
+
+    /**
+     * 批量删除商户应用配置
+     *
+     * @param ids 需要删除的商户应用配置主键集合
+     * @return 结果
+     */
+    int deleteMerchantAppConfigByIds(Long[] ids);
+
+    /**
+     * 删除商户应用配置信息
+     *
+     * @param id 商户应用配置主键
+     * @return 结果
+     */
+    int deleteMerchantAppConfigById(Long id);
+}

+ 30 - 10
fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java

@@ -32,6 +32,8 @@ import com.fs.config.cloud.CloudHostProper;
 import com.fs.core.config.WxMaConfiguration;
 import com.fs.core.config.WxPayProperties;
 import com.fs.core.utils.OrderCodeUtils;
+import com.fs.course.domain.FsCoursePlaySourceConfig;
+import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.domain.*;
 import com.fs.his.dto.PackageConfigDTO;
@@ -168,6 +170,12 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
     @Autowired
     private CloudHostProper cloudHostProper;
 
+    @Autowired
+    private FsCoursePlaySourceConfigMapper fsCoursePlaySourceConfigMapper;
+
+    @Autowired
+    private MerchantAppConfigMapper merchantAppConfigMapper;
+
     /**
      * 查询套餐订单
      *
@@ -954,8 +962,20 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
 
         FsUser user=userService.selectFsUserByUserId(param.getUserId());
 
-        String json = configService.selectConfigByKey("his.pay");
-        PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
+        if (StringUtils.isBlank(param.getAppId())) {
+            throw new IllegalArgumentException("appId不能为空");
+        }
+        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectCoursePlaySourceConfigByAppId(param.getAppId());
+        if (fsCoursePlaySourceConfig == null) {
+            throw new CustomException("未找到appId对应的小程序配置: " + param.getAppId());
+        }
+        Long merchantConfigId = fsCoursePlaySourceConfig.getMerchantConfigId();
+        if (merchantConfigId == null || merchantConfigId <= 0) {
+            throw new CustomException("小程序没有配置商户信息");
+        }
+        MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
+        FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+//        PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
 
         //金牛多小程序支付
         String openId = null;
@@ -970,7 +990,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                 openId = fsUserWx.getOpenId();
             }
         } else {
-            appId = payConfigDTO.getAppId();
+            appId = fsCoursePlaySourceConfig.getAppid();
             openId = Objects.isNull(user) ? "" : user.getMaOpenId();
             if (StringUtils.isBlank(openId)){
                 Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
@@ -991,7 +1011,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                 }
                 FsStorePayment storePayment=new FsStorePayment();
                 storePayment.setStatus(0);
-                storePayment.setPayMode(payConfigDTO.getType());
+                storePayment.setPayMode(merchantAppConfig.getMerchantType());
                 storePayment.setBusinessCode(fsPackageOrder.getOrderSn());
                 storePayment.setPayCode(payCode);
                 storePayment.setPayMoney(fsPackageOrder.getPayMoney());
@@ -1005,12 +1025,12 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                 storePayment.setUserId(user.getUserId());
                 storePayment.setStoreId(fsPackageOrder.getStoreId());
                 storePayment.setBusinessId(fsPackageOrder.getOrderId().toString());
+                storePayment.setAppId(appId);
+                storePayment.setMerConfigId(merchantAppConfig.getId());
                 if(storePaymentService.insertFsStorePayment(storePayment)>0){
-                    if (payConfigDTO.getType().equals("wx")) {
+                    if (merchantAppConfig.getMerchantType().equals("wx")) {
                         //创建微信订单
                         WxPayConfig payConfig = new WxPayConfig();
-                        SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.pay");
-                        FsPayConfig fsPayConfig = new Gson().fromJson(sysConfig.getConfigValue(), FsPayConfig.class);
                         payConfig.setAppId(appId);
                         payConfig.setMchId(fsPayConfig.getWxMchId());
                         payConfig.setMchKey(fsPayConfig.getWxMchKey());
@@ -1035,7 +1055,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                             e.printStackTrace();
                             throw new CustomException("支付失败" + e.getMessage());
                         }
-                    } else if (payConfigDTO.getType().equals("yb")) {
+                    } else if (merchantAppConfig.getMerchantType().equals("yb")) {
                         WxJspayDTO p = new WxJspayDTO();
                         // 使用setter方法为对象赋值
                         p.setPayMoney(storePayment.getPayMoney().toString());
@@ -1056,7 +1076,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                         } else {
                             throw new CustomException("支付失败");
                         }
-                    } else if (payConfigDTO.getType().equals("tz")) {
+                    } else if (merchantAppConfig.getMerchantType().equals("tz")) {
                         PayCreateOrder o = new PayCreateOrder();
                         o.setOrderNo("package" + storePayment.getPayCode()); // 业务系统订单号
                         o.setTrxAmt(storePayment.getPayMoney().doubleValue()); // 交易金额
@@ -1081,7 +1101,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                         mt.setTradeNo(result.getBody().getOrderFlowNo());
                         fsStorePaymentMapper.updateFsStorePayment(mt);
                         return R.ok().put("isPay", 0).put("data", result).put("type", "tz");
-                    }else if (payConfigDTO.getType().equals("hf")) {
+                    }else if (merchantAppConfig.getMerchantType().equals("hf")) {
                         logger.info("创建汇付订单");
                         HuiFuCreateOrder o = new HuiFuCreateOrder();
                         o.setTradeType("T_MINIAPP");

+ 272 - 40
fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java

@@ -41,10 +41,13 @@ import com.fs.core.config.WxMaConfiguration;
 import com.fs.core.config.WxPayProperties;
 import com.fs.core.utils.OrderCodeUtils;
 import com.fs.course.config.RedPacketConfig;
+import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.domain.FsCourseRedPacketLog;
+import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
 import com.fs.course.service.IFsCourseRedPacketLogService;
 import com.fs.course.service.IFsUserCourseOrderService;
 import com.fs.course.service.IFsUserVipOrderService;
+import com.fs.his.config.IntegralConfig;
 import com.fs.his.domain.*;
 import com.fs.his.dto.PayConfigDTO;
 import com.fs.his.enums.PaymentMethodEnum;
@@ -179,6 +182,12 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
     @Autowired
     private RedisCache redisCache;
 
+    @Autowired
+    private FsCoursePlaySourceConfigMapper fsCoursePlaySourceConfigMapper;
+
+    @Autowired
+    private MerchantAppConfigMapper merchantAppConfigMapper;
+
     @Autowired
     @Qualifier("redisTemplateForBigDecimal")
     private RedisTemplate<String,BigDecimal> redisTemplate;
@@ -433,12 +442,23 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
 
             if(fsStorePayment.getPayMode().equals("wx")){
                 WxPayConfig payConfig = new WxPayConfig();
-                SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.pay");
-                FsPayConfig fsPayConfig = new Gson().fromJson(sysConfig.getConfigValue(), FsPayConfig.class);
-                payConfig.setAppId(fsPayConfig.getAppId());
+                if (StringUtils.isBlank(fsStorePayment.getAppId())) {
+                    throw new IllegalArgumentException("appId不能为空");
+                }
+                FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectCoursePlaySourceConfigByAppId(fsStorePayment.getAppId());
+                if (fsCoursePlaySourceConfig == null) {
+                    throw new CustomException("未找到appId对应的小程序配置: " + fsStorePayment.getAppId());
+                }
+                Long merchantConfigId = fsCoursePlaySourceConfig.getMerchantConfigId();
+                if (merchantConfigId == null || merchantConfigId <= 0) {
+                    throw new CustomException("小程序没有配置商户信息");
+                }
+                MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
+                FsPayConfig fsPayConfig = com.alibaba.fastjson.JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+                payConfig.setAppId(fsCoursePlaySourceConfig.getAppid());
                 payConfig.setMchId(fsPayConfig.getWxMchId());
                 payConfig.setMchKey(fsPayConfig.getWxMchKey());
-                payConfig.setKeyPath(wxPayProperties.getKeyPath());
+                payConfig.setKeyPath(fsPayConfig.getKeyPath());
                 payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
                 payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
                 wxPayService.setConfig(payConfig);
@@ -515,6 +535,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
                 request.setReqSeqId("refund-"+fsStorePayment.getPayCode());
                 Map<String, Object> extendInfoMap = new HashMap<>();
                 extendInfoMap.put("org_req_seq_id", orderType+"-"+fsStorePayment.getPayCode());
+                request.setAppId(fsStorePayment.getAppId());
                 request.setExtendInfo(extendInfoMap);
                 //处理分账退款
                 //1.判断是否是全额退款
@@ -1608,8 +1629,19 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
             return R.error("用户不存在!");
         }
 
-        String json = configService.selectConfigByKey("his.pay");
-        PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
+        if (StringUtils.isBlank(param.getAppId())) {
+            throw new IllegalArgumentException("appId不能为空");
+        }
+        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectCoursePlaySourceConfigByAppId(param.getAppId());
+        if (fsCoursePlaySourceConfig == null) {
+            throw new CustomException("未找到appId对应的小程序配置: " + param.getAppId());
+        }
+        Long merchantConfigId = fsCoursePlaySourceConfig.getMerchantConfigId();
+        if (merchantConfigId == null || merchantConfigId <= 0) {
+            throw new CustomException("小程序没有配置商户信息");
+        }
+        MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
+        FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
         String openId = null;
         String appId = param.getAppId();
         if (StringUtils.isNotBlank(appId)) {
@@ -1622,7 +1654,7 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
                 openId = fsUserWx.getOpenId();
             }
         } else {
-            appId = payConfigDTO.getAppId();
+            appId = merchantAppConfig.getAppId();
             openId = Objects.isNull(user) ? "" : user.getMaOpenId();
             if (StringUtils.isBlank(openId)){
                 Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
@@ -1667,40 +1699,240 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
         storePayment.setRemark("商城收款订单支付");
         storePayment.setOpenId(openId);
         storePayment.setUserId(user.getUserId());
-        storePayment.setPayMode("hf");//目前微信收款仅支持汇付
-        fsStorePaymentMapper.insertFsStorePayment(storePayment);
-
-        //汇付支付
-        HuiFuCreateOrder o = new HuiFuCreateOrder();
-        o.setTradeType("T_MINIAPP");
-        o.setOpenid(openId);
-        o.setReqSeqId("payment-"+storePayment.getPayCode());
-        o.setTransAmt(storePayment.getPayMoney().toString());
-        o.setGoodsDesc("商城订单支付");
-        o.setAppId(appId);
-        //公司分账
-        try {
-            HuiFuUtils.doDiv(o,company.getCompanyId());
-            //存储分账明细
-            HuiFuUtils.saveDivItem(o, storePayment.getPayCode(), storePayment.getPayCode());
-        } catch (Exception e) {
-            logger.error("-------------微信收款分账出错:{}", e.getMessage());
-        }
-        HuifuCreateOrderResult result = huiFuService.createOrder(o);
-        if(result.getResp_code()!=null&&(result.getResp_code().equals("00000000")||result.getResp_code().equals("00000100"))){
-            FsStorePayment mt=new FsStorePayment();
-            mt.setPaymentId(storePayment.getPaymentId());
-            mt.setTradeNo(result.getHf_seq_id());
-            mt.setAppId(appId);
-            fsStorePaymentMapper.updateFsStorePayment(mt);
-            Map<String, Object> resultMap = com.alibaba.fastjson.JSON.parseObject(result.getPay_info(), new TypeReference<Map<String, Object>>() {});
-            String s = (String) resultMap.get("package");
-            resultMap.put("packageValue",s);
-            return R.ok().put("result",resultMap);
-        }
-        else{
-            return R.error(result.getResp_desc());
+        storePayment.setPayMode(merchantAppConfig.getMerchantType());
+        storePayment.setAppId(appId);
+        storePayment.setMerConfigId(merchantAppConfig.getId());
+
+        if (fsStorePaymentMapper.insertFsStorePayment(storePayment) > 0) {
+            if (merchantAppConfig.getMerchantType().equals("wx")) {
+                //创建微信订单
+                WxPayConfig payConfig = new WxPayConfig();
+                payConfig.setAppId(appId);
+                payConfig.setMchId(fsPayConfig.getWxMchId());
+                payConfig.setMchKey(fsPayConfig.getWxMchKey());
+                payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                payConfig.setKeyPath(null);
+                payConfig.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
+                wxPayService.setConfig(payConfig);
+                WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
+                orderRequest.setOpenid(openId);//公众号支付提供用户openid
+                orderRequest.setBody("收款支付");
+                orderRequest.setOutTradeNo("payment-" + storePayment.getPayCode());
+                orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));//测试
+                //orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(money));//测试
+                orderRequest.setTradeType("JSAPI");
+                orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
+                //调用统一下单接口,获取"预支付交易会话标识"
+                try {
+                    WxPayMpOrderResult orderResult = wxPayService.createOrder(orderRequest);
+                    return R.ok().put("data", orderResult).put("type", "wx").put("isPay", 0);
+                } catch (WxPayException e) {
+                    e.printStackTrace();
+                    throw new CustomException("支付失败" + e.getMessage());
+                }
+            } else if (merchantAppConfig.getMerchantType().equals("hf")) {
+
+                //汇付支付
+                HuiFuCreateOrder o = new HuiFuCreateOrder();
+                o.setTradeType("T_MINIAPP");
+                o.setOpenid(openId);
+                o.setReqSeqId("payment-"+storePayment.getPayCode());
+                o.setTransAmt(storePayment.getPayMoney().toString());
+                o.setGoodsDesc("商城订单支付");
+                o.setAppId(appId);
+                //公司分账
+                try {
+                    HuiFuUtils.doDiv(o,company.getCompanyId());
+                    //存储分账明细
+                    HuiFuUtils.saveDivItem(o, storePayment.getPayCode(), storePayment.getPayCode());
+                } catch (Exception e) {
+                    logger.error("-------------微信收款分账出错:{}", e.getMessage());
+                }
+                HuifuCreateOrderResult result = huiFuService.createOrder(o);
+
+                if(result.getResp_code()!=null&&(result.getResp_code().equals("00000000")||result.getResp_code().equals("00000100"))){
+                    FsStorePayment mt=new FsStorePayment();
+                    mt.setPaymentId(storePayment.getPaymentId());
+                    mt.setTradeNo(result.getHf_seq_id());
+                    mt.setAppId(appId);
+                    fsStorePaymentMapper.updateFsStorePayment(mt);
+                    Map<String, Object> resultMap = com.alibaba.fastjson.JSON.parseObject(result.getPay_info(), new TypeReference<Map<String, Object>>() {});
+                    String s = (String) resultMap.get("package");
+                    resultMap.put("packageValue",s);
+                    return R.ok().put("result",resultMap);
+                }
+                else{
+                    return R.error(result.getResp_desc());
+                }
+            }
+        }else {
+            return R.error("新增订单失败!");
         }
+        return R.error("支付失败!");
+
     }
+//    @Override
+//    public String integralV3TransferNotify(String notifyData, HttpServletRequest request) {
+//        logger.info("zyp \n【收到转账回调V3】:{}",notifyData);
+//        try {
+//            String json = configService.selectConfigByKey("his.integral");
+//            IntegralConfig config = JSONUtil.toBean(json, IntegralConfig.class);
+//            //创建微信订单
+//            WxPayConfig payConfig = new WxPayConfig();
+//            BeanUtils.copyProperties(config,payConfig);
+//            WxPayService wxPayService = new WxPayServiceImpl();
+//            wxPayService.setConfig(payConfig);
+//            SignatureHeader signatureHeader = new SignatureHeader();
+//            signatureHeader.setTimeStamp(request.getHeader("Wechatpay-Timestamp"));
+//            signatureHeader.setNonce(request.getHeader("Wechatpay-Nonce"));
+//            signatureHeader.setSerial(request.getHeader("Wechatpay-Serial"));
+//            signatureHeader.setSignature(request.getHeader("Wechatpay-Signature"));
+//            TransferBillsNotifyResult result = wxPayService.parseTransferBillsNotifyV3Result(notifyData,signatureHeader);
+//            if (result.getResult().getState().equals("SUCCESS")) {
+//                return WxPayNotifyResponse.success("处理成功");
+//            }else {
+//                return WxPayNotifyResponse.fail("");
+//            }
+//        } catch (WxPayException e) {
+//            e.printStackTrace();
+//            logger.error("zyp \n【转账回调异常】:{}", e.getReturnMsg());
+//            return WxPayNotifyResponse.fail(e.getMessage());
+//        }
+//    }
+//
+//    @Override
+//    @Transactional
+//    public R sendAppRedPacket(WxSendRedPacketParam param) {
+//        //组合返回参数
+//        R result = new R();
+//        String json = configService.selectConfigByKey("his.AppRedPacket");
+//        AppRedPacketConfig config = JSONUtil.toBean(json, AppRedPacketConfig.class);
+//        if (config.getIsNew() != null && config.getIsNew() == 1) {
+//            result = sendRedPacketV3(param, config);
+//        } else {
+//            result= sendRedPacketLegacy(param, config);
+//        }
+//
+//        result.put("mchId", config.getMchId());
+//        result.put("isNew",config.getIsNew());
+//        logger.info("App提现返回:{}",result);
+//        return result;
+//    }
+//
+//    // 内部方法:处理新版本的发红包逻辑
+//    private R sendRedPacketV3(WxSendRedPacketParam param,AppRedPacketConfig config) {
+//
+//        WxPayConfig payConfig = new WxPayConfig();
+//        BeanUtils.copyProperties(config, payConfig);
+//        WxPayService wxPayService = new WxPayServiceImpl();
+//        wxPayService.setConfig(payConfig);
+//        TransferService transferService = wxPayService.getTransferService();
+//
+//        TransferBillsRequest request = new TransferBillsRequest();
+//        request.setAppid(param.getAppId());
+//        request.setOpenid(param.getOpenId());
+//
+//        String code =  OrderCodeUtils.getOrderSn();
+//        if(StringUtils.isEmpty(code)){
+//            return R.error("订单生成失败,请重试");
+//        }
+////        String code = String.valueOf(IdUtil.getSnowflake(0, 0).nextId());
+//        request.setOutBillNo("fsAppRed" + code);
+//        if (param.getAmount() == null) {
+//            return R.error();
+//        }
+//        Integer amount = WxPayUnifiedOrderRequest.yuanToFen(param.getAmount().toString());
+//        request.setTransferAmount(amount);
+//        request.setTransferRemark("提现红包领取");
+//        request.setUserRecvPerception("活动奖励");
+//        request.setNotifyUrl(config.getNotifyUrl());
+//        request.setTransferSceneId("1000");
+//
+//        // 设置场景信息
+//        List<TransferBillsRequest.TransferSceneReportInfo> transferSceneReportInfos = new ArrayList<>();
+//        TransferBillsRequest.TransferSceneReportInfo info1 = new TransferBillsRequest.TransferSceneReportInfo();
+//        info1.setInfoType("活动名称");
+//        info1.setInfoContent("提现红包领取");
+//        transferSceneReportInfos.add(info1);
+//
+//        TransferBillsRequest.TransferSceneReportInfo info2 = new TransferBillsRequest.TransferSceneReportInfo();
+//        info2.setInfoType("奖励说明");
+//        info2.setInfoContent("提现红包领取");
+//        transferSceneReportInfos.add(info2);
+//        request.setTransferSceneReportInfos(transferSceneReportInfos);
+//
+//
+//        try {
+//            logger.info("app商家转账开始:[param:{}]", request);
+//            TransferBillsResult transferBillsResult = transferService.transferBills(request);
+//            logger.info("Method...商家转账支付完成:[msg:{}]", transferBillsResult);
+//            return R.ok("发送红包成功").put("data", transferBillsResult).put("mchId", config.getMchId())
+//                    .put("package",transferBillsResult.getPackageInfo())
+//                    .put("appId",param.getAppId())
+//                    .put("orderCode",request.getOutBillNo());
+//        } catch (Exception e) {
+//            logger.error("app商家转账支付失败:参数: {} :原因: {}", request, e.getMessage(),e);
+//            throw new RuntimeException(e);
+//        }
+//    }
+//
+//    private R sendRedPacketLegacy(WxSendRedPacketParam param, AppRedPacketConfig config) {
+//        //如果服务号的配置存在,小程序红包接口可以使用服务号来发红包,重新赋值
+//        //仅老商户支持
+//        if (param.getOpenId()!=null && StringUtils.isNotEmpty(param.getAppId())){
+////            config.setAppId(param.getAppId());
+//            param.setOpenId(param.getOpenId());
+//        }
+//        WxPayConfig payConfig = new WxPayConfig();
+//        BeanUtils.copyProperties(config, payConfig);
+//        WxPayService wxPayService = new WxPayServiceImpl();
+//        wxPayService.setConfig(payConfig);
+//        TransferService transferService = wxPayService.getTransferService();
+//
+//        TransferBatchesRequest request = new TransferBatchesRequest();
+////        request.setAppid(config.getAppId());
+//
+//
+//        // todo 如果未配置负载均衡请还原原本的单号方式
+////        String code = IdUtil.getSnowflake(0, 0).nextIdStr();
+//        String code =  OrderCodeUtils.getOrderSn();
+//        if(StringUtils.isEmpty(code)){
+//            return R.error("红包单号生成失败,请重试");
+//        }
+//        request.setOutBatchNo("fsIntegral" + code);
+//        request.setBatchRemark("积分提现");
+//        request.setBatchName("积分提现");
+//        Integer amount = WxPayUnifiedOrderRequest.yuanToFen(param.getAmount().toString());
+//        request.setTotalAmount(amount);
+//        request.setTotalNum(1);
+//        request.setNotifyUrl(config.getNotifyUrl());
+//
+//        ArrayList<TransferBatchesRequest.TransferDetail> transferDetailList = new ArrayList<>();
+//        TransferBatchesRequest.TransferDetail transferDetail = new TransferBatchesRequest.TransferDetail();
+//        transferDetail.setOpenid(param.getOpenId());
+//        String code1 = IdUtil.getSnowflake(0, 0).nextIdStr();
+//        transferDetail.setOutDetailNo("fsCourse" + code1);
+//        transferDetail.setTransferAmount(amount);
+//        transferDetail.setTransferRemark("积分提现成功!");
+//        transferDetailList.add(transferDetail);
+//        request.setTransferDetailList(transferDetailList);
+//
+//        try {
+//            TransferBatchesResult transferBatchesResult = transferService.transferBatches(request);
+//            return R.ok("积分提现成功").put("orderCode", transferBatchesResult.getOutBatchNo()).put("batchId", transferBatchesResult.getBatchId()).put("mchId", config.getMchId());
+//        } catch (Exception e) {
+//            logger.error("商家转账支付失败:参数: {} :原因: {}", com.alibaba.fastjson.JSON.toJSONString(param), e.getMessage(),e);
+//            if (e instanceof WxPayException) {
+////            if (e instanceof WxPayException && "济南联志健康".equals(signProjectName)) {
+//                WxPayException wxPayException = (WxPayException) e;
+//                String customErrorMsg = wxPayException.getCustomErrorMsg();
+//                if (null != customErrorMsg && customErrorMsg.startsWith("商户运营账户资金不足")) {
+//                    return R.error("[积分提现] 账户余额不足,请联系管理员!");
+//                }
+//            }
+//            throw new RuntimeException(e);
+//        }
+//    }
 
 }

+ 201 - 0
fs-service/src/main/java/com/fs/his/service/impl/MerchantAppConfigServiceImpl.java

@@ -0,0 +1,201 @@
+package com.fs.his.service.impl;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.core.domain.entity.SysDictType;
+import com.fs.his.domain.FsPayConfig;
+import com.fs.his.domain.MerchantAppConfig;
+import com.fs.his.mapper.MerchantAppConfigMapper;
+import com.fs.his.service.IMerchantAppConfigService;
+import com.fs.hisStore.domain.FsPayConfigScrm;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.mapper.SysConfigMapper;
+import com.fs.system.mapper.SysDictTypeMapper;
+import com.google.gson.Gson;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * 商户应用配置Service业务层处理
+ *
+ * @author fs
+ * @date 2025-12-05
+ */
+@Service
+@Slf4j
+public class MerchantAppConfigServiceImpl extends ServiceImpl<MerchantAppConfigMapper, MerchantAppConfig> implements IMerchantAppConfigService {
+
+    @Autowired
+    private SysConfigMapper sysConfigMapper;
+
+    /**
+     * 异步初始化方法
+     */
+    @PostConstruct
+    @Async("merchantInitExecutor")
+    public void init() {
+        log.info("开始异步初始化商户配置表...");
+
+        // 使用CompletableFuture进行异步初始化
+        CompletableFuture.runAsync(() -> {
+            try {
+                // 延迟5秒,等待数据库连接就绪
+                Thread.sleep(5000);
+                Integer count = baseMapper.checkTableExists();
+                if (ObjectUtil.isNotNull(count)&&count>0) {
+                    log.info("异步初始化商户配置表完成");
+                    return;
+                }
+                // 1. 检查并创建表
+                initMerchantTable();
+
+            } catch (Exception e) {
+                log.error("初始化商户配置表失败", e);
+            }
+        });
+    }
+
+    /**
+     * 初始化商户配置表
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void initMerchantTable() {
+        try {
+            // 检查表是否存在
+            log.info("商户配置表不存在,开始创建...");
+            baseMapper.createMerchantAppConfigTable();
+            log.info("商户配置表创建成功");
+        } catch (Exception e) {
+            log.error("初始化商户配置表失败", e);
+            throw e;
+        }
+    }
+    /**
+     * 查询商户应用配置
+     *
+     * @param id 商户应用配置主键
+     * @return 商户应用配置
+     */
+    @Override
+    public MerchantAppConfig selectMerchantAppConfigById(Long id)
+    {
+        return baseMapper.selectMerchantAppConfigById(id);
+    }
+
+    /**
+     * 查询商户应用配置列表
+     *
+     * @param merchantAppConfig 商户应用配置
+     * @return 商户应用配置
+     */
+    @Override
+    public List<MerchantAppConfig> selectMerchantAppConfigList(MerchantAppConfig merchantAppConfig)
+    {
+        return baseMapper.selectMerchantAppConfigList(merchantAppConfig);
+    }
+
+    /**
+     * 新增商户应用配置
+     *
+     * @param merchantAppConfig 商户应用配置
+     * @return 结果
+     */
+    @Override
+    public int insertMerchantAppConfig(MerchantAppConfig merchantAppConfig)
+    {
+        FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+        switch (merchantAppConfig.getMerchantType()){
+            case "yb": // 易宝
+                merchantAppConfig.setMerchantId(fsPayConfig.getYbAccount());
+                merchantAppConfig.setCallbackUrl(fsPayConfig.getYbNotifyUrl());
+
+                break;
+            case "tz": // 台州
+                merchantAppConfig.setMerchantId(fsPayConfig.getTzPlatMerCstNo());
+                merchantAppConfig.setCallbackUrl(fsPayConfig.getTzPayDecrypt());
+                break;
+            case "wx": // 微信
+                merchantAppConfig.setMerchantId(fsPayConfig.getWxMchId());
+                merchantAppConfig.setCallbackUrl(fsPayConfig.getNotifyUrlScrm());
+                break;
+            case "hf": // 汇付
+                merchantAppConfig.setMerchantId(fsPayConfig.getHuifuId());
+                merchantAppConfig.setCallbackUrl(fsPayConfig.getHfPayNotifyUrl());
+                break;
+            default:
+                throw new RuntimeException("商户类型错误");
+        }
+
+        return baseMapper.insertMerchantAppConfig(merchantAppConfig);
+    }
+
+    /**
+     * 修改商户应用配置
+     *
+     * @param merchantAppConfig 商户应用配置
+     * @return 结果
+     */
+    @Override
+    public int updateMerchantAppConfig(MerchantAppConfig merchantAppConfig)
+    {
+        FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+        switch (merchantAppConfig.getMerchantType()){
+            case "yb": // 易宝
+                merchantAppConfig.setMerchantId(fsPayConfig.getYbAccount());
+                merchantAppConfig.setCallbackUrl(fsPayConfig.getYbNotifyUrl());
+
+                break;
+            case "tz": // 台州
+                merchantAppConfig.setMerchantId(fsPayConfig.getTzPlatMerCstNo());
+                merchantAppConfig.setCallbackUrl(fsPayConfig.getTzPayDecrypt());
+                break;
+            case "wx": // 微信
+                merchantAppConfig.setMerchantId(fsPayConfig.getWxMchId());
+                merchantAppConfig.setCallbackUrl(fsPayConfig.getNotifyUrlScrm());
+                break;
+            case "hf": // 汇付
+                merchantAppConfig.setMerchantId(fsPayConfig.getHuifuId());
+                merchantAppConfig.setCallbackUrl(fsPayConfig.getHfPayNotifyUrl());
+                break;
+            default:
+                throw new RuntimeException("商户类型错误");
+        }
+        return baseMapper.updateMerchantAppConfig(merchantAppConfig);
+    }
+
+    /**
+     * 批量删除商户应用配置
+     *
+     * @param ids 需要删除的商户应用配置主键
+     * @return 结果
+     */
+    @Override
+    public int deleteMerchantAppConfigByIds(Long[] ids)
+    {
+        return baseMapper.deleteMerchantAppConfigByIds(ids);
+    }
+
+    /**
+     * 删除商户应用配置信息
+     *
+     * @param id 商户应用配置主键
+     * @return 结果
+     */
+    @Override
+    public int deleteMerchantAppConfigById(Long id)
+    {
+        MerchantAppConfig merchantAppConfig = new MerchantAppConfig();
+        merchantAppConfig.setId( id);
+        merchantAppConfig.setIsDeleted(1L);
+        return baseMapper.updateMerchantAppConfig(merchantAppConfig);
+    }
+}

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

@@ -353,5 +353,9 @@ public class FsStoreOrderScrm extends BaseEntity
 
     // 线下支付金额
     private BigDecimal offlinePayAmount;
+    // 小程序id
+    private String appId;
+    // 小程序类型(1-制单小程序,2-公域小程序)
+    private Integer mimiType;
 
 }

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

@@ -121,7 +121,7 @@ public interface FsUserScrmMapper
     @Update("update fs_user set pay_count=pay_count+1" +
             " where user_id=#{userId}")
     int incPayCount(Long userId);
-    @Select("select * from fs_user where phone=#{phone}")
+    @Select("select * from fs_user where phone=#{phone} and is_del=0 order by create_time limit 1")
     FsUserScrm selectFsUserByPhone(String phone);
 
 

+ 2 - 0
fs-service/src/main/java/com/fs/hisStore/param/FsStoreOrderCreateParam.java

@@ -56,4 +56,6 @@ public class FsStoreOrderCreateParam implements Serializable
     private Integer orderMedium; //媒体来源
 
     private Boolean isUserApp = true;
+
+    private String appId;
 }

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

@@ -297,4 +297,6 @@ public interface IFsStoreOrderScrmService
     void getErpOrderDeliverySendTime(Long id, String extendOrderId);
 
     List<FsStoreOrderScrm> selectDeliveryTimeBatch(String time);
+
+    R pay(FsStoreOrderPayParam param);
 }

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

@@ -766,11 +766,11 @@ public class FsStoreAfterSalesScrmServiceImpl implements IFsStoreAfterSalesScrmS
                         //处理分账退款
                         //1.判断是否是全额退款
                         CompanyDivItem companyDivItem = null;
-                        try {
-                            companyDivItem = HuiFuUtils.doRefundDiv(payment.getPayMoney(), refundAmount, payment.getPayCode(), extendInfoMap);
-                        } catch (Exception e) {
-                            logger.error("-----------------分账退款处理失败{}", e.getMessage());
-                        }
+//                        try {
+//                            companyDivItem = HuiFuUtils.doRefundDiv(payment.getPayMoney(), refundAmount, payment, extendInfoMap);
+//                        } catch (Exception e) {
+//                            logger.error("-----------------分账退款处理失败{}", e.getMessage());
+//                        }
                         HuiFuRefundResult refund = huiFuService.refund(request);
                         logger.info("退款:"+refund);
                         if((refund.getResp_code().equals("00000000")||refund.getResp_code().equals("00000100"))&&(refund.getTrans_stat().equals("S")||refund.getTrans_stat().equals("P"))){
@@ -778,15 +778,15 @@ public class FsStoreAfterSalesScrmServiceImpl implements IFsStoreAfterSalesScrmS
                             payment.setStatus(-1);
                             payment.setRefundTime(new Date());
                             paymentService.updateFsStorePayment(payment);
-                            try {
-                                //处理分账退款明细表
-                                if (companyDivItem !=null && companyDivItem.getId() != null) {
-                                    companyDivItem.setIsRefund(1);
-                                    companyDivItemService.updateCompanyDivItem(companyDivItem);
-                                }
-                            } catch (Exception e) {
-                                logger.error("-----------------分账退款明细处理失败{}", e.getMessage());
-                            }
+//                            try {
+//                                //处理分账退款明细表
+//                                if (companyDivItem !=null && companyDivItem.getId() != null) {
+//                                    companyDivItem.setIsRefund(1);
+//                                    companyDivItemService.updateCompanyDivItem(companyDivItem);
+//                                }
+//                            } catch (Exception e) {
+//                                logger.error("-----------------分账退款明细处理失败{}", e.getMessage());
+//                            }
                         }else {
                             TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                             return R.error(refund.getResp_desc());

+ 251 - 4
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java

@@ -10,6 +10,9 @@ import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.TypeReference;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.fs.api.param.OrderListParam;
 import com.fs.api.vo.OrderListVO;
 import com.fs.api.vo.ProductListVO;
@@ -22,7 +25,9 @@ import com.fs.common.event.TemplateListenEnum;
 import com.fs.common.exception.CustomException;
 import com.fs.common.exception.ServiceException;
 import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.ip.IpUtils;
 import com.fs.company.domain.*;
 import com.fs.company.mapper.CompanyDeptMapper;
 import com.fs.company.mapper.CompanyMapper;
@@ -34,7 +39,9 @@ import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.core.config.WxPayProperties;
 import com.fs.core.utils.OrderCodeUtils;
+import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.dto.FsOrderDeliveryNoteDTO;
+import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
 import com.fs.erp.domain.*;
 import com.fs.erp.dto.*;
 import com.fs.erp.mapper.FsErpFinishPushMapper;
@@ -63,7 +70,9 @@ import com.fs.hisapi.domain.ApiResponse;
 import com.fs.hisapi.param.CreateOrderParam;
 import com.fs.hisapi.param.RecipeDetailParam;
 import com.fs.hisapi.service.HisApiService;
+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.sdk.opps.core.utils.HuiFuUtils;
 import com.fs.huifuPay.service.HuiFuService;
@@ -77,6 +86,7 @@ import com.fs.hisStore.enums.*;
 import com.fs.hisStore.service.*;
 import com.fs.system.service.ISysConfigService;
 import com.fs.ybPay.domain.RefundResult;
+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;
@@ -130,6 +140,9 @@ import static com.fs.hisStore.constants.StoreConstants.DELIVERY;
 public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
 
     Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Autowired
+    private FsCoursePlaySourceConfigMapper fsCoursePlaySourceConfigMapper;
     @Autowired
     private CompanyMoneyLogsMapper moneyLogsMapper;
     @Autowired
@@ -317,6 +330,9 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     @Autowired
     private ICompanyDivItemService companyDivItemService;
 
+    @Autowired
+    private MerchantAppConfigMapper merchantAppConfigMapper;
+
     /**
      * 查询订单
      *
@@ -639,6 +655,22 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             Boolean isIntegral = false;
             //组合数据
             FsStoreOrderScrm storeOrder = new FsStoreOrderScrm();
+            if(StringUtils.isNotEmpty(param.getAppId())){
+                // 获取小程序配置 看是否为公域下单小程序
+                FsCoursePlaySourceConfig coursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectOne(new LambdaQueryWrapper<FsCoursePlaySourceConfig>()
+                        .eq(FsCoursePlaySourceConfig::getAppid, param.getAppId()));
+                if(coursePlaySourceConfig==null){
+                    return R.error("小程序配置不存在");
+                }
+
+                if(coursePlaySourceConfig.getMimiType()==2){// 公域小程序
+                    storeOrder.setMimiType(2);
+                }else{
+                    storeOrder.setMimiType(1); // 制单小程序
+                }
+                storeOrder.setAppId(param.getAppId());
+            }
+
             storeOrder.setStoreHouseCode("CK01");
             String json = configService.selectConfigByKey("store.config");
             StoreConfig config= JSONUtil.toBean(json, StoreConfig.class);
@@ -2154,13 +2186,19 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             if(payments!=null){
                 for(FsStorePaymentScrm payment:payments){
                     if (payment.getPayMode()==null||payment.getPayMode().equals("wx")){
+                        String payType = payment.getPayMode();
+                        if ("wxApp".equals(payment.getPayMode())){
+                            payType = "wx";
+                        }
+                        MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigByAppId(payment.getAppId(),payType);
+                        FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+
+
                         WxPayConfig payConfig = new WxPayConfig();
-                        String json = configService.selectConfigByKey("store.pay");
-                        FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
-                        payConfig.setAppId(fsPayConfig.getAppId());
+                        payConfig.setAppId(payment.getAppId());
                         payConfig.setMchId(fsPayConfig.getWxMchId());
                         payConfig.setMchKey(fsPayConfig.getWxMchKey());
-                        payConfig.setKeyPath(wxPayProperties.getKeyPath());
+                        payConfig.setKeyPath(fsPayConfig.getKeyPath());
                         payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
                         payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
                         wxPayService.setConfig(payConfig);
@@ -3865,6 +3903,215 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         }
     }
 
+    @Override
+    @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
+    public R pay(FsStoreOrderPayParam param) {
+        FsStoreOrderScrm order=this.selectFsStoreOrderById(param.getOrderId());
+        if(order==null){
+            return R.error("订单不存在");
+        }
+        if(order.getStatus()!= OrderInfoEnum.STATUS_0.getValue()){
+            return R.error("订单状态不正确");
+        }
+        String orderId=redisCache.getCacheObject("isPaying:"+param.getOrderId());
+        if(StringUtils.isNotEmpty(orderId)&&orderId.equals(order.getId().toString())){
+            return R.error("正在支付中...");
+        }
+
+        FsUserScrm user=userService.selectFsUserById(order.getUserId());
+        if(user!=null){
+            //已改价处理
+            if(order.getIsEditMoney()!=null&&order.getIsEditMoney()==1){
+                //改过价不做处理
+
+            }
+            else{
+                String config=configService.selectConfigByKey("his.store");
+                com.fs.store.config.StoreConfig storeConfig= JSONUtil.toBean(config, com.fs.store.config.StoreConfig.class);
+                if(param.getPayType().equals(1)){
+                    order.setPayType("1");
+                    order.setPayMoney(order.getPayPrice());
+                    order.setPayDelivery(BigDecimal.ZERO);
+                }
+                else if(param.getPayType().equals(2)){
+                    order.setPayType("2");
+                    BigDecimal payMoney=order.getPayPrice().multiply(new BigDecimal(storeConfig.getPayRate())).divide(new BigDecimal(100));
+                    payMoney=new BigDecimal(payMoney.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
+                    // 如果小程序需要支付的金额小于0.01元,不能走物流代收,让走货到付款 xgb
+                    if (payMoney.compareTo(new BigDecimal("0.01")) < 0) {
+                        return R.error("物流代收计算支付金额为0,不允许选择物流代收");
+                    }
+                    order.setPayDelivery(order.getPayPrice().subtract(payMoney));
+                    order.setPayMoney(payMoney);
+                }
+                else if(param.getPayType().equals(3)){
+                    //货到付款
+                    order.setPayType("3");
+                    BigDecimal amount=redisCache.getCacheObject("orderAmount:"+order.getId());
+                    BigDecimal payMoney = BigDecimal.ZERO;
+                    if (amount != null){
+                        payMoney=amount;
+                    }
+                    //运费
+//                    BigDecimal payPostage = order.getPayPostage();
+//                    if (payPostage == null || payPostage.compareTo(BigDecimal.ZERO) <= 0){
+//                        payPostage = storeConfig.getPayPostage();
+//                        if (payPostage == null){
+//                            payPostage = BigDecimal.ZERO;
+//                        }
+//                        order.setPayPrice(order.getPayPrice().add(payPostage));
+//                    }
+//                    order.setPayPostage(payPostage);
+//                    payMoney = payMoney.add(payPostage);
+                    order.setPayMoney(payMoney);
+                    order.setPayDelivery(order.getPayPrice().subtract(payMoney) );
+                }
+                this.updateFsStoreOrder(order);
+            }
+            String payCode = IdUtil.getSnowflake(0, 0).nextIdStr();
+            if((order.getPayType().equals("1")||order.getPayType().equals("2")||order.getPayType().equals("3")||order.getPayType().equals("5")) && order.getPayMoney().compareTo(new BigDecimal(0))>0){
+                if(StringUtils.isBlank(param.getAppId())){
+                    param.setAppId("wx11a2ce7c2bbc4521"); // 默认用会员商城的appid 后面去掉这段逻辑
+                }
+
+                FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectOne(new LambdaQueryWrapper<FsCoursePlaySourceConfig>()
+                        .eq(FsCoursePlaySourceConfig::getAppid, param.getAppId()));
+                if (fsCoursePlaySourceConfig == null) {
+                    throw new CustomException("未找到appId对应的小程序配置: " + param.getAppId());
+                }
+                Long merchantConfigId = fsCoursePlaySourceConfig.getMerchantConfigId();
+                if (merchantConfigId == null || merchantConfigId <= 0) {
+                    throw new CustomException("小程序没有配置商户信息");
+                }
+                MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
+                if(merchantAppConfig == null){
+                    throw new CustomException("未找到商户信息");
+                }
+
+                FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+                FsStorePaymentScrm storePayment=new FsStorePaymentScrm();
+                storePayment.setCompanyId(order.getCompanyId());
+                storePayment.setCompanyUserId(order.getCompanyUserId());
+                storePayment.setPayMode(merchantAppConfig.getMerchantType());
+                storePayment.setStatus(0);
+                storePayment.setPayCode(payCode);
+                storePayment.setPayMoney(order.getPayMoney());
+                storePayment.setCreateTime(new Date());
+                storePayment.setPayTypeCode("weixin");
+                storePayment.setBusinessType(2);
+                storePayment.setRemark("商城订单支付");
+                storePayment.setOpenId(user.getRealName());
+                storePayment.setUserId(user.getUserId());
+                storePayment.setBusinessOrderId(order.getId().toString());
+                storePayment.setOrderId(order.getId());
+                storePayment.setAppId(param.getAppId());
+                storePayment.setMerConfigId(merchantAppConfig.getId());
+                fsStorePaymentMapper.insertFsStorePayment(storePayment);
+
+                if (merchantAppConfig.getMerchantType().equals("hf")){
+                    HuiFuCreateOrder o = new HuiFuCreateOrder();
+                    o.setTradeType("T_MINIAPP");
+                    o.setOpenid(user.getMaOpenId());
+                    o.setReqSeqId("store-"+storePayment.getPayCode());
+                    o.setTransAmt(storePayment.getPayMoney().toString());
+                    o.setGoodsDesc("商城订单支付");
+                    o.setAppId(param.getAppId());
+                    try {
+
+                        HuiFuUtils.doDiv(o,order.getCompanyId());
+                        //存储分账明细
+                        HuiFuUtils.saveDivItem(o, order.getOrderCode(), storePayment.getPayCode());
+                    } catch (Exception e) {
+                        logger.error("-------------分账出错:{}", e.getMessage());
+                    }
+                    HuifuCreateOrderResult result = huiFuService.createOrder(o);
+                    if(result.getResp_code()!=null&&(result.getResp_code().equals("00000000")||result.getResp_code().equals("00000100"))){
+                        FsStorePaymentScrm mt=new FsStorePaymentScrm();
+                        mt.setPaymentId(storePayment.getPaymentId());
+                        mt.setTradeNo(result.getHf_seq_id());
+                        mt.setAppId(param.getAppId());
+                        mt.setBusinessCode(order.getOrderCode());
+                        fsStorePaymentMapper.updateFsStorePayment(mt);
+                        redisCache.setCacheObject("isPaying:"+order.getId(),order.getId().toString(),1, TimeUnit.MINUTES);
+                        Map<String, Object> resultMap = JSON.parseObject(result.getPay_info(), new TypeReference<Map<String, Object>>() {});
+                        String s = (String) resultMap.get("package");
+                        resultMap.put("packageValue",s);
+                        return R.ok().put("payType",param.getPayType()).put("result",resultMap);
+                    }
+                    else{
+                        return R.error(result.getResp_desc());
+                    }
+                }else  if (merchantAppConfig.getMerchantType().equals("wx")){
+                    WxPayConfig payConfig = new WxPayConfig();
+                    payConfig.setAppId(fsCoursePlaySourceConfig.getAppid());
+                    payConfig.setMchId(fsPayConfig.getWxMchId());
+                    payConfig.setMchKey(fsPayConfig.getWxMchKey());
+                    payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                    payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                    payConfig.setKeyPath(fsPayConfig.getKeyPath());
+                    payConfig.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
+                    wxPayService.setConfig(payConfig);
+                    WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
+                    orderRequest.setOpenid(user.getMaOpenId());//公众号支付提供用户openid
+                    orderRequest.setBody("商城订单支付");
+                    orderRequest.setOutTradeNo("store-" + storePayment.getPayCode());
+                    orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));//测试
+                    orderRequest.setTradeType("JSAPI");
+                    orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
+                    //调用统一下单接口,获取"预支付交易会话标识"
+                    try {
+                        WxPayMpOrderResult orderResult = wxPayService.createOrder(orderRequest);
+                        return R.ok().put("result", orderResult).put("type", "wx").put("isPay", 0).put("payType",param.getPayType());
+                    } catch (WxPayException e) {
+                        e.printStackTrace();
+                        throw new CustomException("支付失败" + e.getMessage());
+                    }
+                }
+            }else if(order.getPayType().equals("1") && order.getPayMoney().compareTo(BigDecimal.ZERO) ==0 ){// 判断0金额订单
+                logger.info("订单支付金额0,{}", order.getId());
+                FsStorePaymentScrm storePayment=new FsStorePaymentScrm();
+                storePayment.setCompanyId(order.getCompanyId());
+                storePayment.setCompanyUserId(order.getCompanyUserId());
+//                storePayment.setPayMode(fsPayConfig.getType());
+                storePayment.setStatus(1);
+                storePayment.setPayCode(payCode);
+                storePayment.setPayMoney(order.getPayMoney());
+                storePayment.setCreateTime(new Date());
+                storePayment.setPayTypeCode("weixin");
+                storePayment.setBusinessType(2);
+                storePayment.setRemark("商城订单支付");
+                storePayment.setOpenId(user.getRealName());
+                storePayment.setUserId(user.getUserId());
+                storePayment.setBusinessOrderId(order.getId().toString());
+                storePayment.setOrderId(order.getId());
+                storePayment.setAppId(param.getAppId());
+                fsStorePaymentMapper.insertFsStorePayment(storePayment);
+
+                FsStoreOrderScrm storeOrder = new FsStoreOrderScrm();
+                storeOrder.setId(order.getId());
+                storeOrder.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
+                storeOrder.setStatus(OrderInfoEnum.STATUS_1.getValue());
+                storeOrder.setPayTime(new Date());
+                fsStoreOrderMapper.updateFsStoreOrder(storeOrder);
+                // 添加订单审核
+                addOrderAudit(order);
+
+                return R.ok().put("payType",4);
+            }
+            else if(order.getPayType().equals("3") && order.getPayMoney().compareTo(new BigDecimal(0))<=0){
+                //货到付款
+                IFsStoreOrderScrmService fsStoreOrderScrmService = (IFsStoreOrderScrmService) AopContext.currentProxy();
+                fsStoreOrderScrmService.payConfirm(2,order.getId(),null,null,null,null);
+                return R.ok().put("payType",param.getPayType());
+            }
+            return R.error();
+        }
+        else{
+            return R.error("用户OPENID不存在");
+        }
+    }
+
+
     @Override
     public int create(Long orderId, String type, String msg) {
         FsStoreOrderLogsScrm logs=new FsStoreOrderLogsScrm();

+ 12 - 0
fs-service/src/main/java/com/fs/huifuPay/sdk/opps/core/request/V2TradePaymentScanpayQueryRequest.java

@@ -47,6 +47,10 @@ public class V2TradePaymentScanpayQueryRequest extends BaseRequest {
     @JSONField(name = "party_order_id")
     private String partyOrderId;
 
+
+
+    String appId; //多小程序支付
+
     @Override
     public FunctionCodeEnum getFunctionCode() {
         return FunctionCodeEnum.V2_TRADE_PAYMENT_SCANPAY_QUERY;
@@ -121,4 +125,12 @@ public class V2TradePaymentScanpayQueryRequest extends BaseRequest {
         this.partyOrderId = partyOrderId;
     }
 
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
 }

+ 48 - 22
fs-service/src/main/java/com/fs/huifuPay/service/impl/HuiFuServiceImpl.java

@@ -2,12 +2,18 @@ package com.fs.huifuPay.service.impl;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.spring.SpringUtils;
+import com.fs.course.domain.FsCoursePlaySourceConfig;
+import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
 import com.fs.his.domain.FsHfpayConfig;
 import com.fs.his.domain.FsPayConfig;
+import com.fs.his.domain.MerchantAppConfig;
 import com.fs.his.mapper.FsHfpayConfigMapper;
+import com.fs.his.mapper.MerchantAppConfigMapper;
 import com.fs.huifuPay.domain.*;
 import com.fs.huifuPay.sdk.opps.core.config.MerConfig;
 import com.fs.huifuPay.sdk.opps.core.request.*;
@@ -20,6 +26,7 @@ import com.google.gson.Gson;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
@@ -35,7 +42,10 @@ import static com.fs.huifuPay.demo.init.BaseCommon.doInit;
 public class HuiFuServiceImpl implements HuiFuService {
     FsPayConfig config;
     Logger logger= LoggerFactory.getLogger(getClass());
-
+    @Autowired
+    private FsCoursePlaySourceConfigMapper fsCoursePlaySourceConfigMapper;
+    @Autowired
+    private MerchantAppConfigMapper merchantAppConfigMapper;
     @Override
     public HuifuCreateOrderResult createOrder(HuiFuCreateOrder order) {
         logger.info("汇付传参HuiFuCreateOrder==============>{}",order);
@@ -43,15 +53,9 @@ public class HuiFuServiceImpl implements HuiFuService {
         try {
 
             if (order.getAppId() != null) {
-                FsHfpayConfigMapper fsHfpayConfigMapper = SpringUtils.getBean(FsHfpayConfigMapper.class);
-                FsHfpayConfig fsHfpayConfig = fsHfpayConfigMapper.selectByAppId(order.getAppId());
-                if (fsHfpayConfig != null) {
-                    //多汇付支付获取配置
-                    doInit(getMerConfig(fsHfpayConfig));
-                } else {
-                    //多小程序
-                    doInit(getMerConfig());
-                }
+                //多小程序
+                doInit(getMerConfig(order.getAppId()));
+//                doInit(getMerConfig());
             } else {
                 doInit(getMerConfig());
             }
@@ -131,7 +135,12 @@ public class HuiFuServiceImpl implements HuiFuService {
 
     @Override
     public HuiFuQueryOrderResult queryOrder(V2TradePaymentScanpayQueryRequest request) throws Exception{
-        doInit(getMerConfig());
+        if (request.getAppId() != null) {
+            //多汇付支付获取配置
+            doInit(getMerConfig(request.getAppId()));
+        } else {
+            doInit(getMerConfig());
+        }
         Map<String, Object> response = doExecute(request);
         String jsonString = JSONObject.toJSONString(response);
         HuiFuQueryOrderResult huiFuQueryOrderResult = JSON.parseObject(jsonString, HuiFuQueryOrderResult.class);
@@ -152,12 +161,17 @@ public class HuiFuServiceImpl implements HuiFuService {
     public HuiFuRefundResult refund(V2TradePaymentScanpayRefundRequest request) {
         HuiFuRefundResult huiFuRefundResult=null;
         try {
-            doInit(getMerConfig());
+            if(ObjectUtils.isNotNull(request.getAppId())){
+                doInit(getMerConfig(request.getAppId()));
+            } else {
+                doInit(getMerConfig());
+            }
             request.setReqDate(DateTools.getCurrentDateYYYYMMDD());
             Map<String, Object> response = doExecute(request);
             String jsonString = JSONObject.toJSONString(response);
             huiFuRefundResult = JSON.parseObject(jsonString, HuiFuRefundResult.class);
         } catch (Exception e){
+            e.printStackTrace();
             throw  new CustomException("退款创建失败");
         }
         return huiFuRefundResult;
@@ -282,7 +296,7 @@ public class HuiFuServiceImpl implements HuiFuService {
         try {
             if (order.getAppId() != null) {
                 //多汇付支付获取配置
-                doInit(getMerConfig());
+                doInit(getMerConfig(order.getAppId()));
             } else {
                 doInit(getMerConfig());
             }
@@ -345,16 +359,28 @@ public class HuiFuServiceImpl implements HuiFuService {
         return merConfig;
     }
 
-    public MerConfig getMerConfig(FsHfpayConfig fsHfpayConfig) {
+    public MerConfig getMerConfig(String appId) {
+        if (StringUtils.isBlank(appId)) {
+            throw new IllegalArgumentException("appId不能为空");
+        }
+        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectOne(new LambdaQueryWrapper<FsCoursePlaySourceConfig>()
+                .eq(FsCoursePlaySourceConfig::getAppid, appId));
+        if (fsCoursePlaySourceConfig == null) {
+            throw new CustomException("未找到appId对应的小程序配置: " + appId);
+        }
+        Long merchantConfigId = fsCoursePlaySourceConfig.getMerchantConfigId();
+        if (merchantConfigId == null || merchantConfigId <= 0) {
+            throw new CustomException("小程序没有配置商户信息");
+        }
+        MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
+        FsPayConfig fsPayConfig = com.hc.openapi.tool.fastjson.JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+
         MerConfig merConfig = new MerConfig();
-        merConfig.setProcutId(fsHfpayConfig.getHfProductId());
-        merConfig.setSysId(fsHfpayConfig.getHfSysId());
-        merConfig.setRsaPrivateKey(fsHfpayConfig.getHfRsaPrivateKey());
-        merConfig.setRsaPublicKey(fsHfpayConfig.getHfRsaPublicKey());
-        merConfig.setHuifuId(fsHfpayConfig.getHuifuId());
-
-        FsPayConfig fsPayConfig = new FsPayConfig();
-        BeanUtils.copyProperties(fsHfpayConfig,fsPayConfig);
+        merConfig.setProcutId(fsPayConfig.getHfProductId());
+        merConfig.setSysId(fsPayConfig.getHfSysId());
+        merConfig.setRsaPrivateKey(fsPayConfig.getHfRsaPrivateKey());
+        merConfig.setRsaPublicKey(fsPayConfig.getHfRsaPublicKey());
+        merConfig.setHuifuId(fsPayConfig.getHuifuId());
 
         config = fsPayConfig;
         return merConfig;

+ 137 - 0
fs-service/src/main/resources/mapper/MerchantAppConfigMapper.xml

@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.his.mapper.MerchantAppConfigMapper">
+
+    <resultMap type="MerchantAppConfig" id="MerchantAppConfigResult">
+        <result property="id"    column="id"    />
+        <result property="merchantType"    column="merchant_type"    />
+        <result property="appId"    column="app_id"    />
+        <result property="callbackUrl"    column="callback_url"    />
+        <result property="dataJson"    column="data_json"    />
+        <result property="createdTime"    column="created_time"    />
+        <result property="updatedTime"    column="updated_time"    />
+        <result property="isDeleted"    column="is_deleted"    />
+        <result property="createdBy"    column="created_by"    />
+        <result property="updatedBy"    column="updated_by"    />
+        <result property="merchantId"    column="merchant_id"    />
+    </resultMap>
+
+    <!-- 检查表是否存在 -->
+    <select id="checkTableExists" resultType="java.lang.Integer">
+        SELECT COUNT(*) FROM information_schema.tables
+        WHERE table_schema = DATABASE() AND table_name = 'merchant_app_config'
+    </select>
+
+    <!-- 创建商户配置表 -->
+    <update id="createMerchantAppConfigTable">
+        CREATE TABLE `merchant_app_config` (
+        `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+        `merchant_type` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商户类型:如WECHAT_PAY、ALIPAY等',
+        `app_id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '应用ID',
+        `callback_url` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '回调地址,用于接收支付结果等通知',
+        `data_json` json DEFAULT NULL COMMENT '扩展配置数据,JSON格式存储其他配置信息',
+        `created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+        `updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
+        `is_deleted` tinyint NOT NULL DEFAULT '0' COMMENT '删除状态:0-正常,1-已删除',
+        `created_by` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '创建人ID或用户名',
+        `updated_by` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '修改人ID或用户名',
+        `merchant_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '商户号',
+        PRIMARY KEY (`id`),
+        KEY `idx_merchant_type` (`merchant_type`),
+        KEY `idx_app_id` (`app_id`),
+        KEY `idx_created_time` (`created_time`),
+        KEY `merchant_app_config_merchant_type_IDX` (`merchant_type`,`is_deleted`,`merchant_id`) USING BTREE
+        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='商户应用配置表'
+    </update>
+
+
+    <sql id="selectMerchantAppConfigVo">
+        select id, merchant_type, app_id, merchant_id,callback_url, data_json, created_time, updated_time, is_deleted, created_by, updated_by from merchant_app_config
+    </sql>
+
+    <select id="selectMerchantAppConfigList" parameterType="MerchantAppConfig" resultMap="MerchantAppConfigResult">
+        <include refid="selectMerchantAppConfigVo"/>
+        <where>
+            <if test="merchantId != null and merchantId != ''"> and merchant_id = #{merchantId}</if>
+            <if test="merchantType != null  and merchantType != ''"> and merchant_type = #{merchantType}</if>
+            <if test="appId != null  and appId != ''"> and  FIND_IN_SET(#{appId},app_id)  </if>
+            <if test="params.beginCreatedTime != null and params.beginCreatedTime != '' and params.endCreatedTime != null and params.endCreatedTime != ''"> and created_time between #{params.beginCreatedTime} and #{params.endCreatedTime}</if>
+            <if test="isDeleted != null "> and is_deleted = #{isDeleted}</if>
+             <if test="id != null"> and id = #{id}</if>
+        </where>
+    </select>
+
+    <select id="selectMerchantAppConfigById" parameterType="Long" resultMap="MerchantAppConfigResult">
+        <include refid="selectMerchantAppConfigVo"/>
+        where id = #{id}
+    </select>
+
+
+    <insert id="insertMerchantAppConfig" parameterType="MerchantAppConfig" useGeneratedKeys="true" keyProperty="id">
+        insert into merchant_app_config
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="merchantType != null and merchantType != ''">merchant_type,</if>
+            <if test="appId != null and appId != ''">app_id,</if>
+            <if test="callbackUrl != null">callback_url,</if>
+            <if test="dataJson != null">data_json,</if>
+            <if test="createdTime != null">created_time,</if>
+            <if test="updatedTime != null">updated_time,</if>
+            <if test="isDeleted != null">is_deleted,</if>
+            <if test="createdBy != null and createdBy != ''">created_by,</if>
+            <if test="updatedBy != null and updatedBy != ''">updated_by,</if>
+            <if test="merchantId != null and merchantId != ''">merchant_id,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="merchantType != null and merchantType != ''">#{merchantType},</if>
+            <if test="appId != null and appId != ''">#{appId},</if>
+            <if test="callbackUrl != null">#{callbackUrl},</if>
+            <if test="dataJson != null">#{dataJson},</if>
+            <if test="createdTime != null">#{createdTime},</if>
+            <if test="updatedTime != null">#{updatedTime},</if>
+            <if test="isDeleted != null">#{isDeleted},</if>
+            <if test="createdBy != null and createdBy != ''">#{createdBy},</if>
+            <if test="updatedBy != null and updatedBy != ''">#{updatedBy},</if>
+            <if test="merchantId != null and merchantId != ''">#{merchantId},</if>
+         </trim>
+    </insert>
+
+    <update id="updateMerchantAppConfig" parameterType="MerchantAppConfig">
+        update merchant_app_config
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="merchantType != null and merchantType != ''">merchant_type = #{merchantType},</if>
+            <if test="appId != null and appId != ''">app_id = #{appId},</if>
+            <if test="callbackUrl != null">callback_url = #{callbackUrl},</if>
+            <if test="dataJson != null">data_json = #{dataJson},</if>
+            <if test="createdTime != null">created_time = #{createdTime},</if>
+            <if test="updatedTime != null">updated_time = #{updatedTime},</if>
+            <if test="isDeleted != null">is_deleted = #{isDeleted},</if>
+            <if test="createdBy != null and createdBy != ''">created_by = #{createdBy},</if>
+            <if test="updatedBy != null and updatedBy != ''">updated_by = #{updatedBy},</if>
+            <if test="merchantId != null and merchantId != ''">merchant_id = #{merchantId},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteMerchantAppConfigById" parameterType="Long">
+        delete from merchant_app_config where id = #{id}
+    </delete>
+
+    <delete id="deleteMerchantAppConfigByIds" parameterType="String">
+        delete from merchant_app_config where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+    <select id="selectMerchantAppConfigByAppId" resultMap="MerchantAppConfigResult">
+        select a.id, a.merchant_type, a.app_id, a.merchant_id, a.callback_url,
+               a.data_json, a.created_time, a.updated_time, a.is_deleted,
+               a.created_by, a.updated_by
+        from merchant_app_config a
+                 left join fs_course_play_source_config fcpsc on a.id = fcpsc.merchant_config_id
+        where a.merchant_type = #{payType}
+          and fcpsc.appid like CONCAT('%', #{appId}, '%')
+    </select>
+</mapper>

+ 8 - 0
fs-service/src/main/resources/mapper/course/FsCoursePlaySourceConfigMapper.xml

@@ -29,4 +29,12 @@
         </if>
         order by fcpsc.id desc
     </select>
+
+    <select id="selectCoursePlaySourceConfigByAppId" resultType="com.fs.course.domain.FsCoursePlaySourceConfig">
+        select
+            fcpsc.*
+        from fs_course_play_source_config fcpsc
+        where fcpsc.is_del = 0 and fcpsc.appid= #{appid}
+       limit 1
+    </select>
 </mapper>

+ 4 - 0
fs-service/src/main/resources/mapper/hisStore/FsStoreOrderScrmMapper.xml

@@ -248,6 +248,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="followTime != null">follow_time,</if>
             <if test="followDoctorId != null">follow_doctor_id,</if>
             <if test="cycle != null">cycle,</if>
+            <if test="appId != null and appId != ''">app_id,</if>
+            <if test="mimiType != null ">mimi_type,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="orderCode != null and orderCode != ''">#{orderCode},</if>
@@ -334,6 +336,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="followTime != null">#{followTime},</if>
             <if test="followDoctorId != null">#{followDoctorId},</if>
             <if test="cycle != null">#{cycle},</if>
+            <if test="appId != null">app_id,</if>
+            <if test="mimiType != null">mimi_type,</if>
          </trim>
     </insert>
 

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

@@ -124,6 +124,9 @@ public class WxPayController {
                         break;
                     case "product":
                         courseProductOrderService.payConfirm("",orderId[1],tradeNo,"",1,tradeNo,null);
+                    case "payment":
+                        paymentService.payConfirm(orderId[1], outtradeno,tradeNo,null);
+
                 }
                 return WxPayNotifyResponse.success("处理成功!");
             }else{

+ 270 - 181
fs-user-app/src/main/java/com/fs/app/controller/store/StoreOrderScrmController.java

@@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.TypeReference;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.fs.app.annotation.Login;
 import com.fs.app.controller.AppBaseController;
 import com.fs.common.config.FSSysConfig;
@@ -18,7 +19,12 @@ import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.ip.IpUtils;
 import com.fs.core.config.WxMaConfiguration;
+import com.fs.course.domain.FsCoursePlaySourceConfig;
+import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
 import com.fs.erp.service.IErpOrderService;
+import com.fs.his.domain.FsPayConfig;
+import com.fs.his.domain.MerchantAppConfig;
+import com.fs.his.mapper.MerchantAppConfigMapper;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.hisStore.config.FsErpConfig;
 import com.fs.hisStore.domain.*;
@@ -50,6 +56,8 @@ import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import me.chanjar.weixin.common.error.WxErrorException;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -65,6 +73,8 @@ import java.time.LocalDateTime;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 
+import static com.fs.hisStore.constants.UserAppsLockConstant.LOCK_KEY_PAY;
+
 
 @Api("商城接口")
 @RestController
@@ -104,6 +114,11 @@ public class StoreOrderScrmController extends AppBaseController {
     private IFsStoreAfterSalesScrmService afterSalesService;
     @Autowired
     private IFsStoreProductPackageScrmService productPackageService;
+
+    @Autowired
+    private FsCoursePlaySourceConfigMapper fsCoursePlaySourceConfigMapper;
+    @Autowired
+    private MerchantAppConfigMapper merchantAppConfigMapper;
     @Autowired
     IPayService ybPayService;
     @Autowired
@@ -115,6 +130,8 @@ public class StoreOrderScrmController extends AppBaseController {
     @Autowired
     @Qualifier("wdtErpOrderServiceImpl")
     private IErpOrderService wdtOrderService;
+    @Autowired
+    private RedissonClient redissonClient;
 
     @Autowired
     @Qualifier("k9OrderScrmServiceImpl")
@@ -269,199 +286,253 @@ public class StoreOrderScrmController extends AppBaseController {
         return R.ok().put("data",dto);
     }
 
+    /**
+     * @Description: 小程序 自己下单 制单
+     * @Param:
+     * @Return:
+     * @Author xgb
+     * @Date 2026/4/29 19:57
+     */
     @Login
     @ApiOperation("创建订单")
     @PostMapping("/create")
     public R create(@Validated @RequestBody FsStoreOrderCreateParam param, HttpServletRequest request){
-        String userId=getUserId();
+        String appId=request.getParameter("appId");
+        if(StringUtils.isNotBlank(appId)){
+            param.setAppId(appId);
+        }
         param.setIsUserApp(false);
         return orderService.createOrder(Long.parseLong(getUserId()),param);
     }
 
+
+
+
+
+
+
     @Login
     @ApiOperation("支付")
     @PostMapping("/pay")
-    @Transactional
-    //@Synchronized
     public R pay(HttpServletRequest request, @Validated @RequestBody FsStoreOrderPayParam param)
     {
-        logger.info("支付开始{}",param);
-        FsStoreOrderScrm order=orderService.selectFsStoreOrderById(param.getOrderId());
-        if(order==null){
-            return R.error("订单不存在");
-        }
-        if(order.getStatus()!= OrderInfoEnum.STATUS_0.getValue()){
-            return R.error("订单状态不正确");
-        }
-        String orderId=redisCache.getCacheObject("isPaying:"+order.getId());
-        if(StringUtils.isNotEmpty(orderId)&&orderId.equals(order.getId().toString())){
-            return R.error("正在支付中...");
-        }
+        Long orderId = param.getOrderId();
+        logger.info("开始处理支付请求, 订单号: {}, 支付类型: {}", orderId, param.getPayType());
 
-        FsUserScrm user=userService.selectFsUserById(order.getUserId());
-        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())){
-            //已改价处理
-            if(order.getIsEditMoney()!=null&&order.getIsEditMoney()==1){
-                //改过价不做处理
+        RLock lock = redissonClient.getLock(String.format(LOCK_KEY_PAY,orderId));
+        R result = null;
 
+        try {
+            boolean locked = lock.tryLock(100, 30000, TimeUnit.MILLISECONDS);
+
+            if (!locked) {
+                logger.warn("订单正在处理中,获取锁失败, 订单号: {}", orderId);
+                return R.error("订单正在处理中,请勿重复提交");
             }
-            else{
-                String config=configService.selectConfigByKey("his.store");
-                StoreConfig storeConfig= JSONUtil.toBean(config,StoreConfig.class);
-                if(param.getPayType().equals(1)){
-                    order.setPayType("1");
-                    order.setPayMoney(order.getPayPrice());
-                    order.setPayDelivery(BigDecimal.ZERO);
-                }
-                else if(param.getPayType().equals(2)){
-                    order.setPayType("2");
-                    BigDecimal payMoney=order.getPayPrice().multiply(new BigDecimal(storeConfig.getPayRate())).divide(new BigDecimal(100));
-                    payMoney=new BigDecimal(payMoney.setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
-                    order.setPayDelivery(order.getPayPrice().subtract(payMoney));
-                    order.setPayMoney(payMoney);
-                }
-                else if(param.getPayType().equals(3)){
-                    //货到付款
-                    order.setPayType("3");
-                    BigDecimal amount=redisCache.getCacheObject("orderAmount:"+order.getId());
-                    BigDecimal payMoney = BigDecimal.ZERO;
-                    if (amount != null){
-                        payMoney=amount;
-                    }
-                    order.setPayMoney(payMoney);
-                    order.setPayDelivery(order.getPayPrice().subtract(payMoney) );
-//                    order.setPayMoney(BigDecimal.ZERO);
-                }
-                orderService.updateFsStoreOrder(order);
-            }
-            String payCode = IdUtil.getSnowflake(0, 0).nextIdStr();
-//            order.setOrderCode(orderCode);
-//            if(order.getPayType().equals("1")||order.getPayType().equals("2")){
-            if((order.getPayType().equals("1")||order.getPayType().equals("2")||order.getPayType().equals("3")) && order.getPayMoney().compareTo(new BigDecimal(0))>0){
-                String json = configService.selectConfigByKey(STORE_PAY_CONF);
-                FsPayConfigScrm fsPayConfig = JSON.parseObject(json, FsPayConfigScrm.class);
-                FsStorePaymentScrm storePayment=new FsStorePaymentScrm();
-                storePayment.setCompanyId(order.getCompanyId());
-                storePayment.setCompanyUserId(order.getCompanyUserId());
-                storePayment.setPayMode(fsPayConfig.getType());
-                storePayment.setStatus(0);
-                storePayment.setPayCode(payCode);
-                storePayment.setPayMoney(order.getPayMoney());
-                storePayment.setCreateTime(new Date());
-                storePayment.setPayTypeCode("weixin");
-                storePayment.setBusinessType(2);
-                storePayment.setRemark("商城订单支付");
-                storePayment.setOpenId(user.getMaOpenId());
-                storePayment.setUserId(user.getUserId());
-                storePayment.setBusinessOrderId(order.getId().toString());
-                storePayment.setOrderId(order.getId());
-                storePayment.setAppId(param.getAppId());
-                fsStorePaymentMapper.insertFsStorePayment(storePayment);
-
-                if (fsPayConfig.getType().equals("hf")){
-                    HuiFuCreateOrder o = new HuiFuCreateOrder();
-                    o.setTradeType("T_MINIAPP");
-                    o.setOpenid(user.getMaOpenId());
-                    o.setReqSeqId("store-"+storePayment.getPayCode());
-                    o.setTransAmt(storePayment.getPayMoney().toString());
-                    o.setGoodsDesc("商城订单支付");
-                    if (param != null && StringUtils.isNotBlank(param.getAppId())) {
-                        o.setAppId(param.getAppId());
-                    }
-                    try {
-                        HuiFuUtils.doDiv(o,order.getCompanyId());
-                        //存储分账明细
-                        HuiFuUtils.saveDivItem(o, order.getOrderCode(), storePayment.getPayCode());
-                    } catch (Exception e) {
-                        logger.error("-------------分账出错:{}", e.getMessage());
-                    }
-                    HuifuCreateOrderResult result = huiFuService.createOrder(o);
-                    if(result.getResp_code()!=null&&(result.getResp_code().equals("00000000")||result.getResp_code().equals("00000100"))){
-                        FsStorePaymentScrm mt=new FsStorePaymentScrm();
-                        mt.setPaymentId(storePayment.getPaymentId());
-                        mt.setTradeNo(result.getHf_seq_id());
-                        fsStorePaymentMapper.updateFsStorePayment(mt);
-                        redisCache.setCacheObject("isPaying:"+order.getId(),order.getId().toString(),1, TimeUnit.MINUTES);
-                        Map<String, Object> resultMap = JSON.parseObject(result.getPay_info(), new TypeReference<Map<String, Object>>() {});
-                        String s = (String) resultMap.get("package");
-                        resultMap.put("packageValue",s);
-                        return R.ok().put("payType",param.getPayType()).put("result",resultMap);
-                    }
-                    else{
-                        return R.error(result.getResp_desc());
-                    }
-                }else  if (fsPayConfig.getType().equals("wx")){
-                    WxPayConfig payConfig = new WxPayConfig();
-                    payConfig.setAppId(fsPayConfig.getAppId());
-                    payConfig.setMchId(fsPayConfig.getWxMchId());
-                    payConfig.setMchKey(fsPayConfig.getWxMchKey());
-                    payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
-                    payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
-                    payConfig.setKeyPath(fsPayConfig.getKeyPath());
-                    payConfig.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
-                    wxPayService.setConfig(payConfig);
-                    WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
-                    orderRequest.setOpenid(user.getMaOpenId());//公众号支付提供用户openid
-                    orderRequest.setBody("商城订单支付");
-                    orderRequest.setOutTradeNo("store-" + storePayment.getPayCode());
-                    orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));//测试
-                    //orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(money));//测试
-                    orderRequest.setTradeType("JSAPI");
-                    orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
-                    //调用统一下单接口,获取"预支付交易会话标识"
-                    try {
-                        WxPayMpOrderResult orderResult = wxPayService.createOrder(orderRequest);
-                        return R.ok().put("result", orderResult).put("type", "wx").put("isPay", 0).put("payType",param.getPayType());
-                    } catch (WxPayException e) {
-                        e.printStackTrace();
-                        throw new CustomException("支付失败" + e.getMessage());
-                    }
-                }
-            }else if(order.getPayType().equals("1") && order.getPayMoney().compareTo(BigDecimal.ZERO) ==0 ){// 判断0金额订单
-                logger.info("订单支付金额0,{}", order.getId());
-                FsStorePaymentScrm storePayment=new FsStorePaymentScrm();
-                storePayment.setCompanyId(order.getCompanyId());
-                storePayment.setCompanyUserId(order.getCompanyUserId());
-//                storePayment.setPayMode(fsPayConfig.getType());
-                storePayment.setStatus(1);
-                storePayment.setPayCode(payCode);
-                storePayment.setPayMoney(order.getPayMoney());
-                storePayment.setCreateTime(new Date());
-                storePayment.setPayTypeCode("weixin");
-                storePayment.setBusinessType(2);
-                storePayment.setRemark("商城订单支付");
-                storePayment.setOpenId(user.getRealName());
-                storePayment.setUserId(user.getUserId());
-                storePayment.setBusinessOrderId(order.getId().toString());
-                storePayment.setOrderId(order.getId());
-                storePayment.setAppId(param.getAppId());
-                fsStorePaymentMapper.insertFsStorePayment(storePayment);
-
-                FsStoreOrderScrm storeOrder = new FsStoreOrderScrm();
-                storeOrder.setId(order.getId());
-                storeOrder.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
-                storeOrder.setStatus(OrderInfoEnum.STATUS_1.getValue());
-                storeOrder.setPayTime(new Date());
-                orderService.updateFsStoreOrder(storeOrder);
-                // 添加订单审核
-                addOrderAudit(order);
-
-                return R.ok().put("payType",4);
-            }
-//            else if(order.getPayType().equals("3")){
-            else if(order.getPayType().equals("3") && order.getPayMoney().compareTo(new BigDecimal(0))<=0){
-                //货到付款
-                orderService.payConfirm(2,order.getId(),null,null,null,null);
-                return R.ok().put("payType",param.getPayType());
+
+            result = orderService.pay(param);
+
+        } catch (InterruptedException e) {
+            logger.error("获取支付锁的过程被中断, 订单号: {}", orderId, e);
+            Thread.currentThread().interrupt();
+            return R.error("支付处理被中断,请稍后重试");
+        } catch (Throwable e) {
+            logger.error("支付过程中发生异常, 订单号: {}", orderId, e);
+            throw e;
+        } finally {
+            if (lock.isHeldByCurrentThread()) {
+                lock.unlock();
+                logger.debug("支付锁已释放, 订单号: {}", orderId);
             }
-            return R.error();
-        }
-        else{
-            return R.error("用户OPENID不存在");
         }
 
+        return result;
     }
 
+//    @Login
+//    @ApiOperation("支付")
+//    @PostMapping("/pay")
+//    @Transactional
+//    //@Synchronized
+//    public R pay(HttpServletRequest request, @Validated @RequestBody FsStoreOrderPayParam param)
+//    {
+//        logger.info("支付开始{}",param);
+//        FsStoreOrderScrm order=orderService.selectFsStoreOrderById(param.getOrderId());
+//        if(order==null){
+//            return R.error("订单不存在");
+//        }
+//        if(order.getStatus()!= OrderInfoEnum.STATUS_0.getValue()){
+//            return R.error("订单状态不正确");
+//        }
+//        String orderId=redisCache.getCacheObject("isPaying:"+order.getId());
+//        if(StringUtils.isNotEmpty(orderId)&&orderId.equals(order.getId().toString())){
+//            return R.error("正在支付中...");
+//        }
+//
+//        FsUserScrm user=userService.selectFsUserById(order.getUserId());
+//        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())){
+//            //已改价处理
+//            if(order.getIsEditMoney()!=null&&order.getIsEditMoney()==1){
+//                //改过价不做处理
+//
+//            }
+//            else{
+//                String config=configService.selectConfigByKey("his.store");
+//                StoreConfig storeConfig= JSONUtil.toBean(config,StoreConfig.class);
+//                if(param.getPayType().equals(1)){
+//                    order.setPayType("1");
+//                    order.setPayMoney(order.getPayPrice());
+//                    order.setPayDelivery(BigDecimal.ZERO);
+//                }
+//                else if(param.getPayType().equals(2)){
+//                    order.setPayType("2");
+//                    BigDecimal payMoney=order.getPayPrice().multiply(new BigDecimal(storeConfig.getPayRate())).divide(new BigDecimal(100));
+//                    payMoney=new BigDecimal(payMoney.setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
+//                    order.setPayDelivery(order.getPayPrice().subtract(payMoney));
+//                    order.setPayMoney(payMoney);
+//                }
+//                else if(param.getPayType().equals(3)){
+//                    //货到付款
+//                    order.setPayType("3");
+//                    BigDecimal amount=redisCache.getCacheObject("orderAmount:"+order.getId());
+//                    BigDecimal payMoney = BigDecimal.ZERO;
+//                    if (amount != null){
+//                        payMoney=amount;
+//                    }
+//                    order.setPayMoney(payMoney);
+//                    order.setPayDelivery(order.getPayPrice().subtract(payMoney) );
+////                    order.setPayMoney(BigDecimal.ZERO);
+//                }
+//                orderService.updateFsStoreOrder(order);
+//            }
+//            String payCode = IdUtil.getSnowflake(0, 0).nextIdStr();
+////            order.setOrderCode(orderCode);
+////            if(order.getPayType().equals("1")||order.getPayType().equals("2")){
+//            if((order.getPayType().equals("1")||order.getPayType().equals("2")||order.getPayType().equals("3")) && order.getPayMoney().compareTo(new BigDecimal(0))>0){
+//                String json = configService.selectConfigByKey(STORE_PAY_CONF);
+//                FsPayConfigScrm fsPayConfig = JSON.parseObject(json, FsPayConfigScrm.class);
+//                FsStorePaymentScrm storePayment=new FsStorePaymentScrm();
+//                storePayment.setCompanyId(order.getCompanyId());
+//                storePayment.setCompanyUserId(order.getCompanyUserId());
+//                storePayment.setPayMode(fsPayConfig.getType());
+//                storePayment.setStatus(0);
+//                storePayment.setPayCode(payCode);
+//                storePayment.setPayMoney(order.getPayMoney());
+//                storePayment.setCreateTime(new Date());
+//                storePayment.setPayTypeCode("weixin");
+//                storePayment.setBusinessType(2);
+//                storePayment.setRemark("商城订单支付");
+//                storePayment.setOpenId(user.getMaOpenId());
+//                storePayment.setUserId(user.getUserId());
+//                storePayment.setBusinessOrderId(order.getId().toString());
+//                storePayment.setOrderId(order.getId());
+//                storePayment.setAppId(param.getAppId());
+//                fsStorePaymentMapper.insertFsStorePayment(storePayment);
+//
+//                if (fsPayConfig.getType().equals("hf")){
+//                    HuiFuCreateOrder o = new HuiFuCreateOrder();
+//                    o.setTradeType("T_MINIAPP");
+//                    o.setOpenid(user.getMaOpenId());
+//                    o.setReqSeqId("store-"+storePayment.getPayCode());
+//                    o.setTransAmt(storePayment.getPayMoney().toString());
+//                    o.setGoodsDesc("商城订单支付");
+//                    if (param != null && StringUtils.isNotBlank(param.getAppId())) {
+//                        o.setAppId(param.getAppId());
+//                    }
+//                    try {
+//                        HuiFuUtils.doDiv(o,order.getCompanyId());
+//                        //存储分账明细
+//                        HuiFuUtils.saveDivItem(o, order.getOrderCode(), storePayment.getPayCode());
+//                    } catch (Exception e) {
+//                        logger.error("-------------分账出错:{}", e.getMessage());
+//                    }
+//                    HuifuCreateOrderResult result = huiFuService.createOrder(o);
+//                    if(result.getResp_code()!=null&&(result.getResp_code().equals("00000000")||result.getResp_code().equals("00000100"))){
+//                        FsStorePaymentScrm mt=new FsStorePaymentScrm();
+//                        mt.setPaymentId(storePayment.getPaymentId());
+//                        mt.setTradeNo(result.getHf_seq_id());
+//                        fsStorePaymentMapper.updateFsStorePayment(mt);
+//                        redisCache.setCacheObject("isPaying:"+order.getId(),order.getId().toString(),1, TimeUnit.MINUTES);
+//                        Map<String, Object> resultMap = JSON.parseObject(result.getPay_info(), new TypeReference<Map<String, Object>>() {});
+//                        String s = (String) resultMap.get("package");
+//                        resultMap.put("packageValue",s);
+//                        return R.ok().put("payType",param.getPayType()).put("result",resultMap);
+//                    }
+//                    else{
+//                        return R.error(result.getResp_desc());
+//                    }
+//                }else  if (fsPayConfig.getType().equals("wx")){
+//                    WxPayConfig payConfig = new WxPayConfig();
+//                    payConfig.setAppId(fsPayConfig.getAppId());
+//                    payConfig.setMchId(fsPayConfig.getWxMchId());
+//                    payConfig.setMchKey(fsPayConfig.getWxMchKey());
+//                    payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+//                    payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+//                    payConfig.setKeyPath(fsPayConfig.getKeyPath());
+//                    payConfig.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
+//                    wxPayService.setConfig(payConfig);
+//                    WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
+//                    orderRequest.setOpenid(user.getMaOpenId());//公众号支付提供用户openid
+//                    orderRequest.setBody("商城订单支付");
+//                    orderRequest.setOutTradeNo("store-" + storePayment.getPayCode());
+//                    orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));//测试
+//                    //orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(money));//测试
+//                    orderRequest.setTradeType("JSAPI");
+//                    orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
+//                    //调用统一下单接口,获取"预支付交易会话标识"
+//                    try {
+//                        WxPayMpOrderResult orderResult = wxPayService.createOrder(orderRequest);
+//                        return R.ok().put("result", orderResult).put("type", "wx").put("isPay", 0).put("payType",param.getPayType());
+//                    } catch (WxPayException e) {
+//                        e.printStackTrace();
+//                        throw new CustomException("支付失败" + e.getMessage());
+//                    }
+//                }
+//            }else if(order.getPayType().equals("1") && order.getPayMoney().compareTo(BigDecimal.ZERO) ==0 ){// 判断0金额订单
+//                logger.info("订单支付金额0,{}", order.getId());
+//                FsStorePaymentScrm storePayment=new FsStorePaymentScrm();
+//                storePayment.setCompanyId(order.getCompanyId());
+//                storePayment.setCompanyUserId(order.getCompanyUserId());
+////                storePayment.setPayMode(fsPayConfig.getType());
+//                storePayment.setStatus(1);
+//                storePayment.setPayCode(payCode);
+//                storePayment.setPayMoney(order.getPayMoney());
+//                storePayment.setCreateTime(new Date());
+//                storePayment.setPayTypeCode("weixin");
+//                storePayment.setBusinessType(2);
+//                storePayment.setRemark("商城订单支付");
+//                storePayment.setOpenId(user.getRealName());
+//                storePayment.setUserId(user.getUserId());
+//                storePayment.setBusinessOrderId(order.getId().toString());
+//                storePayment.setOrderId(order.getId());
+//                storePayment.setAppId(param.getAppId());
+//                fsStorePaymentMapper.insertFsStorePayment(storePayment);
+//
+//                FsStoreOrderScrm storeOrder = new FsStoreOrderScrm();
+//                storeOrder.setId(order.getId());
+//                storeOrder.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
+//                storeOrder.setStatus(OrderInfoEnum.STATUS_1.getValue());
+//                storeOrder.setPayTime(new Date());
+//                orderService.updateFsStoreOrder(storeOrder);
+//                // 添加订单审核
+//                addOrderAudit(order);
+//
+//                return R.ok().put("payType",4);
+//            }
+////            else if(order.getPayType().equals("3")){
+//            else if(order.getPayType().equals("3") && order.getPayMoney().compareTo(new BigDecimal(0))<=0){
+//                //货到付款
+//                orderService.payConfirm(2,order.getId(),null,null,null,null);
+//                return R.ok().put("payType",param.getPayType());
+//            }
+//            return R.error();
+//        }
+//        else{
+//            return R.error("用户OPENID不存在");
+//        }
+//
+//    }
+
     private void addOrderAudit(FsStoreOrderScrm order) {
         if (!getAuditSwitch()) {
             return;
@@ -682,12 +753,17 @@ public class StoreOrderScrmController extends AppBaseController {
     }
 
 
+
+
     @Login
     @ApiOperation("亲友支付")
     @PostMapping("/otherPayment")
-    @Transactional
     public R otherPayment(@Validated @RequestBody FsStoreOrderOtherPayParam param, HttpServletRequest request){
-        final WxMaService wxService = WxMaConfiguration.getMaService(properties.getConfigs().get(0).getAppid());
+        String appId=request.getHeader("appId");
+        if (StringUtils.isEmpty(appId)){
+            appId=properties.getConfigs().get(0).getAppid(); // 兼容线上版本,后面去掉
+        }
+        final WxMaService wxService = WxMaConfiguration.getMaService(appId);
         try {
             String ip = IpUtil.getRequestIp();
             WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
@@ -721,8 +797,21 @@ public class StoreOrderScrmController extends AppBaseController {
                 return R.error("正在支付中...");
             }
 
-            String json = configService.selectConfigByKey(STORE_PAY_CONF);
-            FsPayConfigScrm fsPayConfig = JSON.parseObject(json, FsPayConfigScrm.class);
+            FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectOne(new LambdaQueryWrapper<FsCoursePlaySourceConfig>()
+                    .eq(FsCoursePlaySourceConfig::getAppid, appId));
+            if (fsCoursePlaySourceConfig == null) {
+                throw new CustomException("未找到appId对应的小程序配置: " + param.getAppId());
+            }
+            Long merchantConfigId = fsCoursePlaySourceConfig.getMerchantConfigId();
+            if (merchantConfigId == null || merchantConfigId <= 0) {
+                throw new CustomException("小程序没有配置商户信息");
+            }
+            MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
+            if(merchantAppConfig == null){
+                throw new CustomException("未找到商户信息");
+            }
+
+            FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
             String payCode = IdUtil.getSnowflake(0, 0).nextIdStr();
             //易宝支付
             FsStorePaymentScrm storePayment=new FsStorePaymentScrm();
@@ -730,7 +819,7 @@ public class StoreOrderScrmController extends AppBaseController {
             storePayment.setCompanyUserId(order.getCompanyUserId());
             storePayment.setStatus(0);
             storePayment.setPayCode(payCode);
-            storePayment.setPayMode(fsPayConfig.getType());
+            storePayment.setPayMode(merchantAppConfig.getMerchantType());
             storePayment.setPayMoney(order.getPayMoney());
             storePayment.setCreateTime(new Date());
             storePayment.setPayTypeCode("weixin");
@@ -743,7 +832,7 @@ public class StoreOrderScrmController extends AppBaseController {
             storePayment.setAppId(param.getAppId());
             fsStorePaymentMapper.insertFsStorePayment(storePayment);
 
-            if (fsPayConfig.getType().equals("hf")){
+            if (merchantAppConfig.getMerchantType().equals("hf")){
                 HuiFuCreateOrder o = new HuiFuCreateOrder();
                 o.setTradeType("T_MINIAPP");
                 o.setOpenid(user.getMaOpenId());
@@ -774,15 +863,15 @@ public class StoreOrderScrmController extends AppBaseController {
                 else{
                     return R.error(result.getResp_desc());
                 }
-            }else  if (fsPayConfig.getType().equals("wx")){
+            }else  if (merchantAppConfig.getMerchantType().equals("wx")){
                 //创建微信订单
                 WxPayConfig payConfig = new WxPayConfig();
-                payConfig.setAppId(fsPayConfig.getAppId());
+                payConfig.setAppId(fsCoursePlaySourceConfig.getAppid());
                 payConfig.setMchId(fsPayConfig.getWxMchId());
                 payConfig.setMchKey(fsPayConfig.getWxMchKey());
                 payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
                 payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
-                payConfig.setKeyPath(null);
+                payConfig.setKeyPath(fsPayConfig.getKeyPath());
                 payConfig.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
                 wxPayService.setConfig(payConfig);
                 WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();

+ 19 - 0
fs-user-app/src/main/java/com/fs/app/controller/store/UserScrmController.java

@@ -5,6 +5,7 @@ import cn.hutool.core.img.ImgUtil;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.extra.qrcode.QrCodeUtil;
 import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.fs.app.annotation.Login;
 import com.fs.app.controller.AppBaseController;
 import com.fs.common.OrderUtils;
@@ -13,6 +14,8 @@ import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.common.exception.CustomException;
 import com.fs.common.param.BaseQueryParam;
+import com.fs.course.domain.FsCoursePlaySourceConfig;
+import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
 import com.fs.course.param.newfs.FsUserCourseBeMemberParam;
 import com.fs.course.service.IFsUserCourseVideoService;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
@@ -72,6 +75,9 @@ public class UserScrmController extends AppBaseController {
     @Autowired
     private IFsUserScrmService fsUserService;
 
+    @Autowired
+    private FsCoursePlaySourceConfigMapper fsCoursePlaySourceConfigMapper;
+
     /**
      * 获取用户信息
      * @param request
@@ -88,6 +94,19 @@ public class UserScrmController extends AppBaseController {
                     user.setIsShow(1);
                 }
             }
+
+            String appId=request.getHeader("appId");
+            if(!StringUtils.isEmpty(appId)){
+                FsCoursePlaySourceConfig coursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectOne(new LambdaQueryWrapper<FsCoursePlaySourceConfig>()
+                        .eq(FsCoursePlaySourceConfig::getAppid, appId));
+                if(coursePlaySourceConfig==null){
+                    return R.error("小程序配置不存在");
+                }
+                if(coursePlaySourceConfig.getMimiType()==2){// 公域小程序允许直接下单
+                    user.setIsShow(1);
+                }
+            }
+
             return R.ok().put("user",user);
         } catch (Exception e){