package com.fs.hisStore.service.impl;


import java.math.BigDecimal;

import java.util.*;


import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.fs.common.annotation.DataScope;
import com.fs.common.config.FSSysConfig;
import com.fs.common.core.domain.R;
import com.fs.common.core.redis.RedisCache;
import com.fs.common.utils.CloudHostUtils;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.StringUtils;
import com.fs.company.domain.Company;
import com.fs.company.domain.CompanyUser;
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.FsCourseRedPacketLog;
import com.fs.course.mapper.FsCourseRedPacketLogMapper;
import com.fs.course.service.IFsCourseRedPacketLogService;
import com.fs.his.config.FsSysConfig;
import com.fs.his.domain.FsUser;
import com.fs.his.domain.FsUserWx;
import com.fs.his.service.IFsUserService;
import com.fs.his.service.IFsUserWxService;
import com.fs.his.utils.ConfigUtil;
import com.fs.his.utils.HttpUtil;
import com.fs.hisStore.enums.SysConfigEnum;
import com.fs.hisStore.param.*;
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.pay.pay.config.PayConfig;
import com.fs.pay.pay.dto.WxJspayDTO;
import com.fs.hisStore.vo.FsStorePaymentStatisticsVO;
import com.fs.system.oss.CloudStorageService;
import com.fs.system.oss.OSSFactory;
import com.fs.system.service.ISysConfigService;
import com.fs.wx.miniapp.config.WxMaProperties;
import com.fs.hisStore.domain.FsUserScrm;
import com.fs.hisStore.service.IFsUserScrmService;
import com.fs.hisStore.vo.FsStorePaymentVO;
import com.fs.pay.service.IPayService;
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.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 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 com.fs.hisStore.mapper.FsStorePaymentScrmMapper;
import com.fs.hisStore.domain.FsStorePaymentScrm;
import com.fs.hisStore.service.IFsStorePaymentScrmService;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;

/**
 * 支付明细Service业务层处理
 *
 * @author fs
 * @date 2022-06-20
 */
@Service
public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
{
    Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private WxMaProperties properties;
    @Autowired
    private IPayService payService;
    @Autowired
    private FSSysConfig sysConfig;
    @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;

    /**
     * 查询支付明细
     *
     * @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 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
    @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;

    @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("注册失败客服已停用，或不存在！");
            }
        }

        //生成支付流水
        String orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();
        FsStorePaymentScrm storePayment=new FsStorePaymentScrm();
        storePayment.setCompanyId(param.getCompanyId());
        //判断销售是否存在
        if (param.getCompanyUserId()!=null){
            storePayment.setCompanyUserId(param.getCompanyUserId());
        }
        storePayment.setStatus(0);
        storePayment.setPayCode(orderSn);
        storePayment.setPayMoney(param.getPayMoney());
        storePayment.setCreateTime(new Date());
        storePayment.setPayTypeCode("weixin");
        storePayment.setBusinessType(1);//微信收款
        storePayment.setRemark(StringUtils.isNotBlank(param.getRemark()) ? param.getRemark() : "商城收款订单支付");
        storePayment.setOpenId(user.getMaOpenId());
        storePayment.setUserId(user.getUserId());
        storePayment.setPayMode("hf");//目前微信收款仅支持汇付
        storePayment.setAppId(param.getAppId());
        fsStorePaymentMapper.insertFsStorePayment(storePayment);

        //汇付支付
        HuiFuCreateOrder o = new HuiFuCreateOrder();
        o.setTradeType("T_MINIAPP");
        o.setOpenid(user.getMaOpenId());
        o.setReqSeqId("payment-"+storePayment.getPayCode());
        o.setTransAmt(storePayment.getPayMoney().toString());
        o.setGoodsDesc("商城订单支付");
        o.setAppId(param.getAppId());
        //公司分账
        try {
            HuiFuUtils.doDiv(o,company.getCompanyId());
            //存储分账明细
            HuiFuUtils.saveDivItem(o, storePayment.getPayCode(), storePayment.getPayCode());
        } catch (Exception e) {
            logger.error("-------------微信收款分账出错：{}", e.getMessage());
        }
        HuifuCreateOrderResult result = huiFuService.createOrder(o);
        if(result.getResp_code()!=null&&(result.getResp_code().equals("00000000")||result.getResp_code().equals("00000100"))){
            FsStorePaymentScrm mt=new FsStorePaymentScrm();
            mt.setPaymentId(storePayment.getPaymentId());
            mt.setTradeNo(result.getHf_seq_id());
            fsStorePaymentMapper.updateFsStorePayment(mt);
            Map<String, Object> resultMap = JSON.parseObject(result.getPay_info(), new TypeReference<Map<String, Object>>() {});
            String s = (String) resultMap.get("package");
            resultMap.put("packageValue",s);
            return R.ok().put("result",resultMap);
        }
        else{
            return R.error(result.getResp_desc());
        }
    }
}
