Jelajahi Sumber

feat:app原生支付相关代码迁移

caoliqin 1 bulan lalu
induk
melakukan
e12bba3588
27 mengubah file dengan 1073 tambahan dan 81 penghapusan
  1. 8 1
      fs-service/pom.xml
  2. 9 0
      fs-service/src/main/java/com/fs/app/service/AppPayService.java
  3. 80 1
      fs-service/src/main/java/com/fs/app/service/impl/AppPayServiceImpl.java
  4. 2 0
      fs-service/src/main/java/com/fs/course/param/FsUserCourseOrderDoPayParam.java
  5. 2 0
      fs-service/src/main/java/com/fs/course/param/FsUserVipOrderPayUParam.java
  6. 4 0
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseOrderService.java
  7. 4 0
      fs-service/src/main/java/com/fs/course/service/IFsUserVipOrderService.java
  8. 190 4
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseOrderServiceImpl.java
  9. 191 0
      fs-service/src/main/java/com/fs/course/service/impl/FsUserVipOrderServiceImpl.java
  10. 11 0
      fs-service/src/main/java/com/fs/his/domain/FsPayConfig.java
  11. 1 0
      fs-service/src/main/java/com/fs/his/param/FsInquiryOrderDoPayParam.java
  12. 1 0
      fs-service/src/main/java/com/fs/his/param/FsPackageOrderDoPayParam.java
  13. 1 0
      fs-service/src/main/java/com/fs/his/param/FsStoreOrderDoPayParam.java
  14. 3 1
      fs-service/src/main/java/com/fs/his/service/IFsPackageOrderService.java
  15. 92 17
      fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java
  16. 94 0
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreAfterSalesServiceImpl.java
  17. 71 3
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java
  18. 103 1
      fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java
  19. 6 0
      fs-service/src/main/java/com/fs/his/service/impl/MerchantAppConfigServiceImpl.java
  20. 4 0
      fs-service/src/main/java/com/fs/system/mapper/SysConfigMapper.java
  21. 1 1
      fs-service/src/main/resources/mapper/his/FsStorePaymentMapper.xml
  22. 25 15
      fs-service/src/main/resources/mapper/system/SysConfigMapper.xml
  23. 61 20
      fs-user-app/src/main/java/com/fs/app/controller/AppPayController.java
  24. 9 0
      fs-user-app/src/main/java/com/fs/app/controller/CourseOrderController.java
  25. 90 16
      fs-user-app/src/main/java/com/fs/app/controller/InquiryOrderController.java
  26. 1 1
      fs-user-app/src/main/java/com/fs/app/controller/PackageOrderController.java
  27. 9 0
      fs-user-app/src/main/java/com/fs/app/controller/UserVipController.java

+ 8 - 1
fs-service/pom.xml

@@ -123,7 +123,7 @@
         <dependency>
             <groupId>com.github.binarywang</groupId>
             <artifactId>weixin-java-pay</artifactId>
-            <version>4.7.2.B</version>
+            <version>4.8.0</version>
         </dependency>
         <dependency>
             <groupId>com.github.binarywang</groupId>
@@ -303,6 +303,13 @@
             <version>1.3.1</version>
         </dependency>
 
+        <!-- 支付宝-->
+        <dependency>
+            <groupId>com.alipay.sdk</groupId>
+            <artifactId>alipay-sdk-java</artifactId>
+            <version>4.38.0.ALL</version>
+        </dependency>
+
 
     </dependencies>
 

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

@@ -1,12 +1,21 @@
 package com.fs.app.service;
 
+import com.fs.common.core.domain.R;
 import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
 
+import java.util.Map;
+
 public interface AppPayService {
 
+    /**
+     * 支付宝回调
+     */
+    String aliNotify(Map<String, String> params);
 
     /**
      * 微信支付回调
      */
     String wxNotify(WxPayOrderNotifyResult result);
+
+    R getPayConfig(String appId);
 }

+ 80 - 1
fs-service/src/main/java/com/fs/app/service/impl/AppPayServiceImpl.java

@@ -1,17 +1,28 @@
 package com.fs.app.service.impl;
 
 import com.fs.app.service.AppPayService;
+import com.fs.common.core.domain.R;
+import com.fs.course.service.IFsUserCourseOrderService;
+import com.fs.course.service.IFsUserVipOrderService;
+import com.fs.his.domain.FsPayConfig;
+import com.fs.his.domain.MerchantAppConfig;
 import com.fs.his.service.IFsInquiryOrderService;
 import com.fs.his.service.IFsPackageOrderService;
 import com.fs.hisStore.service.IFsStoreOrderScrmService;
 import com.fs.live.service.ILiveOrderService;
+import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
 import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
+import com.google.gson.Gson;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
+import com.alipay.api.internal.util.AlipaySignature;
+
+import java.util.Map;
 
 @Slf4j
 @Service
@@ -31,6 +42,60 @@ public class AppPayServiceImpl implements AppPayService {
     @Autowired
     private IFsPackageOrderService packageOrderService;
 
+    @Autowired
+    private IFsUserCourseOrderService courseOrderService;
+    @Autowired
+    private IFsUserVipOrderService vipOrderService;
+
+
+    /**
+     * 支付宝回调
+     */
+    @Override
+    public String aliNotify(Map<String, String> params) {
+        log.info("支付宝回调参数: {}", params);
+        SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.pay");
+        FsPayConfig fsPayConfig = new Gson().fromJson(sysConfig.getConfigValue(), FsPayConfig.class);
+        try {
+            boolean flag = AlipaySignature.rsaCheckV1(params, fsPayConfig.getAliPublicKey(), "UTF-8","RSA2");
+            if (!flag) {
+                log.info("支付宝回调验签失败:{}", params);
+            }
+
+            String tradeStatus = params.get("trade_status");
+            if (!"TRADE_SUCCESS".equals(tradeStatus)) {
+                return "success";
+            }
+
+            String[] arr = params.get("out_trade_no").split("-");
+            String tradeNo = params.get("trade_no");
+            switch (arr[0]) {
+                case "inquiry":
+                    inquiryOrderService.payConfirm("", arr[1],"","",1,tradeNo,"");
+                    break;
+//                case "store":
+//                    storeOrderService.payConfirm("", arr[1],"","",1,tradeNo,"");
+//                    break;
+                case "package":
+                    packageOrderService.payConfirm("", arr[1],"","",1,tradeNo,"");
+                    break;
+                case "appvip":
+                    vipOrderService.payConfirm("", arr[1],"","",1,tradeNo,"");
+                    break;
+                case "course":
+                    courseOrderService.payConfirm("", arr[1],"","",1,tradeNo,"");
+                    break;
+            }
+
+
+        } catch (Exception e) {
+            log.info("支付宝回调异常:{}", e);
+            throw new RuntimeException(e);
+        }
+
+        return "success";
+    }
+
     @Override
     public String wxNotify(WxPayOrderNotifyResult result) {
         log.info("微信回调参数: {}", result);
@@ -49,15 +114,29 @@ public class AppPayServiceImpl implements AppPayService {
                 break;
             case "store":
                 storeOrderService.payConfirm(1, null,tradeNoArr[1],"",result.getTransactionId(),"");
-
             case "live":
                 liveOrderService.payConfirm(1, null,tradeNoArr[1],"",result.getTransactionId(),"");
                 break;
             case "package":
                 packageOrderService.payConfirm("", tradeNoArr[1],"","",1,result.getTransactionId(),"");
                 break;
+            case "appvip":
+                vipOrderService.payConfirm("", tradeNoArr[1],"","",1,result.getTransactionId(),"");
+                break;
+            case "course":
+                courseOrderService.payConfirm("", tradeNoArr[1],"","",1,result.getTransactionId(),"");
+                break;
         }
         return WxPayNotifyResponse.success("OK");
     }
 
+    @Override
+    public R getPayConfig(String appId) {
+        MerchantAppConfig merchantAppConfig = sysConfigMapper.getPayConfig(appId);
+        if (merchantAppConfig == null || StringUtils.isEmpty(merchantAppConfig.getMerchantType())) {
+            return R.error("商户信息不存在");
+        }
+        return R.ok(merchantAppConfig.getMerchantType());
+    }
+
 }

+ 2 - 0
fs-service/src/main/java/com/fs/course/param/FsUserCourseOrderDoPayParam.java

@@ -11,4 +11,6 @@ public class FsUserCourseOrderDoPayParam implements Serializable {
     Long orderId;
     Long userId;
     private String appId;
+
+    private String payType;
 }

+ 2 - 0
fs-service/src/main/java/com/fs/course/param/FsUserVipOrderPayUParam.java

@@ -12,4 +12,6 @@ public class FsUserVipOrderPayUParam implements Serializable {
    @NotNull(message = "orderId不能为空")
    private Long orderId;
    private String appId;
+
+   private String payType;
 }

+ 4 - 0
fs-service/src/main/java/com/fs/course/service/IFsUserCourseOrderService.java

@@ -9,6 +9,8 @@ import com.fs.course.vo.FsUserCourseOrderListPVO;
 import com.fs.course.vo.FsUserCourseOrderListUVO;
 import com.fs.his.param.FsPackageOrderDoPayParam;
 
+import javax.servlet.http.HttpServletRequest;
+
 /**
  * 课程订单信息Service接口
  *
@@ -84,4 +86,6 @@ public interface IFsUserCourseOrderService
     R createIntegralOrder(FsUserCourseOrderCreateParam param);
 
     List<FsUserCourseOrderListUVO> selectFsUserCourseOrderListUVO(FsUserCourseOrderListUParam param);
+
+    R appPayment(FsUserCourseOrderDoPayParam param, HttpServletRequest request);
 }

+ 4 - 0
fs-service/src/main/java/com/fs/course/service/IFsUserVipOrderService.java

@@ -11,6 +11,8 @@ import com.fs.course.param.FsUserVipOrderPayUParam;
 import com.fs.course.vo.FsUserVipOrderListPVO;
 import com.fs.his.param.FsPackageOrderDoPayParam;
 
+import javax.servlet.http.HttpServletRequest;
+
 /**
  * 购买会员订单Service接口
  *
@@ -78,4 +80,6 @@ public interface IFsUserVipOrderService
     R payConfirm(String orderSn,String payCode, String tradeNo,String payType,Integer type,String bankTransactionId,String bankSerialNo);
 
     R aliPayment(FsUserVipOrderPayUParam param);
+
+    R appPayment(FsUserVipOrderPayUParam param, HttpServletRequest request);
 }

+ 190 - 4
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseOrderServiceImpl.java

@@ -6,6 +6,12 @@ import java.util.*;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.diagnosis.DiagnosisUtils;
+import com.alipay.api.domain.AlipayTradeAppPayModel;
+import com.alipay.api.request.AlipayTradeAppPayRequest;
+import com.alipay.api.response.AlipayTradeAppPayResponse;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.core.domain.R;
@@ -19,6 +25,7 @@ import com.fs.core.utils.OrderCodeUtils;
 import com.fs.course.domain.*;
 import com.fs.course.mapper.*;
 import com.fs.course.param.*;
+import com.fs.course.service.IFsCoursePlaySourceConfigService;
 import com.fs.course.service.IFsUserCourseStudyService;
 import com.fs.course.vo.FsUserCourseOrderListPVO;
 import com.fs.course.vo.FsUserCourseOrderListUVO;
@@ -29,10 +36,7 @@ import com.fs.his.enums.FsUserIntegralLogTypeEnum;
 import com.fs.his.mapper.*;
 import com.fs.his.param.FsPackageOrderDoPayParam;
 import com.fs.his.param.FsUserAddIntegralTemplateParam;
-import com.fs.his.service.IFsCouponService;
-import com.fs.his.service.IFsStorePaymentService;
-import com.fs.his.service.IFsUserCouponService;
-import com.fs.his.service.IFsUserIntegralLogsService;
+import com.fs.his.service.*;
 import com.fs.huifuPay.domain.HuiFuCreateOrder;
 import com.fs.huifuPay.domain.HuifuCreateOrderResult;
 import com.fs.huifuPay.service.HuiFuService;
@@ -55,6 +59,7 @@ import com.github.binarywang.wxpay.config.WxPayConfig;
 import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.binarywang.wxpay.service.WxPayService;
 import com.google.gson.Gson;
+import lombok.extern.slf4j.Slf4j;
 import org.checkerframework.checker.units.qual.A;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -63,6 +68,7 @@ import org.springframework.stereotype.Service;
 import com.fs.course.service.IFsUserCourseOrderService;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.interceptor.TransactionAspectSupport;
+import javax.servlet.http.HttpServletRequest;
 
 /**
  * 课程订单信息Service业务层处理
@@ -70,6 +76,7 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport;
  * @author fs
  * @date 2024-05-21
  */
+@Slf4j
 @Service
 public class FsUserCourseOrderServiceImpl implements IFsUserCourseOrderService
 {
@@ -133,6 +140,14 @@ public class FsUserCourseOrderServiceImpl implements IFsUserCourseOrderService
     private IFsUserIntegralLogsService userIntegralLogsService;
     @Autowired
     private FsUserWxMapper fsUserWxMapper;
+    @Autowired
+    private FsUserMapper userMapper;
+    @Autowired
+    private IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService;
+    @Autowired
+    private IMerchantAppConfigService merchantAppConfigService;
+    @Autowired
+    private IFsUserService fsUserService;
 
 
 
@@ -367,6 +382,177 @@ public class FsUserCourseOrderServiceImpl implements IFsUserCourseOrderService
         }
     }
 
+    @Override
+    public R appPayment(FsUserCourseOrderDoPayParam param, HttpServletRequest request) {
+        FsUserCourseOrder order = fsUserCourseOrderMapper.selectFsUserCourseOrderByOrderId(param.getOrderId());
+        if (order == null) {
+            return R.error("订单不存在");
+        }
+        if (order.getStatus() != 1) {
+            return R.error("非法操作");
+        }
+
+        FsUser user = userMapper.selectFsUserByUserId(param.getUserId());
+        if (user == null) {
+            return R.error("用户不存在");
+        }
+
+        if (order.getPayMoney().compareTo(new BigDecimal(0)) <= 0) {
+            this.payConfirm(order.getOrderCode(),"","","",2,null,null);
+            return R.ok().put("isPay",1);
+        }
+
+        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigService.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 = merchantAppConfigService.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
+        FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+        String openId = null;
+        String appId = param.getAppId();
+        if (request.getHeader("sourcetype") != null && "APP".equals(request.getHeader("sourcetype"))) {
+            FsUser fsUser = fsUserService.selectFsUserByUserId(param.getUserId().longValue());
+            openId = fsUser.getAppOpenId();
+        } else {
+            if (StringUtils.isNotBlank(appId)) {
+                //查询fs_user_wx的openId
+                Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                        .eq(FsUserWx::getFsUserId, param.getUserId())
+                        .eq(FsUserWx::getAppId, appId);
+                FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+                if (fsUserWx != null) {
+                    openId = fsUserWx.getOpenId();
+                }
+            } else {
+                appId = merchantAppConfig.getAppId();
+                openId = Objects.isNull(user) ? "" : user.getMaOpenId();
+                if (StringUtils.isBlank(openId)){
+                    Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                            .eq(FsUserWx::getFsUserId, param.getUserId())
+                            .eq(FsUserWx::getAppId, appId);
+                    FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+                    if (Objects.nonNull(fsUserWx)){
+                        openId = fsUserWx.getOpenId();
+                    }
+                }
+            }
+        }
+
+        if ("hf".equals(merchantAppConfig.getMerchantType()) && "wx".equals(param.getPayType()) && StringUtils.isBlank(openId)) {
+            return R.error("用户OPENID不存在");
+        }
+
+        String payCode = OrderCodeUtils.getOrderSn();
+        if (StringUtils.isEmpty(payCode)) {
+            return R.error("订单生成失败,请重试");
+        }
+
+        FsStorePayment storePayment = new FsStorePayment();
+        storePayment.setStatus(0);
+        storePayment.setPayMode(merchantAppConfig.getMerchantType());
+        storePayment.setBusinessCode(order.getOrderCode());
+        storePayment.setPayCode(payCode);
+        storePayment.setPayMoney(order.getPayMoney());
+        storePayment.setCreateTime(new Date());
+        storePayment.setPayTypeCode("app");
+        storePayment.setBusinessType(4);
+        storePayment.setRemark("课程订单支付");
+        storePayment.setPayTypeCode(param.getPayType());
+        storePayment.setUserId(user.getUserId());
+        storePayment.setBusinessId(order.getOrderId().toString());
+        storePayment.setMerConfigId(merchantAppConfig.getId());
+        storePayment.setAppId(param.getAppId());
+        if (storePaymentService.insertFsStorePayment(storePayment) > 0) {
+            if (!"hf".equals(merchantAppConfig.getMerchantType()) && !"appPay".equals(merchantAppConfig.getMerchantType())) {
+                return R.error("支付暂不可用!");
+            }
+
+            if ("hf".equals(merchantAppConfig.getMerchantType())) {
+                HuiFuCreateOrder o = new HuiFuCreateOrder();
+                o.setTradeType(param.getPayType().equals("wx") ? "T_MINIAPP" : "A_NATIVE");
+                o.setOpenid(openId);
+                o.setAppId(appId);
+                o.setReqSeqId("course-"+storePayment.getPayCode());
+                o.setTransAmt(storePayment.getPayMoney().toString());
+                o.setAppId(param.getAppId());
+                o.setGoodsDesc("课程订单支付");
+                HuifuCreateOrderResult result = huiFuService.createOrder(o);
+                FsStorePayment mt=new FsStorePayment();
+                mt.setPaymentId(storePayment.getPaymentId());
+                mt.setTradeNo(result.getHf_seq_id());
+                mt.setAppId(appId);
+                storePaymentService.updateFsStorePayment(mt);
+                return R.ok().put("isPay",0).put("data",result).put("type","hf");
+            } else if ("appPay".equals(merchantAppConfig.getMerchantType()) && "wx".equals(param.getPayType())) {
+                //创建微信订单
+                WxPayConfig payConfig = new WxPayConfig();
+                payConfig.setAppId(appId);
+                payConfig.setMchId(fsPayConfig.getWxAppMchId());
+                payConfig.setMchKey(fsPayConfig.getWxAppMchKey());
+                payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                payConfig.setKeyPath(null);
+                payConfig.setNotifyUrl(fsPayConfig.getWxAppNotifyUrl());
+                wxPayService.setConfig(payConfig);
+                WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
+                orderRequest.setBody("课程订单支付");
+                orderRequest.setOutTradeNo("course-"+storePayment.getPayCode());
+                orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));
+                orderRequest.setTradeType("APP");
+                orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(request));
+                orderRequest.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
+                //调用统一下单接口,获取"预支付交易会话标识"
+                try {
+                    log.info("会员开通订单支付 调用微信入参:{}", orderRequest.toString());
+                    Object result = wxPayService.createOrder(orderRequest);
+                    log.info("会员开通订单支付 调用微信出参:{}", result.toString());
+                    return R.ok().put("data",result).put("type","wxApp").put("isPay",0);
+                } catch (WxPayException e) {
+                    e.printStackTrace();
+                    throw new CustomException("会员开通订单支付"+e.getMessage());
+                }
+            } else if ("appPay".equals(merchantAppConfig.getMerchantType()) && "ali".equals(param.getPayType())) {
+                // 实例化客户端
+                AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", fsPayConfig.getAliAppId(), fsPayConfig.getAliPrivateKey(), "json", "utf-8", fsPayConfig.getAliPublicKey(), "RSA2");
+                // 构造请求参数以调用接口
+                AlipayTradeAppPayRequest aliRequest = new AlipayTradeAppPayRequest();
+                AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
+                // 商户订单号
+                model.setOutTradeNo("course-" + storePayment.getPayCode());
+                // 订单总金额
+                model.setTotalAmount(storePayment.getPayMoney().toString());
+                // 订单标题
+                model.setSubject("课程订单支付");
+                aliRequest.setBizModel(model);
+                aliRequest.setNotifyUrl(fsPayConfig.getAliNotifyUrl());
+
+                try {
+                    log.info("会员开通订单支付 调用支付宝入参:{}", aliRequest.toString());
+                    AlipayTradeAppPayResponse result = alipayClient.sdkExecute(aliRequest);
+                    if (!result.isSuccess()) {
+                        String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(result);
+                        log.error("支付宝支付调用失败 诊断链接:{}", diagnosisUrl);
+                        throw new CustomException(result.getSubMsg());
+                    }
+
+                    log.info("会员开通订单支付 调用支付宝入参:{}", result.toString());
+
+                    return R.ok().put("isPay", 0).put("data", result).put("type", "aliPay");
+                } catch (Exception e){
+                    log.info("支付宝支付异常: {}", e);
+                    throw new CustomException("支付系统异常,请稍后重试");
+                }
+            }
+        }
+
+        return R.error();
+    }
+
     @Override
     public R payment(FsUserCourseOrderDoPayParam param) {
         FsUserCourseOrder order = fsUserCourseOrderMapper.selectFsUserCourseOrderByOrderId(param.getOrderId());

+ 191 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsUserVipOrderServiceImpl.java

@@ -11,6 +11,13 @@ import java.util.Objects;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.diagnosis.DiagnosisUtils;
+import com.alipay.api.domain.AlipayTradeAppPayModel;
+import com.alipay.api.request.AlipayTradeAppPayRequest;
+import com.alipay.api.response.AlipayTradeAppPayResponse;
+import com.fs.course.service.IFsCoursePlaySourceConfigService;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.core.domain.R;
@@ -34,6 +41,8 @@ import com.fs.his.domain.*;
 import com.fs.his.dto.PayConfigDTO;
 import com.fs.his.mapper.*;
 import com.fs.his.service.IFsStorePaymentService;
+import com.fs.his.service.IFsUserService;
+import com.fs.his.service.IMerchantAppConfigService;
 import com.fs.hisStore.domain.FsPayConfigScrm;
 import com.fs.huifuPay.domain.HuiFuCreateOrder;
 import com.fs.huifuPay.domain.HuifuCreateOrderResult;
@@ -55,6 +64,7 @@ import com.github.binarywang.wxpay.config.WxPayConfig;
 import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.binarywang.wxpay.service.WxPayService;
 import com.google.gson.Gson;
+import lombok.extern.slf4j.Slf4j;
 import org.checkerframework.checker.units.qual.A;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -66,12 +76,15 @@ import com.fs.course.service.IFsUserVipOrderService;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.interceptor.TransactionAspectSupport;
 
+import javax.servlet.http.HttpServletRequest;
+
 /**
  * 购买会员订单Service业务层处理
  *
  * @author fs
  * @date 2024-06-27
  */
+@Slf4j
 @Service
 public class FsUserVipOrderServiceImpl implements IFsUserVipOrderService
 {
@@ -114,6 +127,13 @@ public class FsUserVipOrderServiceImpl implements IFsUserVipOrderService
     @Autowired
     private FsUserWxMapper fsUserWxMapper;
 
+    @Autowired
+    private IFsCoursePlaySourceConfigService fsCoursePlaySourceConfigService;
+    @Autowired
+    private IMerchantAppConfigService merchantAppConfigService;
+    @Autowired
+    private IFsUserService fsUserService;
+
 
     /**
      * 查询购买会员订单
@@ -221,6 +241,177 @@ public class FsUserVipOrderServiceImpl implements IFsUserVipOrderService
     }
 
 
+    @Override
+    @Transactional
+    public R appPayment(FsUserVipOrderPayUParam param, HttpServletRequest request) {
+        FsUserVipOrder order = fsUserVipOrderMapper.selectFsUserVipOrderByOrderId(param.getOrderId());
+        if (order == null) {
+            return R.error("订单不存在");
+        }
+        if (order.getStatus() != 0) {
+            return R.error("非法操作");
+        }
+
+        FsUser user = userMapper.selectFsUserByUserId(param.getUserId());
+        if (user == null) {
+            return R.error("用户不存在");
+        }
+
+        if (order.getPayMoney().compareTo(new BigDecimal(0)) <= 0) {
+            this.payConfirm(order.getOrderCode(),"","","",2,null,null);
+            handleVipPurchaseCallback(param.getUserId(),order.getPackageId(),order.getOrderId());
+            return R.ok().put("isPay",1);
+        }
+
+        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigService.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 = merchantAppConfigService.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
+        FsPayConfig fsPayConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+        String openId = null;
+        String appId = param.getAppId();
+        if (request.getHeader("sourcetype") != null && "APP".equals(request.getHeader("sourcetype"))) {
+            FsUser fsUser = fsUserService.selectFsUserByUserId(param.getUserId().longValue());
+            openId = fsUser.getAppOpenId();
+        } else {
+            if (StringUtils.isNotBlank(appId)) {
+                //查询fs_user_wx的openId
+                Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                        .eq(FsUserWx::getFsUserId, param.getUserId())
+                        .eq(FsUserWx::getAppId, appId);
+                FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+                if (fsUserWx != null) {
+                    openId = fsUserWx.getOpenId();
+                }
+            } else {
+                appId = merchantAppConfig.getAppId();
+                openId = Objects.isNull(user) ? "" : user.getMaOpenId();
+                if (StringUtils.isBlank(openId)){
+                    Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                            .eq(FsUserWx::getFsUserId, param.getUserId())
+                            .eq(FsUserWx::getAppId, appId);
+                    FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+                    if (Objects.nonNull(fsUserWx)){
+                        openId = fsUserWx.getOpenId();
+                    }
+                }
+            }
+        }
+
+        if ("hf".equals(merchantAppConfig.getMerchantType()) && "wx".equals(param.getPayType()) && StringUtils.isBlank(openId)) {
+            return R.error("用户OPENID不存在");
+        }
+
+        String payCode = OrderCodeUtils.getOrderSn();
+        if (StringUtils.isEmpty(payCode)) {
+            return R.error("订单生成失败,请重试");
+        }
+
+        FsStorePayment storePayment = new FsStorePayment();
+        storePayment.setStatus(0);
+        storePayment.setPayMode(merchantAppConfig.getMerchantType());
+        storePayment.setBusinessCode(order.getOrderCode());
+        storePayment.setPayCode(payCode);
+        storePayment.setPayMoney(order.getPayMoney());
+        storePayment.setCreateTime(new Date());
+        storePayment.setPayTypeCode("app");
+        storePayment.setBusinessType(5);
+        storePayment.setRemark("会员开通订单支付");
+        storePayment.setPayTypeCode(param.getPayType());
+        storePayment.setUserId(user.getUserId());
+        storePayment.setBusinessId(order.getOrderId().toString());
+        storePayment.setMerConfigId(merchantAppConfig.getId());
+        storePayment.setAppId(param.getAppId());
+        if (storePaymentService.insertFsStorePayment(storePayment) > 0) {
+            if (!"hf".equals(merchantAppConfig.getMerchantType()) && !"appPay".equals(merchantAppConfig.getMerchantType())) {
+                return R.error("支付暂不可用!");
+            }
+
+            if ("hf".equals(merchantAppConfig.getMerchantType())) {
+                HuiFuCreateOrder o = new HuiFuCreateOrder();
+                o.setTradeType(param.getPayType().equals("wx") ? "T_MINIAPP" : "A_NATIVE");
+                o.setOpenid(openId);
+                o.setAppId(appId);
+                o.setReqSeqId("appvip-"+storePayment.getPayCode());
+                o.setTransAmt(storePayment.getPayMoney().toString());
+                o.setAppId(param.getAppId());
+                o.setGoodsDesc("会员开通订单支付");
+                HuifuCreateOrderResult result = huiFuService.createOrder(o);
+                FsStorePayment mt=new FsStorePayment();
+                mt.setPaymentId(storePayment.getPaymentId());
+                mt.setTradeNo(result.getHf_seq_id());
+                mt.setAppId(appId);
+                storePaymentService.updateFsStorePayment(mt);
+                return R.ok().put("isPay",0).put("data",result).put("type","hf");
+            } else if ("appPay".equals(merchantAppConfig.getMerchantType()) && "wx".equals(param.getPayType())) {
+                //创建微信订单
+                WxPayConfig payConfig = new WxPayConfig();
+                payConfig.setAppId(appId);
+                payConfig.setMchId(fsPayConfig.getWxAppMchId());
+                payConfig.setMchKey(fsPayConfig.getWxAppMchKey());
+                payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                payConfig.setKeyPath(null);
+                payConfig.setNotifyUrl(fsPayConfig.getWxAppNotifyUrl());
+                wxPayService.setConfig(payConfig);
+                WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
+                orderRequest.setBody("会员开通订单支付");
+                orderRequest.setOutTradeNo("appvip-"+storePayment.getPayCode());
+                orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));
+                orderRequest.setTradeType("APP");
+                orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(request));
+                orderRequest.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
+                //调用统一下单接口,获取"预支付交易会话标识"
+                try {
+                    log.info("会员开通订单支付 调用微信入参:{}", orderRequest.toString());
+                    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());
+                }
+            } else if ("appPay".equals(merchantAppConfig.getMerchantType()) && "ali".equals(param.getPayType())) {
+                // 实例化客户端
+                AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", fsPayConfig.getAliAppId(), fsPayConfig.getAliPrivateKey(), "json", "utf-8", fsPayConfig.getAliPublicKey(), "RSA2");
+                // 构造请求参数以调用接口
+                AlipayTradeAppPayRequest aliRequest = new AlipayTradeAppPayRequest();
+                AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
+                // 商户订单号
+                model.setOutTradeNo("appvip-" + storePayment.getPayCode());
+                // 订单总金额
+                model.setTotalAmount(storePayment.getPayMoney().toString());
+                // 订单标题
+                model.setSubject("会员开通订单支付");
+                aliRequest.setBizModel(model);
+                aliRequest.setNotifyUrl(fsPayConfig.getAliNotifyUrl());
+
+                try {
+                    log.info("会员开通订单支付 调用微信入参:{}", aliRequest.toString());
+                    AlipayTradeAppPayResponse result = alipayClient.sdkExecute(aliRequest);
+                    if (!result.isSuccess()) {
+                        String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(result);
+                        log.error("支付宝支付调用失败 诊断链接:{}", diagnosisUrl);
+                        throw new CustomException(result.getSubMsg());
+                    }
+
+                    return R.ok().put("isPay", 0).put("data", result).put("type", "aliPay");
+                } catch (Exception e){
+                    log.info("支付宝支付异常: {}", e);
+                    throw new CustomException("支付系统异常,请稍后重试");
+                }
+            }
+        }
+
+        return R.error();
+    }
+
+
     @Override
     public R payment(FsUserVipOrderPayUParam param) {
         FsUserVipOrder order = fsUserVipOrderMapper.selectFsUserVipOrderByOrderId(param.getOrderId());

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

@@ -37,4 +37,15 @@ public class FsPayConfig {
     private String hfPayOnlineNotifyUrl;
     private String hfRefundNotifyUrl;
     private String hfOnlineRefundNotifyUrl;
+
+    private String aliAppId;
+    private String aliPrivateKey;
+    private String aliPublicKey;
+    private String aliNotifyUrl;
+
+    private String wxAppMchId;
+    private String wxAppMchKey;
+    private String wxAppNotifyUrl;
+    private String wxAppAppId;
+    private String wxAppKeyPath;
 }

+ 1 - 0
fs-service/src/main/java/com/fs/his/param/FsInquiryOrderDoPayParam.java

@@ -10,5 +10,6 @@ public class FsInquiryOrderDoPayParam implements Serializable {
     Long userId;
 
     private String appId;
+    private String payType;
 
 }

+ 1 - 0
fs-service/src/main/java/com/fs/his/param/FsPackageOrderDoPayParam.java

@@ -13,4 +13,5 @@ public class FsPackageOrderDoPayParam implements Serializable {
 
     private String appId;//小程序id
     private String createPackageOrderKey;
+    private String payType;
 }

+ 1 - 0
fs-service/src/main/java/com/fs/his/param/FsStoreOrderDoPayParam.java

@@ -12,4 +12,5 @@ public class FsStoreOrderDoPayParam implements Serializable {
     Long userId;
 
     private String appId;
+    private String payType;
 }

+ 3 - 1
fs-service/src/main/java/com/fs/his/service/IFsPackageOrderService.java

@@ -13,6 +13,8 @@ import com.fs.his.param.*;
 import com.fs.his.vo.*;
 import io.swagger.models.auth.In;
 
+import javax.servlet.http.HttpServletRequest;
+
 /**
  * 套餐订单Service接口
  *
@@ -95,7 +97,7 @@ public interface IFsPackageOrderService
 
     Integer PackageStoreOrderRefund(Long orderId,String opeName);
 
-    R payment(FsPackageOrderDoPayParam param);
+    R payment(FsPackageOrderDoPayParam param, HttpServletRequest request);
 
     R cancel(FsPackageOrderCancelParam param);
 

+ 92 - 17
fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java

@@ -17,6 +17,12 @@ import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.diagnosis.DiagnosisUtils;
+import com.alipay.api.domain.AlipayTradeAppPayModel;
+import com.alipay.api.request.AlipayTradeAppPayRequest;
+import com.alipay.api.response.AlipayTradeAppPayResponse;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.constant.FsConstants;
@@ -77,6 +83,7 @@ import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.binarywang.wxpay.service.WxPayService;
 import com.google.common.reflect.TypeToken;
 import com.google.gson.Gson;
+import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -87,12 +94,15 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.interceptor.TransactionAspectSupport;
 
+import javax.servlet.http.HttpServletRequest;
+
 /**
  * 套餐订单Service业务层处理
  *
  * @author fs
  * @date 2023-08-25
  */
+@Slf4j
 @Service
 public class FsPackageOrderServiceImpl implements IFsPackageOrderService
 {
@@ -976,7 +986,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
 
     @Override
     @Transactional
-    public R payment(FsPackageOrderDoPayParam param) {
+    public R payment(FsPackageOrderDoPayParam param, HttpServletRequest request) {
         //更新订单状态
         FsPackageOrder fsPackageOrder=fsPackageOrderMapper.selectFsPackageOrderByOrderId(param.getOrderId());
         if(!fsPackageOrder.getStatus().equals(FsPackageOrderStatusEnum.STATUS_1.getValue())){
@@ -1009,30 +1019,40 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
         //金牛多小程序支付
         String openId = null;
         String appId = param.getAppId();
-        if (StringUtils.isNotBlank(appId)) {
-            //查询fs_user_wx的openId
-            Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
-                    .eq(FsUserWx::getFsUserId, param.getUserId())
-                    .eq(FsUserWx::getAppId, appId);
-            FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
-            if (fsUserWx != null) {
-                openId = fsUserWx.getOpenId();
-            }
+        if (request.getHeader("sourcetype") != null && "APP".equals(request.getHeader("sourcetype"))) {
+            FsUser fsUser = fsUserService.selectFsUserByUserId(param.getUserId().longValue());
+            openId = fsUser.getAppOpenId();
         } else {
-            appId = fsCoursePlaySourceConfig.getAppid();
-            openId = Objects.isNull(user) ? "" : user.getMaOpenId();
-            if (StringUtils.isBlank(openId)){
+            if (StringUtils.isNotBlank(appId)) {
+                //查询fs_user_wx的openId
                 Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
                         .eq(FsUserWx::getFsUserId, param.getUserId())
                         .eq(FsUserWx::getAppId, appId);
                 FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
-                if (Objects.nonNull(fsUserWx)){
+                if (fsUserWx != null) {
                     openId = fsUserWx.getOpenId();
                 }
+            } else {
+                appId = fsCoursePlaySourceConfig.getAppid();
+                openId = Objects.isNull(user) ? "" : user.getMaOpenId();
+                if (StringUtils.isBlank(openId)){
+                    Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                            .eq(FsUserWx::getFsUserId, param.getUserId())
+                            .eq(FsUserWx::getAppId, appId);
+                    FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+                    if (Objects.nonNull(fsUserWx)){
+                        openId = fsUserWx.getOpenId();
+                    }
+                }
             }
         }
 
-        if(user!=null&& StringUtils.isNotEmpty(openId)){
+        if (user != null
+                && (
+                StringUtils.isNotEmpty(openId)
+                        || "appPay".equals(merchantAppConfig.getMerchantType())
+                        || ("hf".equals(merchantAppConfig.getMerchantType()) && "ali".equals(param.getPayType()))
+        )) {
             if(fsPackageOrder.getPayMoney().compareTo(new BigDecimal(0))==1){
                 String payCode =  OrderCodeUtils.getOrderSn();
                 if(StringUtils.isEmpty(payCode)){
@@ -1045,7 +1065,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                 storePayment.setPayCode(payCode);
                 storePayment.setPayMoney(fsPackageOrder.getPayMoney());
                 storePayment.setCreateTime(new Date());
-                storePayment.setPayTypeCode("weixin");
+                storePayment.setPayTypeCode(!"appPay".equals(merchantAppConfig.getMerchantType()) ? "weixin" : param.getPayType());
                 storePayment.setBusinessType(3);
                 storePayment.setCompanyId(fsPackageOrder.getCompanyId());
                 storePayment.setCompanyUserId(fsPackageOrder.getCompanyUserId());
@@ -1133,7 +1153,7 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                     }else if (merchantAppConfig.getMerchantType().equals("hf")) {
                         logger.info("创建汇付订单");
                         HuiFuCreateOrder o = new HuiFuCreateOrder();
-                        o.setTradeType("T_MINIAPP");
+                        o.setTradeType(StringUtils.isEmpty(param.getPayType()) || param.getPayType().equals("wx") ? "T_MINIAPP" : "A_NATIVE");
                         o.setOpenid(openId);
                         o.setReqSeqId("package-"+storePayment.getPayCode());
                         o.setTransAmt(storePayment.getPayMoney().toString());
@@ -1156,6 +1176,61 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
                         mt.setAppId(appId);
                         storePaymentService.updateFsStorePayment(mt);
                         return R.ok().put("isPay", 0).put("data", result).put("type", "hf");
+                    } else if (merchantAppConfig.getMerchantType().equals("appPay") && "wx".equals(param.getPayType())) {
+                        //创建微信订单
+                        WxPayConfig payConfig = new WxPayConfig();
+                        payConfig.setAppId(appId);
+                        payConfig.setMchId(fsPayConfig.getWxAppMchId());
+                        payConfig.setMchKey(fsPayConfig.getWxAppMchKey());
+                        payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                        payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                        payConfig.setKeyPath(null);
+                        payConfig.setNotifyUrl(fsPayConfig.getWxAppNotifyUrl());
+                        wxPayService.setConfig(payConfig);
+                        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
+                        orderRequest.setBody("套餐包订单支付");
+                        orderRequest.setOutTradeNo("package-"+storePayment.getPayCode());
+                        orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));
+                        orderRequest.setTradeType("APP");
+                        orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(request));
+                        orderRequest.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
+                        //调用统一下单接口,获取"预支付交易会话标识"
+                        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());
+                        }
+                    } else if (merchantAppConfig.getMerchantType().equals("appPay") && "ali".equals(param.getPayType())) {
+                        // 实例化客户端
+                        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", fsPayConfig.getAliAppId(), fsPayConfig.getAliPrivateKey(), "json", "utf-8", fsPayConfig.getAliPublicKey(), "RSA2");
+
+                        // 构造请求参数以调用接口
+                        AlipayTradeAppPayRequest aliRequest = new AlipayTradeAppPayRequest();
+                        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
+                        // 商户订单号
+                        model.setOutTradeNo("package-" + storePayment.getPayCode());
+                        // 订单总金额
+                        model.setTotalAmount(storePayment.getPayMoney().toString());
+                        // 订单标题r
+                        model.setSubject("套餐包订单支付");
+
+                        aliRequest.setBizModel(model);
+                        aliRequest.setNotifyUrl(fsPayConfig.getAliNotifyUrl());
+
+                        try {
+                            AlipayTradeAppPayResponse result = alipayClient.sdkExecute(aliRequest);
+                            if (!result.isSuccess()) {
+                                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(result);
+                                log.error("支付宝支付调用失败 诊断链接:{}", diagnosisUrl);
+                                throw new CustomException(result.getSubMsg());
+                            }
+
+                            return R.ok().put("isPay", 0).put("data", result).put("type", "aliPay");
+                        } catch (Exception e){
+                            log.info("支付宝支付异常: {}", e);
+                        }
                     }
                 }
             }

+ 94 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsStoreAfterSalesServiceImpl.java

@@ -15,6 +15,12 @@ import cn.hutool.core.util.IdUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.domain.AlipayTradeRefundModel;
+import com.alipay.api.request.AlipayTradeRefundRequest;
+import com.alipay.api.response.AlipayTradeRefundResponse;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
@@ -76,7 +82,9 @@ import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
 import com.github.binarywang.wxpay.config.WxPayConfig;
 import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
 import com.google.gson.Gson;
+import lombok.extern.slf4j.Slf4j;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -92,6 +100,7 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport;
  * @author fs
  * @date 2023-06-13
  */
+@Slf4j
 @Service
 public class FsStoreAfterSalesServiceImpl implements IFsStoreAfterSalesService {
     @Autowired
@@ -618,6 +627,69 @@ public class FsStoreAfterSalesServiceImpl implements IFsStoreAfterSalesService {
                 } else {
                     throw new CustomException("退款请求失败" + refund.getResp_desc());
                 }
+            } else if ("appPay".equals(payment.getPayMode()) && "wx".equals(payment.getPayTypeCode())) {
+                // 处理微信退款
+                WxPayService wxPayService = getWxPayService(fsPayConfig);
+                WxPayRefundRequest refundRequest = new WxPayRefundRequest();
+                refundRequest.setOutTradeNo(orderType+"-"+payment.getPayCode());
+                refundRequest.setOutRefundNo(orderType+"-"+payment.getPayCode());
+                refundRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
+                refundRequest.setRefundFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
+                try {
+                    log.info("微信api证书路径:{}",fsPayConfig.getWxAppKeyPath());
+                    log.info("微信请求退款入参:{}",refundRequest);
+                    WxPayRefundResult refundResult = wxPayService.refund(refundRequest);
+                    log.info("微信请求退款出参:{}",refundResult);
+                    WxPayRefundQueryResult refundQueryResult = wxPayService.refundQuery("", refundResult.getOutTradeNo(), refundResult.getOutRefundNo(), refundResult.getRefundId());
+                    if (refundQueryResult != null && refundQueryResult.getResultCode().equals("SUCCESS")) {
+                        FsStorePayment paymentMap = new FsStorePayment();
+                        paymentMap.setPaymentId(payment.getPaymentId());
+                        paymentMap.setStatus(-1);
+                        paymentMap.setRefundTime(DateUtils.getNowDate());
+                        paymentMap.setRefundMoney(payment.getPayMoney());
+                        fsStorePaymentMapper.updateFsStorePayment(paymentMap);
+
+                        updateStatus(payment);
+                    } else {
+                        throw new CustomException("退款请求失败" + refundQueryResult.getReturnMsg());
+                    }
+
+                } catch (WxPayException e) {
+                    throw new CustomException("退款请求失败" + e);
+                }
+
+            } else if ("appPay".equals(payment.getPayMode()) && "ali".equals(payment.getPayTypeCode())) {
+                // 实例化客户端
+                SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.pay");
+                AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", fsPayConfig.getAliAppId(), fsPayConfig.getAliPrivateKey(), "json", "utf-8", fsPayConfig.getAliPublicKey(), "RSA2");
+                // 构造请求参数以调用接口
+                AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
+                AlipayTradeRefundModel model = new AlipayTradeRefundModel();
+                model.setOutTradeNo(orderType+"-"+payment.getPayCode());
+                model.setRefundAmount(payment.getPayMoney().toString());
+                request.setBizModel(model);
+                log.info("支付宝请求退款入参:{}",request);
+                try {
+                    AlipayTradeRefundResponse response = alipayClient.execute(request);
+                    log.info("支付宝请求退款出参:{}",response);
+                    if (response.isSuccess()) {
+                        FsStorePayment paymentMap = new FsStorePayment();
+                        paymentMap.setPaymentId(payment.getPaymentId());
+                        paymentMap.setStatus(-1);
+                        paymentMap.setRefundTime(DateUtils.getNowDate());
+                        paymentMap.setRefundMoney(payment.getPayMoney());
+                        fsStorePaymentMapper.updateFsStorePayment(paymentMap);
+
+                        updateStatus(payment);
+                    } else {
+//                        String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
+                        throw new CustomException("支付宝退款请求失败" + response.getSubMsg());
+                    }
+
+                } catch (AlipayApiException e) {
+                    throw new CustomException("支付宝退款请求失败" + e);
+                }
+
             }
             //管易作废
             if (StringUtils.isNotEmpty(fsStoreOrder.getExtendOrderId())) {
@@ -667,6 +739,28 @@ public class FsStoreAfterSalesServiceImpl implements IFsStoreAfterSalesService {
         return i;
     }
 
+    private void updateStatus(FsStorePayment fsStorePayment){
+        switch (fsStorePayment.getBusinessType()){
+            case 1:
+                FsInquiryOrder fsInquiryOrder = new FsInquiryOrder();
+                fsInquiryOrder.setOrderId(Long.valueOf(fsStorePayment.getBusinessId()));
+                fsInquiryOrder.setStatus(-2);
+                fsInquiryOrderMapper.updateFsInquiryOrder(fsInquiryOrder);
+                break;
+        }
+    }
+
+    private WxPayService getWxPayService(FsPayConfig fsPayConfig){
+        WxPayConfig payConfig = new WxPayConfig();
+        payConfig.setAppId(fsPayConfig.getWxAppAppId());
+        payConfig.setMchId(fsPayConfig.getWxAppMchId());
+        payConfig.setMchKey(fsPayConfig.getWxAppMchKey());
+        payConfig.setKeyPath(fsPayConfig.getWxAppKeyPath());
+        payConfig.setNotifyUrl(fsPayConfig.getWxAppNotifyUrl());
+        WxPayServiceImpl payService = new WxPayServiceImpl();
+        payService.setConfig(payConfig);
+        return payService;
+    }
 
 
     @Override

+ 71 - 3
fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java

@@ -5,6 +5,12 @@ import cn.hutool.core.net.URLDecoder;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONUtil;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.diagnosis.DiagnosisUtils;
+import com.alipay.api.domain.AlipayTradeAppPayModel;
+import com.alipay.api.request.AlipayTradeAppPayRequest;
+import com.alipay.api.response.AlipayTradeAppPayResponse;
 import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -3016,7 +3022,12 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
             }
         }
 
-        if (user != null && StringUtils.isNotEmpty(openId)) {
+        if (user != null
+                && (
+                StringUtils.isNotEmpty(openId)
+                        || "appPay".equals(merchantAppConfig.getMerchantType())
+                        || ("hf".equals(merchantAppConfig.getMerchantType()) && "ali".equals(param.getPayType()))
+        )) {
 
             if (order.getPayMoney().compareTo(new BigDecimal(0)) == 0) {
                 this.payConfirm(order.getOrderCode(), "", "", "", 2,null,null);
@@ -3033,7 +3044,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
                 storePayment.setPayMoney(order.getPayMoney());
                 storePayment.setBusinessCode(order.getOrderCode());
                 storePayment.setCreateTime(new Date());
-                storePayment.setPayTypeCode("weixin");
+                storePayment.setPayTypeCode(!"appPay".equals(merchantAppConfig.getMerchantType()) ? "weixin" : param.getPayType());
                 storePayment.setBusinessType(2);
                 storePayment.setRemark("药品订单支付");
                 storePayment.setOpenId(openId);
@@ -3121,7 +3132,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
                         return R.ok().put("isPay", 0).put("data", result).put("type", "tz");
                     } else if (merchantAppConfig.getMerchantType().equals("hf")) {
                         HuiFuCreateOrder o = new HuiFuCreateOrder();
-                        o.setTradeType("T_MINIAPP");
+                        o.setTradeType(StringUtils.isEmpty(param.getPayType()) || param.getPayType().equals("wx") ? "T_MINIAPP" : "A_NATIVE");
                         o.setOpenid(openId);
                         o.setAppId(appId);
                         o.setReqSeqId("store-" + storePayment.getPayCode());
@@ -3134,8 +3145,65 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
                         mt.setAppId(appId);
                         storePaymentService.updateFsStorePayment(mt);
                         return R.ok().put("isPay", 0).put("data", result).put("type", "hf");
+                    } else if (merchantAppConfig.getMerchantType().equals("appPay") && "wx".equals(param.getPayType())) {
+                    //创建微信订单
+                    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.getWxAppMchId());
+                    payConfig.setMchKey(fsPayConfig.getWxAppMchKey());
+                    payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                    payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                    payConfig.setKeyPath(null);
+                    payConfig.setNotifyUrl(fsPayConfig.getWxAppNotifyUrl());
+                    wxPayService.setConfig(payConfig);
+                    WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
+                    orderRequest.setBody("药品订单支付");
+                    orderRequest.setOutTradeNo("store-"+storePayment.getPayCode());
+                    orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));
+                    orderRequest.setTradeType("APP");
+                    orderRequest.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
+                    //调用统一下单接口,获取"预支付交易会话标识"
+                    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());
                     }
+                    } else if (merchantAppConfig.getMerchantType().equals("appPay") && "ali".equals(param.getPayType())) {
+                        // 实例化客户端
+                        SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.pay");
+                        FsPayConfig fsPayConfig = new Gson().fromJson(sysConfig.getConfigValue(), FsPayConfig.class);
+                        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", fsPayConfig.getAliAppId(), fsPayConfig.getAliPrivateKey(), "json", "utf-8", fsPayConfig.getAliPublicKey(), "RSA2");
+
+                        // 构造请求参数以调用接口
+                        AlipayTradeAppPayRequest aliRequest = new AlipayTradeAppPayRequest();
+                        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
+                        // 商户订单号
+                        model.setOutTradeNo("store-" + storePayment.getPayCode());
+                        // 订单总金额
+                        model.setTotalAmount(storePayment.getPayMoney().toString());
+                        // 订单标题r
+                        model.setSubject("药品订单支付");
+
+                        aliRequest.setBizModel(model);
+                        aliRequest.setNotifyUrl(fsPayConfig.getAliNotifyUrl());
+
+                        try {
+                            AlipayTradeAppPayResponse result = alipayClient.sdkExecute(aliRequest);
+                            if (!result.isSuccess()) {
+                                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(result);
+                                log.error("支付宝支付调用失败 诊断链接:{}", diagnosisUrl);
+                                throw new CustomException(result.getSubMsg());
+                            }
 
+                            return R.ok().put("isPay", 0).put("data", result).put("type", "aliPay");
+                        } catch (Exception e) {
+                            log.info("支付宝支付异常: {}", e);
+                        }
+                    }
                 } else {
                     return R.error("用户不存在");
 

+ 103 - 1
fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java

@@ -14,6 +14,13 @@ import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSONObject;
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.diagnosis.DiagnosisUtils;
+import com.alipay.api.domain.AlipayTradeRefundModel;
+import com.alipay.api.request.AlipayTradeRefundRequest;
+import com.alipay.api.response.AlipayTradeRefundResponse;
 import com.alibaba.fastjson.TypeReference;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
@@ -98,7 +105,9 @@ import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.binarywang.wxpay.service.TransferService;
 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 lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
 
 import org.apache.commons.lang3.exception.ExceptionUtils;
@@ -125,6 +134,7 @@ import javax.servlet.http.HttpServletRequest;
  * @author fs
  * @date 2023-08-11
  */
+@Slf4j
 @Service
 @EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)
 public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
@@ -222,6 +232,9 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
     @Autowired
     private FsStorePaymentErrorMapper fsStorePaymentErrorMapper;
 
+    @Autowired
+    private FsInquiryOrderMapper fsInquiryOrderMapper;
+
     /**
      * 红包账户锁
      */
@@ -568,11 +581,101 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
                 }else {
                     throw new CustomException("退款请求失败"+refund.getResp_desc());
                 }
+            } else if ("appPay".equals(fsStorePayment.getPayMode()) && "wx".equals(fsStorePayment.getPayTypeCode())) {
+                MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsStorePayment.getMerConfigId());
+                FsPayConfig fsPayConfig = com.alibaba.fastjson.JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+
+                // 处理微信退款
+                WxPayService wxPayService = getWxPayService(fsPayConfig);
+                WxPayRefundRequest refundRequest = new WxPayRefundRequest();
+                refundRequest.setOutTradeNo(orderType+"-"+fsStorePayment.getPayCode());
+                refundRequest.setOutRefundNo(orderType+"-"+fsStorePayment.getPayCode());
+                refundRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(fsStorePayment.getPayMoney().toString()));
+                refundRequest.setRefundFee(WxPayUnifiedOrderRequest.yuanToFen(fsStorePayment.getPayMoney().toString()));
+                log.info("微信退款入参:{}",refundRequest);
+                try {
+                    WxPayRefundResult refundResult = wxPayService.refund(refundRequest);
+                    WxPayRefundQueryResult refundQueryResult = wxPayService.refundQuery("", refundResult.getOutTradeNo(), refundResult.getOutRefundNo(), refundResult.getRefundId());
+                    log.info("微信退款出参:{}",refundQueryResult);
+                    if (refundQueryResult != null && refundQueryResult.getResultCode().equals("SUCCESS")) {
+                        FsStorePayment paymentMap = new FsStorePayment();
+                        paymentMap.setPaymentId(fsStorePayment.getPaymentId());
+                        paymentMap.setStatus(-1);
+                        paymentMap.setRefundTime(DateUtils.getNowDate());
+                        paymentMap.setRefundMoney(fsStorePayment.getPayMoney());
+                        fsStorePaymentMapper.updateFsStorePayment(paymentMap);
+
+                        updateStatus(fsStorePayment);
+                    } else {
+                        throw new CustomException("退款请求失败" + refundQueryResult.getReturnMsg());
+                    }
+
+                } catch (WxPayException e) {
+                    throw new CustomException("退款请求失败" + e);
+                }
+
+            } else if ("appPay".equals(fsStorePayment.getPayMode()) && "ali".equals(fsStorePayment.getPayTypeCode())) {
+                MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsStorePayment.getMerConfigId());
+                FsPayConfig fsPayConfig = com.alibaba.fastjson.JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
+                AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", fsPayConfig.getAliAppId(), fsPayConfig.getAliPrivateKey(), "json", "utf-8", fsPayConfig.getAliPublicKey(), "RSA2");
+                // 构造请求参数以调用接口
+                AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
+                AlipayTradeRefundModel model = new AlipayTradeRefundModel();
+                model.setOutTradeNo(orderType+"-"+fsStorePayment.getPayCode());
+                model.setRefundAmount(fsStorePayment.getPayMoney().toString());
+                request.setBizModel(model);
+                log.info("支付宝请求退款入参:{}",request.toString());
+                try {
+                    AlipayTradeRefundResponse response = alipayClient.execute(request);
+                    log.info("支付宝请求退款出参:{}",response.toString());
+                    if (response.isSuccess()) {
+                        FsStorePayment paymentMap = new FsStorePayment();
+                        paymentMap.setPaymentId(fsStorePayment.getPaymentId());
+                        paymentMap.setStatus(-1);
+                        paymentMap.setRefundTime(DateUtils.getNowDate());
+                        paymentMap.setRefundMoney(fsStorePayment.getPayMoney());
+                        fsStorePaymentMapper.updateFsStorePayment(paymentMap);
+
+                        updateStatus(fsStorePayment);
+                    } else {
+//                        String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
+                        throw new CustomException("支付宝退款请求失败" + response.getSubMsg());
+                    }
+
+                } catch (AlipayApiException e) {
+                    throw new CustomException("支付宝退款请求失败" + e);
+                }
+
             }
         }
         return R.ok();
     }
 
+    private void updateStatus(FsStorePayment fsStorePayment){
+        switch (fsStorePayment.getBusinessType()){
+            case 1:
+                FsInquiryOrder fsInquiryOrder = new FsInquiryOrder();
+                fsInquiryOrder.setOrderId(Long.valueOf(fsStorePayment.getBusinessId()));
+                fsInquiryOrder.setStatus(-2);
+                fsInquiryOrderMapper.updateFsInquiryOrder(fsInquiryOrder);
+                break;
+        }
+    }
+
+
+    private WxPayService getWxPayService(FsPayConfig fsPayConfig){
+
+        WxPayConfig payConfig = new WxPayConfig();
+        payConfig.setAppId(fsPayConfig.getWxAppAppId());
+        payConfig.setMchId(fsPayConfig.getWxAppMchId());
+        payConfig.setMchKey(fsPayConfig.getWxAppMchKey());
+        payConfig.setKeyPath(fsPayConfig.getWxAppKeyPath());
+        payConfig.setNotifyUrl(fsPayConfig.getWxAppNotifyUrl());
+        WxPayServiceImpl payService = new WxPayServiceImpl();
+        payService.setConfig(payConfig);
+        return payService;
+    }
+
     @Override
     public FsStorePayment selectFsStorePaymentByPaymentCode(String payCode) {
         return fsStorePaymentMapper.selectFsStorePaymentByPaymentCode(payCode);
@@ -1891,7 +1994,6 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
         storePayment.setPayMode(merchantAppConfig.getMerchantType());
         storePayment.setAppId(appId);
         storePayment.setMerConfigId(merchantAppConfig.getId());
-
         if (fsStorePaymentMapper.insertFsStorePayment(storePayment) > 0) {
             if (merchantAppConfig.getMerchantType().equals("wx")) {
                 //创建微信订单

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

@@ -131,6 +131,9 @@ public class MerchantAppConfigServiceImpl extends ServiceImpl<MerchantAppConfigM
                 merchantAppConfig.setMerchantId(fsPayConfig.getHuifuId());
                 merchantAppConfig.setCallbackUrl(fsPayConfig.getHfPayNotifyUrl());
                 break;
+            case "appPay": // app官方支付
+                merchantAppConfig.setMerchantId(fsPayConfig.getAliAppId() + "&" + fsPayConfig.getWxAppMchId());
+                break;
             default:
                 throw new RuntimeException("商户类型错误");
         }
@@ -166,6 +169,9 @@ public class MerchantAppConfigServiceImpl extends ServiceImpl<MerchantAppConfigM
                 merchantAppConfig.setMerchantId(fsPayConfig.getHuifuId());
                 merchantAppConfig.setCallbackUrl(fsPayConfig.getHfPayNotifyUrl());
                 break;
+            case "appPay": // app官方支付
+                merchantAppConfig.setMerchantId(fsPayConfig.getAliAppId() + "&" + fsPayConfig.getWxAppMchId());
+                break;
             default:
                 throw new RuntimeException("商户类型错误");
         }

+ 4 - 0
fs-service/src/main/java/com/fs/system/mapper/SysConfigMapper.java

@@ -1,6 +1,8 @@
 package com.fs.system.mapper;
 
 import java.util.List;
+
+import com.fs.his.domain.MerchantAppConfig;
 import com.fs.system.domain.SysConfig;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Select;
@@ -71,4 +73,6 @@ public interface SysConfigMapper
 
     @Select("select * from sys_config where config_key=#{configKey}")
     SysConfig selectConfigByConfigKey(String configKey);
+
+    MerchantAppConfig getPayConfig(String appId);
 }

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

@@ -35,7 +35,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
 
     <sql id="selectFsStorePaymentVo">
-        select payment_id, pay_code,is_share,share_status,share_code,share_money,business_code,pay_mode, pay_type_code,company_id,company_user_id, pay_money, pay_time, create_time, trade_no, user_id, open_id, business_type, business_id, status, remark, bank_transaction_id, bank_serial_no, refund_money, refund_time, store_id,app_id from fs_store_payment
+        select payment_id, pay_code,is_share,share_status,share_code,share_money,business_code,pay_mode, pay_type_code,company_id,company_user_id, pay_money, pay_time, create_time, trade_no, user_id, open_id, business_type, business_id, status, remark, bank_transaction_id, bank_serial_no, refund_money, refund_time, store_id,app_id, mer_config_id from fs_store_payment
     </sql>
 
     <select id="selectFsStorePaymentList" parameterType="FsStorePayment" resultMap="FsStorePaymentResult">

+ 25 - 15
fs-service/src/main/resources/mapper/system/SysConfigMapper.xml

@@ -3,7 +3,7 @@
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.fs.system.mapper.SysConfigMapper">
-    
+
     <resultMap type="SysConfig" id="SysConfigResult">
     	<id     property="configId"      column="config_id"      />
         <result property="configName"    column="config_name"    />
@@ -15,12 +15,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="updateBy"      column="update_by"      />
         <result property="updateTime"    column="update_time"    />
     </resultMap>
-    
+
     <sql id="selectConfigVo">
-        select config_id, config_name, config_key, config_value, config_type, create_by, create_time, update_by, update_time, remark 
+        select config_id, config_name, config_key, config_value, config_type, create_by, create_time, update_by, update_time, remark
 		from sys_config
     </sql>
-    
+
     <!-- 查询条件 -->
 	<sql id="sqlwhereSearch">
 		<where>
@@ -32,12 +32,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 			</if>
 		</where>
 	</sql>
-    
+
     <select id="selectConfig" parameterType="SysConfig" resultMap="SysConfigResult">
         <include refid="selectConfigVo"/>
         <include refid="sqlwhereSearch"/>
     </select>
-    
+
     <select id="selectConfigList" parameterType="SysConfig" resultMap="SysConfigResult">
         <include refid="selectConfigVo"/>
         <where>
@@ -58,12 +58,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 			</if>
 		</where>
     </select>
-    
+
     <select id="checkConfigKeyUnique" parameterType="String" resultMap="SysConfigResult">
         <include refid="selectConfigVo"/>
         where config_key = #{configKey} limit 1
     </select>
-    
+
+    <select id="getPayConfig" resultType="com.fs.his.domain.MerchantAppConfig">
+        SELECT
+            b.*
+        FROM
+            `fs_course_play_source_config` a
+                LEFT JOIN merchant_app_config b ON a.merchant_config_id = b.id
+        WHERE
+            a.appid = #{appId}
+    </select>
+
     <insert id="insertConfig" parameterType="SysConfig">
         insert into sys_config (
 			<if test="configName != null and configName != '' ">config_name,</if>
@@ -83,9 +93,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  			sysdate()
 		)
     </insert>
-	 
+
     <update id="updateConfig" parameterType="SysConfig">
-        update sys_config 
+        update sys_config
         <set>
             <if test="configName != null and configName != ''">config_name = #{configName},</if>
             <if test="configKey != null and configKey != ''">config_key = #{configKey},</if>
@@ -97,16 +107,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </set>
         where config_id = #{configId}
     </update>
-	
+
     <delete id="deleteConfigById" parameterType="Long">
         delete from sys_config where config_id = #{configId}
     </delete>
-    
+
     <delete id="deleteConfigByIds" parameterType="Long">
-        delete from sys_config where config_id in 
+        delete from sys_config where config_id in
         <foreach item="configId" collection="array" open="(" separator="," close=")">
         	#{configId}
         </foreach>
     </delete>
-    
-</mapper>
+
+</mapper>

+ 61 - 20
fs-user-app/src/main/java/com/fs/app/controller/AppPayController.java

@@ -2,6 +2,7 @@ package com.fs.app.controller;
 
 
 import com.fs.app.service.AppPayService;
+import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.StringUtils;
 import com.fs.course.domain.FsCoursePlaySourceConfig;
@@ -23,10 +24,12 @@ 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 org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
 
 @Slf4j
 @Api("app支付接口")
@@ -44,6 +47,24 @@ public class AppPayController extends AppBaseController {
     @Autowired
     private SysConfigMapper sysConfigMapper;
 
+    @ApiOperation("支付宝回调")
+    @PostMapping("/aliNotify")
+    public String aliNotify(HttpServletRequest request) {
+        Map<String, String> params = new HashMap<String, String>();
+        Map requestParams = request.getParameterMap();
+        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
+            String name = (String) iter.next();
+            String[] values = (String[]) requestParams.get(name);
+            String valueStr = "";
+            for (int i = 0; i < values.length; i++) {
+                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
+            }
+            //乱码解决,这段代码在出现乱码时使用。
+            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
+            params.put(name, valueStr);
+        }
+        return appPayService.aliNotify(params);
+    }
 
     @ApiOperation("微信支付回调")
     @PostMapping("/wxNotify")
@@ -53,24 +74,44 @@ public class AppPayController extends AppBaseController {
         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);
+    @ApiOperation("获取支付配置")
+    @GetMapping("/getPayConfig")
+    public R getPayConfig(@RequestParam String appId){
+        return appPayService.getPayConfig(appId);
+    }
 
+//    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;
+//    }
+
+    private WxPayService getWxPayService(){
+        SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.pay");
+        FsPayConfig fsPayConfig = new Gson().fromJson(sysConfig.getConfigValue(), 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());
+        payConfig.setAppId(fsPayConfig.getWxAppAppId());
+        payConfig.setMchId(fsPayConfig.getWxAppMchId());
+        payConfig.setMchKey(fsPayConfig.getWxAppMchKey());
+        payConfig.setKeyPath(fsPayConfig.getWxAppKeyPath());
+        payConfig.setNotifyUrl(fsPayConfig.getWxAppNotifyUrl());
         WxPayServiceImpl payService = new WxPayServiceImpl();
         payService.setConfig(payConfig);
         return payService;

+ 9 - 0
fs-user-app/src/main/java/com/fs/app/controller/CourseOrderController.java

@@ -110,4 +110,13 @@ public class CourseOrderController extends  AppBaseController{
         return R.ok().put("order",order);
     }
 
+    @Login
+    @ApiOperation("app支付")
+    @PostMapping("/appPayment")
+    public R appPayment(@Validated @RequestBody FsUserCourseOrderDoPayParam param,HttpServletRequest request)
+    {
+        param.setUserId(Long.parseLong(getUserId()));
+        return courseOrderService.appPayment(param,request);
+    }
+
 }

+ 90 - 16
fs-user-app/src/main/java/com/fs/app/controller/InquiryOrderController.java

@@ -2,6 +2,13 @@ package com.fs.app.controller;
 
 
 import cn.hutool.json.JSONUtil;
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.diagnosis.DiagnosisUtils;
+import com.alipay.api.domain.AlipayTradeAppPayModel;
+import com.alipay.api.request.AlipayTradeAppPayRequest;
+import com.alipay.api.response.AlipayTradeAppPayResponse;
 import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -54,6 +61,7 @@ import com.github.pagehelper.PageInfo;
 import com.google.gson.Gson;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.logging.log4j.core.LogEvent;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -67,6 +75,7 @@ import java.math.BigDecimal;
 import java.util.*;
 
 
+@Slf4j
 @Api("订单接口")
 @RestController
 @RequestMapping(value="/app/inquiryOrder")
@@ -120,6 +129,9 @@ public class InquiryOrderController extends  AppBaseController {
     private ISysConfigService configService;
     @Autowired
     private IFsUserWxService userWxService;
+
+    @Autowired
+    private IFsUserService fsUserService;
     @Login
     @ApiOperation("确认订单")
     @PostMapping("/confirm")
@@ -295,26 +307,31 @@ public class InquiryOrderController extends  AppBaseController {
 
         String openId = null;
         String appId = param.getAppId();
-        if (StringUtils.isNotBlank(appId)) {
-            //查询fs_user_wx的openId
-            Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
-                    .eq(FsUserWx::getFsUserId, param.getUserId())
-                    .eq(FsUserWx::getAppId, appId);
-            FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
-            if (fsUserWx != null) {
-                openId = fsUserWx.getOpenId();
-            }
+        if (request.getHeader("sourcetype") != null && "APP".equals(request.getHeader("sourcetype"))) {
+            FsUser fsUser = fsUserService.selectFsUserByUserId(param.getUserId().longValue());
+            openId = fsUser.getAppOpenId();
         } else {
-            appId = merchantAppConfig.getAppId();
-            openId = Objects.isNull(user) ? "" : user.getMaOpenId();
-            if (StringUtils.isBlank(openId)){
+            if (StringUtils.isNotBlank(appId)) {
+                //查询fs_user_wx的openId
                 Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
                         .eq(FsUserWx::getFsUserId, param.getUserId())
                         .eq(FsUserWx::getAppId, appId);
                 FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
-                if (Objects.nonNull(fsUserWx)){
+                if (fsUserWx != null) {
                     openId = fsUserWx.getOpenId();
                 }
+            } else {
+                appId = merchantAppConfig.getAppId();
+                openId = Objects.isNull(user) ? "" : user.getMaOpenId();
+                if (StringUtils.isBlank(openId)) {
+                    Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                            .eq(FsUserWx::getFsUserId, param.getUserId())
+                            .eq(FsUserWx::getAppId, appId);
+                    FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+                    if (Objects.nonNull(fsUserWx)) {
+                        openId = fsUserWx.getOpenId();
+                    }
+                }
             }
         }
         //String json=configService.selectConfigByKey("his.pay");
@@ -335,7 +352,7 @@ public class InquiryOrderController extends  AppBaseController {
 //            }
 //        }
 
-        if (StringUtils.isBlank(openId)){
+        if ("hf".equals(merchantAppConfig.getMerchantType()) && "wx".equals(param.getPayType()) && StringUtils.isBlank(openId)) {
             return R.error("用户OPENID不存在");
         }
 
@@ -357,12 +374,13 @@ public class InquiryOrderController extends  AppBaseController {
             storePayment.setBusinessCode(order.getOrderSn());
             storePayment.setPayMoney(order.getPayMoney());
             storePayment.setCreateTime(new Date());
-            storePayment.setPayTypeCode("weixin");
+            storePayment.setPayTypeCode(!"appPay".equals(merchantAppConfig.getMerchantType()) ? "weixin" : param.getPayType());
             storePayment.setBusinessType(1);
             storePayment.setRemark("问诊订单支付");
             storePayment.setOpenId(openId);
             storePayment.setUserId(user.getUserId());
             storePayment.setBusinessId(order.getOrderId().toString());
+            storePayment.setMerConfigId(merchantAppConfig.getId());
             if(storePaymentService.insertFsStorePayment(storePayment)>0){
                 if(merchantAppConfig.getMerchantType().equals("wx")){
                     //创建微信订单
@@ -441,7 +459,7 @@ public class InquiryOrderController extends  AppBaseController {
                     return R.ok().put("isPay",0).put("data",result).put("type","tz");
                 }else if(merchantAppConfig.getMerchantType().equals("hf")){
                     HuiFuCreateOrder o = new HuiFuCreateOrder();
-                    o.setTradeType("T_MINIAPP");
+                    o.setTradeType(StringUtils.isEmpty(param.getPayType()) || param.getPayType().equals("wx") ? "T_MINIAPP" : "A_NATIVE");
                     o.setOpenid(openId);
                     o.setAppId(appId);
                     o.setReqSeqId("inquiry-"+storePayment.getPayCode());
@@ -455,6 +473,62 @@ public class InquiryOrderController extends  AppBaseController {
                     mt.setAppId(appId);
                     storePaymentService.updateFsStorePayment(mt);
                     return R.ok().put("isPay",0).put("data",result).put("type","hf");
+                } else if (merchantAppConfig.getMerchantType().equals("appPay") && "wx".equals(param.getPayType())) {
+                    //创建微信订单
+                    WxPayConfig payConfig = new WxPayConfig();
+                    payConfig.setAppId(appId);
+                    payConfig.setMchId(fsPayConfig.getWxAppMchId());
+                    payConfig.setMchKey(fsPayConfig.getWxAppMchKey());
+                    payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                    payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                    payConfig.setKeyPath(null);
+                    payConfig.setNotifyUrl(fsPayConfig.getWxAppNotifyUrl());
+                    wxPayService.setConfig(payConfig);
+                    WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
+                    orderRequest.setBody("问诊订单支付");
+                    orderRequest.setOutTradeNo("inquiry-"+storePayment.getPayCode());
+                    orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));
+                    orderRequest.setTradeType("APP");
+                    orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(request));
+                    orderRequest.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
+                    //调用统一下单接口,获取"预支付交易会话标识"
+                    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());
+                    }
+                } else if (merchantAppConfig.getMerchantType().equals("appPay") && "ali".equals(param.getPayType())) {
+                    // 实例化客户端
+                    AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", fsPayConfig.getAliAppId(), fsPayConfig.getAliPrivateKey(), "json", "utf-8", fsPayConfig.getAliPublicKey(), "RSA2");
+
+                    // 构造请求参数以调用接口
+                    AlipayTradeAppPayRequest aliRequest = new AlipayTradeAppPayRequest();
+                    AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
+                    // 商户订单号
+                    model.setOutTradeNo("inquiry-" + storePayment.getPayCode());
+                    // 订单总金额
+                    model.setTotalAmount(storePayment.getPayMoney().toString());
+                    // 订单标题r
+                    model.setSubject("问诊订单支付");
+
+                    aliRequest.setBizModel(model);
+                    aliRequest.setNotifyUrl(fsPayConfig.getAliNotifyUrl());
+
+                    try {
+                        AlipayTradeAppPayResponse result = alipayClient.sdkExecute(aliRequest);
+                        if (!result.isSuccess()) {
+                            String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(result);
+                            log.error("支付宝支付调用失败 诊断链接:{}", diagnosisUrl);
+                            throw new CustomException(result.getSubMsg());
+                        }
+
+                        return R.ok().put("isPay", 0).put("data", result).put("type", "aliPay");
+                    } catch (Exception e) {
+                        log.info("支付宝支付异常: {}", e);
+                        throw new CustomException("支付系统异常,请稍后重试");
+                    }
                 }
             }
             else{

+ 1 - 1
fs-user-app/src/main/java/com/fs/app/controller/PackageOrderController.java

@@ -78,7 +78,7 @@ public class PackageOrderController extends  AppBaseController {
     public R payment(HttpServletRequest request, @Validated @RequestBody FsPackageOrderDoPayParam param)
     {
         param.setUserId(Long.parseLong(getUserId()));
-        return packageOrderService.payment(param);
+        return packageOrderService.payment(param, request);
     }
 
     @Login

+ 9 - 0
fs-user-app/src/main/java/com/fs/app/controller/UserVipController.java

@@ -127,6 +127,15 @@ public class UserVipController extends  AppBaseController{
         return R.ok();
     }
 
+    @Login
+    @ApiOperation("app支付")
+    @PostMapping("/appPayment")
+    public R appPayment(@Validated @RequestBody FsUserVipOrderPayUParam param,HttpServletRequest request)
+    {
+        param.setUserId(Long.parseLong(getUserId()));
+        return fsUserVipOrderService.appPayment(param,request);
+    }
+
     public boolean isSameYearMonthDay(LocalDate date1, LocalDate date2) {
         return date1.isEqual(date2);
     }