Explorar o código

Merge remote-tracking branch 'origin/Payment-Configuration' into Payment-Configuration

xgb hai 1 semana
pai
achega
ac946c901b

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

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

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

@@ -13,6 +13,8 @@ import com.fs.company.domain.CompanyUser;
 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.vo.FsStoreOrderAmountScrmStatsVo;
 import com.fs.his.vo.FsStoreOrderExcelVO;
@@ -365,4 +367,6 @@ public interface IFsStoreOrderScrmService
     R orderRemark(FsStoreOrderScrm orderScrm);
 
     int updateStoreOrderItemJson(Long orderId,Integer backendEditProductType);
+
+    R payment(FsIntegralOrderDoPayParam param, PaymentMethodEnum paymentMethodEnum);
 }

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

@@ -5,6 +5,7 @@ import java.util.Map;
 
 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;
@@ -122,4 +123,6 @@ public interface IFsStorePaymentScrmService
      * 批量导入更新微信订单发货状态
      * **/
     R oneClickShipping();
+
+    R processPaymentScrm(PayOrderParam payOrderParam);
 }

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

@@ -62,13 +62,14 @@ 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.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.IFsStorePaymentService;
 import com.fs.his.service.IFsUserIntegralLogsService;
 import com.fs.his.service.IFsUserWatchService;
 import com.fs.his.utils.ConfigUtil;
@@ -79,6 +80,7 @@ import com.fs.his.vo.FsPrescribeVO;
 import com.fs.hisStore.config.FsErpConfig;
 import com.fs.hisStore.constants.ErpTypeEnum;
 import com.fs.hisStore.dto.*;
+import com.fs.hisStore.enums.ShipperCodeEnum;
 import com.fs.hisStore.mapper.*;
 import com.fs.hisStore.param.*;
 import com.fs.hisStore.vo.*;
@@ -180,6 +182,8 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     Logger logger = LoggerFactory.getLogger(getClass());
     @Autowired
     private CompanyMoneyLogsMapper moneyLogsMapper;
+    @Autowired
+    private IFsStorePaymentScrmService storePaymentService;
 
     @Autowired
     private CompanyUserUserMapper companyUserUserMapper;
@@ -1065,7 +1069,7 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             for (FsStoreCartQueryVO vo : carts) {
                 // 检查限购
                 checkAndRecordPurchaseLimit(userId, vo.getProductId(), vo.getCartNum());
-                
+
                 FsStoreCartDTO fsStoreCartDTO = new FsStoreCartDTO();
                 fsStoreCartDTO.setProductId(vo.getProductId());
                 fsStoreCartDTO.setPrice(vo.getPrice());
@@ -3179,25 +3183,25 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         if (product == null) {
             return;
         }
-        
+
         // 如果商品没有设置限购,直接返回
         if (product.getPurchaseLimit() == null || product.getPurchaseLimit() <= 0) {
             return;
         }
-        
+
         // 查询用户已购买的数量
         FsStoreProductPurchaseLimitScrm purchaseLimit = purchaseLimitService.selectByProductIdAndUserId(productId, userId);
         int purchasedNum = 0;
         if (purchaseLimit != null) {
             purchasedNum = purchaseLimit.getNum();
         }
-        
+
         // 检查是否超过限购数量
         if (purchasedNum + num > product.getPurchaseLimit()) {
             int productTotalNum = purchasedNum + num;
             throw new CustomException("该商品限购" + product.getPurchaseLimit() + "件,您已购买" + productTotalNum + "件,无法继续购买");
         }
-        
+
         // 记录限购数量(在订单创建成功后记录,这里先检查)
     }
 
@@ -3214,12 +3218,12 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             if (product == null) {
                 continue;
             }
-            
+
             // 如果商品没有设置限购,跳过
             if (product.getPurchaseLimit() == null || product.getPurchaseLimit() <= 0) {
                 continue;
             }
-            
+
             // 减少限购数量
             purchaseLimitService.decreasePurchaseLimit(vo.getProductId(), order.getUserId(), Math.toIntExact(vo.getNum()));
         }
@@ -5681,4 +5685,39 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
     public FsStoreOrderAmountScrmStatsVo selectFsStoreOrderAmountScrmStats(FsStoreOrderAmountScrmStatsQueryDto queryDto) {
         return fsStoreOrderMapper.selectFsStoreOrderAmountScrmStats(queryDto);
     }
+
+
+
+    /**
+     * 预支付
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public R payment(FsIntegralOrderDoPayParam param, PaymentMethodEnum paymentMethod) {
+        FsStoreOrderScrm order = fsStoreOrderMapper.selectFsStoreOrderById(param.getOrderId());
+        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);
+    }
+
+
+    /**
+     * 构建参数
+     */
+    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);
+        payOrderParam.setBusinessType(BusinessTypeEnum.INTEGRAL_ORDER);
+        return payOrderParam;
+    }
 }

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

@@ -42,8 +42,11 @@ import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
 import com.fs.course.mapper.FsCourseRedPacketLogMapper;
 import com.fs.course.service.IFsCourseRedPacketLogService;
 import com.fs.his.domain.*;
+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;
@@ -77,6 +80,7 @@ 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.hc.openapi.tool.fastjson.JSON;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
 import org.slf4j.Logger;
@@ -104,7 +108,8 @@ public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
     Logger logger = LoggerFactory.getLogger(getClass());
     @Autowired
     private WxPayService wxPayService;
-
+    @Autowired
+    private FsUserWxMapper userWxMapper;
     @Autowired
     private FsCoursePlaySourceConfigMapper fsCoursePlaySourceConfigMapper;
     @Autowired
@@ -1102,4 +1107,256 @@ public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
             return false;
         }
     }
+
+    /**
+     * 发起支付
+     * @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("用户不存在");
+        }
+
+        FsPayConfig payConfig=new FsPayConfig();
+        //支付宝可以不需要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 (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);
+            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 = createStorePaymentScrm(payConfig, user, payOrderParam);
+
+        // 根据配置类型创建第三方支付订单
+        return createThirdPartyPaymentScrm(payConfig, storePayment, user, payOrderParam);
+    }
+
+    /**
+     * 判断是否微信支付
+     * @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 "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";
+            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());
+        }
+    }
+
+    /**
+     * 构建微信支付配置
+     */
+    private WxPayConfig buildWxPayConfig(FsPayConfig fsPayConfig) {
+        WxPayConfig payConfig = new WxPayConfig();
+        payConfig.setAppId(fsPayConfig.getAppId());
+        payConfig.setMchId(fsPayConfig.getWxMchId());
+        payConfig.setMchKey(fsPayConfig.getWxMchKey());
+        payConfig.setSubAppId(StringUtils.trimToNull(null));
+        payConfig.setSubMchId(StringUtils.trimToNull(null));
+        payConfig.setKeyPath(null);
+        payConfig.setNotifyUrl(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();
+        storePayment.setStatus(0);
+        storePayment.setPayMode(payConfig.getType());
+        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;
+    }
+
 }

+ 1 - 1
fs-service/src/main/resources/mapper/company/CompanyFsUserMapper.xml

@@ -48,7 +48,7 @@
                 LEFT JOIN fs_user_company_user fsu ON u.user_id = fsu.user_id
                 LEFT JOIN company_fs_user cfs on u.user_id=cfs.fs_user_id
         <where>
-            (fsu.company_id =#{companyId} or fsu.company_id is null)
+            (u.company_id =#{companyId} or u.company_id is null)
             <if test="phone != null and phone != ''">
                 and u.phone = #{phone}
             </if>

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

@@ -2,13 +2,18 @@ package com.fs.app.controller.app;
 
 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.his.param.FsUserAddIntegralTemplateParam;
 import com.fs.his.service.IFsUserIntegralLogsService;
+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;
@@ -29,6 +34,9 @@ public class AppController extends AppBaseController {
     @Autowired
     private IFsUserIntegralLogsService userIntegralLogsService;
 
+    @Autowired
+    private IFsStoreOrderScrmService fsStoreOrderScrmService;
+
     /**
      * @Description: APP 获取积分  28-下载
      * @Param:
@@ -44,4 +52,13 @@ public class AppController extends AppBaseController {
         return userIntegralLogsService.addIntegralTemplate(param);
     }
 
+
+    @Login
+    @RepeatSubmit
+    @ApiOperation("支付宝支付")
+    @PostMapping("/aliPayment")
+    public R aliPayment(@Validated @RequestBody FsIntegralOrderDoPayParam param) {
+        param.setUserId(Long.parseLong(getUserId()));
+        return fsStoreOrderScrmService.payment(param, PaymentMethodEnum.ALIPAY);
+    }
 }