package com.fs.hisStore.service.impl;


import java.math.BigDecimal;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.shop.request.shipping.*;
import cn.binarywang.wx.miniapp.bean.shop.request.shipping.*;
import cn.binarywang.wx.miniapp.bean.shop.response.WxMaOrderShippingInfoBaseResponse;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fs.common.annotation.DataScope;
import com.fs.common.config.FSSysConfig;
import com.fs.common.core.domain.R;
import com.fs.common.core.page.TableDataInfo;
import com.fs.common.core.redis.RedisCache;
import com.fs.common.exception.CustomException;
import com.fs.common.exception.CustomException;
import com.fs.common.exception.ServiceException;
import com.fs.common.utils.CloudHostUtils;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.ServletUtils;
import com.fs.common.utils.StringUtils;
import com.fs.common.utils.ip.IpUtils;
import com.fs.company.domain.Company;
import com.fs.company.domain.CompanyUser;
import com.fs.company.domain.RechargeRecord;
import com.fs.company.mapper.CompanyConfigMapper;
import com.fs.company.service.ICompanyService;
import com.fs.company.service.ICompanyUserService;
import com.fs.core.config.WxMaConfiguration;
import com.fs.core.utils.OrderCodeUtils;
import com.fs.course.config.RedPacketConfig;
import com.fs.course.domain.FsCoursePlaySourceConfig;
import com.fs.course.domain.FsCourseRedPacketLog;
import com.fs.course.mapper.FsCoursePlaySourceConfigMapper;
import com.fs.course.mapper.FsCourseRedPacketLogMapper;
import com.fs.course.service.IFsCourseRedPacketLogService;
import com.fs.his.config.AppConfig;
import com.fs.his.domain.*;
import com.fs.his.domain.FsPayConfig;
import com.fs.his.domain.FsUser;
import com.fs.his.domain.FsUserWx;
import com.fs.his.domain.MerchantAppConfig;
import com.fs.his.dto.PayConfigDTO;
import com.fs.his.enums.PaymentMethodEnum;
import com.fs.his.mapper.FsUserWxMapper;
import com.fs.his.mapper.MerchantAppConfigMapper;
import com.fs.his.param.PayOrderParam;
import com.fs.his.service.IFsUserService;
import com.fs.his.service.IFsUserWxService;
import com.fs.his.utils.ConfigUtil;
import com.fs.hisStore.config.StoreConfig;
import com.fs.hisStore.config.StoreConfig;
import com.fs.hisStore.domain.FsStoreOrderScrm;
import com.fs.hisStore.domain.FsStorePaymentScrm;
import com.fs.hisStore.domain.FsUserScrm;
import com.fs.hisStore.enums.OrderInfoEnum;
import com.fs.hisStore.enums.StatTypeEnum;
import com.fs.his.utils.HttpUtil;
import com.fs.hisStore.config.StoreConfig;
import com.fs.hisStore.enums.SysConfigEnum;
import com.fs.hisStore.mapper.FsStoreOrderScrmMapper;
import com.fs.hisStore.mapper.FsStorePaymentScrmMapper;
import com.fs.hisStore.param.*;
import com.fs.hisStore.service.IFsStorePaymentScrmService;
import com.fs.hisStore.vo.*;
import com.fs.huifuPay.domain.HuiFuCreateOrder;
import com.fs.huifuPay.domain.HuifuCreateOrderResult;
import com.fs.huifuPay.sdk.opps.core.utils.HuiFuUtils;
import com.fs.huifuPay.service.HuiFuService;
import com.fs.live.domain.LiveOrder;
import com.fs.live.domain.LiveOrderPayment;
import com.fs.live.mapper.LiveOrderMapper;
import com.fs.live.mapper.LiveOrderPaymentMapper;
import com.fs.pay.pay.dto.WxJspayDTO;
import com.fs.pay.service.IPayService;
import com.fs.system.oss.CloudStorageService;
import com.fs.system.oss.OSSFactory;
import com.fs.system.service.ISysConfigService;
import com.fs.utils.TwelveDigitSnowflake;
import com.fs.hisStore.domain.FsUserScrm;
import com.fs.hisStore.service.IFsUserScrmService;
import com.fs.pay.service.IPayService;
import com.fs.utils.TwelveDigitSnowflake;
import com.fs.wx.miniapp.config.WxMaProperties;
import com.fs.wx.order.utils.WxShippingErrorHandler;
import com.fs.ybPay.domain.CreateWxOrderResult;
import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayTransferBatchesNotifyV3Result;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.transfer.*;
import com.github.binarywang.wxpay.config.WxPayConfig;
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.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.hc.openapi.tool.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 支付明细Service业务层处理
 *
 * @author fs
 * @date 2022-06-20
 */
@Service
@Slf4j
public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
{
    Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private WxPayService wxPayService;
    @Autowired
    private FsUserWxMapper userWxMapper;
    @Autowired
    private LiveOrderPaymentMapper liveOrderPaymentMapper;
//    @Autowired
//    private RechargeRecordMapper rechargeRecordMapper;

    @Autowired
    private FsCoursePlaySourceConfigMapper fsCoursePlaySourceConfigMapper;
    @Autowired
    private MerchantAppConfigMapper merchantAppConfigMapper;
    @Autowired
    private FsStorePaymentScrmMapper fsStorePaymentMapper;
    @Autowired
    private IFsUserScrmService userService;

    @Autowired
    private ICompanyUserService companyUserService;
    @Autowired
    private ICompanyService companyService;
    @Autowired
    IPayService ybPayService;
    @Autowired
    private ConfigUtil configUtil;
    @Autowired
    private ISysConfigService configService;

    @Autowired
    private IFsCourseRedPacketLogService redPacketLogService;

    @Autowired
    private CompanyConfigMapper companyConfigMapper;

    @Autowired
    private HuiFuService huiFuService;

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private LiveOrderMapper liveOrderMapper;
    @Autowired
    private FsStoreOrderScrmMapper storeOrderScrmMapper;

    /**
     * 查询支付明细
     *
     * @param paymentId 支付明细ID
     * @return 支付明细
     */
    @Override
    public FsStorePaymentScrm selectFsStorePaymentById(Long paymentId)
    {
        return fsStorePaymentMapper.selectFsStorePaymentById(paymentId);
    }

    /**
     * 查询支付明细列表
     *
     * @param fsStorePayment 支付明细
     * @return 支付明细
     */
    @Override
    public List<FsStorePaymentScrm> selectFsStorePaymentList(FsStorePaymentScrm fsStorePayment)
    {
        return fsStorePaymentMapper.selectFsStorePaymentList(fsStorePayment);
    }

    /**
     * 新增支付明细
     *
     * @param fsStorePayment 支付明细
     * @return 结果
     */
    @Override
    public int insertFsStorePayment(FsStorePaymentScrm fsStorePayment)
    {
        fsStorePayment.setCreateTime(DateUtils.getNowDate());
        return fsStorePaymentMapper.insertFsStorePayment(fsStorePayment);
    }

    /**
     * 修改支付明细
     *
     * @param fsStorePayment 支付明细
     * @return 结果
     */
    @Override
    public int updateFsStorePayment(FsStorePaymentScrm fsStorePayment)
    {
        return fsStorePaymentMapper.updateFsStorePayment(fsStorePayment);
    }

    /**
     * 批量删除支付明细
     *
     * @param paymentIds 需要删除的支付明细ID
     * @return 结果
     */
    @Override
    public int deleteFsStorePaymentByIds(Long[] paymentIds)
    {
        return fsStorePaymentMapper.deleteFsStorePaymentByIds(paymentIds);
    }

    /**
     * 删除支付明细信息
     *
     * @param paymentId 支付明细ID
     * @return 结果
     */
    @Override
    public int deleteFsStorePaymentById(Long paymentId)
    {
        return fsStorePaymentMapper.deleteFsStorePaymentById(paymentId);
    }

    @Override
    @Transactional
    public R payment(FsStorePaymentPayParam payment) {
        if(payment.getPayMoney().compareTo(new BigDecimal(0.0))<1){
            return R.error("支付金额必须大于0");
        }
        // //获取OPENID
        // final WxMaService wxService = WxMaConfiguration.getMaService(properties.getConfigs().get(0).getAppid());
        String orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();
        // WxMaJscode2SessionResult session = null;
        // try {
        //     session = wxService.getUserService().getSessionInfo(payment.getCode());
        // } catch (WxErrorException e) {
        //     e.printStackTrace();
        // }
        CompanyUser companyUser=companyUserService.selectCompanyUserById(payment.getCompanyUserId());
        FsUserScrm user=userService.selectFsUserById(payment.getUserId());
        // if(user==null){
        //     //写入
        //     user=new FsUser();
        //     user.setPhone("");
        //     user.setUsername("");
        //     user.setNickname("微信用户");
        //     user.setStatus(1);
        //     user.setOpenId(session.getOpenid());
        //     user.setLastIp(IpUtil.getRequestIp());
        //     user.setIsWeixinAuth(0);
        //     userService.insertFsUser(user);
        // }
        FsStorePaymentScrm storePayment=new FsStorePaymentScrm();
        storePayment.setCompanyId(payment.getCompanyId());
        storePayment.setCompanyUserId(payment.getCompanyUserId());
        storePayment.setStatus(0);
        storePayment.setPayCode(orderSn);
        storePayment.setPayMoney(payment.getPayMoney());
        storePayment.setCreateTime(new Date());
        storePayment.setPayTypeCode("weixin");
        storePayment.setBusinessType(1);
        storePayment.setRemark(payment.getRemark());
        storePayment.setOpenId(user.getMaOpenId());
        storePayment.setUserId(user.getUserId());
        if(companyUser==null){
            return R.error("销售帐号不存在");
        }
        storePayment.setDeptId(companyUser.getDeptId());
        fsStorePaymentMapper.insertFsStorePayment(storePayment);
        //易宝支付

        WxJspayDTO p = new WxJspayDTO();
        // 使用setter方法为对象赋值
        p.setPayMoney(storePayment.getPayMoney().toString());
        p.setLowOrderId("payment-"+storePayment.getPayCode());
        p.setBody("超重/肥胖/气血/代谢/美乳/慢病医学管理方案服务");
        p.setIsMinipg("1");
        //p.setReturnUrl(PayConfig.notifyUrl);
        p.setReturnUrl(configUtil.generateConfigByKey(SysConfigEnum.RED_PACKET_CONFIG.getKey()).getString("notifyUrlScrm"));
        p.setOpenId(user.getMaOpenId());
        p.setAttach("");
        p.setStoreid("0");
        CreateWxOrderResult wxOrder = ybPayService.createWxOrder(p);
        if(wxOrder.getStatus().equals("100")){
            FsStorePaymentScrm ment=new FsStorePaymentScrm();
            ment.setPaymentId(storePayment.getPaymentId());
            ment.setTradeNo(wxOrder.getUpOrderId());
            fsStorePaymentMapper.updateFsStorePayment(ment);
            return R.ok().put("result",wxOrder.getPay_info());
        }
        else{
            return R.error(wxOrder.getMessage());
        }
        //小雨点支付
//        CreatePayDTO createPayDTO=new CreatePayDTO();
//        createPayDTO.setMerchOrderNo("payment-"+storePayment.getPayCode());
//        List<TradeOrder> orders=new ArrayList<>();
//        TradeOrder order=new TradeOrder();
//        order.setAmount(storePayment.getPayMoney().toString());
//        order.setSubMerchOrderNo("payment-"+storePayment.getPayCode());
//        order.setTradeName("超重/肥胖/气血/代谢/美乳/慢病医学管理方案服务");
//        order.setPayeeOutUserId(sysConfig.getPayPartnerId());
//        orders.add(order);
//        createPayDTO.setOrders(orders);
//        payService.createOrder(createPayDTO);
//        PayDTO payDTO=new PayDTO();
//        payDTO.setOrigMerchOrderNo("payment-"+storePayment.getPayCode());
//        payDTO.setOpenID(user.getMaOpenId());
//        payDTO.setAppID(wxPayProperties.getAppId());
//        payDTO.setPayerOutUserId(user.getUserId().toString());
//        payDTO.setPayerOutUserName(user.getNickname());
//        payDTO.setUserIp(IPUtils.getIpAddr(ServletUtils.getRequest()));
//        return R.ok().put("result",payService.payOrder(payDTO));


    }

    @Override
    public FsStorePaymentScrm selectFsStorePaymentByCode(String payCode) {
        return fsStorePaymentMapper.selectFsStorePaymentByCode(payCode);
    }

    @Override
    public List<FsStorePaymentVO> selectFsStorePaymentListQuery(FsStorePaymentParam fsStorePayment) {
        return fsStorePaymentMapper.selectFsStorePaymentListQuery(fsStorePayment);
    }

    @Override
    public Map<String, BigDecimal> calculateTotalAmount(FsStorePaymentParam fsStorePayment) {
        FsStorePaymentAmountVO fsStorePaymentAmountVO = fsStorePaymentMapper.calculateTotalAmount(fsStorePayment);
        BigDecimal totalPaymentAmount = BigDecimal.ZERO;
        BigDecimal totalRefundAmount = BigDecimal.ZERO;
        if (StringUtils.isNotNull(fsStorePaymentAmountVO)) {
            totalPaymentAmount = fsStorePaymentAmountVO.getTotalPaymentAmount() == null
                    ? BigDecimal.ZERO : fsStorePaymentAmountVO.getTotalPaymentAmount();
            totalRefundAmount = fsStorePaymentAmountVO.getTotalRefundAmount() == null
                    ? BigDecimal.ZERO : fsStorePaymentAmountVO.getTotalRefundAmount();
        }
        Map<String, BigDecimal> resultMap = new HashMap<>();
        resultMap.put("totalPaymentAmount", totalPaymentAmount);
        resultMap.put("totalRefundAmount", totalRefundAmount);
        return resultMap;
    }

    @Override
    public List<FsStorePaymentVO> exportFsStorePaymentList(FsStorePaymentParam fsStorePayment) {
        return fsStorePaymentMapper.exportFsStorePaymentList(fsStorePayment);
    }

    @Override
    @DataScope(deptAlias = "cu",userAlias = "cu")
    public List<FsStorePaymentVO> selectFsStorePaymentListQueryVO(FsStorePaymentParam fsStorePayment) {
        return fsStorePaymentMapper.selectFsStorePaymentListQueryVO(fsStorePayment);
    }

    @Override
    public List<FsStorePaymentVO> selectFsMyStorePaymentListQueryVO(FsStorePaymentParam fsStorePayment) {
        return fsStorePaymentMapper.selectFsMyStorePaymentListQueryVO(fsStorePayment);
    }

    @Override
    public List<FsStorePaymentScrm> selectFsStorePaymentByOrderId(Long orderId) {
        return fsStorePaymentMapper.selectFsStorePaymentByOrderId(orderId);
    }

    @Override
    public Long selectFsStorePaymentCount(int type,Long companyId,Long companyUserId) {
        return fsStorePaymentMapper.selectFsStorePaymentCount(type,companyId,companyUserId);
    }

    @Override
    @Transactional
    public String payConfirm(String payCode,String tradeNo,String bankTransactionId,String bankSerialNo) {
        //更新订单状态
        FsStorePaymentScrm storePayment=fsStorePaymentMapper.selectFsStorePaymentByCode(payCode);
        if(!storePayment.getStatus().equals(0)){
            return "";
        }
        storePayment.setStatus(1);
        storePayment.setPayTime(new Date());
        storePayment.setTradeNo(tradeNo);
        storePayment.setBankSerialNo(bankSerialNo);
        storePayment.setBankTransactionId(bankTransactionId);
        fsStorePaymentMapper.updateFsStorePayment(storePayment);
        //增加佣金
//        if(storePayment.getCompanyId()!=null&&storePayment.getCompanyId()>0){
//            companyService.addCompanyPaymentMoney(storePayment);
//        }
        return "SUCCESS";
    }

    @Override
    @Transactional
    public String refund(String orderCode) {
        FsStorePaymentScrm payment=fsStorePaymentMapper.selectFsStorePaymentByCode(orderCode);
        payment.setStatus(-1);
        payment.setRefundTime(new Date());
        fsStorePaymentMapper.updateFsStorePayment(payment);
        //收款 减去所有
        if(payment.getCompanyId()!=null&&payment.getCompanyId()>0){
            companyService.subCompanyPaymentMoney(payment);
        }
        return "success";
    }

    @Override
    public List<JSONObject> selectFsStorePaymentCounts(Map<String, Object> toMap) {
        return fsStorePaymentMapper.selectFsStorePaymentCounts(toMap);
    }

    @Override
    public List<FsStorePaymentStatisticsVO> selectFsStorePaymentStatisticsList(FsStoreStatisticsParam param) {
        return fsStorePaymentMapper.selectFsStorePaymentStatisticsList(param);
    }

    @Override
    public List<FsStorePaymentScrm> selectFsStorePaymentByOrder(Long orderId) {
        return fsStorePaymentMapper.selectFsStorePaymentByOrder(orderId);
    }

    @Override
    public FsStorePaymentScrm selectFsStorePaymentByTradeNo(String tradeNo) {
        return fsStorePaymentMapper.selectFsStorePaymentByTradeNo(tradeNo);
    }

    @Override
    public List<FsStorePaymentScrm> selectFsStorePaymentByAll() {
        return fsStorePaymentMapper.selectFsStorePaymentByAll();
    }

    @Override
    @Transactional
    public R sendRedPacket(WxSendRedPacketParam param) {
        String json;
        RedPacketConfig config = new RedPacketConfig();
        // 根据红包模式获取配置
        switch (param.getRedPacketMode()){
            case 1:
                json = configService.selectConfigByKey("redPacket.config");
                config = JSONUtil.toBean(json, RedPacketConfig.class);
                break;
            case 2:
                json = configService.selectConfigByKey("redPacket.config");
                config = JSONUtil.toBean(json, RedPacketConfig.class);
                break;
        }
        //H5的用公众号的appid发，小程序的用小程序的appid来发
        if (param.getSource()==2){
            config.setAppId(param.getAppId());
        }
        //组合返回参数
        R result = new R();
        // 根据 isNew 判断使用哪种发红包方式
        if (config.getIsNew() != null && config.getIsNew() == 1) {
            result = sendRedPacketV3Internal(param, config);
        } else {
            result= sendRedPacketLegacyInternal(param, config);
        }
        result.put("isNew",config.getIsNew());
//        result.put("mchId",config.getMchId());

        result.put("mchId",config.getMchId());
        System.out.println("发红包返回"+result);
        return result;
    }

    // 内部方法：处理新版本的发红包逻辑
    private R sendRedPacketV3Internal(WxSendRedPacketParam param, RedPacketConfig config) {
        WxPayConfig payConfig = new WxPayConfig();
        BeanUtils.copyProperties(config, payConfig);
        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);
        TransferService transferService = wxPayService.getTransferService();

        TransferBillsRequest request = new TransferBillsRequest();
        request.setAppid(config.getAppId());
        System.out.println("appid:"+config.getAppId());
        request.setOpenid(param.getOpenId());

//        String code = String.valueOf(IdUtil.getSnowflake(0, 0).nextId());
        String code =  OrderCodeUtils.getOrderSn();
        if(StringUtils.isEmpty(code)){
            return R.error("红包单号生成失败，请重试");
        }
        request.setOutBillNo("fsCourse" + code);

        Integer amount = WxPayUnifiedOrderRequest.yuanToFen(param.getAmount() != null ? param.getAmount().toString() : "0.1");
        request.setTransferAmount(amount);
        request.setTransferRemark("活动奖励");
        request.setUserRecvPerception("活动奖励");
        request.setNotifyUrl(config.getNotifyUrlScrm());
        request.setTransferSceneId("1000");

        // 设置场景信息
        List<TransferBillsRequest.TransferSceneReportInfo> transferSceneReportInfos = new ArrayList<>();
        TransferBillsRequest.TransferSceneReportInfo info1 = new TransferBillsRequest.TransferSceneReportInfo();
        info1.setInfoType("活动名称");
        info1.setInfoContent("新会员有礼");
        transferSceneReportInfos.add(info1);

        TransferBillsRequest.TransferSceneReportInfo info2 = new TransferBillsRequest.TransferSceneReportInfo();
        info2.setInfoType("奖励说明");
        info2.setInfoContent("注册会员抽奖一等奖");
        transferSceneReportInfos.add(info2);
        request.setTransferSceneReportInfos(transferSceneReportInfos);

        try {
            TransferBillsResult transferBillsResult = transferService.transferBills(request);
            logger.info("商家转账支付完成:[msg:{}]", transferBillsResult);
            return R.ok("发送红包成功").put("data", transferBillsResult);
        } catch (WxPayException e) {
            e.printStackTrace();
            logger.info("商家转账支付失败：[msg:{}]", e.getMessage());
            return R.error("发送失败");
        }
    }

    // 内部方法：处理旧版本的发红包逻辑
    private R sendRedPacketLegacyInternal(WxSendRedPacketParam param, RedPacketConfig config) {
        WxPayConfig payConfig = new WxPayConfig();
        BeanUtils.copyProperties(config, payConfig);
        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);
        TransferService transferService = wxPayService.getTransferService();

        TransferBatchesRequest request = new TransferBatchesRequest();
        request.setAppid(config.getAppId());
//        String code = IdUtil.getSnowflake(0, 0).nextIdStr();
        String code =  OrderCodeUtils.getOrderSn();
        if(StringUtils.isEmpty(code)){
            return R.error("红包单号生成失败，请重试");
        }
        request.setOutBatchNo("fsCourse" + code);
        request.setBatchRemark("课堂答题奖励");
        request.setBatchName("课堂答题奖励");
        Integer amount = WxPayUnifiedOrderRequest.yuanToFen(param.getAmount().toString());
        request.setTotalAmount(amount);
        request.setTotalNum(1);
        request.setNotifyUrl(config.getNotifyUrlScrm());

        ArrayList<TransferBatchesRequest.TransferDetail> transferDetailList = new ArrayList<>();
        TransferBatchesRequest.TransferDetail transferDetail = new TransferBatchesRequest.TransferDetail();
//        transferDetail.setOpenid(param.getOpenId());

        String openId;
        //临时方法，有code的时候获取一下客户的openId
        if (StringUtils.isNotEmpty(param.getCode())){
            WxMaService wxService = WxMaConfiguration.getMaService(param.getAppId());
            try {
                WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
                openId = session.getOpenid();
                logger.info("修改或新增openId:{},userId:{},appId:{}",session.getOpenid(),param.getUser().getUserId(),param.getAppId());
                handleFsUserWx(param.getUser(),param.getAppId(),session);
            } catch (WxErrorException e){
                return R.error("openId获取失败," + e.getMessage());
            }
        }else {
            openId = param.getOpenId();
        }

        transferDetail.setOpenid(openId);
        String code1 = IdUtil.getSnowflake(0, 0).nextIdStr();
        transferDetail.setOutDetailNo("fsCourse" + code1);
        transferDetail.setTransferAmount(amount);
        transferDetail.setTransferRemark("恭喜同学，认真听课，奖励你一朵小红花!");
        transferDetailList.add(transferDetail);
        request.setTransferDetailList(transferDetailList);

        try {
            TransferBatchesResult transferBatchesResult = transferService.transferBatches(request);
            return R.ok("发送红包成功").put("orderCode", transferBatchesResult.getOutBatchNo()).put("batchId", transferBatchesResult.getBatchId());
        } catch (WxPayException e) {
            e.printStackTrace();
            return R.error("发送失败");
        }
    }

    @Autowired
    private IFsUserWxService fsUserWxService;

    private void handleFsUserWx(FsUserScrm user, String appId, WxMaJscode2SessionResult session) {
        // 尝试更新
//        FsUserWx userWx = fsUserWxService.selectByAppIdAndUserId(appId,user.getUserId(),1);
//        if (userWx!=null && !userWx.getOpenId().equals(session.getOpenid())){
//            userWx.setOpenId(session.getOpenid());
//            fsUserWxService.updateById(userWx);
//        }else {
//            userWx = new FsUserWx();
//            userWx.setType(1);
//            userWx.setFsUserId(user.getUserId());
//            userWx.setAppId(appId);
//            userWx.setOpenId(session.getOpenid());
//            userWx.setUnionId(session.getUnionid() == null ? "" : session.getUnionid());
//            userWx.setCreateTime(new Date());
//            userWx.setUpdateTime(new Date());
//            fsUserWxService.save(userWx);
//        }
        boolean updated = fsUserWxService.lambdaUpdate()
                .eq(FsUserWx::getFsUserId, user.getUserId())
                .eq(FsUserWx::getAppId,appId )
                .eq(FsUserWx::getOpenId, session.getOpenid())
                .set(FsUserWx::getUnionId, session.getUnionid() == null ? "" : session.getUnionid())
                .set(FsUserWx::getUpdateTime, new Date())
                .update();

        // 如果更新失败（记录不存在），则插入
        if (!updated) {
            FsUserWx fsUserWx = new FsUserWx();
            fsUserWx.setType(1);
            fsUserWx.setFsUserId(user.getUserId());
            fsUserWx.setAppId(appId);
            fsUserWx.setOpenId(session.getOpenid());
            fsUserWx.setUnionId(session.getUnionid() == null ? "" : session.getUnionid());
            fsUserWx.setCreateTime(new Date());
            fsUserWx.setUpdateTime(new Date());
            fsUserWxService.save(fsUserWx);
        }
    }


    @Override
    public R sendRedPacketTest(WxSendRedPacketParam param) {

        RedPacketConfig config = new RedPacketConfig();
        // 根据红包模式获取配置

        String  json = configService.selectConfigByKey("redPacket.config");
        config = JSONUtil.toBean(json, RedPacketConfig.class);

        param.setSource(2);
        param.setAmount(param.getAmount());


        WxPayConfig payConfig = new WxPayConfig();
        BeanUtils.copyProperties(config, payConfig);
        payConfig.setAppId(param.getAppId());
        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);
        TransferService transferService = wxPayService.getTransferService();

        TransferBatchesRequest request = new TransferBatchesRequest();
        request.setAppid(param.getAppId());
        String code = IdUtil.getSnowflake(0, 0).nextIdStr();
        request.setOutBatchNo("fsCourse" + code);
        request.setBatchRemark("课堂答题奖励");
        request.setBatchName("课堂答题奖励");
        Integer amount = WxPayUnifiedOrderRequest.yuanToFen(param.getAmount().toString());
        request.setTotalAmount(amount);
        request.setTotalNum(1);
        request.setNotifyUrl(config.getNotifyUrlScrm());

        ArrayList<TransferBatchesRequest.TransferDetail> transferDetailList = new ArrayList<>();
        TransferBatchesRequest.TransferDetail transferDetail = new TransferBatchesRequest.TransferDetail();
        transferDetail.setOpenid(param.getOpenId());

//        String openId;
//        //临时方法，有code的时候获取一下客户的openId
//        if (StringUtils.isNotEmpty(param.getCode())){
//            WxMaService wxService = WxMaConfiguration.getMaService(param.getAppId());
//            try {
//                WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
//                openId = session.getOpenid();
//            } catch (WxErrorException e){
//                return R.error("openId获取失败," + e.getMessage());
//            }
//        }else {
//            openId = param.getOpenId();
//        }
//        transferDetail.setOpenid(openId);
        String code1 = IdUtil.getSnowflake(0, 0).nextIdStr();
        transferDetail.setOutDetailNo("fsCourse" + code1);
        transferDetail.setTransferAmount(amount);
        transferDetail.setTransferRemark("恭喜同学，认真听课，奖励你一朵小红花!");
        transferDetailList.add(transferDetail);
        request.setTransferDetailList(transferDetailList);

        try {
            TransferBatchesResult transferBatchesResult = transferService.transferBatches(request);
            return R.ok("发送红包成功").put("orderCode", transferBatchesResult.getOutBatchNo()).put("batchId", transferBatchesResult.getBatchId());
        } catch (WxPayException e) {
            e.printStackTrace();
            return R.error("发送失败");
        }
    }

    @Override
    public R sendRedPacketV3(WxSendRedPacketParam param) {
        return null;
    }

    @Override
    public String transferNotify(String notifyData, HttpServletRequest request) {
        logger.info("zyp \n【收到转账回调】：{}",notifyData);
        try {
            String json = configService.selectConfigByKey("redPacket.config");
            RedPacketConfig config = JSONUtil.toBean(json, RedPacketConfig.class);
            //创建微信订单
            WxPayConfig payConfig = new WxPayConfig();
            BeanUtils.copyProperties(config,payConfig);
            System.out.println(payConfig);
            logger.info("到零钱回调：{}",payConfig);
            WxPayService wxPayService = new WxPayServiceImpl();
            wxPayService.setConfig(payConfig);
            SignatureHeader signatureHeader = new SignatureHeader();
            signatureHeader.setTimeStamp(request.getHeader("Wechatpay-Timestamp"));
            signatureHeader.setNonce(request.getHeader("Wechatpay-Nonce"));
            signatureHeader.setSerial(request.getHeader("Wechatpay-Serial"));
            signatureHeader.setSignature(request.getHeader("Wechatpay-Signature"));
            WxPayTransferBatchesNotifyV3Result result = wxPayService.parseTransferBatchesNotifyV3Result(notifyData,signatureHeader);
            logger.info("到零钱回调：{}",result.getResult());
            if (result.getResult().getBatchStatus().equals("FINISHED") && result.getResult().getFailNum()==0) {
                R r = redPacketLogService.syncRedPacket(result.getResult().getOutBatchNo(),result.getResult().getBatchId());
                logger.info("result:{}",r);
                if (r.get("code").equals(200)){
                    return WxPayNotifyResponse.success("处理成功");
                }else {
                    return WxPayNotifyResponse.fail("");
                }
            }else {
                return WxPayNotifyResponse.fail("");
            }
        } catch (WxPayException e) {
            logger.error("zyp \n【转账回调异常】：{}", e.getReturnMsg());
            return WxPayNotifyResponse.fail(e.getMessage());
        }
    }

    @Override
    public String v3TransferNotify(String notifyData, HttpServletRequest request) {
        logger.info("zyp \n【收到转账回调】：{}",notifyData);
        try {
            String json = configService.selectConfigByKey("redPacket.config");
            RedPacketConfig config = JSONUtil.toBean(json, RedPacketConfig.class);
            //创建微信订单
            WxPayConfig payConfig = new WxPayConfig();
            BeanUtils.copyProperties(config,payConfig);
            WxPayService wxPayService = new WxPayServiceImpl();
            wxPayService.setConfig(payConfig);
            SignatureHeader signatureHeader = new SignatureHeader();
            signatureHeader.setTimeStamp(request.getHeader("Wechatpay-Timestamp"));
            signatureHeader.setNonce(request.getHeader("Wechatpay-Nonce"));
            signatureHeader.setSerial(request.getHeader("Wechatpay-Serial"));
            signatureHeader.setSignature(request.getHeader("Wechatpay-Signature"));
            TransferBillsNotifyResult result = wxPayService.parseTransferBillsNotifyV3Result(notifyData,signatureHeader);
            logger.info("到零钱回调：{}",result.getResult());
            if (result.getResult().getState().equals("SUCCESS")) {
                R r = redPacketLogService.syncRedPacket(result.getResult().getOutBillNo(),result.getResult().getTransferBillNo());
                logger.info("result:{}",r);
                if (r.get("code").equals(200)){
                    return WxPayNotifyResponse.success("处理成功");
                }else {
                    return WxPayNotifyResponse.fail("");
                }
            }else {
                return WxPayNotifyResponse.fail("");
            }
        } catch (WxPayException e) {
            logger.error("zyp \n【转账回调异常】：{}", e.getReturnMsg(),e);
            return WxPayNotifyResponse.fail(e.getMessage());
        }
    }

    @Autowired
    private FsCourseRedPacketLogMapper redPacketLogMapper;

    @Override
    public void bufaRedPacket() {
//        String json = configService.selectConfigByKey("redPacket.config");
//        RedPacketConfig config = JSONUtil.toBean(json, RedPacketConfig.class);
        List<FsCourseRedPacketLog> logs = redPacketLogMapper.selectFailAll();
        String appId = "wx414427b10866c04e";
        for (FsCourseRedPacketLog log : logs){
            FsUserScrm user = userService.selectFsUserById(log.getUserId());
            WxSendRedPacketParam param = new WxSendRedPacketParam();
            param.setAppId(appId);
            if (user==null || user.getMaOpenId()==null){
                continue;
            }
            param.setOpenId(user.getMaOpenId());
            param.setAmount(log.getAmount());
            R r = this.sendRedPacketTest(param);
            if (r.get("code").equals(200)){
                log.setOutBatchNo(r.get("orderCode").toString());
                log.setBatchId(r.get("batchId").toString());
                redPacketLogMapper.updateFsCourseRedPacketLog(log);
                logger.info("更新完成：{}",log.getLogId());
            }

        }

//        Thread.sleep(30000);
//        List<FsCourseRedPacketLog> logs2 = redPacketLogMapper.selectFail();
//        String appId = "wx414427b10866c04e";
//        for (FsCourseRedPacketLog log : logs){
//            FsUser user = userService.selectFsUserById(log.getUserId());
//            WxSendRedPacketParam param = new WxSendRedPacketParam();
//            param.setAppId(appId);
//            if (user==null || user.getMaOpenId()==null){
//                continue;
//            }
//            param.setOpenId(user.getMaOpenId());
//            param.setAmount(log.getAmount());
//            R r = this.sendRedPacketTest(param);
//            if (r.get("code").equals(200)){
//                log.setOutBatchNo(r.get("orderCode").toString());
//                log.setBatchId(r.get("batchId").toString());
//                redPacketLogMapper.updateFsCourseRedPacketLog(log);
//                logger.info("更新完成：{}",log.getLogId());
//            }
//
//        }
    }

    @Override
    public R sendRewardByTest(Long userId) {
        List<FsCourseRedPacketLog> logs = redPacketLogMapper.selectFail(userId);
        String appId = "wx414427b10866c04e";
        for (FsCourseRedPacketLog log : logs) {
            FsUserScrm user = userService.selectFsUserById(log.getUserId());
            WxSendRedPacketParam param = new WxSendRedPacketParam();
            param.setAppId(appId);
            if (user == null || user.getMaOpenId() == null) {
                continue;
            }
            param.setOpenId(user.getMaOpenId());
            param.setAmount(log.getAmount());
            R r = this.sendRedPacketTest(param);
            if (r.get("code").equals(200)) {
                log.setOutBatchNo(r.get("orderCode").toString());
                log.setBatchId(r.get("batchId").toString());
                redPacketLogMapper.updateFsCourseRedPacketLog(log);
                logger.info("更新完成：{}", log.getLogId());
            }
        }
        return R.ok();
    }


    @Override
    public R getWxaCodeByPayment(FsStorePaymentGetWxaCodeParam param)  {
        final WxMaService wxMaService = WxMaConfiguration.getMaService(param.getAppId());
        String scene;
        //判断销售id
        if (param.getCompanyUserId() == null){
            scene = "companyId="+ param.getCompanyId();
        }else {
            scene = "companyId="+ param.getCompanyId()+"&"+"companyUserId="+ param.getCompanyUserId();
        }
        byte[] file;
        try {
            if(CloudHostUtils.hasCloudHostName("鸿森堂")){
                file = wxMaService.getQrcodeService().createWxaCodeBytes(
                        "pages_user/user/pay?" + scene,
                        "release",
                        430,
                        true,
                        null,
                        true);
            } else {
                file = wxMaService.getQrcodeService().createWxaCodeBytes(
                        "pages_user/user/pay?companyId=" + param.getCompanyId(),
                        "release",
                        430,
                        true,
                        null,
                        true);
            }
            logger.info("生成的二维码参数：{}", "pages_user/user/pay?" + scene);


            // 上传图片到存储桶
            String suffix = ".png";
            CloudStorageService storage = OSSFactory.build();
            String url;
            try {
                url = storage.uploadSuffix(file, suffix);
            }  catch (Exception e) {
                // 记录错误日志
                logger.error("生成图片失败:{}",e.getMessage(),e);
                return R.error("生成图片失败");
            }
            if(CloudHostUtils.hasCloudHostName("鸿森堂")){
                redisCache.setCacheObject("company-wxa-code:" + param.getCompanyId() + ":" + param.getAppId() + ":" + param.getCompanyUserId(), url);
            } else {
                redisCache.setCacheObject("company-wxa-code:" + param.getCompanyId() + ":" + param.getAppId(), url);
            }
            // 返回成功信息
            return R.ok().put("url",url);

        } catch (WxErrorException e) {
            logger.error(e.getMessage(), e);
            return R.error("微信接口调用失败: " + e.getMessage());
        }
    }


    @Autowired
    private IFsUserService fsUserService;
    @Autowired
    private FsUserWxMapper fsUserWxMapper;

    @Override
    public R paymentByWxaCode(FsStorePaymentPayParam param) {
        FsUser user = fsUserService.selectFsUserById(param.getUserId());
        if (user==null){
            return R.error("用户不存在！");
        }
        Company company = companyService.selectCompanyById(param.getCompanyId());
        if (company==null || company.getStatus()==0){
            return R.error("服务商不存在，或已被停用！");
        }
        if(param.getPayMoney().compareTo(new BigDecimal(0.0))<1){
            return R.error("支付金额必须大于0");
        }
        if (param.getCompanyUserId()!=null){
            CompanyUser companyUser = companyUserService.selectCompanyUserById(param.getCompanyUserId());
            if(companyUser == null || companyUser.getStatus().equals("1")){
                return R.error("注册失败客服已停用，或不存在！");
            }
        }
        if (StringUtils.isBlank(param.getAppId())) {
            throw new IllegalArgumentException("appId不能为空");
        }
        FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectCoursePlaySourceConfigByAppId(param.getAppId());
        if (fsCoursePlaySourceConfig == null) {
            throw new CustomException("未找到appId对应的小程序配置: " + param.getAppId());
        }
        Long merchantConfigId = fsCoursePlaySourceConfig.getMerchantConfigId();
        if (merchantConfigId == null || merchantConfigId <= 0) {
            throw new CustomException("小程序没有配置商户信息");
        }
        MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
        FsPayConfig fsPayConfig = com.hc.openapi.tool.fastjson.JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
        //生成支付流水
        String orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();

        //获取用户openid
        String openId = null;
        String appId = param.getAppId();

        //查询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 {
            openId = user.getMaOpenId();
        }

        if (StringUtils.isEmpty(openId)){
            return R.error("openId参数错误！");
        }

        FsStorePaymentScrm storePayment=new FsStorePaymentScrm();
        storePayment.setCompanyId(param.getCompanyId());
        //判断销售是否存在
        if (param.getCompanyUserId()!=null){
            storePayment.setCompanyUserId(param.getCompanyUserId());
        }
        storePayment.setStatus(0);
        storePayment.setPayCode(orderSn);
        storePayment.setOriginalAmount(param.getPayMoney());

        //验证扫码立减金是否开启
        final String STORE_CONFIG_KEY = "store.config";
        String jsonConfig = configService.selectConfigByKey(STORE_CONFIG_KEY);
        StoreConfig storeConfig = JSONUtil.toBean(jsonConfig, StoreConfig.class);
        if (isValidDiscountConfig(storeConfig)) {
            //校验立减金是否大于当前支付金额
            if(storeConfig.getScanCodeDiscountAmount().compareTo(param.getPayMoney()) < 0){
                param.setPayMoney(param.getPayMoney().subtract(storeConfig.getScanCodeDiscountAmount()));
                storePayment.setReductionAmount(storeConfig.getScanCodeDiscountAmount());
            }
        }

        storePayment.setPayMoney(param.getPayMoney());
        storePayment.setCreateTime(new Date());
        storePayment.setPayTypeCode("weixin");
        storePayment.setBusinessType(1);//微信收款
        storePayment.setRemark(StringUtils.isNotBlank(param.getRemark()) ? param.getRemark() : "商城收款订单支付");
        storePayment.setOpenId(openId);
        storePayment.setUserId(user.getUserId());

        if (merchantAppConfig.getMerchantType().equals("wx")){
            storePayment.setPayMode("wx");
        }else if (merchantAppConfig.getMerchantType().equals("hf")) {
            storePayment.setPayMode("hf");
        }
        storePayment.setAppId(param.getAppId());
        storePayment.setMerConfigId(merchantAppConfig.getId());
        if (fsStorePaymentMapper.insertFsStorePayment(storePayment) > 0) {
            if (merchantAppConfig.getMerchantType().equals("wx")) {
                //创建微信订单
                WxPayConfig payConfig = new WxPayConfig();
                payConfig.setAppId(appId);
                payConfig.setMchId(fsPayConfig.getWxMchId());
                payConfig.setMchKey(fsPayConfig.getWxMchKey());
                payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
                payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
                payConfig.setKeyPath(null);
                payConfig.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
                wxPayService.setConfig(payConfig);
                WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
                orderRequest.setOpenid(openId);//公众号支付提供用户openid
                orderRequest.setBody("收款支付");
                orderRequest.setOutTradeNo("payment-" + storePayment.getPayCode());
                orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));//测试
                //orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(money));//测试
                orderRequest.setTradeType("JSAPI");
                orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
                //调用统一下单接口，获取"预支付交易会话标识"
                try {
                    WxPayMpOrderResult orderResult = wxPayService.createOrder(orderRequest);
                    return R.ok().put("result", orderResult).put("type", "wx").put("isPay", 0);
                } catch (WxPayException e) {
                    e.printStackTrace();
                    throw new CustomException("支付失败" + e.getMessage());
                }
            } else if (merchantAppConfig.getMerchantType().equals("hf")) {

                //汇付支付
                HuiFuCreateOrder o = new HuiFuCreateOrder();
                o.setTradeType("T_MINIAPP");
                o.setOpenid(openId);
                o.setReqSeqId("payment-"+storePayment.getPayCode());
                o.setTransAmt(storePayment.getPayMoney().toString());
                o.setGoodsDesc("商城订单支付");
                o.setAppId(appId);
                //公司分账
                try {
                    HuiFuUtils.doDiv(o,company.getCompanyId(), storePayment.getMerConfigId());
                    //存储分账明细
                    HuiFuUtils.saveDivItem(o, storePayment.getPayCode(), storePayment.getPayCode());
                } catch (Exception e) {
                    logger.error("-------------微信收款分账出错：{}", e.getMessage());
                }
                HuifuCreateOrderResult result = huiFuService.createOrder(o);

                if(result.getResp_code()!=null&&(result.getResp_code().equals("00000000")||result.getResp_code().equals("00000100"))){
                    FsStorePaymentScrm mt=new FsStorePaymentScrm();
                    mt.setPaymentId(storePayment.getPaymentId());
                    mt.setTradeNo(result.getHf_seq_id());
                    mt.setAppId(appId);
                    fsStorePaymentMapper.updateFsStorePayment(mt);
                    Map<String, Object> resultMap = com.alibaba.fastjson.JSON.parseObject(result.getPay_info(), new TypeReference<Map<String, Object>>() {});
                    String s = (String) resultMap.get("package");
                    resultMap.put("packageValue",s);
                    return R.ok().put("result",resultMap);
                }
                else{
                    return R.error(result.getResp_desc());
                }
            }
        }else {
            return R.error("新增订单失败！");
        }
        return R.error("支付失败！");

    }

    @Override
    public FsStoreScanPaymentStatVo getScanPaymentStat(FsStoreScanPaymentStatParam param) {
        if (!StatTypeEnum.isValid(param.getStatType())) {
            throw new ServiceException("操作失败，无效的统计类型！有效类型为：" + StatTypeEnum.getAllValidTypes());
        }

        StatTypeEnum statTypeEnum = param.toStatTypeEnum();
        FsStoreScanPaymentStatVo paymentStatVo = null;
        DateTimeFormatter formatter = null;

        switch (statTypeEnum) {
            case DAY:
                paymentStatVo = fsStorePaymentMapper.getScanPaymentDayStat(param);
                formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                break;
            case MONTH:
                paymentStatVo = fsStorePaymentMapper.getScanPaymentMonthStat(param);
                formatter = DateTimeFormatter.ofPattern("yyyy-MM");
                break;
            case YEAR:
                paymentStatVo = fsStorePaymentMapper.getScanPaymentYearStat(param);
                formatter = DateTimeFormatter.ofPattern("yyyy");
                break;
            case DATE:
                if (StringUtils.isEmpty(param.getStartDate())) {
                    throw new ServiceException("操作失败，开始日期不能为空！");
                } else if (StringUtils.isEmpty(param.getEndDate())) {
                    throw new ServiceException("操作失败，结束日期不能为空！");
                }
                paymentStatVo = fsStorePaymentMapper.getScanPaymentDateStat(param);
                break;
            default:
                throw new ServiceException("未支持的统计类型：" + statTypeEnum);
        }

        if (paymentStatVo == null || statTypeEnum.getCode().equals(4) && paymentStatVo != null && paymentStatVo.getTotalSales() == null) {
            paymentStatVo = new FsStoreScanPaymentStatVo();
            paymentStatVo.setPayCount(0);
            paymentStatVo.setTotalSales(BigDecimal.ZERO);
            paymentStatVo.setTotalReturn(BigDecimal.ZERO);
            paymentStatVo.setTableDataInfo(new TableDataInfo());

            String statPeriod;
            switch (statTypeEnum) {
                case DAY:
                case MONTH:
                case YEAR:
                    statPeriod = LocalDate.now().format(formatter);
                    break;
                case DATE:
                    statPeriod = param.getStartDate() + "-" + param.getEndDate();
                    break;
                default:
                    statPeriod = "";
            }
            paymentStatVo.setStatPeriod(statPeriod);
        }

        return paymentStatVo;
    }

    @Override
    public List<FsStoreScanPaymentStatDetailsVo> getScanPaymentStatPage(FsStoreScanPaymentStatParam param) {
        StatTypeEnum statTypeEnum = param.toStatTypeEnum();
        List<FsStoreScanPaymentStatDetailsVo> paymentStatDetailsVos = null;
        switch (statTypeEnum) {
            case DAY://日
                paymentStatDetailsVos = fsStorePaymentMapper.getScanPaymentDayStatDetails(param);
                break;
            case MONTH://月
                paymentStatDetailsVos = fsStorePaymentMapper.getScanPaymentMonthStatPage(param);
                break;
            case YEAR://年
                paymentStatDetailsVos = fsStorePaymentMapper.getScanPaymentYearStatPage(param);
                break;
            case DATE://日期
                if(StringUtils.isEmpty(param.getStartDate())){
                    throw new ServiceException("操作失败，开始日期不能为空！");
                }else if(StringUtils.isEmpty(param.getEndDate())){
                    throw new ServiceException("操作失败，结日期不能为空！");
                }
                paymentStatDetailsVos = fsStorePaymentMapper.getScanPaymentDateStatPage(param);
                break;
        }
        return paymentStatDetailsVos;
    }

    @Override
    public FsStoreScanPaymentDetailVo getScanPaymentDetail(Long paymentId) {
        if (paymentId == null) {
            throw new ServiceException("操作失败，支付ID不能为空！");
        }

        FsStorePaymentScrm payment = fsStorePaymentMapper.selectFsStorePaymentById(paymentId);
        if (payment == null) {
            throw new ServiceException("支付记录不存在！");
        }

        // 转换为VO
        FsStoreScanPaymentDetailVo detailVo = new FsStoreScanPaymentDetailVo();
        detailVo.setPaymentId(payment.getPaymentId());
        detailVo.setPayMoney(payment.getPayMoney());
        detailVo.setRemark(payment.getRemark());
        detailVo.setPayTime(payment.getPayTime());
        detailVo.setPayCode(payment.getPayCode());
        detailVo.setTradeNo(payment.getTradeNo());
        detailVo.setBankTransactionId(payment.getBankTransactionId());
        detailVo.setBankSerialNo(payment.getBankSerialNo());
        detailVo.setRefundMoney(payment.getRefundMoney());
        detailVo.setRefundTime(new Date());
        detailVo.setRefundAuditStatus(payment.getRefundAuditStatus());
        detailVo.setStatus(payment.getStatus());
        detailVo.setPayTypeCode(payment.getPayTypeCode());
        detailVo.setOriginalAmount(payment.getOriginalAmount());
        detailVo.setReductionAmount(payment.getReductionAmount());
        detailVo.setBusinessType(payment.getBusinessType());
        detailVo.setBusinessOrderId(payment.getBusinessOrderId());

        // 设置状态文本
        detailVo.setStatusText(getStatusText(payment.getStatus()));
        detailVo.setPayTypeText(getPayTypeText(payment.getPayTypeCode()));

        return detailVo;
    }

    /**
     * 获取支付状态文本
     */
    private String getStatusText(Integer status) {
        if (status == null) {
            return "未知";
        }
        switch (status) {
            case 0:
                return "未支付";
            case 1:
                return "已支付";
            case -1:
                return "已退款";
            default:
                return "未知";
        }
    }

    /**
     * 获取支付方式文本
     */
    private String getPayTypeText(String payTypeCode) {
        if (StringUtils.isEmpty(payTypeCode)) {
            return "未知";
        }
        switch (payTypeCode) {
            case "weixin":
                return "微信支付";
            case "alipay":
                return "支付宝";
            case "unionpay":
                return "银联支付";
            default:
                return payTypeCode;
        }
    }
    /**
     * 验证立减配置是否有效
     * @param config 店铺配置对象
     * @return 配置是否有效
     */
    private boolean isValidDiscountConfig(StoreConfig config) {
        return config != null
                && Boolean.TRUE.equals(config.getScanCodeDiscountEnabled())
                && config.getScanCodeDiscountAmount() != null
                && config.getScanCodeDiscountAmount().compareTo(BigDecimal.ZERO) > 0;
    }



    @Override
    @Transactional
    public R auditRefund(Long paymentId, Integer auditStatus, String auditRemark, String auditor) {
        logger.info("开始退款审核，paymentId: {}, auditStatus: {}, auditRemark: {}, auditor: {}",
                paymentId, auditStatus, auditRemark, auditor);

        // 参数校验
        if (paymentId == null) {
            return R.error("支付ID不能为空");
        }
        if (auditStatus == null || (auditStatus != 1 && auditStatus != 2)) {
            return R.error("审核状态错误，1-通过，2-拒绝");
        }

        // 查询支付记录
        FsStorePaymentScrm payment = fsStorePaymentMapper.selectFsStorePaymentById(paymentId);
        if (payment == null) {
            return R.error("支付记录不存在");
        }

        // 检查支付状态
        if (payment.getStatus() != 1) {
            return R.error("只有已支付的订单才能申请退款");
        }

        // 检查是否已经审核过
        if (payment.getRefundAuditStatus() != null && payment.getRefundAuditStatus() != 0) {
            return R.error("该退款申请已经审核过，不能重复审核");
        }

        // 更新审核信息
        payment.setRefundAuditStatus(auditStatus);
        payment.setRefundAuditBy(auditor);
        payment.setRefundAuditTime(new Date());
        payment.setRefundAuditRemark(auditRemark);

        logger.info("即将更新数据库，审核人: {}", auditor);

        int updateResult = fsStorePaymentMapper.updateFsStorePayment(payment);
        if (updateResult > 0) {
            logger.info("数据库更新成功，更新行数: {}", updateResult);

            // 验证数据是否正确写入
            FsStorePaymentScrm updatedPayment = fsStorePaymentMapper.selectFsStorePaymentById(paymentId);
            logger.info("数据库中的审核人: {}, 审核状态: {}, 审核时间: {}",
                    updatedPayment.getRefundAuditBy(),
                    updatedPayment.getRefundAuditStatus(),
                    updatedPayment.getRefundAuditTime());

            String statusText = auditStatus == 1 ? "通过" : "拒绝";
            return R.ok("退款审核" + statusText + "成功");
        } else {
            logger.error("数据库更新失败，更新行数: {}", updateResult);
            return R.error("审核失败，请重试");
        }
    }

    @Override
    public FsStorePaymentScrm selectPaymentByUserId(Long userId) {
        return fsStorePaymentMapper.selectPaymentByUserId(userId);
    }


    @Override
    public R oneClickShipping() {
        try {
            StringBuilder builder = new StringBuilder();
            //获取商城配置
            String json = configService.selectConfigByKey("store.config");
            StoreConfig config = JSONUtil.toBean(json, StoreConfig.class);
            //验证是否开启微信发货
            if (config.getIsWeChatShipping() != null && config.getIsWeChatShipping()) {
                //获取支付信息
                List<FsStorePaymentUsetVo> paymentList = fsStorePaymentMapper.getPaymentUsetInfoList();
                if (paymentList.isEmpty()) {
                    return R.ok("操作成功，暂无同步订单信息！");
                }
                String uploadTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"))
                        .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
                Map<String, List<FsStorePaymentUsetVo>> paymentUsetVoMap = paymentList.stream().collect(Collectors.groupingBy(FsStorePaymentUsetVo::getAppId));
                for (Map.Entry<String, List<FsStorePaymentUsetVo>> entry : paymentUsetVoMap.entrySet()) {
                    List<String> successList = new ArrayList<>();
                    List<String> failedList = new ArrayList<>();
                    String appId = entry.getKey();
                    List<FsStorePaymentUsetVo> userPayments = entry.getValue();
                    final WxMaService wxService = WxMaConfiguration.getMaService(appId);
                    if (!userPayments.isEmpty()) {
                        for (FsStorePaymentUsetVo v : userPayments) {
                            // 上传物流信息到微信
                            if (uploadShippingInfoToWechat(wxService, v, uploadTime)) {
                                successList.add(v.getBankTransactionId());
                            }else {
                                failedList.add(v.getBankTransactionId());
                            }
                        }
                        //批量更新数据
                        if (!successList.isEmpty()) {
                            fsStorePaymentMapper.batchUpadte(successList);
                        }
                        if(!failedList.isEmpty()){
                            fsStorePaymentMapper.batchUpadteFailed(failedList);
                        }
                    }
                }
            }
            return R.ok(builder.toString().equals("") ? "操作成功！" : builder.toString());
        } catch (Exception e) {
            log.error("导入发货单快递信息失败", e);
            return R.error("导入失败：" + e.getMessage());
        }
    }

    private boolean uploadShippingInfoToWechat(WxMaService wxService,
                                               FsStorePaymentUsetVo dto,
                                               String uploadTime) {
        try {
            WxMaOrderShippingInfoUploadRequest request = new WxMaOrderShippingInfoUploadRequest();
            OrderKeyBean orderKeyBean = new OrderKeyBean();
            orderKeyBean.setOrderNumberType(2);
            orderKeyBean.setTransactionId(dto.getBankTransactionId());//交易订单号ID
            request.setOrderKey(orderKeyBean);
            request.setDeliveryMode(1);
            request.setLogisticsType(4);
            List<ShippingListBean> shippingList = new ArrayList<>();
            ShippingListBean shippingListBean = new ShippingListBean();
            //默认物品信息
            shippingListBean.setTrackingNo(String.valueOf(new TwelveDigitSnowflake(1).nextId()));
            shippingListBean.setExpressCompany("FS");
            shippingListBean.setItemDesc("默认商品");
            ContactBean contactBean = new ContactBean();
            contactBean.setReceiverContact(dto.getPhone());
            shippingListBean.setContact(contactBean);

            shippingList.add(shippingListBean);
            request.setShippingList(shippingList);
            request.setUploadTime(uploadTime);
            // 设置支付者信息
            PayerBean payerBean = new PayerBean();
            payerBean.setOpenid(dto.getOpenId());
            request.setPayer(payerBean);
            // 上传物流信息
            WxMaOrderShippingInfoBaseResponse re = wxService.getWxMaOrderShippingService().upload(request);
            // 使用统一的错误处理工具类
            return WxShippingErrorHandler.handleError(re.getErrCode(), re.getErrMsg(), dto.getBankTransactionId());
        } catch (Exception e) {
            // 使用统一的异常错误处理工具类
            return WxShippingErrorHandler.handleExceptionError(e.getMessage(), dto.getBankTransactionId());
        }
    }


    /**
     * 发起支付
     * @param payOrderParam 入参
     * @return R
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public R processPaymentScrm( PayOrderParam payOrderParam) {
        logger.info("发起支付 payOrderParam: {}", JSON.toJSONString(payOrderParam));

        if (payOrderParam.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new CustomException("支付金额不正确");
        }

        FsUserScrm user = userService.selectFsUserById(payOrderParam.getUserId());
        if (Objects.isNull(user)) {
            throw new CustomException("用户不存在");
        }
        if (PaymentMethodEnum.CZ_PAY == payOrderParam.getPaymentMethod()) {
            if (user.getRechargeBalance().compareTo(BigDecimal.ZERO) <= 0) {
                throw new CustomException("余额不足！请先充值。");
            }
        }
        String type = null;
        FsPayConfig payConfig = new FsPayConfig();
        if (PaymentMethodEnum.WX_APP == payOrderParam.getPaymentMethod()) {
            String json = configService.selectConfigByKey("app.config");
            AppConfig config = JSONUtil.toBean(json, AppConfig.class);
            payOrderParam.setAppId(config.getAppId());
            type = "wxApp";
        }
        //支付宝可以不需要appid（在没有appid的情况下）【ps:小程序的支付宝没传appid 就G】
        if ((PaymentMethodEnum.ALIPAY == payOrderParam.getPaymentMethod())
                && StringUtils.isBlank(payOrderParam.getAppId())) {
            String json = configService.selectConfigByKey("his.pay");
            PayConfigDTO payConfigDTO = JSONUtil.toBean(json, PayConfigDTO.class);
            payConfig.setType(payConfigDTO.getType());
        }else if(!(PaymentMethodEnum.CZ_PAY == payOrderParam.getPaymentMethod())){
            if (StringUtils.isBlank(payOrderParam.getAppId())) {
                throw new IllegalArgumentException("appId不能为空");
            }
            FsCoursePlaySourceConfig fsCoursePlaySourceConfig = fsCoursePlaySourceConfigMapper.selectCoursePlaySourceConfigByAppId(payOrderParam.getAppId());
            if (fsCoursePlaySourceConfig == null) {
                throw new CustomException("未找到appId对应的小程序配置: " + payOrderParam.getAppId());
            }
            Long merchantConfigId = fsCoursePlaySourceConfig.getMerchantConfigId();
            if (merchantConfigId == null || merchantConfigId <= 0) {
                throw new CustomException("小程序没有配置商户信息");
            }

            MerchantAppConfig merchantAppConfig = merchantAppConfigMapper.selectMerchantAppConfigById(fsCoursePlaySourceConfig.getMerchantConfigId());
            payConfig = JSON.parseObject(merchantAppConfig.getDataJson(), FsPayConfig.class);
            if (StringUtils.isNotEmpty(type)) {
                payConfig.setType(type);
            } else {
                payConfig.setType(merchantAppConfig.getMerchantType());
            }
            payConfig.setAppId(fsCoursePlaySourceConfig.getAppid());

            logger.debug("支付配置 his.pay: {}", payConfig);
        }


//        FsPayConfig payConfig = JSONUtil.toBean(json, FsPayConfig.class);

        if (isWechatPayment(payOrderParam.getPaymentMethod())) {
            String openId = getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod(), payConfig);
            if (StringUtils.isBlank(openId)) {
                throw new CustomException("用户OPENID不存在");
            }
        }

        FsStorePaymentScrm storePayment = new FsStorePaymentScrm();

        // 1. 根据业务类型创建对应的支付对象
        if (payOrderParam.getBusinessType().getPrefix().equals("live")) {
            // 处理直播业务支付
            LiveOrderPayment liveOrderPayment = createLiveStorePayment(payConfig, user, payOrderParam);
            BeanUtils.copyProperties(liveOrderPayment, storePayment);

            // 处理储值支付
            if (isRechargePayment(payOrderParam)) {
                return processLiveRechargePayment(liveOrderPayment, user);
            }
        } else {
            // 处理商城业务支付
            storePayment = createStorePaymentScrm(payConfig, user, payOrderParam);

//            // 处理储值支付
//            if (isRechargePayment(payOrderParam)) {
//                return processStoreRechargePayment(storePayment, user);
//            }
        }
        // 根据配置类型创建第三方支付订单
        return createThirdPartyPaymentScrm(payConfig, storePayment, user, payOrderParam);
    }

    @Override
    public List<FsStorePaymentScrm> selectFsStorePaymentByOrderIdApp(Long id) {
        return fsStorePaymentMapper.selectFsStorePaymentByOrderIdApp(id);
    }

    /**
     * 判断是否为储值支付
     * @param payOrderParam 支付订单参数
     * @return true:储值支付 false:其他支付方式
     */
    private boolean isRechargePayment(PayOrderParam payOrderParam) {
        return PaymentMethodEnum.CZ_PAY == payOrderParam.getPaymentMethod();
    }

    /**
     * 处理直播储值支付
     * @param liveOrderPayment 直播订单支付信息
     * @param user 用户信息
     * @return 支付处理结果
     */
    private R processLiveRechargePayment(LiveOrderPayment liveOrderPayment, FsUserScrm user) {
        // 查询直播订单信息
        LiveOrder liveOrder = liveOrderMapper.selectLiveOrderByOrderId(liveOrderPayment.getBusinessId());
        Company company = companyService.selectCompanyById(liveOrder.getCompanyId());

        // 扣减用户储值余额
        deductUserRechargeBalance(user, liveOrder.getPayMoney());

        // 更新直播订单状态
        updateLiveOrderStatus(liveOrder);

        // 创建消费记录
        return R.ok();
    }

    /**
     * 处理商城储值支付
     * @param storePayment 商城订单支付信息
     * @param user 用户信息
     * @return 支付处理结果
     */
    private R processStoreRechargePayment(FsStorePaymentScrm storePayment, FsUserScrm user) {
        // 查询商城订单信息
        FsStoreOrderScrm fsStoreOrderScrm = storeOrderScrmMapper.selectFsStoreOrderById(storePayment.getOrderId());
        Company company = companyService.selectCompanyById(fsStoreOrderScrm.getCompanyId());

        // 扣减用户储值余额
        deductUserRechargeBalance(user, storePayment.getPayMoney());

        // 更新商城订单状态
        updateStoreOrderStatus(fsStoreOrderScrm);

        // 创建消费记录
        return R.ok();
    }

    /**
     * 扣减用户储值余额
     * @param user 用户信息
     * @param amount 扣减金额
     */
    private void deductUserRechargeBalance(FsUserScrm user, BigDecimal amount) {
        user.setRechargeBalance(user.getRechargeBalance().subtract(amount));
        userService.updateFsUser(user);
    }

    /**
     * 更新直播订单状态
     * @param liveOrder 直播订单
     */
    private void updateLiveOrderStatus(LiveOrder liveOrder) {
        liveOrder.setStatus(OrderInfoEnum.STATUS_1.getValue());
        liveOrder.setPayTime(LocalDateTime.now());
        liveOrder.setIsPay("1");
        liveOrderMapper.updateLiveOrder(liveOrder);
    }

    /**
     * 更新商城订单状态
     * @param storeOrder 商城订单
     */
    private void updateStoreOrderStatus(FsStoreOrderScrm storeOrder) {
        storeOrder.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
        storeOrder.setStatus(OrderInfoEnum.STATUS_1.getValue());
        storeOrder.setPayTime(new Date());
        storeOrderScrmMapper.updateFsStoreOrder(storeOrder);
    }



    /**
     * 订单支付成功后,增加消费记录
     * @param orderId 订单ID
     * @param orderNo 订单编号
     * @param userId 用户ID
     * @param userName 用户姓名
     * @param amount 消费金额
     * @return 影响行数
     */
//    public int createConsumptionRecord(Long orderId, String orderNo, Long userId,
//                                       String userName, BigDecimal amount,Company company
//    ) {
//        RechargeRecord record = new RechargeRecord();
//        record.setUserId(userId);
//        record.setUserName(userName);
//        record.setTotalAmount(amount);
//        record.setTransactionId(generateTransactionId());
//        record.setOrderId(orderId);
//        record.setOrderNo(orderNo);
//        record.setBusinessType(1); // 1-消费
//        if (ObjectUtil.isEmpty(company)){
//            record.setRemark("订单消费，自主下单没有归属公司");
//        }else {
//            record.setCompanyId(company.getCompanyId());
//            record.setCompanyName(company.getCompanyName());
//            record.setRemark("订单消费");
//        }
//        record.setCreateTime(new Date());
//        record.setDelFlag("0");
//
//        return rechargeRecordMapper.insertRechargeRecord(record);
//    }

    /**
     * 生成交易流水号
     * @return 交易流水号
     */
    private String generateTransactionId() {
        return "TXF" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
    }
    /**
     * 直播订单支付信息
     *
     * @param payConfig
     * @param user
     * @param payOrderParam
     * @return
     */
    private LiveOrderPayment createLiveStorePayment(FsPayConfig payConfig, FsUserScrm user, PayOrderParam payOrderParam) {
        String payCode = OrderCodeUtils.getOrderSn();
        if (StringUtils.isEmpty(payCode)) {
            throw new CustomException("订单生成失败，请重试");
        }

        LiveOrderPayment storePayment = new LiveOrderPayment();

        if (PaymentMethodEnum.CZ_PAY == payOrderParam.getPaymentMethod()){
            storePayment.setStatus(1);
            storePayment.setPayMode("cz");
        }else {
            storePayment.setStatus(0);
            storePayment.setPayMode(payConfig.getType());
        }
        storePayment.setAppId(payConfig.getAppId());
        storePayment.setBusinessCode(payOrderParam.getOrderCode());
        storePayment.setPayCode(payCode);
        storePayment.setPayMoney(payOrderParam.getAmount());
        storePayment.setCreateTime(new Date());
        storePayment.setPayTypeCode(payOrderParam.getPaymentMethod().getDesc());
        storePayment.setBusinessType(payOrderParam.getBusinessType().getCode());
        storePayment.setCompanyId(payOrderParam.getCompanyId());
        storePayment.setCompanyUserId(payOrderParam.getCompanyUserId());
        storePayment.setRemark(payOrderParam.getBusinessType().getDesc());
        storePayment.setStoreId(payOrderParam.getStoreId());
        storePayment.setUserId(user.getUserId());
        storePayment.setBusinessId(payOrderParam.getOrderId().toString());

        // 设置openId（如果是微信支付）
        if (isWechatPayment(payOrderParam.getPaymentMethod())) {
            storePayment.setOpenId(getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod(), payConfig));
        }

        if (liveOrderPaymentMapper.insertLiveOrderPayment(storePayment) <= 0) {
            throw new CustomException("支付订单创建失败");
        }

        return storePayment;
    }

    /**
     * 判断是否微信支付
     * @param method 支付类型
     * @return boolean
     */
    private boolean isWechatPayment(PaymentMethodEnum method) {
        return method == PaymentMethodEnum.MINIAPP_WECHAT || method == PaymentMethodEnum.H5_WECHAT;
    }

    /**
     * 根据支付方式获取对应的openId
     */
    private String getOpenIdForPaymentMethod(FsUserScrm user, PaymentMethodEnum method, FsPayConfig payConfig) {
        String openId;
        switch (method) {
            case MINIAPP_WECHAT:
                openId = user.getMaOpenId();
                break;
            case H5_WECHAT:
                openId = user.getMpOpenId();
                break;
            default:
                openId = null;
        }

        if (StringUtils.isBlank(openId)) {
            Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
                    .eq(FsUserWx::getFsUserId, user.getUserId())
                    .eq(FsUserWx::getAppId, payConfig.getAppId());
            FsUserWx fsUserWx = userWxMapper.selectOne(queryWrapper);
            if (Objects.nonNull(fsUserWx)) {
                openId = fsUserWx.getOpenId();
            }
        }

        return openId;
    }

    /**
     * 发起预支付
     */
    private R createThirdPartyPaymentScrm(FsPayConfig payConfig, FsStorePaymentScrm storePayment, FsUserScrm user, PayOrderParam payOrderParam) {
        switch (payConfig.getType()) {
            case "wx":
                return createWxPayment(storePayment, user, payOrderParam, payConfig);
            case "wxApp":
                return createWxAppPayment(storePayment, user, payOrderParam, payConfig);
            case "hf":
                return createHfPayment(storePayment, user, payOrderParam, payConfig);
            default:
                throw new CustomException("不支持的支付方式");
        }
    }

    /**
     * 汇付
     */
    private R createHfPayment(FsStorePaymentScrm storePayment, FsUserScrm user, PayOrderParam payOrderParam, FsPayConfig payConfig) {
        logger.debug("创建汇付订单");

        HuiFuCreateOrder order = new HuiFuCreateOrder();
        order.setTradeType(getHfTradeType(payOrderParam.getPaymentMethod()));
        order.setReqSeqId(payOrderParam.getBusinessType().getPrefix() + "-" + storePayment.getPayCode());
        order.setTransAmt(storePayment.getPayMoney().toString());
        order.setGoodsDesc(payOrderParam.getBusinessType().getDesc());

        // 微信支付需要设置openid
        if (isWechatPayment(payOrderParam.getPaymentMethod())) {
            order.setOpenid(getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod(), payConfig));
        }

        HuifuCreateOrderResult result = huiFuService.createOrder(order);
        logger.debug("汇付支付创建结果: {}", result);

        updateStorePaymentTradeNo(storePayment.getPaymentId(), result.getHf_seq_id());
        return R.ok().put("isPay", 0).put("data", result).put("type", "hf");
    }

    /**
     * 获取汇付交易类型
     */
    private String getHfTradeType(PaymentMethodEnum paymentMethod) {
        switch (paymentMethod) {
            case MINIAPP_WECHAT:
                return "T_MINIAPP";
            case H5_WECHAT:
                return "T_JSAPI";
            case ALIPAY:
            case H5_ALIPAY:
                return "A_NATIVE";
            case T_NATIVE:
                return "T_NATIVE";
            default:
                throw new CustomException("不支持的支付方式");
        }
    }

    /**
     * 更新支付订单交易号
     */
    private void updateStorePaymentTradeNo(Long paymentId, String tradeNo) {
        FsStorePaymentScrm updatePayment = new FsStorePaymentScrm();
        updatePayment.setPaymentId(paymentId);
        updatePayment.setTradeNo(tradeNo);
        fsStorePaymentMapper.updateFsStorePayment(updatePayment);
    }


    /**
     * 微信支付
     */
    private R createWxPayment(FsStorePaymentScrm storePayment, FsUserScrm user, PayOrderParam payOrderParam, FsPayConfig payConfig) {
        PaymentMethodEnum paymentMethod = payOrderParam.getPaymentMethod();
        if (paymentMethod != PaymentMethodEnum.MINIAPP_WECHAT) {
            logger.debug("微信支付 PaymentMethod: {}", paymentMethod.name());
            throw new CustomException("不支持的支付方式");
        }

        WxPayConfig wxPayConfig = buildWxPayConfig(payConfig);
        wxPayService.setConfig(wxPayConfig);

        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
        orderRequest.setOpenid(getOpenIdForPaymentMethod(user, paymentMethod, payConfig));
        orderRequest.setBody(payOrderParam.getBusinessType().getDesc());
        orderRequest.setOutTradeNo(payOrderParam.getBusinessType().getPrefix() + "-" + storePayment.getPayCode());
        orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));
        orderRequest.setTradeType("JSAPI");
        orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(ServletUtils.getRequest()));

        try {
            WxPayMpOrderResult orderResult = wxPayService.createOrder(orderRequest);
            return R.ok().put("data", orderResult).put("type", "wx").put("isPay", 0);
        } catch (WxPayException e) {
            logger.error("微信支付发起失败: {}", e.getMessage(), e);
            throw new CustomException("支付失败: " + e.getMessage());
        }
    }

    /**
     * 微信App支付
     */
    private R createWxAppPayment(FsStorePaymentScrm storePayment, FsUserScrm user, PayOrderParam payOrderParam, FsPayConfig payConfig) {
        //创建微信订单
        WxPayConfig wxPayConfig = buildWxPayConfig(payConfig);

        wxPayConfig.setAppId(wxPayConfig.getAppId());
        wxPayConfig.setMchId(wxPayConfig.getMchId());
        wxPayConfig.setMchKey(wxPayConfig.getMchKey());
        wxPayConfig.setSubAppId(StringUtils.trimToNull(null));
        wxPayConfig.setSubMchId(StringUtils.trimToNull(null));
        wxPayConfig.setKeyPath(null);
        wxPayConfig.setNotifyUrl(wxPayConfig.getNotifyUrl());
        wxPayService.setConfig(wxPayConfig);
        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
        orderRequest.setBody(payOrderParam.getBusinessType().getDesc());
        orderRequest.setOutTradeNo(payOrderParam.getBusinessType().getPrefix() + "-" + storePayment.getPayCode());
        orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));
        orderRequest.setTradeType("APP");
        orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
        orderRequest.setNotifyUrl(wxPayConfig.getNotifyUrl());
        //调用统一下单接口，获取"预支付交易会话标识"
        try {
            Object result = wxPayService.createOrder(orderRequest);
            return R.ok().put("data",result).put("type","wxApp").put("isPay",0);
        } catch (WxPayException e) {
            e.printStackTrace();
            throw new CustomException("支付失败"+e.getMessage());
        }
    }

    /**
     * 构建微信支付配置
     */
    private WxPayConfig buildWxPayConfig(FsPayConfig fsPayConfig) {
        WxPayConfig payConfig = new WxPayConfig();
        payConfig.setAppId(StringUtils.trimToNull(fsPayConfig.getAppId()));
        payConfig.setMchId(StringUtils.trimToNull(fsPayConfig.getWxMchId()));
        payConfig.setMchKey(StringUtils.trimToNull(fsPayConfig.getWxMchKey()));
        payConfig.setSubAppId(StringUtils.trimToNull(null));
        payConfig.setSubMchId(StringUtils.trimToNull(null));
        payConfig.setKeyPath(null);
        payConfig.setNotifyUrl(StringUtils.trimToNull(fsPayConfig.getNotifyUrlScrm()));
        return payConfig;
    }


    /**
     * 创建支付订单
     */
    private FsStorePaymentScrm createStorePaymentScrm(FsPayConfig payConfig, FsUserScrm user, PayOrderParam payOrderParam) {
        String payCode = OrderCodeUtils.getOrderSn();
        if (StringUtils.isEmpty(payCode)) {
            throw new CustomException("订单生成失败，请重试");
        }

        FsStorePaymentScrm storePayment = new FsStorePaymentScrm();
        if (PaymentMethodEnum.CZ_PAY == payOrderParam.getPaymentMethod()){
            storePayment.setStatus(1);
            storePayment.setPayMode("cz");
        }else {
            storePayment.setStatus(0);
            storePayment.setPayMode(payConfig.getType());
        }
        storePayment.setAppId(payConfig.getAppId());
        storePayment.setOrderId(payOrderParam.getOrderId());
        storePayment.setBusinessCode(payOrderParam.getOrderCode());
        storePayment.setPayCode(payCode);
        storePayment.setPayMoney(payOrderParam.getAmount());
        storePayment.setCreateTime(new Date());
        storePayment.setPayTypeCode(payOrderParam.getPaymentMethod().getDesc());
        storePayment.setBusinessType(payOrderParam.getBusinessType().getCode());
        storePayment.setCompanyId(payOrderParam.getCompanyId());
        storePayment.setCompanyUserId(payOrderParam.getCompanyUserId());
        storePayment.setRemark(payOrderParam.getBusinessType().getDesc());
        storePayment.setStoreId(payOrderParam.getStoreId());
        storePayment.setUserId(user.getUserId());
        storePayment.setBusinessId(payOrderParam.getOrderId().toString());

        // 设置openId（如果是微信支付）
        if (isWechatPayment(payOrderParam.getPaymentMethod())) {
            storePayment.setOpenId(getOpenIdForPaymentMethod(user, payOrderParam.getPaymentMethod(), payConfig));
        }

        if (fsStorePaymentMapper.insertFsStorePayment(storePayment) <= 0) {
            throw new CustomException("支付订单创建失败");
        }

        return storePayment;
    }
}
