1
0

3 Revīzijas e55b7492f2 ... 3d7c247c6d

Autors SHA1 Ziņojums Datums
  xw 3d7c247c6d 上传视频库同步更新课程管理对应的视频的时长 4 dienas atpakaļ
  xw 1a7ee60980 app商城申请退款和小程序申请退款 4 dienas atpakaļ
  xw b723355f30 app商城购买,回调 5 dienas atpakaļ
26 mainītis faili ar 1325 papildinājumiem un 62 dzēšanām
  1. 1 1
      fs-admin/src/main/java/com/fs/course/controller/FsVideoResourceController.java
  2. 17 0
      fs-service/src/main/java/com/fs/app/AppPayService.java
  3. 72 0
      fs-service/src/main/java/com/fs/app/impl/AppPayServiceImpl.java
  4. 179 0
      fs-service/src/main/java/com/fs/company/domain/RechargeRecord.java
  5. 1 1
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java
  6. 1 1
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java
  7. 2 2
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  8. 3 0
      fs-service/src/main/java/com/fs/his/config/AppConfig.java
  9. 2 0
      fs-service/src/main/java/com/fs/his/enums/BusinessTypeEnum.java
  10. 4 1
      fs-service/src/main/java/com/fs/his/enums/PaymentMethodEnum.java
  11. 10 0
      fs-service/src/main/java/com/fs/his/mapper/MerchantAppConfigMapper.java
  12. 6 0
      fs-service/src/main/java/com/fs/his/param/FsIntegralOrderDoPayParam.java
  13. 3 0
      fs-service/src/main/java/com/fs/hisStore/domain/FsStoreOrderScrm.java
  14. 6 0
      fs-service/src/main/java/com/fs/hisStore/domain/FsUserScrm.java
  15. 1 1
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreAfterSalesScrmMapper.java
  16. 7 0
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStorePaymentScrmMapper.java
  17. 6 0
      fs-service/src/main/java/com/fs/hisStore/service/IFsStoreOrderScrmService.java
  18. 5 0
      fs-service/src/main/java/com/fs/hisStore/service/IFsStorePaymentScrmService.java
  19. 97 20
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreAfterSalesScrmServiceImpl.java
  20. 210 31
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java
  21. 532 0
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStorePaymentScrmServiceImpl.java
  22. 7 1
      fs-service/src/main/java/com/fs/huifuPay/service/impl/HuiFuServiceImpl.java
  23. 9 0
      fs-service/src/main/resources/mapper/MerchantAppConfigMapper.xml
  24. 9 3
      fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml
  25. 84 0
      fs-user-app/src/main/java/com/fs/app/controller/AppPayController.java
  26. 51 0
      fs-user-app/src/main/java/com/fs/app/controller/store/AppController.java

+ 1 - 1
fs-admin/src/main/java/com/fs/course/controller/FsVideoResourceController.java

@@ -144,7 +144,7 @@ public class FsVideoResourceController extends BaseController {
             return AjaxResult.success();
         }
         fsVideoResourceService.updateById(fsVideoResource);
-        fsUserCourseVideoService.updateVideoByVideoUrl(fsVideoResource.getVideoUrl(),fsVideoResourceResult.getOldVideoUrl(),fsVideoResource.getThumbnail(),fsVideoResource.getFileName());
+        fsUserCourseVideoService.updateVideoByVideoUrl(fsVideoResource.getVideoUrl(),fsVideoResourceResult.getOldVideoUrl(),fsVideoResource.getThumbnail(),fsVideoResource.getFileName(),fsVideoResource.getDuration());
         return AjaxResult.success();
     }
 

+ 17 - 0
fs-service/src/main/java/com/fs/app/AppPayService.java

@@ -0,0 +1,17 @@
+package com.fs.app;
+
+import com.fs.common.core.domain.R;
+import com.fs.his.param.FsPackageOrderDoPayParam;
+import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
+
+
+import java.util.Map;
+
+public interface AppPayService {
+
+
+    /**
+     * 微信支付回调
+     */
+    String wxNotify(WxPayOrderNotifyResult result);
+}

+ 72 - 0
fs-service/src/main/java/com/fs/app/impl/AppPayServiceImpl.java

@@ -0,0 +1,72 @@
+package com.fs.app.impl;
+
+import com.fs.app.AppPayService;
+import com.fs.his.service.IFsInquiryOrderService;
+import com.fs.his.service.IFsPackageOrderService;
+import com.fs.his.service.IFsStoreOrderService;
+import com.fs.hisStore.service.IFsStoreOrderScrmService;
+import com.fs.live.service.ILiveOrderService;
+import com.fs.system.mapper.SysConfigMapper;
+import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
+import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class AppPayServiceImpl implements AppPayService {
+
+    @Autowired
+    private SysConfigMapper sysConfigMapper;
+    @Autowired
+    private IFsInquiryOrderService inquiryOrderService;
+    @Lazy
+    @Autowired
+    private IFsStoreOrderScrmService storeOrderService;
+
+    @Lazy
+    @Autowired
+    private ILiveOrderService liveOrderService;
+    @Autowired
+    private IFsPackageOrderService packageOrderService;
+
+    @Override
+    public String wxNotify(WxPayOrderNotifyResult result) {
+        log.info("微信回调参数: {}", result);
+        if (!"SUCCESS".equals(result.getReturnCode())){
+            return WxPayNotifyResponse.success("微信回调失败");
+        }
+
+        if (!"SUCCESS".equals(result.getResultCode())){
+            return WxPayNotifyResponse.success("交易失败");
+        }
+
+        String outTradeNo = result.getOutTradeNo();
+        String[] tradeNoArr = outTradeNo.split("-");
+        if (tradeNoArr.length < 2) {
+            log.info("微信回调订单号格式异常, outTradeNo: {}", outTradeNo);
+            return WxPayNotifyResponse.success("OK");
+        }
+        switch (tradeNoArr[0]) {
+            case "inquiry":
+                inquiryOrderService.payConfirm("", tradeNoArr[1],"","",1,result.getTransactionId(),"");
+                break;
+            case "store":
+                storeOrderService.payConfirm(1, null, tradeNoArr[1], outTradeNo, result.getTransactionId(), null);
+                break;
+            case "live":
+                liveOrderService.payConfirm(1, null, tradeNoArr[1], outTradeNo, result.getTransactionId(), null);
+                break;
+            case "package":
+                packageOrderService.payConfirm("", tradeNoArr[1],"","",1,result.getTransactionId(),"");
+                break;
+            default:
+                log.warn("微信回调未知订单前缀, outTradeNo: {}", outTradeNo);
+                break;
+        }
+        return WxPayNotifyResponse.success("OK");
+    }
+
+}

+ 179 - 0
fs-service/src/main/java/com/fs/company/domain/RechargeRecord.java

@@ -0,0 +1,179 @@
+package com.fs.company.domain;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 储值支付记录对象 recharge_record
+ *
+ * @author ruoyi
+ * @date 2026-03-17
+ */
+public class RechargeRecord extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 主键ID */
+    private Long id;
+
+    /** 用户ID */
+    @Excel(name = "用户ID")
+    private Long userId;
+
+    /** 用户姓名 */
+    @Excel(name = "用户姓名")
+    private String userName;
+
+    /** 储值金额 */
+    @Excel(name = "储值金额")
+    private BigDecimal totalAmount;
+
+    /** 交易流水号 */
+    @Excel(name = "交易流水号")
+    private String transactionId;
+
+    /** 订单ID */
+    private Long orderId;
+
+    /** 订单编号 */
+    private String orderNo;
+
+    /** 业务类型:0-充值,1-消费 */
+    @Excel(name = "业务类型", readConverterExp = "0=充值,1=消费")
+    private Integer businessType;
+
+    /** 公司ID */
+    @Excel(name = "公司ID")
+    private Long companyId;
+
+    /** 公司名称 */
+    @Excel(name = "公司名称")
+    private String companyName;
+
+    /** 删除标志:0-未删除,1-已删除 */
+    private String delFlag;
+
+    public void setId(Long id)
+    {
+        this.id = id;
+    }
+
+    public Long getId()
+    {
+        return id;
+    }
+    public void setUserId(Long userId)
+    {
+        this.userId = userId;
+    }
+
+    public Long getUserId()
+    {
+        return userId;
+    }
+    public void setUserName(String userName)
+    {
+        this.userName = userName;
+    }
+
+    public String getUserName()
+    {
+        return userName;
+    }
+    public void setTotalAmount(BigDecimal totalAmount)
+    {
+        this.totalAmount = totalAmount;
+    }
+
+    public BigDecimal getTotalAmount()
+    {
+        return totalAmount;
+    }
+    public void setTransactionId(String transactionId)
+    {
+        this.transactionId = transactionId;
+    }
+
+    public String getTransactionId()
+    {
+        return transactionId;
+    }
+    public Integer getBusinessType()
+    {
+        return businessType;
+    }
+
+    public void setBusinessType(Integer businessType)
+    {
+        this.businessType = businessType;
+    }
+    public Long getCompanyId()
+    {
+        return companyId;
+    }
+
+    public void setCompanyId(Long companyId)
+    {
+        this.companyId = companyId;
+    }
+    public String getCompanyName()
+    {
+        return companyName;
+    }
+
+    public void setCompanyName(String companyName)
+    {
+        this.companyName = companyName;
+    }
+    public String getDelFlag()
+    {
+        return delFlag;
+    }
+    public void setDelFlag(String delFlag)
+    {
+        this.delFlag = delFlag;
+    }
+
+    public Long getOrderId() {
+        return orderId;
+    }
+
+    public RechargeRecord setOrderId(Long orderId) {
+        this.orderId = orderId;
+        return this;
+    }
+
+    public String getOrderNo() {
+        return orderNo;
+    }
+
+    public RechargeRecord setOrderNo(String orderNo) {
+        this.orderNo = orderNo;
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+                .append("id", getId())
+                .append("userId", getUserId())
+                .append("userName", getUserName())
+                .append("totalAmount", getTotalAmount())
+                .append("transactionId", getTransactionId())
+                .append("businessType", getBusinessType())
+                .append("companyId", getCompanyId())
+                .append("companyName", getCompanyName())
+                .append("remark", getRemark())
+                .append("createBy", getCreateBy())
+                .append("createTime", getCreateTime())
+                .append("updateBy", getUpdateBy())
+                .append("updateTime", getUpdateTime())
+                .append("delFlag", getDelFlag())
+                .toString();
+    }
+}

+ 1 - 1
fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java

@@ -65,7 +65,7 @@ public interface FsUserCourseVideoMapper extends BaseMapper<FsUserCourseVideo> {
      * @return 结果
      */
     public int updateFsUserCourseVideo(FsUserCourseVideo fsUserCourseVideo);
-    int updateVideoByVideoUrl(@Param("videoUrl") String videoUrl,@Param("thumbnail")String thumbnail, @Param("ids") List<Long> ids,@Param("fileName") String fileName);
+    int updateVideoByVideoUrl(@Param("videoUrl") String videoUrl,@Param("thumbnail")String thumbnail, @Param("ids") List<Long> ids,@Param("fileName") String fileName,@Param("duration") Integer duration);
     List<FsUserCourseVideo> selectByVideoUrl(String videoUrl);
 
     @Update("<script> " +

+ 1 - 1
fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java

@@ -207,7 +207,7 @@ public interface IFsUserCourseVideoService extends IService<FsUserCourseVideo> {
     R checkUserInfo(long l);
 
     R updateVideo();
-    AjaxResult updateVideoByVideoUrl(String videoUrl,String oldVideoUrl, String thumbnail,String fileName);
+    AjaxResult updateVideoByVideoUrl(String videoUrl,String oldVideoUrl, String thumbnail,String fileName, Integer duration);
 
     R checkUserInfo(Long userId);
 

+ 2 - 2
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -3969,14 +3969,14 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
     }
 
     @Override
-    public AjaxResult updateVideoByVideoUrl(String videoUrl,String oldVideoUrl, String thumbnail,String fileName) {
+    public AjaxResult updateVideoByVideoUrl(String videoUrl,String oldVideoUrl, String thumbnail,String fileName, Integer duration) {
         List<FsUserCourseVideo> videoList = fsUserCourseVideoMapper.selectByVideoUrl(oldVideoUrl);
         if (CollectionUtils.isEmpty(videoList)){
             log.warn("根据videoUrl:{} 未查询到fs_user_course_video表数据",oldVideoUrl);
             return AjaxResult.success();
         }
         List<Long> idList = videoList.stream().map(FsUserCourseVideo::getVideoId).collect(Collectors.toList());
-        fsUserCourseVideoMapper.updateVideoByVideoUrl(videoUrl,thumbnail, idList,fileName);
+        fsUserCourseVideoMapper.updateVideoByVideoUrl(videoUrl,thumbnail, idList,fileName,duration);
         return AjaxResult.success();
     }
     @Override

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

@@ -72,4 +72,7 @@ public class AppConfig {
 
     //连续提现几天封控
     private BigDecimal limitAmount;
+
+    private Long tongueFlag;
+    private String appId;
 }

+ 2 - 0
fs-service/src/main/java/com/fs/his/enums/BusinessTypeEnum.java

@@ -7,6 +7,8 @@ import lombok.Getter;
 @AllArgsConstructor
 public enum BusinessTypeEnum {
     INTEGRAL_ORDER("integral", 6, "积分商城订单支付"),
+    ORDER_ORDER("store", 8, "商城订单支付"),
+    LIVE_ORDER("live", 9, "直播订单支付"),
     ;
 
     private final String prefix;

+ 4 - 1
fs-service/src/main/java/com/fs/his/enums/PaymentMethodEnum.java

@@ -8,8 +8,11 @@ import lombok.Getter;
 public enum PaymentMethodEnum {
     MINIAPP_WECHAT("weixin"), // 小程序微信支付
     H5_WECHAT("微信"),      // H5微信支付
+    WX_APP("wx_app"),      // H5微信支付
+    T_NATIVE("t_native"),      // H5微信支付
     ALIPAY("alipay"),         // 支付宝支付
-    H5_ALIPAY("alipay");       // H5支付宝支付
+    H5_ALIPAY("alipay"),       // H5支付宝支付
+    CZ_PAY("cz_pay");       // H5支付宝支付  // H5微信支付
 
     private final String desc;
 }

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

@@ -5,6 +5,7 @@ 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接口
@@ -74,4 +75,13 @@ public interface MerchantAppConfigMapper extends BaseMapper<MerchantAppConfig>{
      * @return 结果
      */
     int deleteMerchantAppConfigByIds(Long[] ids);
+
+    /**
+     * 根据appId和支付类型查询商户信息
+     *
+     * @param appId
+     * @param payType
+     * @return
+     */
+    MerchantAppConfig selectMerchantAppConfigByAppId(@Param("appId") String appId, @Param("payType") String payType);
 }

+ 6 - 0
fs-service/src/main/java/com/fs/his/param/FsIntegralOrderDoPayParam.java

@@ -10,4 +10,10 @@ public class FsIntegralOrderDoPayParam {
     private Long orderId;
 
     private Long userId;
+    private String appId;
+
+    /**
+     * 商品类型
+     */
+    private String type;
 }

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

@@ -369,5 +369,8 @@ public class FsStoreOrderScrm extends BaseEntity
     // 后台修改商品类型,0-未修改过;1-总后台;2-销售后台
     private Integer backendEditProductType;
 
+    @TableField(exist = false)
+    private Boolean isLive = false;
+
 
 }

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

@@ -19,6 +19,7 @@ import java.util.Date;
  * @author fs
  * @date 2022-03-15
  */
+@Data
 @TableName("fs_user")
 public class FsUserScrm extends BaseEntity
 {
@@ -187,6 +188,11 @@ public class FsUserScrm extends BaseEntity
      * 小程序appId,多个用逗号分隔
      */
     private String appId;
+    /**
+     * 储值金额
+     */
+    @Excel(name = "储值金额")
+    private BigDecimal rechargeBalance;
 
     public String getAppId() {
         return appId;

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

@@ -102,7 +102,7 @@ public interface FsStoreAfterSalesScrmMapper
             "<if test =\"maps.hfOrderCode != null and  maps.hfOrderCode!='' \"> " +
               "and fsps.pay_code = #{maps.hfOrderCode} " +
             "</if>" +
-            "<if test =\"maps.bankTransactionId != null and  maps.bankTransactionId!='' \"> " +
+            "<if test = 'maps.bankTransactionId != null    '> " +
               "and fsps.bank_transaction_id = #{maps.bankTransactionId} " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +

+ 7 - 0
fs-service/src/main/java/com/fs/hisStore/mapper/FsStorePaymentScrmMapper.java

@@ -371,6 +371,13 @@ public interface FsStorePaymentScrmMapper
     @Select("select * from fs_store_payment_scrm where business_type=2 and order_id=#{orderId} and status=1   ")
     List<FsStorePaymentScrm> selectFsStorePaymentByOrderId(Long orderId);
 
+    /** App 发货(business_type=8),不对接小程序/ERP,仅本地订单发货 */
+    @Select("select * from fs_store_payment_scrm where business_type=8 and order_id=#{orderId} and status=1 order by payment_id desc")
+    List<FsStorePaymentScrm> selectFsStorePaymentByOrderIdBusinessType8(Long orderId);
+
+    @Select("select * from fs_store_payment_scrm where (business_type=2 or business_type=8)  and order_id=#{orderId} and status=1   ")
+    List<FsStorePaymentScrm> selectFsStorePaymentByOrderIdApp(Long orderId);
+
 
     Long selectFsStorePaymentCount(@Param("type") int type,@Param("companyId") Long companyId,@Param("companyUserId") Long companyUserId);
 

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

@@ -9,7 +9,10 @@ import com.fs.course.domain.FsCoursePlaySourceConfig;
 import com.fs.course.dto.FsOrderDeliveryNoteDTO;
 import com.fs.erp.domain.ErpOrder;
 import com.fs.his.dto.FsStoreOrderAmountScrmStatsQueryDto;
+import com.fs.his.enums.PaymentMethodEnum;
+import com.fs.his.param.FsIntegralOrderDoPayParam;
 import com.fs.his.param.FsStoreOrderSalesParam;
+import com.fs.his.param.PayOrderParam;
 import com.fs.his.vo.FsStoreOrderAmountScrmStatsVo;
 import com.fs.his.vo.FsPrescribeVO;
 import com.fs.his.vo.FsStoreOrderExcelVO;
@@ -23,6 +26,7 @@ import com.fs.hisStore.dto.FsStoreOrderComputeDTO;
 import com.fs.hisStore.dto.StoreOrderExpressExportDTO;
 import com.fs.hisStore.param.*;
 import com.fs.hisStore.vo.*;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.text.ParseException;
@@ -402,4 +406,6 @@ public interface IFsStoreOrderScrmService
      * @return R
      */
     R batchDeliveryAllPendingOrders(Integer shipmentType);
+
+    R payment(FsIntegralOrderDoPayParam param, PaymentMethodEnum paymentMethodEnum);
 }

+ 5 - 0
fs-service/src/main/java/com/fs/hisStore/service/IFsStorePaymentScrmService.java

@@ -2,6 +2,7 @@ package com.fs.hisStore.service;
 
 import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.R;
+import com.fs.his.param.PayOrderParam;
 import com.fs.hisStore.domain.FsStorePaymentScrm;
 import com.fs.hisStore.param.*;
 import com.fs.hisStore.vo.FsStorePaymentStatisticsVO;
@@ -166,4 +167,8 @@ public interface IFsStorePaymentScrmService
      * 批量导入更新微信订单发货状态
      * **/
     R oneClickShipping();
+
+    R processPaymentScrm(PayOrderParam payOrderParam);
+
+    List<FsStorePaymentScrm> selectFsStorePaymentByOrderIdApp(Long id);
 }

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

@@ -29,6 +29,7 @@ import com.fs.erp.dto.ErpRefundUpdateRequest;
 import com.fs.erp.mapper.FsJstAftersalePushMapper;
 import com.fs.erp.mapper.FsJstAftersalePushScrmMapper;
 import com.fs.erp.service.IErpOrderService;
+import com.fs.his.config.AppConfig;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.domain.*;
 import com.fs.his.enums.FsStoreAfterSalesStatusEnum;
@@ -70,6 +71,7 @@ import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
 import com.github.binarywang.wxpay.config.WxPayConfig;
 import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
 import com.google.gson.Gson;
 import lombok.Synchronized;
 import org.apache.commons.beanutils.BeanUtils;
@@ -84,6 +86,7 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.sql.Timestamp;
 import java.text.DecimalFormat;
 import java.text.ParseException;
@@ -631,7 +634,7 @@ public class FsStoreAfterSalesScrmServiceImpl implements IFsStoreAfterSalesScrmS
     }
 
     @Override
-    @DataScope(deptAlias = "cu", userAlias = "cu")
+//    @DataScope(deptAlias = "cu", userAlias = "cu")
     public List<FsStoreAfterSalesVO> selectFsStoreAfterSalesListVO(FsStoreAfterSalesScrm fsStoreAfterSales) {
         List<FsStoreAfterSalesVO> fsStoreAfterSalesVOS = fsStoreAfterSalesMapper.selectFsStoreAfterSalesListVO(fsStoreAfterSales);
         List<Long> orderIds = new ArrayList<>();
@@ -858,27 +861,29 @@ public class FsStoreAfterSalesScrmServiceImpl implements IFsStoreAfterSalesScrmS
 
         //将钱退还给用户
         if(order.getPayMoney().compareTo(BigDecimal.ZERO)==1){
-            List<FsStorePaymentScrm> payments=paymentService.selectFsStorePaymentByOrderId(order.getId());
+            List<FsStorePaymentScrm> payments=paymentService.selectFsStorePaymentByOrderIdApp(order.getId());
             if(payments!=null){
+                SysConfig sysConfig = configService.selectConfigByConfigKey("app.config");
+                AppConfig config = new Gson().fromJson(sysConfig.getConfigValue(), AppConfig.class);
 
                 for(FsStorePaymentScrm payment:payments){
+                    if (order.getPayType().equals("99")||order.getPayType().equals("5")){
+                        payment.setAppId(config.getAppId());
+                    }
                     if (StringUtils.isBlank(payment.getAppId())) {
                         throw new IllegalArgumentException("appId不能为空");
                     }
-                    FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectCoursePlaySourceConfigByAppId(payment.getAppId());
-                    if (fsCoursePlaySourceConfig == null) {
-                        throw new CustomException("未找到appId对应的小程序配置: " + payment.getAppId());
+                    String payType = payment.getPayMode();
+                    if ("wxApp".equals(payment.getPayMode())){
+                        payType = "wx";
                     }
-                    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);
 
                     if (payment.getPayMode()==null||payment.getPayMode().equals("wx")){
+                        MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigByAppId(payment.getAppId(),payType);
+                        FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+
                         WxPayConfig payConfig = new WxPayConfig();
-                        payConfig.setAppId(fsCoursePlaySourceConfig.getAppid());
+                        payConfig.setAppId(payment.getAppId());
                         payConfig.setMchId(fsPayConfig.getWxMchId());
                         payConfig.setMchKey(fsPayConfig.getWxMchKey());
                         payConfig.setKeyPath(fsPayConfig.getKeyPath());
@@ -917,20 +922,20 @@ public class FsStoreAfterSalesScrmServiceImpl implements IFsStoreAfterSalesScrmS
                             return R.error("退款请求失败"+e.getErrCodeDes());
                         }
                     }else if (payment.getPayMode()!=null&&payment.getPayMode().equals("hf")){
+                        MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigByAppId(payment.getAppId(),payType);
+                        FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+
                         String huifuId="";
-                        FsHfpayConfigMapper fsHfpayConfigMapper = SpringUtils.getBean(FsHfpayConfigMapper.class);
                         if (payment.getAppId() != null) {
-                            FsHfpayConfig fsHfpayConfig = fsHfpayConfigMapper.selectByAppId(payment.getAppId());
-                            if (fsHfpayConfig == null){
+                            if (merchantAppConfig == null){
                                 huifuId = fsPayConfig.getHuifuId();
                             }else {
-                                huifuId = fsHfpayConfig.getHuifuId();
+                                huifuId = merchantAppConfig.getMerchantId();
                             }
                         } else {
                             if (("益善缘".equals(cloudHostProper.getCompanyName()))) {
 
-                                FsHfpayConfig fsPayConfig2 = fsHfpayConfigMapper.selectByAppId("wx0d1a3dd485268521");
-                                huifuId = fsPayConfig2.getHuifuId();
+                                huifuId = merchantAppConfig.getMerchantId();
                             }else {
                                 huifuId=fsPayConfig.getHuifuId();
                             }
@@ -943,9 +948,17 @@ public class FsStoreAfterSalesScrmServiceImpl implements IFsStoreAfterSalesScrmS
                         request.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(payment.getCreateTime()));
                         request.setReqSeqId("refund-"+payment.getPayCode());
                         Map<String, Object> extendInfoMap = new HashMap<>();
-                        extendInfoMap.put("org_party_order_id", payment.getBankSerialNo());
+                        if (order.getPayType().equals("99")){
+                            request.setOrdAmt(payment.getPayMoney().setScale(2, RoundingMode.DOWN).toString());
+                            extendInfoMap.put("org_req_seq_id", "store-"+payment.getPayCode());
+                        }else {
+                            request.setOrdAmt(payment.getPayMoney().toString());
+                            extendInfoMap.put("org_party_order_id", payment.getBankSerialNo());
+                            request.setAppId(payment.getAppId());
+                        }
+                        request.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(payment.getCreateTime()));
+                        request.setReqSeqId("refund-"+payment.getPayCode());
                         request.setExtendInfo(extendInfoMap);
-                        request.setAppId(payment.getAppId());
                         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"))){
@@ -957,6 +970,42 @@ public class FsStoreAfterSalesScrmServiceImpl implements IFsStoreAfterSalesScrmS
                             TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                             return R.error(refund.getResp_desc());
                         }
+                    }else if ("wxApp".equals(payment.getPayMode()) && "wx_app".equals(payment.getPayTypeCode())) {
+                        // 处理微信退款
+                        WxPayService wxPayService = getWxPayService();
+                        WxPayRefundRequest refundRequest = new WxPayRefundRequest();
+                        refundRequest.setOutTradeNo("store-"+payment.getPayCode());
+                        refundRequest.setOutRefundNo("store-"+payment.getPayCode());
+                        refundRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
+                        refundRequest.setRefundFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
+                        try {
+                            WxPayRefundResult refundResult = wxPayService.refund(refundRequest);
+                            WxPayRefundQueryResult refundQueryResult = wxPayService.refundQuery("", refundResult.getOutTradeNo(), refundResult.getOutRefundNo(), refundResult.getRefundId());
+                            if (refundQueryResult != null && refundQueryResult.getResultCode().equals("SUCCESS")) {
+                                FsStorePaymentScrm paymentMap = new FsStorePaymentScrm();
+                                paymentMap.setPaymentId(payment.getPaymentId());
+                                paymentMap.setStatus(-1);
+                                paymentMap.setRefundTime(DateUtils.getNowDate());
+                                paymentMap.setRefundMoney(payment.getPayMoney());
+                                paymentService.updateFsStorePayment(paymentMap);
+                            } else {
+                                throw new CustomException("退款请求失败" + refundQueryResult.getReturnMsg());
+                            }
+
+                        } catch (WxPayException e) {
+                            throw new CustomException("退款请求失败" + e);
+                        }
+
+//                    }else if (payment.getPayMode()!=null&&payment.getPayMode().equals("cz")) {
+//                        FsStorePaymentScrm paymentMap = new FsStorePaymentScrm();
+//                        paymentMap.setPaymentId(payment.getPaymentId());
+//                        paymentMap.setStatus(-1);
+//                        paymentMap.setRefundTime(DateUtils.getNowDate());
+//                        paymentMap.setRefundMoney(payment.getPayMoney());
+//                        paymentService.updateFsStorePayment(paymentMap);
+//                        FsUserScrm fsUserScrm = userService.selectFsUserById(order.getUserId());
+//                        processStoreRechargePayment(payment,fsUserScrm,order);
+
 
                     }else {
                         TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
@@ -980,6 +1029,34 @@ public class FsStoreAfterSalesScrmServiceImpl implements IFsStoreAfterSalesScrmS
         return R.ok();
     }
 
+    /**
+     * 封装微信参数
+     *
+     * @return
+     */
+    private WxPayService getWxPayService(){
+        SysConfig sysConfig = configService.selectConfigByConfigKey("app.config");
+        AppConfig config = new Gson().fromJson(sysConfig.getConfigValue(), AppConfig.class);
+        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectCoursePlaySourceConfigByAppId(config.getAppId());
+        if (fsCoursePlaySourceConfig == null) {
+            throw new CustomException("未找到appId对应的小程序配置: " + config.getAppId());
+        }
+        MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
+        FsPayConfig payConfig1 = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+
+        WxPayConfig payConfig = new WxPayConfig();
+        payConfig.setAppId(merchantAppConfig.getAppId());
+        payConfig.setMchId(payConfig1.getWxMchId());
+        payConfig.setMchKey(payConfig1.getWxMchKey());
+        payConfig.setSubAppId(StringUtils.trimToNull(null));
+        payConfig.setSubMchId(StringUtils.trimToNull(null));
+        payConfig.setKeyPath(payConfig1.getKeyPath());
+        payConfig.setNotifyUrl(payConfig1.getNotifyUrlScrm());
+        WxPayServiceImpl payService = new WxPayServiceImpl();
+        payService.setConfig(payConfig);
+        return payService;
+    }
+
     @Autowired
     private IFsStoreProductPurchaseLimitScrmService purchaseLimitService;
 

+ 210 - 31
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java

@@ -17,6 +17,8 @@ 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.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.api.param.OrderListParam;
 import com.fs.api.vo.OrderListVO;
 import com.fs.api.vo.ProductListVO;
@@ -61,18 +63,16 @@ import com.fs.erp.dto.ErpRefundUpdateRequest;
 import com.fs.erp.dto.df.*;
 import com.fs.erp.mapper.FsErpFinishPushMapper;
 import com.fs.erp.service.IErpOrderService;
+import com.fs.his.config.AppConfig;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.domain.*;
-import com.fs.his.dto.FsPrescribeUsageDTO;
-import com.fs.his.dto.FsProdItemDTO;
-import com.fs.his.dto.FsStoreOrderAmountScrmStatsQueryDto;
-import com.fs.his.dto.FsStoreOrderItemDTO;
-import com.fs.his.enums.FsStoreOrderLogEnum;
-import com.fs.his.enums.FsStoreOrderStatusEnum;
-import com.fs.his.enums.FsUserIntegralLogTypeEnum;
+import com.fs.his.dto.*;
+import com.fs.his.enums.*;
 import com.fs.his.mapper.*;
+import com.fs.his.param.FsIntegralOrderDoPayParam;
 import com.fs.his.param.FsStoreOrderSalesParam;
 import com.fs.his.param.FsUserAddIntegralTemplateParam;
+import com.fs.his.param.PayOrderParam;
 import com.fs.his.service.IFsPrescribeService;
 import com.fs.his.service.IFsUserIntegralLogsService;
 import com.fs.his.service.IFsUserWatchService;
@@ -88,7 +88,17 @@ import com.fs.hisStore.config.StoreIntegralConfig;
 import com.fs.hisStore.constants.StoreConstants;
 import com.fs.hisStore.domain.*;
 import com.fs.hisStore.dto.*;
+import com.fs.hisStore.dto.ErpRemarkDTO;
+import com.fs.hisStore.dto.ExpressDataDTO;
+import com.fs.hisStore.dto.ExpressInfoDTO;
+import com.fs.hisStore.dto.ExpressNotifyDTO;
+import com.fs.hisStore.dto.ExpressResultDTO;
+import com.fs.hisStore.dto.FsStoreCartDTO;
+import com.fs.hisStore.dto.StoreOrderExpressExportDTO;
+import com.fs.hisStore.dto.StorePackageProductDTO;
+import com.fs.hisStore.dto.StoreProductGroupDTO;
 import com.fs.hisStore.enums.*;
+import com.fs.hisStore.enums.ShipperCodeEnum;
 import com.fs.hisStore.mapper.*;
 import com.fs.hisStore.param.*;
 import com.fs.hisStore.service.*;
@@ -109,9 +119,12 @@ 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;
+import com.fs.live.domain.LiveOrder;
+import com.fs.live.mapper.LiveOrderMapper;
 import com.fs.pay.pay.dto.OrderQueryDTO;
 import com.fs.pay.pay.dto.RefundDTO;
 import com.fs.pay.service.IPayService;
+import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.fs.system.service.ISysConfigService;
 import com.fs.system.service.ISysDictTypeService;
@@ -126,14 +139,18 @@ import com.fs.wx.order.utils.WxShippingErrorHandler;
 import com.fs.ybPay.domain.OrderResult;
 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.WxPayRefundV3Request;
 import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
 import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
 import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
 import com.github.binarywang.wxpay.config.WxPayConfig;
 import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.binarywang.wxpay.service.WxPayService;
+ import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
 import com.google.common.base.Joiner;
+    import com.google.gson.Gson;
 import lombok.Synchronized;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
@@ -157,6 +174,7 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport;
 import javax.annotation.PostConstruct;
 import java.lang.reflect.Field;
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.nio.charset.Charset;
 import java.sql.Timestamp;
 import java.text.ParseException;
@@ -295,6 +313,8 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     private WxPayService wxPayService;
     @Autowired
     private WxPayProperties wxPayProperties;
+    @Autowired
+    private IFsStorePaymentScrmService storePaymentService;
 
     @Autowired
     private FsErpFinishPushMapper fsErpFinishPushMapper;
@@ -2608,24 +2628,26 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             //货到付款
         } else {
             //将钱退还给用户
-            List<FsStorePaymentScrm> payments = paymentService.selectFsStorePaymentByOrderId(order.getId());
+            List<FsStorePaymentScrm> payments = paymentService.selectFsStorePaymentByOrderIdApp(order.getId());
             if (payments != null) {
+                 SysConfig sysConfig = configService.selectConfigByConfigKey("app.config");
+                 AppConfig config = new Gson().fromJson(sysConfig.getConfigValue(), AppConfig.class);
                 for (FsStorePaymentScrm payment : payments) {
+                    if (order.getPayType().equals("99")){
+                        payment.setAppId(config.getAppId());
+                    }
                     if (StringUtils.isBlank(payment.getAppId())) {
                         throw new IllegalArgumentException("appId不能为空");
                     }
-                    FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectCoursePlaySourceConfigByAppId(payment.getAppId());
-                    if (fsCoursePlaySourceConfig == null) {
-                        throw new CustomException("未找到appId对应的小程序配置: " + payment.getAppId());
-                    }
-                    Long merchantConfigId = fsCoursePlaySourceConfig.getMerchantConfigId();
-                    if (merchantConfigId == null || merchantConfigId <= 0) {
-                        throw new CustomException("小程序没有配置商户信息");
+                    String payType = payment.getPayMode();
+                    if ("wxApp".equals(payment.getPayMode())){
+                        payType = "wx";
                     }
-                    MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
-                    FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
 
                     if (payment.getPayMode() == null || payment.getPayMode().equals("wx")) {
+
+                        MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigByAppId(payment.getAppId(),payType);
+                        FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
                         WxPayConfig payConfig = new WxPayConfig();
                         payConfig.setAppId(payment.getAppId());
                         payConfig.setMchId(fsPayConfig.getWxMchId());
@@ -2666,20 +2688,20 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                             return R.error("退款请求失败" + e.getErrCodeDes());
                         }
                     } else if (payment.getPayMode() != null && payment.getPayMode().equals("hf")) {
+                        MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigByAppId(payment.getAppId(),payType);
+                        FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+
                         String huifuId="";
-                        FsHfpayConfigMapper fsHfpayConfigMapper = SpringUtils.getBean(FsHfpayConfigMapper.class);
                         if (payment.getAppId() != null) {
-                            FsHfpayConfig fsHfpayConfig = fsHfpayConfigMapper.selectByAppId(payment.getAppId());
-                            if (fsHfpayConfig == null){
+                            if (merchantAppConfig == null){
                                 huifuId = fsPayConfig.getHuifuId();
                             }else {
-                                huifuId = fsHfpayConfig.getHuifuId();
+                                huifuId = merchantAppConfig.getMerchantId();
                             }
                         } else {
                             if (("益善缘".equals(cloudHostProper.getCompanyName()))) {
 
-                                FsHfpayConfig fsPayConfig2 = fsHfpayConfigMapper.selectByAppId("wx0d1a3dd485268521");
-                                huifuId = fsPayConfig2.getHuifuId();
+                                huifuId = merchantAppConfig.getMerchantId();
                             }else {
                                 huifuId=fsPayConfig.getHuifuId();
                             }
@@ -2689,12 +2711,18 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                         V2TradePaymentScanpayRefundRequest request = new V2TradePaymentScanpayRefundRequest();
                         request.setOrgHfSeqId(payment.getTradeNo());
                         request.setHuifuId(huifuId);
-                        request.setOrdAmt(payment.getPayMoney().toString());
+                        Map<String, Object> extendInfoMap = new HashMap<>();
+                        if (order.getPayType().equals("99")){
+                            request.setOrdAmt(payment.getPayMoney().setScale(2, RoundingMode.DOWN).toString());
+                            extendInfoMap.put("org_req_seq_id", "store-"+payment.getPayCode());
+                        }else {
+                            request.setOrdAmt(payment.getPayMoney().toString());
+                            extendInfoMap.put("org_party_order_id", payment.getBankSerialNo());
+                            request.setAppId(payment.getAppId());
+                        }
+
                         request.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(payment.getCreateTime()));
                         request.setReqSeqId("refund-" + payment.getPayCode());
-                        Map<String, Object> extendInfoMap = new HashMap<>();
-                        extendInfoMap.put("org_party_order_id", payment.getBankSerialNo());
-                        request.setExtendInfo(extendInfoMap);
                         request.setAppId(payment.getAppId());
                         HuiFuRefundResult refund = huiFuService.refund(request);
                         logger.info("退款:" + refund);
@@ -2707,7 +2735,41 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                             TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                             return R.error(refund.getResp_desc());
                         }
+                    }else if ("wxApp".equals(payment.getPayMode()) && "wx_app".equals(payment.getPayTypeCode())) {
+                        // 处理微信退款
+                        WxPayService wxPayService = getWxPayService();
+                        WxPayRefundRequest refundRequest = new WxPayRefundRequest();
+                        refundRequest.setOutTradeNo("store-"+payment.getPayCode());
+                        refundRequest.setOutRefundNo("store-"+payment.getPayCode());
+                        refundRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
+                        refundRequest.setRefundFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
+                        try {
+                            WxPayRefundResult refundResult = wxPayService.refund(refundRequest);
+                            WxPayRefundQueryResult refundQueryResult = wxPayService.refundQuery("", refundResult.getOutTradeNo(), refundResult.getOutRefundNo(), refundResult.getRefundId());
+                            if (refundQueryResult != null && refundQueryResult.getResultCode().equals("SUCCESS")) {
+                                FsStorePaymentScrm paymentMap = new FsStorePaymentScrm();
+                                paymentMap.setPaymentId(payment.getPaymentId());
+                                paymentMap.setStatus(-1);
+                                paymentMap.setRefundTime(DateUtils.getNowDate());
+                                paymentMap.setRefundMoney(payment.getPayMoney());
+                                paymentService.updateFsStorePayment(paymentMap);
+                            } else {
+                                throw new CustomException("退款请求失败" + refundQueryResult.getReturnMsg());
+                            }
+
+                        } catch (WxPayException e) {
+                            throw new CustomException("退款请求失败" + e);
+                        }
 
+//                    }else if (payment.getPayMode()!=null&&payment.getPayMode().equals("cz")) {
+//                        FsStorePaymentScrm paymentMap = new FsStorePaymentScrm();
+//                        paymentMap.setPaymentId(payment.getPaymentId());
+//                        paymentMap.setStatus(-1);
+//                        paymentMap.setRefundTime(DateUtils.getNowDate());
+//                        paymentMap.setRefundMoney(payment.getPayMoney());
+//                        paymentService.updateFsStorePayment(paymentMap);
+//                        FsUserScrm fsUserScrm = userService.selectFsUserById(order.getUserId());
+//                        processStoreRechargePayment(payment,fsUserScrm,order);
                     } else {
                         TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                         return R.error("支付类型异常");
@@ -2793,6 +2855,34 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
 
     }
 
+    /**
+     * 封装微信参数
+     *
+     * @return
+     */
+    private WxPayService getWxPayService(){
+        SysConfig sysConfig = configService.selectConfigByConfigKey("app.config");
+        AppConfig config = new Gson().fromJson(sysConfig.getConfigValue(), AppConfig.class);
+        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectCoursePlaySourceConfigByAppId(config.getAppId());
+        if (fsCoursePlaySourceConfig == null) {
+            throw new CustomException("未找到appId对应的小程序配置: " + config.getAppId());
+        }
+        MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
+        FsPayConfig payConfig1 = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+
+        WxPayConfig payConfig = new WxPayConfig();
+        payConfig.setAppId(merchantAppConfig.getAppId());
+        payConfig.setMchId(payConfig1.getWxMchId());
+        payConfig.setMchKey(payConfig1.getWxMchKey());
+        payConfig.setSubAppId(StringUtils.trimToNull(null));
+        payConfig.setSubMchId(StringUtils.trimToNull(null));
+        payConfig.setKeyPath(payConfig1.getKeyPath());
+        payConfig.setNotifyUrl(payConfig1.getNotifyUrlScrm());
+        WxPayServiceImpl payService = new WxPayServiceImpl();
+        payService.setConfig(payConfig);
+        return payService;
+    }
+
     @Override
     public R updateExpress(FsStoreOrderExpressEditParam param) {
         FsStoreOrderScrm order = fsStoreOrderMapper.selectFsStoreOrderById(param.getOrderId());
@@ -4644,14 +4734,21 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                         .add(vo);
             }
 
-            // 按小程序appId分组订单(从支付记录中获取)
+            // 按小程序appId分组订单(从支付记录中获取);business_type=8 为 App 发货,跳过小程序仅更新本地已发货
             Map<String, List<FsOrderDeliveryNoteDTO>> ordersByAppId = new HashMap<>();
+            List<FsOrderDeliveryNoteDTO> appDeliveryBusinessType8List = new ArrayList<>();
             for (FsOrderDeliveryNoteDTO dto : successList) {
                 String orderNumber = dto.getOrderNumber();
                 // 通过订单号查询订单
                 FsStoreOrderScrm order = fsStoreOrderMapper.selectFsStoreOrderByOrderCode(orderNumber);
                 if (order != null) {
-                    // 查询订单的支付记录获取appId
+                    List<FsStorePaymentScrm> appDeliveryPayments = fsStorePaymentMapper.selectFsStorePaymentByOrderIdBusinessType8(order.getId());
+                    if (!appDeliveryPayments.isEmpty()) {
+                        appDeliveryBusinessType8List.add(dto);
+                        log.debug("订单号: {} 为 business_type=8(App发货),跳过小程序发货流程", orderNumber);
+                        continue;
+                    }
+                    // 查询订单的支付记录获取appId(business_type=2)
                     List<FsStorePaymentScrm> paymentList = fsStorePaymentMapper.selectFsStorePaymentByOrderId(order.getId());
                     if (!paymentList.isEmpty() && paymentList.get(0).getAppId() != null) {
                         String orderAppId = paymentList.get(0).getAppId();
@@ -4669,11 +4766,13 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 }
             }
 
-            if (ordersByAppId.isEmpty()) {
+            if (ordersByAppId.isEmpty() && appDeliveryBusinessType8List.isEmpty()) {
                 return R.error("所有订单都无法获取对应的小程序appId,请确保订单已支付");
             }
 
-            log.info("导入订单涉及{}个小程序,开始分组处理", ordersByAppId.size());
+            if (!ordersByAppId.isEmpty()) {
+                log.info("导入订单涉及{}个小程序,开始分组处理", ordersByAppId.size());
+            }
 
             // 按小程序分组批量上传微信发货信息
             for (Map.Entry<String, List<FsOrderDeliveryNoteDTO>> entry : ordersByAppId.entrySet()) {
@@ -4728,6 +4827,25 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
                 }
             }
 
+            // business_type=8:仅更新本地订单物流与已发货状态,不上传微信小程序
+            if (!appDeliveryBusinessType8List.isEmpty()) {
+                log.info("business_type=8(App发货) 订单共{}条,跳过小程序,仅更新本地发货信息", appDeliveryBusinessType8List.size());
+            }
+            for (FsOrderDeliveryNoteDTO dto : appDeliveryBusinessType8List) {
+                int rowNum = successList.indexOf(dto) + 2;
+                if (StringUtils.isEmpty(dto.getOrderNumber())) {
+                    continue;
+                }
+                String deliverySn = expressDeliveryMap.get(dto.getDeliveryName());
+                if (deliverySn == null) {
+                    result.addFailure(rowNum, dto.getOrderNumber(), dto.getDeliveryId(), "物流公司名称异常");
+                    continue;
+                }
+                dto.setDeliverySn(deliverySn);
+                updateList.add(dto);
+                result.addSuccess();
+            }
+
             //批量更新数据
             if (!updateList.isEmpty()) {
                 batchUpdateDeliveryNotes(updateList);
@@ -6321,4 +6439,65 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             return WxShippingErrorHandler.handleExceptionErrorWithDetail(e.getMessage(), dto.getOrderNumber());
         }
     }
+
+
+    /**
+     * 预支付
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public R payment(FsIntegralOrderDoPayParam param, PaymentMethodEnum paymentMethod) {
+        FsStoreOrderScrm order = buildPayment(param);
+        if (Objects.isNull(order) || !order.getStatus().equals(0)
+                || order.getPayMoney().compareTo(BigDecimal.ZERO) <= 0){
+            return R.error("非法操作");
+        }
+
+        PayOrderParam payOrderParam = buildPayOrderParam(paymentMethod, order);
+        return storePaymentService.processPaymentScrm(payOrderParam);
+    }
+
+    @Autowired
+    private LiveOrderMapper liveOrderMapper;
+
+    public FsStoreOrderScrm buildPayment(FsIntegralOrderDoPayParam param){
+        if(param.getType().equals("live")){
+            LiveOrder liveOrder = liveOrderMapper.selectLiveOrderByOrderId(String.valueOf(param.getOrderId()));
+            if (ObjectUtil.isNotEmpty(liveOrder)){
+                FsStoreOrderScrm orderScrm = new FsStoreOrderScrm();
+                BeanUtils.copyProperties(liveOrder,orderScrm);
+                orderScrm.setId(liveOrder.getOrderId());
+                orderScrm.setUserId(Long.valueOf(liveOrder.getUserId()));
+                orderScrm.setIsLive(true);
+                return orderScrm;
+            }
+        }
+        if (param.getType().equals("store")){
+            FsStoreOrderScrm order = fsStoreOrderMapper.selectFsStoreOrderById(param.getOrderId());
+            if (ObjectUtil.isNotEmpty(order)){
+                return order;
+            }
+        }
+
+        return null;
+    }
+    /**
+     * 构建参数
+     */
+    private static PayOrderParam buildPayOrderParam(PaymentMethodEnum paymentMethod, FsStoreOrderScrm order) {
+        PayOrderParam payOrderParam = new PayOrderParam();
+        payOrderParam.setOrderId(order.getId());
+        payOrderParam.setOrderCode(order.getOrderCode());
+        payOrderParam.setAmount(order.getPayMoney());
+        payOrderParam.setUserId(order.getUserId());
+        payOrderParam.setCompanyId(order.getCompanyId());
+        payOrderParam.setCompanyUserId(order.getCompanyUserId());
+        payOrderParam.setPaymentMethod(paymentMethod);
+        if (order.getIsLive()){
+            payOrderParam.setBusinessType(BusinessTypeEnum.LIVE_ORDER);
+        }else {
+            payOrderParam.setBusinessType(BusinessTypeEnum.ORDER_ORDER);
+        }
+        return payOrderParam;
+    }
 }

+ 532 - 0
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStorePaymentScrmServiceImpl.java

@@ -3,6 +3,7 @@ package com.fs.hisStore.service.impl;
 
 import java.math.BigDecimal;
 
+import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
@@ -16,6 +17,7 @@ import cn.binarywang.wx.miniapp.bean.shop.request.shipping.*;
 import cn.binarywang.wx.miniapp.bean.shop.request.shipping.*;
 import cn.binarywang.wx.miniapp.bean.shop.response.WxMaOrderShippingInfoBaseResponse;
 import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.TypeReference;
@@ -36,6 +38,7 @@ import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.ip.IpUtils;
 import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyUser;
+import com.fs.company.domain.RechargeRecord;
 import com.fs.company.mapper.CompanyConfigMapper;
 import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyUserService;
@@ -47,24 +50,31 @@ import com.fs.course.domain.FsCourseRedPacketLog;
 import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
 import com.fs.course.mapper.FsCourseRedPacketLogMapper;
 import com.fs.course.service.IFsCourseRedPacketLogService;
+import com.fs.his.config.AppConfig;
 import com.fs.his.domain.*;
 import com.fs.his.domain.FsPayConfig;
 import com.fs.his.domain.FsUser;
 import com.fs.his.domain.FsUserWx;
 import com.fs.his.domain.MerchantAppConfig;
+import com.fs.his.dto.PayConfigDTO;
+import com.fs.his.enums.PaymentMethodEnum;
 import com.fs.his.mapper.FsUserWxMapper;
 import com.fs.his.mapper.MerchantAppConfigMapper;
+import com.fs.his.param.PayOrderParam;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.service.IFsUserWxService;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.hisStore.config.StoreConfig;
 import com.fs.hisStore.config.StoreConfig;
+import com.fs.hisStore.domain.FsStoreOrderScrm;
 import com.fs.hisStore.domain.FsStorePaymentScrm;
 import com.fs.hisStore.domain.FsUserScrm;
+import com.fs.hisStore.enums.OrderInfoEnum;
 import com.fs.hisStore.enums.StatTypeEnum;
 import com.fs.his.utils.HttpUtil;
 import com.fs.hisStore.config.StoreConfig;
 import com.fs.hisStore.enums.SysConfigEnum;
+import com.fs.hisStore.mapper.FsStoreOrderScrmMapper;
 import com.fs.hisStore.mapper.FsStorePaymentScrmMapper;
 import com.fs.hisStore.param.*;
 import com.fs.hisStore.service.IFsStorePaymentScrmService;
@@ -73,6 +83,10 @@ import com.fs.huifuPay.domain.HuiFuCreateOrder;
 import com.fs.huifuPay.domain.HuifuCreateOrderResult;
 import com.fs.huifuPay.sdk.opps.core.utils.HuiFuUtils;
 import com.fs.huifuPay.service.HuiFuService;
+import com.fs.live.domain.LiveOrder;
+import com.fs.live.domain.LiveOrderPayment;
+import com.fs.live.mapper.LiveOrderMapper;
+import com.fs.live.mapper.LiveOrderPaymentMapper;
 import com.fs.pay.pay.dto.WxJspayDTO;
 import com.fs.pay.service.IPayService;
 import com.fs.system.oss.CloudStorageService;
@@ -99,6 +113,7 @@ import com.github.binarywang.wxpay.service.WxPayService;
 import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
 import com.google.common.reflect.TypeToken;
 import com.google.gson.Gson;
+import com.hc.openapi.tool.fastjson.JSON;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
@@ -128,6 +143,12 @@ public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
     Logger logger = LoggerFactory.getLogger(getClass());
     @Autowired
     private WxPayService wxPayService;
+    @Autowired
+    private FsUserWxMapper userWxMapper;
+    @Autowired
+    private LiveOrderPaymentMapper liveOrderPaymentMapper;
+//    @Autowired
+//    private RechargeRecordMapper rechargeRecordMapper;
 
     @Autowired
     private FsCoursePlaySourceConfigMapper fsCoursePlaySourceConfigMapper;
@@ -160,6 +181,10 @@ public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
 
     @Autowired
     private RedisCache redisCache;
+    @Autowired
+    private LiveOrderMapper liveOrderMapper;
+    @Autowired
+    private FsStoreOrderScrmMapper storeOrderScrmMapper;
 
     /**
      * 查询支付明细
@@ -1398,4 +1423,511 @@ public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
             return WxShippingErrorHandler.handleExceptionError(e.getMessage(), dto.getBankTransactionId());
         }
     }
+
+
+    /**
+     * 发起支付
+     * @param payOrderParam 入参
+     * @return R
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public R processPaymentScrm( PayOrderParam payOrderParam) {
+        logger.info("发起支付 payOrderParam: {}", JSON.toJSONString(payOrderParam));
+
+        if (payOrderParam.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
+            throw new CustomException("支付金额不正确");
+        }
+
+        FsUserScrm user = userService.selectFsUserById(payOrderParam.getUserId());
+        if (Objects.isNull(user)) {
+            throw new CustomException("用户不存在");
+        }
+        if (PaymentMethodEnum.CZ_PAY == payOrderParam.getPaymentMethod()) {
+            if (user.getRechargeBalance().compareTo(BigDecimal.ZERO) <= 0) {
+                throw new CustomException("余额不足!请先充值。");
+            }
+        }
+        String type = null;
+        FsPayConfig payConfig = new FsPayConfig();
+        if (PaymentMethodEnum.WX_APP == payOrderParam.getPaymentMethod()) {
+            String json = configService.selectConfigByKey("app.config");
+            AppConfig config = JSONUtil.toBean(json, AppConfig.class);
+            payOrderParam.setAppId(config.getAppId());
+            type = "wxApp";
+        }
+        //支付宝可以不需要appid(在没有appid的情况下)【ps:小程序的支付宝没传appid 就G】
+        if ((PaymentMethodEnum.ALIPAY == payOrderParam.getPaymentMethod())
+                && StringUtils.isBlank(payOrderParam.getAppId())) {
+            String json = configService.selectConfigByKey("his.pay");
+            PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
+            payConfig.setType(payConfigDTO.getType());
+        }else if(!(PaymentMethodEnum.CZ_PAY == payOrderParam.getPaymentMethod())){
+            if (StringUtils.isBlank(payOrderParam.getAppId())) {
+                throw new IllegalArgumentException("appId不能为空");
+            }
+            FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectCoursePlaySourceConfigByAppId(payOrderParam.getAppId());
+            if (fsCoursePlaySourceConfig == null) {
+                throw new CustomException("未找到appId对应的小程序配置: " + payOrderParam.getAppId());
+            }
+            Long merchantConfigId = fsCoursePlaySourceConfig.getMerchantConfigId();
+            if (merchantConfigId == null || merchantConfigId <= 0) {
+                throw new CustomException("小程序没有配置商户信息");
+            }
+
+            MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
+            payConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+            if (StringUtils.isNotEmpty(type)) {
+                payConfig.setType(type);
+            } else {
+                payConfig.setType(merchantAppConfig.getMerchantType());
+            }
+            payConfig.setAppId(fsCoursePlaySourceConfig.getAppid());
+
+            logger.debug("支付配置 his.pay: {}", payConfig);
+        }
+
+
+//        FsPayConfig payConfig = JSONUtil.toBean(json, FsPayConfig.class);
+
+        if (isWechatPayment(payOrderParam.getPaymentMethod())) {
+            String openId = getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod(), payConfig);
+            if (StringUtils.isBlank(openId)) {
+                throw new CustomException("用户OPENID不存在");
+            }
+        }
+
+        FsStorePaymentScrm storePayment = new FsStorePaymentScrm();
+
+        // 1. 根据业务类型创建对应的支付对象
+        if (payOrderParam.getBusinessType().getPrefix().equals("live")) {
+            // 处理直播业务支付
+            LiveOrderPayment liveOrderPayment = createLiveStorePayment(payConfig, user, payOrderParam);
+            BeanUtils.copyProperties(liveOrderPayment, storePayment);
+
+            // 处理储值支付
+            if (isRechargePayment(payOrderParam)) {
+                return processLiveRechargePayment(liveOrderPayment, user);
+            }
+        } else {
+            // 处理商城业务支付
+            storePayment = createStorePaymentScrm(payConfig, user, payOrderParam);
+
+//            // 处理储值支付
+//            if (isRechargePayment(payOrderParam)) {
+//                return processStoreRechargePayment(storePayment, user);
+//            }
+        }
+        // 根据配置类型创建第三方支付订单
+        return createThirdPartyPaymentScrm(payConfig, storePayment, user, payOrderParam);
+    }
+
+    @Override
+    public List<FsStorePaymentScrm> selectFsStorePaymentByOrderIdApp(Long id) {
+        return fsStorePaymentMapper.selectFsStorePaymentByOrderIdApp(id);
+    }
+
+    /**
+     * 判断是否为储值支付
+     * @param payOrderParam 支付订单参数
+     * @return true:储值支付 false:其他支付方式
+     */
+    private boolean isRechargePayment(PayOrderParam payOrderParam) {
+        return PaymentMethodEnum.CZ_PAY == payOrderParam.getPaymentMethod();
+    }
+
+    /**
+     * 处理直播储值支付
+     * @param liveOrderPayment 直播订单支付信息
+     * @param user 用户信息
+     * @return 支付处理结果
+     */
+    private R processLiveRechargePayment(LiveOrderPayment liveOrderPayment, FsUserScrm user) {
+        // 查询直播订单信息
+        LiveOrder liveOrder = liveOrderMapper.selectLiveOrderByOrderId(liveOrderPayment.getBusinessId());
+        Company company = companyService.selectCompanyById(liveOrder.getCompanyId());
+
+        // 扣减用户储值余额
+        deductUserRechargeBalance(user, liveOrder.getPayMoney());
+
+        // 更新直播订单状态
+        updateLiveOrderStatus(liveOrder);
+
+        // 创建消费记录
+        return R.ok();
+    }
+
+    /**
+     * 处理商城储值支付
+     * @param storePayment 商城订单支付信息
+     * @param user 用户信息
+     * @return 支付处理结果
+     */
+    private R processStoreRechargePayment(FsStorePaymentScrm storePayment, FsUserScrm user) {
+        // 查询商城订单信息
+        FsStoreOrderScrm fsStoreOrderScrm = storeOrderScrmMapper.selectFsStoreOrderById(storePayment.getOrderId());
+        Company company = companyService.selectCompanyById(fsStoreOrderScrm.getCompanyId());
+
+        // 扣减用户储值余额
+        deductUserRechargeBalance(user, storePayment.getPayMoney());
+
+        // 更新商城订单状态
+        updateStoreOrderStatus(fsStoreOrderScrm);
+
+        // 创建消费记录
+        return R.ok();
+    }
+
+    /**
+     * 扣减用户储值余额
+     * @param user 用户信息
+     * @param amount 扣减金额
+     */
+    private void deductUserRechargeBalance(FsUserScrm user, BigDecimal amount) {
+        user.setRechargeBalance(user.getRechargeBalance().subtract(amount));
+        userService.updateFsUser(user);
+    }
+
+    /**
+     * 更新直播订单状态
+     * @param liveOrder 直播订单
+     */
+    private void updateLiveOrderStatus(LiveOrder liveOrder) {
+        liveOrder.setStatus(OrderInfoEnum.STATUS_1.getValue());
+        liveOrder.setPayTime(LocalDateTime.now());
+        liveOrder.setIsPay("1");
+        liveOrderMapper.updateLiveOrder(liveOrder);
+    }
+
+    /**
+     * 更新商城订单状态
+     * @param storeOrder 商城订单
+     */
+    private void updateStoreOrderStatus(FsStoreOrderScrm storeOrder) {
+        storeOrder.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
+        storeOrder.setStatus(OrderInfoEnum.STATUS_1.getValue());
+        storeOrder.setPayTime(new Date());
+        storeOrderScrmMapper.updateFsStoreOrder(storeOrder);
+    }
+
+
+
+    /**
+     * 订单支付成功后,增加消费记录
+     * @param orderId 订单ID
+     * @param orderNo 订单编号
+     * @param userId 用户ID
+     * @param userName 用户姓名
+     * @param amount 消费金额
+     * @return 影响行数
+     */
+//    public int createConsumptionRecord(Long orderId, String orderNo, Long userId,
+//                                       String userName, BigDecimal amount,Company company
+//    ) {
+//        RechargeRecord record = new RechargeRecord();
+//        record.setUserId(userId);
+//        record.setUserName(userName);
+//        record.setTotalAmount(amount);
+//        record.setTransactionId(generateTransactionId());
+//        record.setOrderId(orderId);
+//        record.setOrderNo(orderNo);
+//        record.setBusinessType(1); // 1-消费
+//        if (ObjectUtil.isEmpty(company)){
+//            record.setRemark("订单消费,自主下单没有归属公司");
+//        }else {
+//            record.setCompanyId(company.getCompanyId());
+//            record.setCompanyName(company.getCompanyName());
+//            record.setRemark("订单消费");
+//        }
+//        record.setCreateTime(new Date());
+//        record.setDelFlag("0");
+//
+//        return rechargeRecordMapper.insertRechargeRecord(record);
+//    }
+
+    /**
+     * 生成交易流水号
+     * @return 交易流水号
+     */
+    private String generateTransactionId() {
+        return "TXF" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
+    }
+    /**
+     * 直播订单支付信息
+     *
+     * @param payConfig
+     * @param user
+     * @param payOrderParam
+     * @return
+     */
+    private LiveOrderPayment createLiveStorePayment(FsPayConfig payConfig, FsUserScrm user, PayOrderParam payOrderParam) {
+        String payCode = OrderCodeUtils.getOrderSn();
+        if (StringUtils.isEmpty(payCode)) {
+            throw new CustomException("订单生成失败,请重试");
+        }
+
+        LiveOrderPayment storePayment = new LiveOrderPayment();
+
+        if (PaymentMethodEnum.CZ_PAY == payOrderParam.getPaymentMethod()){
+            storePayment.setStatus(1);
+            storePayment.setPayMode("cz");
+        }else {
+            storePayment.setStatus(0);
+            storePayment.setPayMode(payConfig.getType());
+        }
+        storePayment.setAppId(payConfig.getAppId());
+        storePayment.setBusinessCode(payOrderParam.getOrderCode());
+        storePayment.setPayCode(payCode);
+        storePayment.setPayMoney(payOrderParam.getAmount());
+        storePayment.setCreateTime(new Date());
+        storePayment.setPayTypeCode(payOrderParam.getPaymentMethod().getDesc());
+        storePayment.setBusinessType(payOrderParam.getBusinessType().getCode());
+        storePayment.setCompanyId(payOrderParam.getCompanyId());
+        storePayment.setCompanyUserId(payOrderParam.getCompanyUserId());
+        storePayment.setRemark(payOrderParam.getBusinessType().getDesc());
+        storePayment.setStoreId(payOrderParam.getStoreId());
+        storePayment.setUserId(user.getUserId());
+        storePayment.setBusinessId(payOrderParam.getOrderId().toString());
+
+        // 设置openId(如果是微信支付)
+        if (isWechatPayment(payOrderParam.getPaymentMethod())) {
+            storePayment.setOpenId(getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod(), payConfig));
+        }
+
+        if (liveOrderPaymentMapper.insertLiveOrderPayment(storePayment) <= 0) {
+            throw new CustomException("支付订单创建失败");
+        }
+
+        return storePayment;
+    }
+
+    /**
+     * 判断是否微信支付
+     * @param method 支付类型
+     * @return boolean
+     */
+    private boolean isWechatPayment(PaymentMethodEnum method) {
+        return method == PaymentMethodEnum.MINIAPP_WECHAT || method == PaymentMethodEnum.H5_WECHAT;
+    }
+
+    /**
+     * 根据支付方式获取对应的openId
+     */
+    private String getOpenIdForPaymentMethod(FsUserScrm user, PaymentMethodEnum method, FsPayConfig payConfig) {
+        String openId;
+        switch (method) {
+            case MINIAPP_WECHAT:
+                openId = user.getMaOpenId();
+                break;
+            case H5_WECHAT:
+                openId = user.getMpOpenId();
+                break;
+            default:
+                openId = null;
+        }
+
+        if (StringUtils.isBlank(openId)) {
+            Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                    .eq(FsUserWx::getFsUserId, user.getUserId())
+                    .eq(FsUserWx::getAppId, payConfig.getAppId());
+            FsUserWx fsUserWx = userWxMapper.selectOne(queryWrapper);
+            if (Objects.nonNull(fsUserWx)) {
+                openId = fsUserWx.getOpenId();
+            }
+        }
+
+        return openId;
+    }
+
+    /**
+     * 发起预支付
+     */
+    private R createThirdPartyPaymentScrm(FsPayConfig payConfig, FsStorePaymentScrm storePayment, FsUserScrm user, PayOrderParam payOrderParam) {
+        switch (payConfig.getType()) {
+            case "wx":
+                return createWxPayment(storePayment, user, payOrderParam, payConfig);
+            case "wxApp":
+                return createWxAppPayment(storePayment, user, payOrderParam, payConfig);
+            case "hf":
+                return createHfPayment(storePayment, user, payOrderParam, payConfig);
+            default:
+                throw new CustomException("不支持的支付方式");
+        }
+    }
+
+    /**
+     * 汇付
+     */
+    private R createHfPayment(FsStorePaymentScrm storePayment, FsUserScrm user, PayOrderParam payOrderParam, FsPayConfig payConfig) {
+        logger.debug("创建汇付订单");
+
+        HuiFuCreateOrder order = new HuiFuCreateOrder();
+        order.setTradeType(getHfTradeType(payOrderParam.getPaymentMethod()));
+        order.setReqSeqId(payOrderParam.getBusinessType().getPrefix() + "-" + storePayment.getPayCode());
+        order.setTransAmt(storePayment.getPayMoney().toString());
+        order.setGoodsDesc(payOrderParam.getBusinessType().getDesc());
+
+        // 微信支付需要设置openid
+        if (isWechatPayment(payOrderParam.getPaymentMethod())) {
+            order.setOpenid(getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod(), payConfig));
+        }
+
+        HuifuCreateOrderResult result = huiFuService.createOrder(order);
+        logger.debug("汇付支付创建结果: {}", result);
+
+        updateStorePaymentTradeNo(storePayment.getPaymentId(), result.getHf_seq_id());
+        return R.ok().put("isPay", 0).put("data", result).put("type", "hf");
+    }
+
+    /**
+     * 获取汇付交易类型
+     */
+    private String getHfTradeType(PaymentMethodEnum paymentMethod) {
+        switch (paymentMethod) {
+            case MINIAPP_WECHAT:
+                return "T_MINIAPP";
+            case H5_WECHAT:
+                return "T_JSAPI";
+            case ALIPAY:
+            case H5_ALIPAY:
+                return "A_NATIVE";
+            case T_NATIVE:
+                return "T_NATIVE";
+            default:
+                throw new CustomException("不支持的支付方式");
+        }
+    }
+
+    /**
+     * 更新支付订单交易号
+     */
+    private void updateStorePaymentTradeNo(Long paymentId, String tradeNo) {
+        FsStorePaymentScrm updatePayment = new FsStorePaymentScrm();
+        updatePayment.setPaymentId(paymentId);
+        updatePayment.setTradeNo(tradeNo);
+        fsStorePaymentMapper.updateFsStorePayment(updatePayment);
+    }
+
+
+    /**
+     * 微信支付
+     */
+    private R createWxPayment(FsStorePaymentScrm storePayment, FsUserScrm user, PayOrderParam payOrderParam, FsPayConfig payConfig) {
+        PaymentMethodEnum paymentMethod = payOrderParam.getPaymentMethod();
+        if (paymentMethod != PaymentMethodEnum.MINIAPP_WECHAT) {
+            logger.debug("微信支付 PaymentMethod: {}", paymentMethod.name());
+            throw new CustomException("不支持的支付方式");
+        }
+
+        WxPayConfig wxPayConfig = buildWxPayConfig(payConfig);
+        wxPayService.setConfig(wxPayConfig);
+
+        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
+        orderRequest.setOpenid(getOpenIdForPaymentMethod(user, paymentMethod, payConfig));
+        orderRequest.setBody(payOrderParam.getBusinessType().getDesc());
+        orderRequest.setOutTradeNo(payOrderParam.getBusinessType().getPrefix() + "-" + 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("data", orderResult).put("type", "wx").put("isPay", 0);
+        } catch (WxPayException e) {
+            logger.error("微信支付发起失败: {}", e.getMessage(), e);
+            throw new CustomException("支付失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 微信App支付
+     */
+    private R createWxAppPayment(FsStorePaymentScrm storePayment, FsUserScrm user, PayOrderParam payOrderParam, FsPayConfig payConfig) {
+        //创建微信订单
+        WxPayConfig wxPayConfig = buildWxPayConfig(payConfig);
+
+        wxPayConfig.setAppId(wxPayConfig.getAppId());
+        wxPayConfig.setMchId(wxPayConfig.getMchId());
+        wxPayConfig.setMchKey(wxPayConfig.getMchKey());
+        wxPayConfig.setSubAppId(StringUtils.trimToNull(null));
+        wxPayConfig.setSubMchId(StringUtils.trimToNull(null));
+        wxPayConfig.setKeyPath(null);
+        wxPayConfig.setNotifyUrl(wxPayConfig.getNotifyUrl());
+        wxPayService.setConfig(wxPayConfig);
+        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
+        orderRequest.setBody(payOrderParam.getBusinessType().getDesc());
+        orderRequest.setOutTradeNo(payOrderParam.getBusinessType().getPrefix() + "-" + storePayment.getPayCode());
+        orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));
+        orderRequest.setTradeType("APP");
+        orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
+        orderRequest.setNotifyUrl(wxPayConfig.getNotifyUrl());
+        //调用统一下单接口,获取"预支付交易会话标识"
+        try {
+            Object result = wxPayService.createOrder(orderRequest);
+            return R.ok().put("data",result).put("type","wxApp").put("isPay",0);
+        } catch (WxPayException e) {
+            e.printStackTrace();
+            throw new CustomException("支付失败"+e.getMessage());
+        }
+    }
+
+    /**
+     * 构建微信支付配置
+     */
+    private WxPayConfig buildWxPayConfig(FsPayConfig fsPayConfig) {
+        WxPayConfig payConfig = new WxPayConfig();
+        payConfig.setAppId(StringUtils.trimToNull(fsPayConfig.getAppId()));
+        payConfig.setMchId(StringUtils.trimToNull(fsPayConfig.getWxMchId()));
+        payConfig.setMchKey(StringUtils.trimToNull(fsPayConfig.getWxMchKey()));
+        payConfig.setSubAppId(StringUtils.trimToNull(null));
+        payConfig.setSubMchId(StringUtils.trimToNull(null));
+        payConfig.setKeyPath(null);
+        payConfig.setNotifyUrl(StringUtils.trimToNull(fsPayConfig.getNotifyUrlScrm()));
+        return payConfig;
+    }
+
+
+    /**
+     * 创建支付订单
+     */
+    private FsStorePaymentScrm createStorePaymentScrm(FsPayConfig payConfig, FsUserScrm user, PayOrderParam payOrderParam) {
+        String payCode = OrderCodeUtils.getOrderSn();
+        if (StringUtils.isEmpty(payCode)) {
+            throw new CustomException("订单生成失败,请重试");
+        }
+
+        FsStorePaymentScrm storePayment = new FsStorePaymentScrm();
+        if (PaymentMethodEnum.CZ_PAY == payOrderParam.getPaymentMethod()){
+            storePayment.setStatus(1);
+            storePayment.setPayMode("cz");
+        }else {
+            storePayment.setStatus(0);
+            storePayment.setPayMode(payConfig.getType());
+        }
+        storePayment.setAppId(payConfig.getAppId());
+        storePayment.setOrderId(payOrderParam.getOrderId());
+        storePayment.setBusinessCode(payOrderParam.getOrderCode());
+        storePayment.setPayCode(payCode);
+        storePayment.setPayMoney(payOrderParam.getAmount());
+        storePayment.setCreateTime(new Date());
+        storePayment.setPayTypeCode(payOrderParam.getPaymentMethod().getDesc());
+        storePayment.setBusinessType(payOrderParam.getBusinessType().getCode());
+        storePayment.setCompanyId(payOrderParam.getCompanyId());
+        storePayment.setCompanyUserId(payOrderParam.getCompanyUserId());
+        storePayment.setRemark(payOrderParam.getBusinessType().getDesc());
+        storePayment.setStoreId(payOrderParam.getStoreId());
+        storePayment.setUserId(user.getUserId());
+        storePayment.setBusinessId(payOrderParam.getOrderId().toString());
+
+        // 设置openId(如果是微信支付)
+        if (isWechatPayment(payOrderParam.getPaymentMethod())) {
+            storePayment.setOpenId(getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod(), payConfig));
+        }
+
+        if (fsStorePaymentMapper.insertFsStorePayment(storePayment) <= 0) {
+            throw new CustomException("支付订单创建失败");
+        }
+
+        return storePayment;
+    }
 }

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

@@ -2,6 +2,7 @@ package com.fs.huifuPay.service.impl;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+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;
@@ -158,12 +159,17 @@ public class HuiFuServiceImpl implements HuiFuService {
     public HuiFuRefundResult refund(V2TradePaymentScanpayRefundRequest request) {
         HuiFuRefundResult huiFuRefundResult=null;
         try {
-            doInit(getMerConfig(request.getAppId()));
+            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;

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

@@ -67,6 +67,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectMerchantAppConfigVo"/>
         where id = #{id}
     </select>
+    <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>
 
     <insert id="insertMerchantAppConfig" parameterType="MerchantAppConfig" useGeneratedKeys="true" keyProperty="id">
         insert into merchant_app_config

+ 9 - 3
fs-service/src/main/resources/mapper/course/FsUserCourseVideoMapper.xml

@@ -254,9 +254,15 @@
         select v.* from fs_user_course_video v where v.is_del = 0 and  v.video_url = #{videoUrl}
     </select>
     <update id="updateVideoByVideoUrl" >
-        update fs_user_course_video set video_url = #{videoUrl},
-                                        thumbnail = #{thumbnail},
-                                        file_name = #{fileName}
+        update fs_user_course_video
+        <set>
+            video_url = #{videoUrl},
+            thumbnail = #{thumbnail},
+            file_name = #{fileName},
+            <if test="duration != null">
+                duration = #{duration},
+            </if>
+        </set>
         where video_id in
         <foreach item="videoId" collection="ids" open="(" separator="," close=")">
             #{videoId}

+ 84 - 0
fs-user-app/src/main/java/com/fs/app/controller/AppPayController.java

@@ -0,0 +1,84 @@
+package com.fs.app.controller;
+
+
+import cn.hutool.json.JSONUtil;
+import com.fs.app.AppPayService;
+import com.fs.common.exception.CustomException;
+import com.fs.common.utils.StringUtils;
+import com.fs.course.domain.FsCoursePlaySourceConfig;
+import com.fs.course.service.IFsCoursePlaySourceConfigService;
+import com.fs.his.config.AppConfig;
+import com.fs.his.domain.FsPayConfig;
+import com.fs.his.domain.MerchantAppConfig;
+import com.fs.his.service.IMerchantAppConfigService;
+import com.fs.system.domain.SysConfig;
+import com.fs.system.mapper.SysConfigMapper;
+import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
+import com.google.gson.Gson;
+import com.hc.openapi.tool.fastjson.JSON;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+@Slf4j
+@Api("app支付接口")
+@RestController
+@RequestMapping("/appPay")
+public class AppPayController extends AppBaseController {
+
+    @Autowired
+    private AppPayService appPayService;
+
+    @Autowired
+    private IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService;
+   @Autowired
+    private IMerchantAppConfigService merchantAppConfigService;
+    @Autowired
+    private SysConfigMapper sysConfigMapper;
+
+
+    @ApiOperation("微信支付回调")
+    @PostMapping("/wxNotify")
+    public String wxNotify(@RequestBody String xmlData) throws WxPayException {
+        WxPayService payService = getWxPayService();
+        WxPayOrderNotifyResult result = payService.parseOrderNotifyResult(xmlData);
+        return appPayService.wxNotify(result);
+    }
+
+    private WxPayService getWxPayService(){
+        SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("app.config");
+        AppConfig config = new Gson().fromJson(sysConfig.getConfigValue(), AppConfig.class);
+        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigService.selectCoursePlaySourceConfigByAppId(config.getAppId());
+        if (fsCoursePlaySourceConfig == null) {
+            throw new CustomException("未找到appId对应的小程序配置: " + config.getAppId());
+        }
+        MerchantAppConfig merchantAppConfig = merchantAppConfigService.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
+        FsPayConfig payConfig1 = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+
+        WxPayConfig payConfig = new WxPayConfig();
+        payConfig.setAppId(payConfig1.getAppId());
+        payConfig.setMchId(payConfig1.getWxMchId());
+        payConfig.setMchKey(payConfig1.getWxMchKey());
+        payConfig.setSubAppId(StringUtils.trimToNull(null));
+        payConfig.setSubMchId(StringUtils.trimToNull(null));
+        payConfig.setKeyPath(null);
+        payConfig.setNotifyUrl(payConfig1.getNotifyUrlScrm());
+        WxPayServiceImpl payService = new WxPayServiceImpl();
+        payService.setConfig(payConfig);
+        return payService;
+    }
+}

+ 51 - 0
fs-user-app/src/main/java/com/fs/app/controller/store/AppController.java

@@ -0,0 +1,51 @@
+package com.fs.app.controller.store;
+
+import com.fs.app.annotation.Login;
+import com.fs.app.controller.AppBaseController;
+import com.fs.common.annotation.RepeatSubmit;
+import com.fs.common.core.domain.R;
+import com.fs.his.enums.PaymentMethodEnum;
+import com.fs.his.param.FsIntegralOrderDoPayParam;
+import com.fs.hisStore.service.IFsStoreOrderScrmService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+
+
+@Api("app登录接口")
+@RestController
+@RequestMapping(value = "/app/api")
+@Slf4j
+public class AppController extends AppBaseController {
+
+    @Autowired
+    private IFsStoreOrderScrmService fsStoreOrderScrmService;
+
+
+    @Login
+    @RepeatSubmit
+    @ApiOperation("微信支付")
+    @PostMapping("/wxPayment")
+    public R wxPayment(@Validated @RequestBody FsIntegralOrderDoPayParam param) {
+        param.setUserId(Long.parseLong(getUserId()));
+        return fsStoreOrderScrmService.payment(param, PaymentMethodEnum.WX_APP);
+    }
+
+
+    @Login
+    @RepeatSubmit
+    @ApiOperation("支付宝支付")
+    @PostMapping("/aliPayment")
+    public R aliPayment(@Validated @RequestBody FsIntegralOrderDoPayParam param) {
+        param.setUserId(Long.parseLong(getUserId()));
+        return fsStoreOrderScrmService.payment(param, PaymentMethodEnum.ALIPAY);
+    }
+}