package cn.com.ty.lift.ud.pay.service.impl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;

import cn.com.ty.lift.common.model.PushMessage;
import cn.com.ty.lift.common.model.PushUserInfo;
import cn.com.ty.lift.ud.chat.mapper.entity.ChatSessionEntity;
import cn.com.ty.lift.ud.chat.mapper.entity.LiftCaseEntity;
import cn.com.ty.lift.ud.chat.service.IChatSessionService;
import cn.com.ty.lift.ud.chat.service.ILiftCaseService;
import cn.com.ty.lift.ud.neety.task.RoomInfo;
import cn.com.ty.lift.ud.neety.task.UserInfo;
import cn.com.ty.lift.ud.operation.mapper.entity.CommissionSettingEntity;
import cn.com.ty.lift.ud.operation.mapper.entity.UserLevelRuleEntity;
import cn.com.ty.lift.ud.operation.mapper.entity.UserRebateRuleEntity;
import cn.com.ty.lift.ud.operation.mapper.entity.VipFeeSettingEntity;
import cn.com.ty.lift.ud.operation.service.ICommissionSettingService;
import cn.com.ty.lift.ud.operation.service.IUserLevelRuleService;
import cn.com.ty.lift.ud.operation.service.IUserRebateRuleService;
import cn.com.ty.lift.ud.operation.service.IVipFeeSettingService;
import cn.com.ty.lift.ud.pay.alipay.AlipayConfig;
import cn.com.ty.lift.ud.pay.alipay.AlipaySupport;
import cn.com.ty.lift.ud.pay.controller.req.PassbackParamsDTO;
import cn.com.ty.lift.ud.payment.mapper.entity.TyBillEntity;
import cn.com.ty.lift.ud.payment.mapper.entity.UserBillEntity;
import cn.com.ty.lift.ud.payment.mapper.entity.UserRechargeDetailEntity;
import cn.com.ty.lift.ud.payment.service.ITyBillService;
import cn.com.ty.lift.ud.payment.service.IUserBillService;
import cn.com.ty.lift.ud.payment.service.IUserRechargeDetailService;
import cn.com.ty.lift.ud.payment.service.IUserWithdrawService;
import cn.com.ty.lift.ud.question.mapper.QuestionBankMapper;
import cn.com.ty.lift.ud.question.mapper.entity.QuestionBankEntity;
import cn.com.ty.lift.ud.question.mapper.entity.QuestionOperateEntity;
import cn.com.ty.lift.ud.question.service.IQuestionOperateService;
import cn.com.ty.lift.ud.redis.RedisUtil;
import cn.com.ty.lift.ud.schoolVideo.mapper.entity.SchoolVideoEntity;
import cn.com.ty.lift.ud.schoolVideo.mapper.entity.SchoolVideoOperateEntity;
import cn.com.ty.lift.ud.schoolVideo.service.ISchoolVideoOperateService;
import cn.com.ty.lift.ud.schoolVideo.service.ISchoolVideoService;
import cn.com.ty.lift.ud.tableDict.service.ITableDictService;
import cn.com.ty.lift.ud.userAccount.mapper.entity.UserAccount;
import cn.com.ty.lift.ud.userAccount.service.IUserAccountService;
import cn.com.ty.lift.ud.userCoupon.mapper.UserCouponMapper;
import cn.com.ty.lift.ud.userInfo.mapper.UserInfoMapper;
import cn.com.ty.lift.ud.userInfo.mapper.entity.UserInfoEntity;
import cn.com.ty.lift.ud.userInfo.service.IUserInfoService;
import cn.com.ty.lift.ud.userRebate.mapper.entity.UserRebateEntity;
import cn.com.ty.lift.ud.userRebate.service.IUserRebateService;
import cn.com.ty.lift.ud.utils.QrCodeUtil;
import cn.com.ty.lift.ud.utils.UUIDUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;

import cn.com.ty.lift.ud.pay.controller.req.AlipayNotifyParam;
import cn.com.ty.lift.ud.pay.controller.req.PayDTO;
import cn.com.ty.lift.ud.pay.service.AlipayService;
import cn.com.xwy.boot.web.dto.RestResponse;

@Service
@Transactional
@Slf4j
public class AlipayServiceImpl implements AlipayService {

    private final Logger logger = LoggerFactory.getLogger(AlipayServiceImpl.class);

    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;
    
    private @Autowired AlipayClient alipayClient;

    private @Autowired AlipayConfig alipayConfig;

    private @Autowired AlipaySupport alipaySupport;

    private @Autowired ILiftCaseService liftCaseService;

    private @Autowired IChatSessionService chatSessionService;

    private @Autowired IUserBillService userBillService;

    private @Autowired IUserRechargeDetailService userRechargeDetailService;

    private @Autowired IUserInfoService userInfo;

    private @Autowired QuestionBankMapper questionBankMapper;

    private @Autowired IQuestionOperateService iQuestionOperateService;

    private @Autowired ICommissionSettingService iCommissionSettingService;

    private @Autowired IUserBillService iUserBillService;

    private @Autowired ITyBillService iTyBillService;

    private @Autowired ISchoolVideoOperateService schoolVideoOperateService;

    private @Autowired ISchoolVideoService schoolVideoService;

    private @Autowired ITableDictService tableDictService;

    private @Autowired IVipFeeSettingService vipFeeSettingService;

    private @Autowired IUserRebateService iUserRebateService;

    private @Autowired UserInfoMapper userInfoMapper;

    private @Autowired IUserLevelRuleService iUserLevelRuleService;

    private @Autowired IUserWithdrawService userWithdrawService;

    @Autowired
    private IUserAccountService iUserAccountService;

    @Autowired
    private IUserRebateRuleService iUserRebateRuleService;

    private @Autowired UserCouponMapper userCouponMapper;
    private @Autowired RedisUtil redis;

    /**
     * app支付
     * 
     * @param payDto
     * @return
     */
    @Override
    public RestResponse alipay(PayDTO payDto) {
        // 此处是相关业务代码

        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        // model.setBody("测试商品信息");
        model.setSubject("测试订单");
        // 唯一订单号 根据项目中实际需要获取相应的
        model.setOutTradeNo(UUID.randomUUID().toString().replace("-", ""));
        // model.setOutTradeNo("sn000000000001");
        // 支付金额
        model.setTotalAmount("0.01");
        model.setProductCode("QUICK_MSECURITY_PAY");
        logger.info("《=========》:{}", model.getOutTradeNo());
        AlipayTradeAppPayResponse tradeAppPayResponse = null;
        try {
            String getBody = alipaySupport.tradeAppPay(model, alipayConfig.getAlipayNotifyUrl());
            if (tradeAppPayResponse.isSuccess()) {
                // 返回支付相关信息(此处可以直接将getBody中的内容直接返回，无需再做一些其他操作)
                logger.info("《=====body====》:{}", tradeAppPayResponse.getBody());
                return RestResponse.success(tradeAppPayResponse.getBody(), "success");
            } else {

            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        return RestResponse.fail("0", "失败");
    }

    /**
     * 交易查询接口。<br>
     * tradeNo和outTradeNo不能同时为空。
     * 
     * @param tradeNo
     * @param outTradeNo
     * @return 订单已支付返回true
     * @throws AlipayApiException
     */
    public boolean tradeQuery(String tradeNo, String outTradeNo) {
        // 不能同时为空。
        if (StringUtils.isBlank(tradeNo) && StringUtils.isBlank(outTradeNo)) {
            logger.error("====订单号和交易流水号不能同时为空====");
            return false;
        }

        // 构建订单查询参数。
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();
        model.setTradeNo(tradeNo);
        model.setOutTradeNo(outTradeNo);

        AlipayTradeQueryRequest tradeQueryRequest = new AlipayTradeQueryRequest();
        tradeQueryRequest.setBizModel(model);

        AlipayTradeQueryResponse tradeQueryResponse;
        try {
            // 证书签名类型时，需要调用certificateExecute查询交易状态。
            tradeQueryResponse = alipayClient.certificateExecute(tradeQueryRequest);
        } catch (AlipayApiException e) {
            logger.error("====查询订单支付状态时发生异常====");
            logger.error(e.getMessage());
            return false;
        }
        if (tradeQueryResponse.isSuccess()) {
            String tradeStatus = tradeQueryResponse.getTradeStatus();
            if (tradeStatus.equals("TRADE_SUCCESS") || tradeStatus.equals("TRADE_FINISHED")) {
                return true;
            }
        }
        return false;
    }

    @Override
    public String alipayNotify(Map<String, String> params) {

        // 支付回调返回的json字符串
        String paramsJson = JSON.toJSONString(params);
        AlipayNotifyParam alipayNotify = JSON.parseObject(paramsJson, AlipayNotifyParam.class);

        try {
            // 支付宝验签 ： params 待验签的从支付宝接收到的参数Map、alipayCertPath 从公钥证书中提取公钥 、charset 参数内容编码集 、signType 指定采用的签名方式，RSA或RSA2
            // true：验签通过；false：验签不通过
            boolean signture = AlipaySignature.rsaCertCheckV1(params, alipayConfig.getAlipayCertPath(),
                alipayConfig.getCharset(), alipayConfig.getSignType());
            if (!signture) {
                logger.info("《=====验签失败====》");
                return "failure";
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        // 查询该订单是否成功支付
        boolean isAlipay = alipaySupport.tradeQuery(alipayNotify.getTradeNo(), alipayNotify.getOutTradeNo());
        logger.info("《=====支付宝订单支付交易状态====》：{}", isAlipay);
        if (isAlipay) {
            // 业务代码

            return "success";
        }
        return "fail";
    }

    public static void main(String[] args) throws AlipayApiException {

        // 构造client
        CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
        certAlipayRequest.setServerUrl("https://openapi.alipaydev.com/gateway.do");
        certAlipayRequest.setAppId("2016102300745149");
        certAlipayRequest.setPrivateKey(
            "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDsjV4UuJbiTi47EkP2QGXaNvA2at6IDO2GbpVzxQV4aiEXrXFDUJYizdfBdwdP6BYdZu/tleWtuTyCyMFOEms45y4X+SrTYbUN+skx5yuPuxpO4QRfErc/ZIJ5KH3W7W+mgIJQeZcrTTm5rTGjmtAC4lrZu4hMGDzvyoin0msaXdv6tVO7S4/MdInJGG60j0MRy+wvz+I0EDPhyoRXcLwlXO7oF3OMVU4WKOxxMuCUQQihOdpsM34f1NQzTyC+oQptTQ4SyXvc6OZrjWC9MG2BDwqBRUiQWN+hH+NH9StG4655C9/3EMolEEkUbhlhgXNVvumosu+n9RAWWIvDzevVAgMBAAECggEAA2ZsycN1d79D7tluXKXEUQSlI0MZ+76j02DXiRh14as02pBFpoAMCGgJB+DcHAvr9XQ7UqDq8jpNYlvcW3DsVZ8NDI8qTGuFHLRUHAGEoMZBtIyLcYplU+Xv8ing1SwIhM4oEVwODjNH9yFEK2PYRZJXV/XYGa/ngFLa7/6YR4K2yayIBiym4nEEiOIRQIAivEcAF4U0csfYvbUGAHvVP9tmF16ygIkh4Uyrkw2Pe/mwx3joYpxVH3T8hxpUxMX7OcGnzKnLI0QfuRrf3Ck6sVmUAu3UiAkSTWQgD4DFTqw6d97K8HflmJqdy/jOVjvJRR6yhY7df5Z5Rp4Aq25laQKBgQD3xZG5ho2xCAub/zHPndTBgi9skwCOYZVLqEqQa8ta1SSx+XHHz+XXnfCx2SFocuL9mDTUP8q+2qYRn1GtzluOv0qvRACz+SBvqJPVxlT5lIpWxHKo0CRFIuGZP5U5K3qbOq19kpnaN1oMTZS7MsWUpRZFykcb5gj/djsYh462LwKBgQD0aGpXtElEpxYMQMTi3/+9x6qHn7f24imCKc02XUmY1ktGgbpcC+Op/LCnX8bcQ9Vp1gNuqTmIbnX3RpN/I7PRoLmoo/TcQXhMCGIuSKImlgY8Bj3YUFjthtLSA8z5Uvni19fp7krk7AYGztaQ/ciBgEtAVZ6hoVF4JGM3DthBOwKBgQCF+IHu+t4qVttQIhBg3kpnx2i1IFcwpXsASaLnrCFsn8sToHjxPWxdxbybrXfu7g/mZyJJkaSixb790FNt0yKWcMCFPBPVPGNZfKFS+caAnNygReBpfwHdkBrDrimVm/jTbkrYlygxYbSC6n/9KFrFIO6GFfWVFDDRULBrdwCnaQKBgGcq7Di5UXQ5U4U4keNyynFBpyo4sV71eLAJFSatmjN5wayxdgkEu8U1dRwxwa+Ysq1KOYisxixg9Eq87+XrHCyQu84D54hR2oW9xDPlVQ0Upu0PdWup/t/E2ZjtIcjczb6DfhCxFcwsFR8qkEgD2G9RyHIPsjZn8gvU0EydZ4uhAoGATk1CafoUqz/2veE+Z18oCFqRx/MUIVUlpsIFspcCRuemerfB6T0oJEYiTQysWieViBE8Vy/anhABMuf9VJiWUOZeRH17lbOFRxz8A1iu4pl3QtEhRMzUhwStKofFT1VKYJ8mvEnssfSn9JqKvwqb8I66lscm+9FidWYzLWeUn9k=");
        certAlipayRequest.setFormat("json");
        certAlipayRequest.setCharset("utf-8");
        certAlipayRequest.setSignType("RSA2");
        certAlipayRequest.setCertPath("D:\\kings\\ud_project\\tywb\\appCertPublicKey_2016102300745149.crt");
        certAlipayRequest.setAlipayPublicCertPath("D:\\kings\\ud_project\\tywb\\alipayCertPublicKey_RSA2.crt");
        certAlipayRequest.setRootCertPath("D:\\kings\\ud_project\\tywb\\alipayRootCert.crt");
        DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);

        // 发送API请求
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody("沙箱环境");
        model.setSubject("沙箱环境");
        // 唯一订单号 根据项目中实际需要获取相应的
        // model.setOutTradeNo(UUID.randomUUID().toString().replace("-", ""));
        model.setOutTradeNo("sn000000000001");
        // 支付金额
        model.setTotalAmount("0.01");
        model.setProductCode("沙箱环境");
        request.setBizModel(model);
        request.setNotifyUrl("http://127.0.0.1/api/alipayNotify");
        AlipayTradeQueryResponse response = alipayClient.sdkExecute(request);
        System.out.println(response.getBody());
    }

    /**
     * 支付宝/余额打赏题目
     * 
     * @param questionId
     *            题库id
     * @param userId
     *            用户id
     * @param tradeNo
     *            支付宝流水号
     * @param totalAmount
     *            打赏金额
     * @param payType
     *            支付类型 1 支付宝 2 余额
     */
    @Override
    public void questionPaymentComplete(Long questionId, Long userId, String tradeNo, String totalAmount,
        Integer payType) {
        // 赏金
        BigDecimal reward = new BigDecimal(totalAmount);
        // 记录行为 question_operate
        QuestionOperateEntity operateEntity = new QuestionOperateEntity();
        operateEntity.setUserId(userId);
        operateEntity.setDataId(questionId);
        operateEntity.setType(4);
        operateEntity.setOrderSerialNumber(tradeNo);
        iQuestionOperateService.save(operateEntity);
        // 查询抽成设置中的题库抽成服务费
        RestResponse latestVersion = iCommissionSettingService.getLatestVersion();
        if (null != latestVersion) {
            CommissionSettingEntity data = (CommissionSettingEntity)latestVersion.getData();
            if (null != data) {
                BigDecimal questionCommission = data.getQuestionCommission();
                BigDecimal subtract = new BigDecimal("100").subtract(questionCommission);
                reward = reward.multiply(subtract).divide(new BigDecimal("100"));
            }
        }
        // 打赏数量加 1
        questionBankMapper.updateReward(questionId, BigDecimal.ZERO);
        // 新增专家账户流水
        QuestionBankEntity questionBankEntity = questionBankMapper.getById(questionId);
        // 新增专家流水记录
        UserBillEntity userBillEntity = new UserBillEntity();
        userBillEntity.setAmount(reward);
        userBillEntity.setUserId(questionBankEntity.getExpert());
        userBillEntity.setTargetUserId(userId);
        userBillEntity.setType(2);
        userBillEntity.setDescr("用户题库打赏");
        userBillEntity.setBusinessType(2);
        userBillEntity.setFlowNum(tradeNo);
        // 查询最近一次的余额
        BigDecimal latestBalance = iUserBillService.getLatestBalance(questionBankEntity.getExpert());
        if (null != latestBalance) {
            userBillEntity.setBalance(latestBalance.add(reward));
        }
        iUserBillService.save(userBillEntity);
        // 修改余额
        userInfoMapper.rechargePayBalance(questionBankEntity.getExpert(), reward);

        // 用户自己也要记录流水
        UserBillEntity billEntity = new UserBillEntity();
        billEntity.setAmount(new BigDecimal(totalAmount));
        billEntity.setUserId(userId);
        billEntity.setTargetUserId(questionBankEntity.getExpert());
        billEntity.setType(1);
        billEntity.setBusinessType(2);
        billEntity.setFlowNum(tradeNo);
        // 查询最近一次的余额
        BigDecimal ba = iUserBillService.getLatestBalance(userId);
        if (payType == 1) {
            billEntity.setDescr("支付宝题库打赏");
            billEntity.setBalance(ba);
        } else {
            billEntity.setDescr("余额题库打赏");
            billEntity.setBalance(ba.subtract(new BigDecimal(totalAmount)));
            // 减少余额
            userInfoMapper.updateUserBalance(userId, new BigDecimal(totalAmount));
        }

        iUserBillService.save(billEntity);

        if (payType == 1) {
            log.info("--- 支付宝题库打赏记录平台流水开始 ---");
            // 记录平台流水
            TyBillEntity tyBill = new TyBillEntity();
            tyBill.setAmount(new BigDecimal(totalAmount));
            tyBill.setCreateTime(LocalDateTime.now());
            tyBill.setUserId(userId);
            tyBill.setFlowNum(tradeNo);
            tyBill.setType(2);// '交易类型 1：支出、2：收入
            tyBill.setBusinessType(2);
            tyBill.setDescr("用户题库打赏");
            BigDecimal balance = iTyBillService.getLatestBalance();
            tyBill.setBalance(balance.add(new BigDecimal(totalAmount)));
            iTyBillService.save(tyBill);
            log.info("--- 支付宝题库打赏记录平台流水结束 ---");
        }

    }

    /**
     * 支付宝/余额打赏视频
     * 
     * @param videoId
     *            视频id
     * @param userId
     *            用户id
     * @param tradeNo
     *            支付宝流水号
     * @param totalAmount
     *            打赏金额
     * @param payType
     *            支付类型 1 支付宝 2 余额
     */
    @Override
    public void videoPaymentComplete(Long videoId, Long userId, String tradeNo, String totalAmount, Integer payType) {
        // 赏金
        BigDecimal reward = new BigDecimal(totalAmount);
        // 记录行为 question_operate
        SchoolVideoOperateEntity videoOperateEntity = new SchoolVideoOperateEntity();
        videoOperateEntity.setUserId(userId);
        videoOperateEntity.setDataId(videoId);
        videoOperateEntity.setType(4);
        videoOperateEntity.setThirdOrderSn(tradeNo);
        schoolVideoOperateService.save(videoOperateEntity);
        // 查询抽成设置中的题库抽成服务费
        RestResponse latestVersion = iCommissionSettingService.getLatestVersion();
        if (null != latestVersion) {
            CommissionSettingEntity data = (CommissionSettingEntity)latestVersion.getData();
            if (null != data) {
                BigDecimal videoCommission = data.getSchoolCommission();
                BigDecimal subtract = new BigDecimal("100").subtract(videoCommission);
                reward = reward.multiply(subtract).divide(new BigDecimal("100"));
            }
        }
        // 打赏数量加 1
        schoolVideoService.updateReward(videoId);
        // 新增专家账户流水
        SchoolVideoEntity videoEntity = schoolVideoService.getById(videoId);

        // 新增专家流水记录
        UserBillEntity userBillEntity = new UserBillEntity();
        userBillEntity.setAmount(reward);
        userBillEntity.setUserId(videoEntity.getUserId());
        userBillEntity.setTargetUserId(userId);
        userBillEntity.setType(2);
        userBillEntity.setDescr("用户视频打赏");
        userBillEntity.setBusinessType(2);
        userBillEntity.setFlowNum(tradeNo);
        // 查询最近一次的余额
        BigDecimal latestBalance = iUserBillService.getLatestBalance(videoEntity.getUserId());
        if (null != latestBalance) {
            userBillEntity.setBalance(latestBalance.add(reward));
        }
        iUserBillService.save(userBillEntity);
        // 修改余额
        userInfoMapper.rechargePayBalance(videoEntity.getUserId(), reward);

        // 用户自己也要记录流水
        UserBillEntity billEntity = new UserBillEntity();
        billEntity.setAmount(new BigDecimal(totalAmount));
        billEntity.setUserId(userId);
        billEntity.setTargetUserId(videoEntity.getUserId());
        billEntity.setType(1);
        billEntity.setBusinessType(2);
        billEntity.setFlowNum(tradeNo);
        // 查询最近一次的余额
        BigDecimal ba = iUserBillService.getLatestBalance(userId);
        if (payType == 1) {
            billEntity.setDescr("支付宝视频打赏");
            billEntity.setBalance(ba);
        } else {
            billEntity.setDescr("余额视频打赏");
            billEntity.setBalance(ba.subtract(new BigDecimal(totalAmount)));
            // 减少余额
            userInfoMapper.updateUserBalance(userId, new BigDecimal(totalAmount));
        }
        iUserBillService.save(billEntity);

        if (payType == 1) {
            log.info("--- 支付宝视频记录平台流水开始 ---");
            // 记录平台流水
            TyBillEntity tyBill = new TyBillEntity();
            tyBill.setAmount(new BigDecimal(totalAmount));
            tyBill.setCreateTime(LocalDateTime.now());
            tyBill.setUserId(userId);
            tyBill.setFlowNum(tradeNo);
            tyBill.setType(2);// '交易类型 1：支出、2：收入
            tyBill.setBusinessType(2);
            tyBill.setDescr("用户视频打赏");
            BigDecimal balance = iTyBillService.getLatestBalance();
            tyBill.setBalance(balance.add(new BigDecimal(totalAmount)));
            iTyBillService.save(tyBill);
            log.info("--- 支付宝视频记录平台流水结束 ---");
        }

    }

    /**
     * 支付完成问诊业务处理
     *
     * @param outTradeNo
     *            订单号
     * @param totalAmount
     *            订单金额
     * @param tradeNo
     *            支付宝流水号
     */
    @Override
    public void zfbCasePaymentComplete(String outTradeNo, String totalAmount, String tradeNo) {
        LocalDateTime date = LocalDateTime.now();
        // 完善订单状态
        QueryWrapper<LiftCaseEntity> orderWrapper = new QueryWrapper<LiftCaseEntity>();
        orderWrapper.eq("order_no", outTradeNo);
        // 诊单信息
        LiftCaseEntity caseEntity = liftCaseService.getOne(orderWrapper);
        final int orderId = caseEntity.getId().intValue();
        // 发起人ID
        Long userId = caseEntity.getCreateUserId();
        String sessionId = UUIDUtil.getUuidByTime9();
        // 支付完成生成聊天室
        ChatSessionEntity entity = new ChatSessionEntity();
        entity.setSessionid(sessionId);
        entity.setStatuz(1); // 状态1:正常0:屏蔽
        entity.setUserId(caseEntity.getCreateUserId().toString());
        entity.setCreateUserId(caseEntity.getCreateUserId().toString());
        entity.setDataTable(1);// '问诊出诊 1问诊2出诊',
        entity.setDataId(orderId);
        entity.setCreateTime(date);
        List<ChatSessionEntity> sessionList = new ArrayList<>();
        sessionList.add(entity);
        chatSessionService.saveBatch(sessionList);
        // 在redis中创建房间
        RoomInfo roomInfo = new RoomInfo();
        roomInfo.setSessionid(entity.getSessionid());
        roomInfo.setDataTable(entity.getDataTable());
        roomInfo.setLastTime(entity.getCreateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
        UserInfo userInfo1 = new UserInfo();
        userInfo1.setUserId(entity.getUserId());
        List<UserInfo> userList = new ArrayList<>();
        userList.add(userInfo1);
        roomInfo.setUserLIst(userList);
        redis.setValue("ROOM:" + entity.getSessionid(), roomInfo);
        // 完善诊单状态
        /**
         * 问诊：0待付款(创建订单） =》 1已付款（待接单）=》 2已接单 =》 3专家确认完成 =》 4用户确认完成(待评价) =》 5待归档（已评价） =》 6已归档 =》 7申诉中 出诊：0待接单(创建订单) =》
         * 1已接单（待报价） =》 2待付款（已报价） =》 3已付款（已付款，专家待确认） =》 4专家确认完成 =》 5用户确认完成（待评价） =》 6已评价（已完成） =》 7申诉中'
         */
        caseEntity.setStatuz(1);
        caseEntity.setSessionId(sessionId);
        caseEntity.setUpdateTime(date);

        caseEntity.setOrderSerialNumber(tradeNo);
        liftCaseService.saveOrUpdate(caseEntity);

        if (caseEntity.getCouponId() != null) {
            // 使用卡券，修改状态
            userCouponMapper.updateOrderIdAndStatusByCouponIdAndUserId(caseEntity.getCouponId(), 2, caseEntity.getId());
        }

        if (caseEntity.getRedEnvelopeId() != null) {
            // 是否使用红包修改状态
            userCouponMapper.updateOrderIdAndStatusByCouponIdAndUserId(caseEntity.getRedEnvelopeId(), 2,
                caseEntity.getId());
        }

        log.info("--- 支付宝问诊记录平台流水开始 ---");
        // 记录平台流水
        TyBillEntity tyBill = new TyBillEntity();
        tyBill.setAmount(new BigDecimal(totalAmount));
        tyBill.setCreateTime(date);
        tyBill.setUserId(userId);
        tyBill.setFlowNum(tradeNo);
        // '交易类型 1：支出、2：收入
        tyBill.setType(2);
        tyBill.setBusinessType(4);
        tyBill.setDescr("问诊收入");
        BigDecimal balance = iTyBillService.getLatestBalance();
        tyBill.setBalance(balance.add(new BigDecimal(totalAmount)));
        iTyBillService.save(tyBill);
        log.info("--- 支付宝问诊记录平台流水结束 ---");

        log.info("开始记录发起问诊用户流水信息");
        // 发起问诊用户新增流水信息
        UserBillEntity billUpEntity = new UserBillEntity();
        billUpEntity.setCreateTime(date);
        billUpEntity.setUserId(userId);
        billUpEntity.setTargetUserId(caseEntity.getChargerId());
        billUpEntity.setAmount(new BigDecimal(totalAmount));
        billUpEntity.setType(1);
        billUpEntity.setBusinessType(4);
        billUpEntity.setDescr("支付宝支付问诊服务费");
        billUpEntity.setFlowNum(tradeNo);
        // 查询最近一次的余额
        BigDecimal latestBalance = iUserBillService.getLatestBalance(userId);
        billUpEntity.setBalance(latestBalance);
        iUserBillService.save(billUpEntity);

        // log.info("开始记录专家流水信息");
        // //专家新增流水信息
        // BigDecimal fee = new BigDecimal("0");
        //
        // if(null != caseEntity && null != caseEntity.getChargerId()){
        // // 计算专家应该获得的服务费
        // BigDecimal expertFee = liftCaseService.getExpertFee(caseEntity.getChargerId());
        // //如果专家存在，就新增流水，修改余额
        // Long chargerId = caseEntity.getChargerId();
        // UserBillEntity billEntity = new UserBillEntity();
        // billEntity.setCreateTime(date);
        // billEntity.setUserId(chargerId);
        // billEntity.setAmount(expertFee);
        // billEntity.setType(2);
        // billEntity.setBusinessType(4);
        // billEntity.setDescr("问诊服务费收入");
        // billEntity.setFlowNum(tradeNo);
        // // 查询最近一次的余额
        // BigDecimal expertBalance = iUserBillService.getLatestBalance(chargerId);
        // billEntity.setBalance(expertBalance.add(expertFee));
        // iUserBillService.save(billEntity);
        // // 专家 user_info 余额增加
        // UserInfoEntity uiEntity = new UserInfoEntity();
        // uiEntity.setUserId(chargerId);
        // uiEntity.setBalance(expertBalance.add(expertFee));
        // userInfoMapper.updateUserInfo(uiEntity);
        // }else{
        // log.info("问诊对应的专家找不到");
        // }
        log.info("记录流水完成");

        log.info("交易成功，处理业务代码完成");
    }

    /**
     * 支付完成出诊业务处理
     *
     * @param outTradeNo
     *            订单号
     * @param totalAmount
     *            订单金额
     * @param tradeNo
     *            支付宝流水号
     */
    @Override
    public void zfbCallPaymentComplete(String outTradeNo, String totalAmount, String tradeNo) {
        LocalDateTime date = LocalDateTime.now();

        // 完善订单状态
        QueryWrapper<LiftCaseEntity> orderWrapper = new QueryWrapper<LiftCaseEntity>();
        orderWrapper.eq("order_no", outTradeNo);
        // 诊单信息
        LiftCaseEntity caseEntity = liftCaseService.getOne(orderWrapper);

        final int orderId = caseEntity.getId().intValue();
        // 发起人ID
        Long userId = caseEntity.getCreateUserId();

//        String sessionId = UUIDUtil.getUuidByTime9();
//        // 支付完成生成聊天室
//        ChatSessionEntity entity = new ChatSessionEntity();
//        entity.setSessionid(sessionId);
//        entity.setStatuz(1); // 状态1:正常0:屏蔽
//        entity.setUserId(caseEntity.getCreateUserId().toString());
//        entity.setCreateUserId(caseEntity.getCreateUserId().toString());
//        entity.setDataTable(2);// '问诊出诊 1问诊2出诊',
//        entity.setDataId(orderId);
//        entity.setCreateTime(date);
//        List<ChatSessionEntity> sessionList = new ArrayList<>();
//        sessionList.add(entity);
//        chatSessionService.saveBatch(sessionList);
//
//        // 在redis中创建房间
//        RoomInfo roomInfo = new RoomInfo();
//        roomInfo.setSessionid(entity.getSessionid());
//        roomInfo.setDataTable(entity.getDataTable());
//        roomInfo.setLastTime(entity.getCreateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
//        UserInfo userInfo1 = new UserInfo();
//        userInfo1.setUserId(entity.getUserId());
//        List<UserInfo> userList = new ArrayList<>();
//        userList.add(userInfo1);
//        roomInfo.setUserLIst(userList);
//        redis.setValue("ROOM:" + entity.getSessionid(), roomInfo);

        // 完善诊单状态
        /**
         * 问诊：0待付款(创建订单） =》 1已付款（待接单）=》 2已接单 =》 3专家确认完成 =》 4用户确认完成(待评价) =》 5待归档（已评价） =》 6已归档 =》 7申诉中 出诊：0待接单(创建订单)
         * =》1已接单（待报价） =》 2待付款（已报价） =》 3已付款（已付款，专家待确认） =》 4专家确认完成 =》 5用户确认完成（待评价） =》 6已评价（已完成） =》 7申诉中'
         */
        caseEntity.setStatuz(3);
        caseEntity.setUpdateTime(date);
        caseEntity.setOrderSerialNumber(tradeNo);
        liftCaseService.saveOrUpdate(caseEntity);

        if (caseEntity.getCouponId() != null) {
            // 使用卡券，修改状态
            userCouponMapper.updateOrderIdAndStatusByCouponIdAndUserId(caseEntity.getCouponId(), 2, caseEntity.getId());
        }

        if (caseEntity.getRedEnvelopeId() != null) {
            // 是否使用红包修改状态
            userCouponMapper.updateOrderIdAndStatusByCouponIdAndUserId(caseEntity.getRedEnvelopeId(), 2,
                caseEntity.getId());
        }

        log.info("--- 支付宝出诊记录平台流水开始 ---");
        // 记录平台流水
        TyBillEntity tyBill = new TyBillEntity();
        tyBill.setAmount(new BigDecimal(totalAmount));
        tyBill.setCreateTime(date);
        tyBill.setUserId(userId);
        tyBill.setFlowNum(tradeNo);
        // '交易类型 1：支出、2：收入
        tyBill.setType(2);
        tyBill.setBusinessType(4);
        tyBill.setDescr("出诊收入");
        BigDecimal balance = iTyBillService.getLatestBalance();
        tyBill.setBalance(balance.add(new BigDecimal(totalAmount)));
        iTyBillService.save(tyBill);
        log.info("--- 支付宝出诊记录平台流水结束 ---");
        log.info("开始记录发起出诊用户流水信息");

        // 发起问诊用户新增流水信息
        UserBillEntity billUpEntity = new UserBillEntity();
        billUpEntity.setCreateTime(date);
        billUpEntity.setUserId(userId);
        billUpEntity.setTargetUserId(caseEntity.getChargerId());
        billUpEntity.setAmount(new BigDecimal(totalAmount));
        billUpEntity.setType(1);
        billUpEntity.setBusinessType(4);
        billUpEntity.setDescr("支付宝支付出诊服务费");
        billUpEntity.setFlowNum(tradeNo);
        // 查询最近一次的余额
        BigDecimal latestBalance = iUserBillService.getLatestBalance(userId);
        billUpEntity.setBalance(latestBalance);
        iUserBillService.save(billUpEntity);

        PushUserInfo pushUserInfo =
            iUserAccountService.getPushUserInfoByUserId(caseEntity.getChargerId().toString());
        PushMessage pushMessage = PushMessage.orderChargeStatus("用戶已付款");
        pushMessage.sendTokenOnPlatform(jmsMessagingTemplate, pushUserInfo);
        // log.info("开始记录专家流水信息");
        // //专家新增流水信息
        // BigDecimal fee = new BigDecimal("0");
        //
        // if(null != caseEntity && null != caseEntity.getChargerId()){
        // // 计算专家应该获得的服务费
        // BigDecimal expertFee = liftCaseService.getExpertFee(caseEntity.getChargerId());
        // //如果专家存在，就新增流水，修改余额
        // Long chargerId = caseEntity.getChargerId();
        // UserBillEntity billEntity = new UserBillEntity();
        // billEntity.setCreateTime(date);
        // billEntity.setUserId(chargerId);
        // billEntity.setAmount(expertFee);
        // billEntity.setType(2);
        // billEntity.setBusinessType(4);
        // billEntity.setDescr("出诊服务费收入");
        // billEntity.setFlowNum(tradeNo);
        // // 查询最近一次的余额
        // BigDecimal expertBalance = iUserBillService.getLatestBalance(chargerId);
        // billEntity.setBalance(expertBalance.add(expertFee));
        // iUserBillService.save(billEntity);
        // // 专家 user_info 余额增加
        // UserInfoEntity uiEntity = new UserInfoEntity();
        // uiEntity.setUserId(chargerId);
        // uiEntity.setBalance(expertBalance.add(expertFee));
        // userInfoMapper.updateUserInfo(uiEntity);
        // }else{
        // log.info("问诊对应的专家找不到");
        // }
        // log.info("记录流水完成");

        log.info("交易成功，处理业务代码完成");
    }

    /**
     * 余额完成问诊业务处理
     *
     * @param outTradeNo
     *            订单号
     * @param totalAmount
     *            订单金额
     * @param tradeNo
     *            自动生成的流水号
     * @param userId
     *            发起用户ID
     */
    @Override
    public void yeCasePaymentComplete(String outTradeNo, String totalAmount, String tradeNo, Long userId) {
        LocalDateTime date = LocalDateTime.now();
        // 完善订单状态
        QueryWrapper<LiftCaseEntity> orderWrapper = new QueryWrapper<LiftCaseEntity>();
        orderWrapper.eq("order_no", outTradeNo);
        // 诊单信息
        LiftCaseEntity caseEntity = liftCaseService.getOne(orderWrapper);

        final int orderId = caseEntity.getId().intValue();
        String sessionId = UUIDUtil.getUuidByTime9();
        // 完善诊单状态
        /**
         * 问诊：0待付款(创建订单） =》 1已付款（待接单）=》 2已接单 =》 3专家确认完成 =》 4用户确认完成(待评价) =》 5待归档（已评价） =》 6已归档 =》 7申诉中 出诊：0待接单(创建订单) =》
         * 1已接单（待报价） =》 2待付款（已报价） =》 3已付款（已付款，专家待确认） =》 4专家确认完成 =》 5用户确认完成（待评价） =》 6已评价（已完成） =》 7申诉中'
         */
        caseEntity.setStatuz(1);
        caseEntity.setSessionId(sessionId);
        caseEntity.setUpdateTime(date);

        caseEntity.setOrderSerialNumber(tradeNo);
        liftCaseService.saveOrUpdate(caseEntity);


        // 支付完成生成聊天室
        ChatSessionEntity entity = new ChatSessionEntity();
        entity.setSessionid(sessionId);
        entity.setStatuz(1); // 状态1:正常0:屏蔽
        entity.setUserId(caseEntity.getCreateUserId().toString());
        entity.setCreateUserId(caseEntity.getCreateUserId().toString());
        entity.setDataTable(1);// '问诊出诊 1问诊2出诊',
        entity.setDataId(orderId);
        entity.setCreateTime(date);
//        List<ChatSessionEntity> sessionList = new ArrayList<>();
//        sessionList.add(entity);

        chatSessionService.save(entity);

        // 在redis中创建房间
        RoomInfo roomInfo = new RoomInfo();
        roomInfo.setSessionid(entity.getSessionid());
        roomInfo.setDataTable(entity.getDataTable());
        roomInfo.setLastTime(entity.getCreateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
        UserInfo userInfo1 = new UserInfo();
        userInfo1.setUserId(entity.getUserId());
        List<UserInfo> userList = new ArrayList<>();
        userList.add(userInfo1);
        roomInfo.setUserLIst(userList);
        redis.setValue("ROOM:" + entity.getSessionid(), roomInfo);



        if (caseEntity.getCouponId() != null) {
            // 使用卡券，修改状态
            userCouponMapper.updateOrderIdAndStatusByCouponIdAndUserId(caseEntity.getCouponId(), 2, caseEntity.getId());
        }

        if (caseEntity.getRedEnvelopeId() != null) {
            // 是否使用红包修改状态
            userCouponMapper.updateOrderIdAndStatusByCouponIdAndUserId(caseEntity.getRedEnvelopeId(), 2,
                caseEntity.getId());
        }

        log.info("开始记录发起问诊用户流水信息");
        // 发起问诊用户新增流水信息
        UserBillEntity billUpEntity = new UserBillEntity();
        billUpEntity.setCreateTime(date);
        billUpEntity.setUserId(userId);
        billUpEntity.setTargetUserId(caseEntity.getChargerId());
        billUpEntity.setAmount(new BigDecimal(totalAmount));
        billUpEntity.setType(1);
        billUpEntity.setBusinessType(4);
        billUpEntity.setDescr("余额完成问诊服务费");
        billUpEntity.setFlowNum(tradeNo);
        // 查询最近一次的余额
        BigDecimal latestBalance = iUserBillService.getLatestBalance(userId);
        billUpEntity.setBalance(latestBalance.subtract(new BigDecimal(totalAmount)));
        iUserBillService.save(billUpEntity);

        // 发起人 user_info 余额减少
        UserInfoEntity uEntity = new UserInfoEntity();
        uEntity.setUserId(userId);
        uEntity.setBalance(latestBalance.subtract(new BigDecimal(totalAmount)));
        userInfoMapper.updateUserInfo(uEntity);

        // log.info("开始记录专家流水信息");
        // //专家新增流水信息
        // BigDecimal fee = new BigDecimal("0");
        //
        // if(null != caseEntity && null != caseEntity.getChargerId()){
        // // 计算专家应该获得的服务费
        // BigDecimal expertFee = liftCaseService.getExpertFee(caseEntity.getChargerId());
        // //如果专家存在，就新增流水，修改余额
        // Long chargerId = caseEntity.getChargerId();
        // UserBillEntity billEntity = new UserBillEntity();
        // billEntity.setCreateTime(date);
        // billEntity.setUserId(chargerId);
        // billEntity.setAmount(expertFee);
        // billEntity.setType(2);
        // billEntity.setBusinessType(4);
        // billEntity.setDescr("问诊服务费收入");
        // billEntity.setFlowNum(tradeNo);
        // // 查询最近一次的余额
        // BigDecimal expertBalance = iUserBillService.getLatestBalance(chargerId);
        // billEntity.setBalance(expertBalance.add(expertFee));
        // iUserBillService.save(billEntity);
        // // 专家 user_info 余额增加
        // UserInfoEntity uiEntity = new UserInfoEntity();
        // uiEntity.setUserId(chargerId);
        // uiEntity.setBalance(expertBalance.add(expertFee));
        // userInfoMapper.updateUserInfo(uiEntity);
        // }else{
        // log.info("问诊对应的专家找不到");
        // }
        // log.info("记录流水完成");

        log.info("交易成功，处理业务代码完成");
    }

    /**
     * 余额成出诊业务处理
     *
     * @param outTradeNo
     *            订单号
     * @param totalAmount
     *            订单金额
     * @param tradeNo
     *            自动生成的流水号
     * @param userId
     *            发起用户ID
     */
    @Override
    public void yeCallPaymentComplete(String outTradeNo, String totalAmount, String tradeNo, Long userId) {
        LocalDateTime date = LocalDateTime.now();

        // 完善订单状态
        QueryWrapper<LiftCaseEntity> orderWrapper = new QueryWrapper<LiftCaseEntity>();
        orderWrapper.eq("order_no", outTradeNo);
        // 诊单信息
        LiftCaseEntity caseEntity = liftCaseService.getOne(orderWrapper);

        final int orderId = caseEntity.getId().intValue();

//        String sessionId = UUIDUtil.getUuidByTime9();
//        // 支付完成生成聊天室
//        ChatSessionEntity entity = new ChatSessionEntity();
//        entity.setSessionid(sessionId);
//        entity.setStatuz(1); // 状态1:正常0:屏蔽
//        entity.setUserId(caseEntity.getCreateUserId().toString());
//        entity.setCreateUserId(caseEntity.getCreateUserId().toString());
//        entity.setDataTable(2);// '问诊出诊 1问诊2出诊',
//        entity.setDataId(orderId);
//        entity.setCreateTime(date);
//        List<ChatSessionEntity> sessionList = new ArrayList<>();
//
//        sessionList.add(entity);
//
//        chatSessionService.saveBatch(sessionList);
//        // 在redis中创建房间
//        RoomInfo roomInfo = new RoomInfo();
//        roomInfo.setSessionid(entity.getSessionid());
//        roomInfo.setDataTable(entity.getDataTable());
//        roomInfo.setLastTime(entity.getCreateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
//        UserInfo userInfo1 = new UserInfo();
//        userInfo1.setUserId(entity.getUserId());
//        List<UserInfo> userList = new ArrayList<>();
//        userList.add(userInfo1);
//        roomInfo.setUserLIst(userList);
//        redis.setValue("ROOM:" + entity.getSessionid(), roomInfo);
        // 完善诊单状态
        /**
         * 问诊：0待付款(创建订单） =》 1已付款（待接单）=》 2已接单 =》 3专家确认完成 =》 4用户确认完成(待评价) =》 5待归档（已评价） =》 6已归档 =》 7申诉中 出诊：0待接单(创建订单)
         * =》1已接单（待报价） =》 2待付款（已报价） =》 3已付款（已付款，专家待确认） =》 4专家确认完成 =》 5用户确认完成（待评价） =》 6已评价（已完成） =》 7申诉中'
         */
        caseEntity.setStatuz(3);
        caseEntity.setUpdateTime(date);
        caseEntity.setOrderSerialNumber(tradeNo);
        liftCaseService.saveOrUpdate(caseEntity);

        if (caseEntity.getCouponId() != null) {
            // 使用卡券，修改状态
            userCouponMapper.updateOrderIdAndStatusByCouponIdAndUserId(caseEntity.getCouponId(), 2, caseEntity.getId());
        }

        if (caseEntity.getRedEnvelopeId() != null) {
            // 是否使用红包修改状态
            userCouponMapper.updateOrderIdAndStatusByCouponIdAndUserId(caseEntity.getRedEnvelopeId(), 2,
                caseEntity.getId());
        }

        log.info("开始记录用户流水信息");
        // 发起问诊用户新增流水信息
        // 减少余额
        userInfoMapper.updateUserBalance(userId, new BigDecimal(totalAmount));
        // 新增消费记录
        UserBillEntity userBillEntity = new UserBillEntity();
        userBillEntity.setAmount(new BigDecimal(totalAmount));
        userBillEntity.setUserId(userId);
        userBillEntity.setTargetUserId(caseEntity.getChargerId());
        userBillEntity.setType(1);
        userBillEntity.setDescr("余额支付出诊服务费");
        userBillEntity.setBusinessType(4);
        // 生成流水号
        userBillEntity.setFlowNum(tradeNo);
        // 查询最近一次的余额
        BigDecimal latestBalance = iUserBillService.getLatestBalance(userId);
        if (null != latestBalance) {
            userBillEntity.setBalance(latestBalance.subtract(new BigDecimal(totalAmount)));
        }
        iUserBillService.save(userBillEntity);

        // 发起人 user_info 余额减少
        UserInfoEntity uEntity = new UserInfoEntity();
        uEntity.setUserId(userId);
        uEntity.setBalance(latestBalance.subtract(new BigDecimal(totalAmount)));
        userInfoMapper.updateUserInfo(uEntity);

        // log.info("开始记录专家流水信息");
        // //专家新增流水信息
        // BigDecimal fee = new BigDecimal("0");
        //
        // if(null != caseEntity && null != caseEntity.getChargerId()){
        // // 计算专家应该获得的服务费
        // BigDecimal expertFee = liftCaseService.getExpertFee(caseEntity.getChargerId());
        // //如果专家存在，就新增流水，修改余额
        // Long chargerId = caseEntity.getChargerId();
        // UserBillEntity billEntity = new UserBillEntity();
        // billEntity.setCreateTime(date);
        // billEntity.setUserId(chargerId);
        // billEntity.setAmount(expertFee);
        // billEntity.setType(2);
        // billEntity.setBusinessType(4);
        // billEntity.setDescr("出诊服务费收入");
        // billEntity.setFlowNum(tradeNo);
        // // 查询最近一次的余额
        // BigDecimal expertBalance = iUserBillService.getLatestBalance(chargerId);
        // billEntity.setBalance(expertBalance.add(expertFee));
        // iUserBillService.save(billEntity);
        // // 专家 user_info 余额增加
        // UserInfoEntity uiEntity = new UserInfoEntity();
        // uiEntity.setUserId(chargerId);
        // uiEntity.setBalance(expertBalance.add(expertFee));
        // userInfoMapper.updateUserInfo(uiEntity);
        // }else{
        // log.info("出诊对应的专家找不到");
        // }
        // log.info("记录流水完成");

        log.info("交易成功，处理业务代码完成");
    }

    /**
     * 完成充值业务处理
     *
     * @param outTradeNo
     *            订单号
     * @param totalAmount
     *            订单金额
     * @param tradeNo
     *            支付宝流水号
     * @param dto
     *            回传参数
     */
    @Override
    public void rechargePay(String outTradeNo, String totalAmount, String tradeNo, PassbackParamsDTO dto) {
        LocalDateTime date = LocalDateTime.now();

        QueryWrapper<UserInfoEntity> queryWrapper = new QueryWrapper<UserInfoEntity>();
        queryWrapper.eq("user_id", dto.getUserId());
        UserInfoEntity user = userInfo.getOne(queryWrapper);

        // 组装用户流水记录
        BigDecimal amount = new BigDecimal(totalAmount);
        UserBillEntity entity = new UserBillEntity();
        entity.setAmount(amount);
        entity.setCreateTime(date);
        entity.setUserId(user.getUserId());
        entity.setTargetUserId(1L);
        entity.setFlowNum(tradeNo);
        entity.setType(2);// '交易类型 1：支出、2：收入
        entity.setBusinessType(3); // '业务类型：如：2 打赏，3 充值，1 充值会员',
        entity.setDescr(dto.getMemo());
        entity.setBalance(user.getBalance().add(amount));
        userBillService.save(entity);

        log.info("--- 支付宝充值记录平台流水开始 ---");
        // 记录平台流水
        TyBillEntity tyBill = new TyBillEntity();
        tyBill.setAmount(amount);
        tyBill.setCreateTime(date);
        tyBill.setUserId(user.getUserId());
        tyBill.setFlowNum(tradeNo);
        tyBill.setType(2);// '交易类型 1：支出、2：收入
        tyBill.setBusinessType(3); // '业务类型：如：2 打赏，3 充值，1 充值会员',
        tyBill.setDescr("用户充值");
        BigDecimal latestBalance = iTyBillService.getLatestBalance();
        tyBill.setBalance(latestBalance.add(amount));
        iTyBillService.save(tyBill);
        log.info("--- 支付宝充值记录平台流水结束 ---");
        // 完善充值记录信息
        QueryWrapper<UserRechargeDetailEntity> rechargeWrapper = new QueryWrapper<UserRechargeDetailEntity>();
        rechargeWrapper.eq("order_sn", outTradeNo);
        UserRechargeDetailEntity rechargeDetail = userRechargeDetailService.getOne(rechargeWrapper);
        rechargeDetail.setPayTime(new Date());
        rechargeDetail.setPayStatus(2);// 订单支付状态、1待支付2、已支付、3支付失败、4已取消',
        rechargeDetail.setMemo(dto.getMemo());
        rechargeDetail.setProductPrice(amount);
        rechargeDetail.setThirdOrderSn(tradeNo);
        rechargeDetail.setUpdateTime(date);
        userRechargeDetailService.saveOrUpdate(rechargeDetail);

        // 更新用户余额
        userInfo.rechargePayBalance(dto.getUserId(), amount);

        log.info("交易成功，处理业务代码完成");
    }

    /**
     * 成为会员业务处理部分
     *
     * @param vipFeeSetting
     *            会费id
     * @param userId
     * @param tradeNo
     * @param totalAmount
     * @return
     */
    @Override
    public void toVIPPaymentComplete(Long vipFeeSetting, Long userId, String tradeNo, String totalAmount) {
        QueryWrapper<VipFeeSettingEntity> queryWrapper = new QueryWrapper<VipFeeSettingEntity>();
        queryWrapper.eq("id", vipFeeSetting);
        VipFeeSettingEntity entity = vipFeeSettingService.getOne(queryWrapper);
        UserInfoEntity userInfoEntity = userInfoMapper.getByUserId(userId);
        if (null == userInfoEntity) {
            log.error("当前用户不存在");
        } else {
            // 根据有效期查询会费
            BigDecimal fee = entity.getPrice();
            UserLevelRuleEntity userLevelRole = iUserLevelRuleService.getById(entity.getUserLevelId());
            if (null == userLevelRole) {
                log.error("当前会员角色等级不存在，请检查");
            }
            // 升级为会员，同时生成唯一的6位数字邀请码,同时修改会员相关的三个字段
            int code = (int)(((Math.random() * 9) + 1) * 100000);
            LocalDateTime vipStartTime = LocalDateTime.now();
            LocalDateTime vipEndTime = LocalDateTime.now();

            if (null != userInfoEntity.getVipStartTime()) {
                vipStartTime = userInfoEntity.getVipStartTime();
            }

            if (null != userInfoEntity.getVipEndTime() && userInfoEntity.getVipFlag() == 2) {
                vipEndTime = userInfoEntity.getVipEndTime().plusMonths(entity.getPeriod());
            } else {
                vipEndTime = vipEndTime.plusMonths(entity.getPeriod());
            }

            int month = monthDiff(LocalDateTime.now(), vipEndTime);
            // 获取VIP的等级
            int level = 1;
            if (month >= 1 && month < 3) {
                level = 1;
            } else if (month >= 3 && month < 12) {
                level = 3;
            } else if (month >= 12) {
                level = 12;
            }
            UserAccount userAccount = iUserAccountService.getOneById(userId);
            UserLevelRuleEntity expert = iUserLevelRuleService.getByCode("EXPERT");
            if (null != userAccount && userAccount.getExpertFlag() == 1) {
                // 专家,如果是专家，user_level_name 显示专家，user_level 保存会员角色ID
                userInfoMapper.toVip(userLevelRole.getId(), expert.getName(), code, vipStartTime, vipEndTime,
                    month > 0 ? month : 0, entity.getId(), userId);
            } else {
                // 不是专家
                userInfoMapper.toVip(userLevelRole.getId(), userLevelRole.getName(), code, vipStartTime, vipEndTime,
                    month > 0 ? month : 0, entity.getId(), userId);
            }

            // 如果是第一次成为会员，或者不是后台直接升级成会员的(是vip但是没有邀请码)
            // user_rebate 中修改此人的会费信息,并且给他的上级返利
            // 判断是否是第一次充值成为会员
            UserBillEntity userBill = iUserBillService.getByUserIdAndBusinessType(userId, 1);
            if (null == userBill && userInfoEntity.getRequestCode() == null) {
                // 第一次成为会员
                // 如果他有上级，上级的user_bill中加入流水信息，余额增加
                UserRebateEntity upUser = iUserRebateService.getUpUser(userId);
                if (null != upUser) {
                    // 查不到上级信息就不给他红利
                    UserInfoEntity userInfo = userInfoMapper.getByUserId(upUser.getUserId());
                    if (null != userInfo) {
                        // 如果他有上级，给上级返利，并保存记录
                        BigDecimal vipFee = saveUpUserRebateInfo(userInfo, upUser, fee, userId, tradeNo);
                        // 如果他有上上级，上上级的user_bill中加入流水信息，余额增加
                        UserRebateEntity upUpUser = iUserRebateService.getUpUser(userInfo.getUserId());
                        if (null != upUpUser) {
                            // 查不到上上级信息就不给他红利
                            UserInfoEntity upUserInfo = userInfoMapper.getByUserId(upUpUser.getUserId());
                            if (null != upUserInfo) {
                                // 给上上级返利，并保存记录
                                saveUpUpUserRebateInfo(upUserInfo, upUpUser, fee, userId, vipFee, userInfo.getUserId(),
                                    tradeNo);
                            }
                        }
                    }
                }
            }
            // ----------------- 充值的人自己也要加上流水信息,余额不变
            BigDecimal latestUserBalance = iUserBillService.getLatestBalance(userId);
            UserBillEntity uBillEntity = new UserBillEntity();
            uBillEntity.setCreateTime(LocalDateTime.now());
            uBillEntity.setUserId(userId);
            uBillEntity.setTargetUserId(1L);
            uBillEntity.setAmount(fee);
            uBillEntity.setType(1);
            uBillEntity.setDescr("充值vip会员");
            uBillEntity.setBusinessType(1);
            uBillEntity.setBalance(latestUserBalance);
            uBillEntity.setFlowNum(tradeNo);
            iUserBillService.save(uBillEntity);

            log.info("--- 充值vip会员记录平台流水开始 ---");
            // 记录平台流水
            TyBillEntity tyBill = new TyBillEntity();
            tyBill.setAmount(fee);
            tyBill.setCreateTime(LocalDateTime.now());
            tyBill.setUserId(userId);
            tyBill.setFlowNum(tradeNo);
            tyBill.setType(2);// '交易类型 1：支出、2：收入
            tyBill.setBusinessType(1);
            tyBill.setDescr("充值vip会员");
            BigDecimal balance = iTyBillService.getLatestBalance();
            tyBill.setBalance(balance.add(fee));
            iTyBillService.save(tyBill);
            log.info("--- 充值vip会员记录平台流水结束 ---");

            // 后台生成二维码，流化后上传到阿里云服务器
            try {
                String qrCodeurl = QrCodeUtil.getQrCode(userId, "/wode/vip");
                // todo 二维码
                UserInfoEntity userInfo = new UserInfoEntity();
                userInfo.setUserId(userId);
                userInfo.setQrCodeUrl(qrCodeurl);
                userInfoMapper.updateUserInfo(userInfo);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }

    /**
     * 给上级返利，并保存记录
     *
     * @param userInfo
     * @param upUser
     * @param fee
     * @param userId
     */
    public BigDecimal saveUpUserRebateInfo(UserInfoEntity userInfo, UserRebateEntity upUser, BigDecimal fee,
        Long userId, String tradeNo) {
        // 询上级获取的返利金额,上级为专家时，userLevel 对应的不是 user_level_rule 里面的专家主键ID
        // 同时为专家和vip时，返利比率以专家为准
        UserRebateRuleEntity userRebateInfo = null;
        if (userInfo.getUserLevel() != null) {
            UserAccount userAccount = iUserAccountService.getOneById(upUser.getUserId());
            if (userAccount.getExpertFlag() == 1) {
                // 是专家
                UserLevelRuleEntity expert = iUserLevelRuleService.getByCode("EXPERT");
                userRebateInfo = iUserRebateRuleService.getRebateByUserLevel(expert.getId());
            } else {
                userRebateInfo = iUserRebateRuleService.getRebateByUserLevel(userInfo.getUserLevel());
            }
            BigDecimal rebate1 = userRebateInfo.getRebate1();
            // 有上级，上级获得返利
            UserBillEntity billUpEntity = new UserBillEntity();
            billUpEntity.setCreateTime(LocalDateTime.now());
            billUpEntity.setUserId(upUser.getUserId());
            billUpEntity.setTargetUserId(upUser.getLowerUserId());
            billUpEntity.setAmount(fee.multiply(rebate1));
            billUpEntity.setType(2);
            billUpEntity.setBusinessType(11);
            billUpEntity.setDescr("一级下线返利");
            billUpEntity.setFlowNum(tradeNo);
            // 查询最近一次的余额
            BigDecimal latestBalance = iUserBillService.getLatestBalance(upUser.getUserId());
            billUpEntity.setBalance(latestBalance.add(fee.multiply(rebate1)));
            iUserBillService.save(billUpEntity);
            // 上一级的 user_info 余额增加
            UserInfoEntity uiEntity = new UserInfoEntity();
            uiEntity.setUserId(userInfo.getUserId());
            uiEntity.setBalance(latestBalance.add(fee.multiply(rebate1)));
            log.info("上级现在的余额是" + latestBalance.add(fee.multiply(rebate1)));
            userInfoMapper.updateUserInfo(uiEntity);
            // user_rebate 中修改此人的上级返利信息
            UserRebateEntity ubEntity = new UserRebateEntity();
            ubEntity.setVipFee(fee.multiply(rebate1));
            ubEntity.setLowerUserId(userId);
            ubEntity.setUserId(upUser.getUserId());
            iUserRebateService.updateByTwoId(ubEntity);
            return fee.multiply(rebate1);
            // todo 给上级发送消息
        }

        return new BigDecimal("0");

    }

    /**
     * 给上上级返利，并保存记录
     *
     * @param upUserInfo
     *            上上级用户信息
     * @param upUpUser
     *            上上级用户
     * @param fee
     * @param userId
     * @param upUserId
     *            上级ID
     */
    public void saveUpUpUserRebateInfo(UserInfoEntity upUserInfo, UserRebateEntity upUpUser, BigDecimal fee,
        Long userId, BigDecimal vipFee, Long upUserId, String tradeNo) {
        // 询上级获取的返利金额,上级为专家时，userLevel 对应的不是 user_level_rule 里面的专家主键ID
        // 同时为专家和vip时，返利比率以专家为准
        UserRebateRuleEntity userRebateInfo = null;
        if (upUserInfo.getUserLevel() != null) {
            UserAccount userAccount = iUserAccountService.getOneById(upUpUser.getUserId());
            if (userAccount.getExpertFlag() == 1) {
                // 是专家
                UserLevelRuleEntity expert = iUserLevelRuleService.getByCode("EXPERT");
                userRebateInfo = iUserRebateRuleService.getRebateByUserLevel(expert.getId());
            } else {
                userRebateInfo = iUserRebateRuleService.getRebateByUserLevel(upUserInfo.getUserLevel());
            }
            BigDecimal rebate2 = userRebateInfo.getRebate2();
            // 有上上级，上级获得返利
            UserBillEntity billUpEntity = new UserBillEntity();
            billUpEntity.setCreateTime(LocalDateTime.now());
            billUpEntity.setUserId(upUpUser.getUserId());
            billUpEntity.setTargetUserId(upUpUser.getLowerUserId());
            billUpEntity.setAmount(fee.multiply(rebate2));
            billUpEntity.setType(2);
            billUpEntity.setBusinessType(11);
            billUpEntity.setDescr("二级下线返利");
            billUpEntity.setFlowNum(tradeNo);
            // 查询最近一次的余额
            BigDecimal latestBalance = iUserBillService.getLatestBalance(upUpUser.getUserId());
            billUpEntity.setBalance(latestBalance.add(fee.multiply(rebate2)));
            iUserBillService.save(billUpEntity);
            // 上上级的 user_info 余额增加
            UserInfoEntity uiEntity = new UserInfoEntity();
            uiEntity.setUserId(upUserInfo.getUserId());
            uiEntity.setBalance(latestBalance.add(fee.multiply(rebate2)));
            userInfoMapper.updateUserInfo(uiEntity);
            log.info("上上级现在的余额是" + latestBalance.add(fee.multiply(rebate2)));
            // user_rebate 中修改此人的上上级返利信息
            UserRebateEntity ubEntity = new UserRebateEntity();
            ubEntity.setVipFeeUp(fee.multiply(rebate2));
            ubEntity.setLowerUserId(userId);
            ubEntity.setUserId(upUserId);
            ubEntity.setVipFee(vipFee);
            iUserRebateService.updateByTwoId(ubEntity);
            // todo 给上上级发送消息
        }

    }

    /**
     * 获取两个时间点的月份差
     *
     * @param dt1
     *            第一个时间点,小的那个时间
     * @param dt2
     *            第二个时间点，大的那个时间
     * @return int，即需求的月数差
     */
    public static int monthDiff(LocalDateTime dt1, LocalDateTime dt2) {
        // 获取第一个时间点的月份
        int month1 = dt1.getMonthValue();
        // 获取第一个时间点的年份
        int year1 = dt1.getYear();
        // 获取第一个时间点的月份
        int month2 = dt2.getMonthValue();
        // 获取第一个时间点的年份
        int year2 = dt2.getYear();
        // 返回两个时间点的月数差
        return (year2 - year1) * 12 + (month2 - month1);
    }

}
