admin
2025-02-25 30d8e227e8d823b6c38c3b9c90ac2df03b63befe
fanli/src/main/java/com/yeshi/fanli/service/impl/money/extract/ExtractServiceImpl.java
@@ -1,1236 +1,1379 @@
package com.yeshi.fanli.service.impl.money.extract;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.yeshi.utils.DateUtil;
import org.yeshi.utils.entity.wx.RedPackParams;
import org.yeshi.utils.entity.wx.RedPackRecord;
import org.yeshi.utils.wx.WXPayUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayFundTransToaccountTransferRequest;
import com.alipay.api.response.AlipayFundTransToaccountTransferResponse;
import com.google.gson.Gson;
import com.yeshi.fanli.dao.mybatis.AccountMessageMapper;
import com.yeshi.fanli.dao.mybatis.AlipayAccountValidNormalHistoryMapper;
import com.yeshi.fanli.dao.mybatis.ExtractAuditRecordMapper;
import com.yeshi.fanli.dao.mybatis.ExtractMapper;
import com.yeshi.fanli.dao.mybatis.ExtractRecordMapper;
import com.yeshi.fanli.dao.mybatis.HongBaoV2Mapper;
import com.yeshi.fanli.dao.mybatis.PayInfoMapper;
import com.yeshi.fanli.dao.mybatis.UserInfoMapper;
import com.yeshi.fanli.dao.mybatis.money.UserMoneyDetailMapper;
import com.yeshi.fanli.dto.HongBao;
import com.yeshi.fanli.dto.money.ExtractOrderStatisticDTO;
import com.yeshi.fanli.entity.bus.user.AlipayTransferResultInfo;
import com.yeshi.fanli.entity.bus.user.Extract;
import com.yeshi.fanli.entity.bus.user.ExtractAuditRecord;
import com.yeshi.fanli.entity.bus.user.ExtractRecord;
import com.yeshi.fanli.entity.bus.user.ExtractWeiXinRecord;
import com.yeshi.fanli.entity.bus.user.HongBaoV2;
import com.yeshi.fanli.entity.bus.user.PayInfo;
import com.yeshi.fanli.entity.bus.user.UserAccountBindingHistory;
import com.yeshi.fanli.entity.bus.user.UserInfo;
import com.yeshi.fanli.entity.common.AdminUser;
import com.yeshi.fanli.entity.money.UserMoneyDetail;
import com.yeshi.fanli.entity.money.UserMoneyDetail.UserMoneyDetailTypeEnum;
import com.yeshi.fanli.exception.ExtractException;
import com.yeshi.fanli.exception.NotExistObjectException;
import com.yeshi.fanli.exception.ObjectStateException;
import com.yeshi.fanli.exception.money.UserMoneyDetailException;
import com.yeshi.fanli.log.LogHelper;
import com.yeshi.fanli.service.inter.config.ConfigService;
import com.yeshi.fanli.service.inter.config.SystemConfigService;
import com.yeshi.fanli.service.inter.money.UserMoneyDebtService;
import com.yeshi.fanli.service.inter.money.UserMoneyDetailService;
import com.yeshi.fanli.service.inter.money.UserMoneyService;
import com.yeshi.fanli.service.inter.money.extract.ExtractRecordService;
import com.yeshi.fanli.service.inter.money.extract.ExtractService;
import com.yeshi.fanli.service.inter.money.extract.ExtractWeiXinRecordService;
import com.yeshi.fanli.service.inter.money.msg.UserMoneyMsgNotificationService;
import com.yeshi.fanli.service.inter.order.HongBaoV2Service;
import com.yeshi.fanli.service.inter.order.OrderUserStatisticService;
import com.yeshi.fanli.service.inter.push.PushService;
import com.yeshi.fanli.service.inter.user.UserAccountBindingHistoryService;
import com.yeshi.fanli.service.inter.user.UserInfoService;
import com.yeshi.fanli.util.CMQManager;
import com.yeshi.fanli.util.Constant;
import com.yeshi.fanli.util.GsonUtil;
import com.yeshi.fanli.util.MoneyBigDecimalUtil;
import com.yeshi.fanli.util.StringUtil;
import com.yeshi.fanli.util.TimeUtil;
import com.yeshi.fanli.util.factory.UserMoneyDetailFactory;
import net.sf.json.JSONObject;
@Service
public class ExtractServiceImpl implements ExtractService {
   @Resource
   private UserInfoService userInfoService;
   @Resource
   private ConfigService configService;
   @Resource
   private ExtractRecordService extractRecordService;
   @Resource
   private SystemConfigService systemConfigService;
   @Resource
   private ExtractMapper extractMapper;
   @Resource
   private ExtractAuditRecordMapper extractAuditRecordMapper;
   @Resource
   private UserInfoMapper userInfoMapper;
   @Resource
   private PayInfoMapper payInfoMapper;
   @Resource
   private AccountMessageMapper accountMessageMapper;
   @Resource
   private ExtractRecordMapper extractRecordMapper;
   @Resource
   private HongBaoV2Mapper hongBaoV2Mapper;
   @Resource
   private HongBaoV2Service hongBaoV2Service;
   @Resource
   private PushService pushService;
   @Resource
   private UserMoneyDetailMapper userMoneyDetailMapper;
   @Resource
   private UserMoneyMsgNotificationService userMoneyMsgNotificationService;
   @Resource
   private AlipayAccountValidNormalHistoryMapper alipayAccountValidNormalHistoryMapper;
   @Resource
   private UserMoneyDetailService userMoneyDetailService;
   @Resource
   private UserAccountBindingHistoryService userAccountBindingHistoryService;
   @Resource
   private UserMoneyDebtService userMoneyDebtService;
   @Resource
   private UserMoneyService userMoneyService;
   @Resource
   private OrderUserStatisticService orderUserStatisticService;
   @Resource
   private ExtractWeiXinRecordService extractWeiXinRecordService;
   @Transactional
   public Integer addExtract(Extract extract) {
      Integer integer = extract(extract);
      return integer;
   }
   @Transactional
   public Integer passExtract(final long id, AdminUser admin) {
      Extract find = extractMapper.selectByPrimaryKeyForUpdate(id);
      if (find == null)
         return Constant.NOT_EXIST_OBJACT;
      if (find.getState() != Extract.STATE_NOT_PROCESS) {
         return Constant.OBJECT_STATE_EXCEPTION;
      }
      // 更改提现状态为处理中
      Extract updateExtract = new Extract();
      updateExtract.setId(id);
      updateExtract.setState(Extract.STATE_PROCESSING);
      extractMapper.updateByPrimaryKeySelective(updateExtract);
      //TODO 新版部署后删除
      // 改变资金记录状态
      UserMoneyDetail detail = userMoneyDetailService
            .selectByTypeAndUidAndIdentifyCode(UserMoneyDetailTypeEnum.extract, find.getUserInfo().getId(), find.getId());
      if (detail != null) {
         UserMoneyDetail update = new UserMoneyDetail(detail.getId());
         update.setShow(true);
         update.setUpdateTime(new Date());
         userMoneyDetailMapper.updateByPrimaryKeySelective(update);
      }
      transfer(find, admin); // 提现通过,支付宝转账
      return null;
   }
   @Transactional
   public synchronized void rejectExtract(long id, String reason, AdminUser admin)
         throws ObjectStateException, NotExistObjectException {
      Extract find = extractMapper.selectByPrimaryKey(id);
      if (find == null) {
         throw new NotExistObjectException("不存在该对象");
      }
      if (find.getState() != Constant.EXTRACT_DEFUALT) {
         throw new ObjectStateException("该状态不等于不为初始状态");
      }
      UserInfo user = find.getUserInfo();
      UserMoneyDetail userMoneyDetail = null;
      try {
         userMoneyDetail = UserMoneyDetailFactory.createExtractReject(find);
      } catch (UserMoneyDetailException e1) {
         e1.printStackTrace();
      }
      // 增加资金
      userMoneyService.addUserMoney(user.getId(), find.getMoney(), userMoneyDetail);
      // 更新原来的状态
      Extract updateExtract = new Extract();
      updateExtract.setId(id);
      updateExtract.setState(Constant.EXTRACT_REJECT);
      updateExtract.setReason(reason);
      extractMapper.updateByPrimaryKeySelective(updateExtract);
      long auditTime = java.lang.System.currentTimeMillis();
      // 更新审核记录
      ExtractAuditRecord auditRecord = new ExtractAuditRecord();
      List<ExtractAuditRecord> records = extractAuditRecordMapper.getbyExtractId(id);
      if (records != null && records.size() > 0) {
         auditRecord = records.get(0);
      }
      // 角色默认:客服
      auditRecord.setAuditRole("客服");
      // 审核人
      auditRecord.setAdminUser(admin);
      // 提现之后金额 不变
      auditRecord.setAfterMoney(auditRecord.getBeforeMoney());
      // 审核时间
      auditRecord.setAuditTime(auditTime);
      // 历史提现金额
      Long uid = user.getId();
      double countSuccessMoneys = extractMapper.countSuccessMoneysByUid(uid);
      auditRecord.setCountMoney(new BigDecimal(countSuccessMoneys));
      // 历史提现次数
      long countSuccess = extractMapper.countSuccessByUid(uid);
      auditRecord.setCountNum(countSuccess);
      // 更新提现记录审核表
      extractAuditRecordMapper.updateByPrimaryKeySelective(auditRecord);
      // 新版资金详情
      // 新版通知
      userMoneyMsgNotificationService.extractFail(find, reason);
   }
   /**
    * 提现申请
    *
    * @param extract
    * @return
    */
   @Transactional
   private Integer extract(Extract extract) {
      UserAccountBindingHistory history = userAccountBindingHistoryService
            .getLatestHistory(extract.getUserInfo().getId(), UserAccountBindingHistory.TYPE_PHONE);
      // 手机号更换绑定的7天内不能提现
      if (history != null && !history.getFirst()
            && (System.currentTimeMillis() - history.getCreateTime().getTime()) < 1000 * 60 * 60 * 24 * 7L)
         return 111;
      final String autoExtract = configService.get("extract_way"); // 是否自动转账
      final String maxCount = configService.get("extract_count_day");
      final String maxMoney = configService.get("extract_money_day");
      UserInfo user = userInfoMapper.selectByPrimaryKeyForUpdate(extract.getUserInfo().getId());
      // 余额不足
      if (user.getMyHongBao().compareTo(extract.getMoney()) < 0) {
         return 3;
      }
      // 有借贷关系
      boolean isHaveToReplay = userMoneyDebtService.isHaveDebtToRepay(extract.getUserInfo().getId());
      if (isHaveToReplay) {
         return 110;
      }
      Integer type = setExtractRecord(extract, maxCount, maxMoney);
      if (type != 0) {
         return type;
      }
      extractMapper.insertSelective(extract);
      ExtractAuditRecord auditRecord = new ExtractAuditRecord();
      auditRecord.setBeforeMoney(user.getMyHongBao());
      auditRecord.setExtract(extract);
      Date minTime = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24 * 180L);
      // 统计数据
      int orderCount50More = orderUserStatisticService.countOrderCount100MoreByUidAndMinTime(user.getId(), minTime);
      BigDecimal weiQuanOrderFanAmount = orderUserStatisticService.sumWeiQuanOrderFanAmountByUid(user.getId(),
            minTime);
      int weiQuanOrderCount = orderUserStatisticService.countWeiQuanOrderByUid(user.getId(), minTime);
      auditRecord.setExtraInfoStr(new Gson()
            .toJson(new ExtractOrderStatisticDTO(orderCount50More, weiQuanOrderCount, weiQuanOrderFanAmount, 0)));
      extractAuditRecordMapper.insertSelective(auditRecord);
      // 新版资金详情
      UserMoneyDetail userMoneyDetail = null;
      try {
         userMoneyDetail = UserMoneyDetailFactory.createExtract(extract);
      } catch (UserMoneyDetailException e2) {
         try {
            LogHelper.errorDetailInfo(e2);
         } catch (Exception e1) {
            e1.printStackTrace();
         }
      }
      // 减去账户资金
      userMoneyService.subUserMoney(extract.getUserInfo().getId(), extract.getMoney(), userMoneyDetail);
      // 添加新版通知
      userMoneyMsgNotificationService.extractApplay(extract);
      if ("是".equals(autoExtract)) {
         LogHelper.userInfo("uid=" + user.getId() + ",提交转账申请!");
      } else {// 暂时不自动提现
         // transfer(extract, null);
         ;
      }
      return null;
   }
   /**
    * 转账
    *
    * @param extract
    * @param session
    */
   @Transactional
   private void transfer(Extract extract, AdminUser adminUser) {
      Integer type = extract.getType();
      if (Constant.ZHIFUBAO == type) {
         extractByZhiFuBao(extract, adminUser);
      } else {
         LogHelper.userInfo("提现类型错误:" + type);
      }
   }
   /**
    * 增加提现记录
    *
    * @param extract
    * @param maxCount
    *            最多提现次数
    * @param maxMoney
    *            最大提现金额
    * @param session
    * @return 如果为0,则增加成功。为1,则超过每日最多提现次数。为2,则超过每日最多提现金额
    */
   @Transactional
   public Integer setExtractRecord(Extract extract, String maxCount, String maxMoney) {
      long uid = extract.getUserInfo().getId();
      BigDecimal money = extract.getMoney();
      List<ExtractRecord> extractRecordList = extractRecordMapper.selectByUidAndToday(uid);
      if (extractRecordList.size() == 0) {
         ExtractRecord er = new ExtractRecord();
         er.setCount(1);
         er.setMoney(money);
         er.setUserInfo(new UserInfo(uid));
         er.setCreateTime(java.lang.System.currentTimeMillis());
         extractRecordMapper.insertSelective(er);
      } else {
         ExtractRecord er = extractRecordList.get(0);
         int count = er.getCount();
         int maxCountInt = Integer.parseInt(maxCount);
         if (count >= maxCountInt) {
            return 1;
         }
         BigDecimal oldMoney = er.getMoney();
         BigDecimal sumMoney = MoneyBigDecimalUtil.add(money, oldMoney);
         BigDecimal maxMoneyDou = new BigDecimal(maxMoney);
         if (maxMoneyDou.compareTo(sumMoney) == -1) {
            return 2;
         }
         ExtractRecord updateER = new ExtractRecord();
         updateER.setId(er.getId());
         updateER.setCount(count + 1);
         updateER.setMoney(sumMoney);
         er.setCreateTime(java.lang.System.currentTimeMillis());
         extractRecordMapper.updateByPrimaryKeySelective(updateER);
      }
      return 0;
   }
   /**
    * 提现到支付宝
    *
    * @param extract
    * @param session
    */
   // TODO 转账逻辑需要改变,固定IP
   @Transactional
   private void extractByZhiFuBao(Extract extract, AdminUser adminUser) {
      LogHelper.userErrorInfo("提现:开始通过提现-" + extract.getId());
      String privateKey = Constant.alipayConfig.getPrivateKey();
      AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
            Constant.alipayConfig.getAppId(), privateKey, "json", "gbk", null, "RSA2");
      AlipayFundTransToaccountTransferRequest request = new AlipayFundTransToaccountTransferRequest();
      String appName = Constant.systemCommonConfig.getProjectChineseName();
      JSONObject json = new JSONObject();
      json.put("out_biz_no", "widthdraw_" + extract.getId());// 最长长度64位,支持英文,下划线,数字
      json.put("payee_type", "ALIPAY_LOGONID");
      json.put("payee_account", extract.getAccount());
      json.put("amount", extract.getMoney());
      json.put("payer_show_name", appName + "App" + "提现");
      json.put("payee_real_name", extract.getName());
      json.put("remark", "来自" + appName + "App" + "的提现");
      request.setBizContent(json.toString());
      AlipayFundTransToaccountTransferResponse response = null;
      try {
         response = alipayClient.execute(request);
         LogHelper.userErrorInfo("提现:支付宝通过提现成功-" + extract.getId());
      } catch (AlipayApiException e) {
         e.printStackTrace();
         LogHelper.userErrorInfo("提现:支付宝提现异常:" + response + ",提现信息" + GsonUtil.toJson(extract));
      }
      try {
         CMQManager.getInstance().addExtractResultMsg(extract, response, adminUser);
         LogHelper.userErrorInfo("提现:添加处理队列成功-" + extract.getId());
      } catch (Exception e) {
         LogHelper
               .userErrorInfo("提现:支付宝提现CMQ异常:" + new Gson().toJson(response) + ",提现信息" + GsonUtil.toJson(extract));
      }
   }
   /**
    * 提现失败
    *
    * @param extract
    * @param msg
    * @param session
    */
   @Transactional
   private void extractFail(Extract extract, String msg) {
      UserInfo user = extract.getUserInfo();
      // MoneyRecord moneyRecord = new MoneyRecord(user, null, extract
      // .getMoney(), "提现", "提现失败", new Date().getTime(), 3);
      if ("付款方余额不足".equals(msg)) {
         Extract updateExtract = new Extract();
         updateExtract.setId(extract.getId());
         updateExtract.setState(Constant.EXTRACT_DEFUALT);
         updateExtract.setReason(msg);
         extractMapper.updateByPrimaryKeySelective(updateExtract);
      } else {
         // 老版本功能
         // List<MoneyRecord> list = moneyRecordDao.list("from MoneyRecord mr
         // where mr.extract.id =" + extract.getId());
         // if (list.size() > 0) {
         // MoneyRecord moneyRecord = list.get(0);
         // moneyRecordMapper.deleteByPrimaryKey(moneyRecord.getId());
         // }
         Extract updateExtract = new Extract();
         updateExtract.setId(extract.getId());
         updateExtract.setState(Constant.EXTRACT_REJECT);
         updateExtract.setReason(msg);
         extractMapper.updateByPrimaryKeySelective(updateExtract);
         UserMoneyDetail userMoneyDetail = null;
         // 新版资金详情
         try {
            userMoneyDetail = UserMoneyDetailFactory.createExtractReject(extract);
         } catch (UserMoneyDetailException e2) {
            try {
               LogHelper.errorDetailInfo(e2);
            } catch (Exception e1) {
               e1.printStackTrace();
            }
         }
         // 增加资金
         userMoneyService.addUserMoney(user.getId(), extract.getMoney(), userMoneyDetail);
         try {
            LogHelper.userInfo("支付宝转账失败:[提现IP:" + extract.getIp() + ",所转账号:" + extract.getAccount() + ",真实姓名:"
                  + extract.getName() + ",所转金额:" + extract.getMoney() + ",失败原因" + extract.getReason() + "]");
         } catch (Exception e) {
            e.printStackTrace();
         }
         // 新版提现
         userMoneyMsgNotificationService.extractFail(extract, null);
      }
   }
   /**
    * 提现成功
    *
    * @param extract
    * @param session
    */
   @Transactional
   private void extractSuccess(Extract extract) {
      // 老版本功能
      // List<MoneyRecord> list = moneyRecordDao.list("from MoneyRecord mr
      // where mr.extract.id = " + extract.getId());
      // MoneyRecord moneyRecord = list.get(0);
      // moneyRecord.setType(3);
      // MoneyRecord updateMoneyRecord = new MoneyRecord();
      // updateMoneyRecord.setId(moneyRecord.getId());
      // updateMoneyRecord.setType(3);
      // moneyRecordMapper.updateByPrimaryKeySelective(updateMoneyRecord);
      Extract updateExtract = new Extract();
      updateExtract.setId(extract.getId());
      updateExtract.setState(Constant.EXTRACT_PASS);
      updateExtract.setReceiveTime(new Date());
      updateExtract.setReason("提现成功");
      extractMapper.updateByPrimaryKeySelective(updateExtract);
      try {
         LogHelper.userInfo("支付宝转账成功:[提现IP:" + extract.getIp() + ",所转账号:" + extract.getAccount() + ",真实姓名:"
               + extract.getName() + ",所转金额:" + extract.getMoney() + "]");
      } catch (Exception e) {
         e.printStackTrace();
      }
      // 新版通知
      userMoneyMsgNotificationService.extractSuccess(extract);
   }
   /**
    * 根据提现记录id获取用户uid
    */
   @Override
   public Extract getExtractById(long id) {
      return extractMapper.selectByPrimaryKey(id);
   }
   @Transactional
   @Override
   public void checkExtract(Long uid) throws ExtractException {
      BigDecimal compensateMoney = extractMapper.computeCompensateByUid(uid);
      if (compensateMoney == null)
         compensateMoney = new BigDecimal(0);
      // 不判定到账红包问题
      Long count = hongBaoV2Mapper.countByUidAndState(uid, HongBao.STATE_YILINGQU);
      if ((count == null || count == 0) && compensateMoney.compareTo(new BigDecimal(0)) == 0) {
         throw new ExtractException(1, "没有已到账的红包");
      }
      // 查询是否有欠账
      boolean isDebt = userMoneyDebtService.isHaveDebtToRepay(uid);
      if (isDebt)
         throw new ExtractException(3, "有欠账未还");
      // 获取所有收入所得
      BigDecimal hongBaoMoney = hongBaoV2Service.computeMoneyByUidAndState(uid, HongBaoV2.STATE_YILINGQU);
      Date now = new Date();
      // 获取提现,获取提现验证
      List<UserMoneyDetailTypeEnum> typeList = new ArrayList<>();
      typeList.add(UserMoneyDetailTypeEnum.extract);
      typeList.add(UserMoneyDetailTypeEnum.extractReject);
      typeList.add(UserMoneyDetailTypeEnum.extractVerify);
      BigDecimal extractMoney = userMoneyDetailService.statisticUserTypeMoneyWithDate(uid, typeList, new Date(0),
            now);
      extractMoney = extractMoney.abs();
      // 获取维权
      typeList = new ArrayList<>();
      typeList.add(UserMoneyDetailTypeEnum.weiQuan);
      typeList.add(UserMoneyDetailTypeEnum.fanliWeiQuan);
      typeList.add(UserMoneyDetailTypeEnum.inviteWeiQuan);
      typeList.add(UserMoneyDetailTypeEnum.shareWeiQuan);
      typeList.add(UserMoneyDetailTypeEnum.hongbaoDeduct);
      BigDecimal weiqaunMoney = userMoneyDetailService.statisticUserTypeMoneyWithDate(uid, typeList, new Date(0),
            now);
      weiqaunMoney = weiqaunMoney.abs();
      BigDecimal balance = userInfoService.selectByPKey(uid).getMyHongBao();
      BigDecimal after = hongBaoMoney.subtract(extractMoney.add(weiqaunMoney).add(balance).add(compensateMoney));
      if (after.compareTo(new BigDecimal("0")) != 0)
         throw new ExtractException(2, "结算资金异常");
   }
   @Override
   public Extract selectByPrimaryKey(Long id) {
      return extractMapper.selectByPrimaryKey(id);
   }
   @Override
   public Extract getMyTaskInfo(Long adminId) {
      return extractMapper.getMyTaskInfo(adminId);
   }
   @Override
   public Extract getNewTaskInfo() {
      return extractMapper.getNewTaskInfo();
   }
   @Override
   public List<Map<String, Object>> getFinishRecord(int pageIndex, int pageSize, String key, String startTime,
         String endTime) {
      return extractMapper.getFinishRecord((pageIndex - 1) * pageSize, pageSize, key, startTime, endTime);
   }
   @Override
   public int updateByPrimaryKeySelective(Extract record) {
      return extractMapper.updateByPrimaryKeySelective(record);
   }
   @Transactional
   @Override
   public void processExtractResult(AlipayTransferResultInfo info) {
      if (info == null)
         return;
      AlipayFundTransToaccountTransferResponse response = info.getAlipayFundTransToaccountTransferResponse();
      Extract extract = info.getExtract();
      AdminUser admin = info.getAdminUser();
      if (response == null)
         return;
      if (extract == null)
         return;
      extract = extractMapper.selectByPrimaryKey(info.getExtract().getId());
      LogHelper.test("提现结果:code-" + response.getCode() + " 信息:" + response.getMsg());
      long uid = extract.getUserInfo().getId();
      if (response.isSuccess()) {
         String code = response.getCode();
         if ("10000".equals(code)) {
            extractSuccess(extract);
         } else {
            extractFail(extract, response.getSubMsg());
         }
      } else {
         extractFail(extract, response.getSubMsg());
      }
      PayInfo payInfo = new PayInfo();
      payInfo.setBizno(response.getOutBizNo());
      payInfo.setCreatetime(new Date());
      payInfo.setExtract(extract);
      if ("10000".equals(response.getCode())) {
         payInfo.setState(1);
      } else {
         payInfo.setState(2);
      }
      payInfo.setOrderId(response.getOrderId());
      payInfo.setOrdertime(response.getPayDate());
      payInfo.setInfo(response.getSubMsg());
      payInfoMapper.insertSelective(payInfo);
      // 更新审核记录
      ExtractAuditRecord auditRecord = null;
      List<ExtractAuditRecord> records = extractAuditRecordMapper.getbyExtractId(extract.getId());
      if (records != null && records.size() > 0) {
         auditRecord = records.get(0);
      }
      if (auditRecord != null) {
         // 提现付款记录
         List<PayInfo> paylist = payInfoMapper.getListbyExtractId(extract.getId());
         if (paylist != null && paylist.size() > 0) {
            // 提现成功 : 提现之前总金额:提现时金额减去提现金额
            BigDecimal exceedMoney = MoneyBigDecimalUtil.sub(auditRecord.getBeforeMoney(), extract.getMoney());
            // 提现之后金额
            auditRecord.setAfterMoney(exceedMoney);
         } else {
            // 提现失败:付款方余额不足、账户信息错误 提现之后金额 不变
            auditRecord.setAfterMoney(auditRecord.getBeforeMoney());
         }
         // 历史提现金额
         double countSuccessMoneys = extractMapper.countSuccessMoneysByUid(uid);
         auditRecord.setCountMoney(new BigDecimal(countSuccessMoneys));
         // 历史提现次数
         long countSuccess = extractMapper.countSuccessByUid(uid);
         auditRecord.setCountNum(countSuccess);
         // 角色默认:客服
         auditRecord.setAuditRole("客服");
         // 审核人
         auditRecord.setAdminUser(admin);
         // 审核时间
         auditRecord.setAuditTime(java.lang.System.currentTimeMillis());
         // 更新提现记录审核表
         extractAuditRecordMapper.updateByPrimaryKeySelective(auditRecord);
      }
      // 外显账户明细
      UserMoneyDetail userMoneyDetail = userMoneyDetailMapper.selectByTypeAndUidAndIdentifyCode(
            UserMoneyDetailTypeEnum.extract, extract.getUserInfo().getId(), extract.getId());
      if (userMoneyDetail != null) {
         UserMoneyDetail detail = new UserMoneyDetail(userMoneyDetail.getId());
         detail.setShow(true);
         detail.setUpdateTime(new Date());
         userMoneyDetailMapper.updateByPrimaryKeySelective(detail);
      }
   }
   @Transactional
   @Override
   public void testExtractSuccess(Long id) {
      Extract extract = extractMapper.selectByPrimaryKey(id);
      extractSuccess(extract);
      Long uid = extract.getUserInfo().getId();
      // 更新审核记录
      ExtractAuditRecord auditRecord = null;
      List<ExtractAuditRecord> records = extractAuditRecordMapper.getbyExtractId(extract.getId());
      if (records != null && records.size() > 0) {
         auditRecord = records.get(0);
      }
      if (auditRecord != null) {
         // 提现付款记录
         List<PayInfo> paylist = payInfoMapper.getListbyExtractId(extract.getId());
         if (paylist != null && paylist.size() > 0) {
            // 提现成功 : 提现之前总金额:提现时金额减去提现金额
            BigDecimal exceedMoney = MoneyBigDecimalUtil.sub(auditRecord.getBeforeMoney(), extract.getMoney());
            // 提现之后金额
            auditRecord.setAfterMoney(exceedMoney);
         } else {
            // 提现失败:付款方余额不足、账户信息错误 提现之后金额 不变
            auditRecord.setAfterMoney(auditRecord.getBeforeMoney());
         }
         // 历史提现金额
         double countSuccessMoneys = extractMapper.countSuccessMoneysByUid(uid);
         auditRecord.setCountMoney(new BigDecimal(countSuccessMoneys));
         // 历史提现次数
         long countSuccess = extractMapper.countSuccessByUid(uid);
         auditRecord.setCountNum(countSuccess);
         // 角色默认:客服
         auditRecord.setAuditRole("客服");
         // 审核人
         auditRecord.setAdminUser(new AdminUser(3L));
         // 审核时间
         auditRecord.setAuditTime(java.lang.System.currentTimeMillis());
         // 更新提现记录审核表
         extractAuditRecordMapper.updateByPrimaryKeySelective(auditRecord);
      }
   }
   @Override
   public BigDecimal sumTodayApplyMoney(Long uid, String day) {
      return extractMapper.sumToadyApplyByUid(uid, day);
   }
   @Override
   public BigDecimal sumVerifyingMoney(Long uid) {
      List<Integer> stateList = new ArrayList<>();
      stateList.add(Extract.STATE_NOT_PROCESS);
      stateList.add(Extract.STATE_PROCESSING);
      BigDecimal money = extractMapper.sumMoneyByUidAndState(uid, stateList);
      if (money == null)
         return new BigDecimal(0);
      else
         return money;
   }
   @Transactional(rollbackFor = Exception.class)
   @Override
   public void autoExtract(UserInfo user) {
      if (user == null || user.getWxOpenId() == null || user.getWxUnionId() == null
            || user.getState() != UserInfo.STATE_NORMAL)
         return;
      Date date = new Date();
      BigDecimal money = new BigDecimal(Constant.AUTO_EXTRACT_MONEY);
      // 1、插入记录
      ExtractWeiXinRecord extractRecord = new ExtractWeiXinRecord();
      extractRecord.setUid(user.getId());
      extractRecord.setOpenId(user.getWxOpenId());
      extractRecord.setUnionId(user.getWxUnionId());
      extractRecord.setMoney(money);
      extractRecord.setCreateTime(date);
      extractRecord.setUpdateTime(date);
      extractWeiXinRecordService.insertSelective(extractRecord);
      // 交易号
      Long recordId = extractRecord.getId();
      String billno = "BanLiExtract" + recordId;
      // 更新记录
      ExtractWeiXinRecord updeteRecord = null;
      String mchId = "1520950211";
      String appId = "wx5c0d167c6e3ad726";
      String key = "XYJkJ2018FAfaodCCx899mLl138rfGVd";
      // 2、发放微信红包
      RedPackParams redPackParams = new RedPackParams();
      redPackParams.setBillno(billno);
      redPackParams.setMchId(mchId);
      redPackParams.setWxappId(appId);
      redPackParams.setSendName("板栗快省");
      redPackParams.setOpenid(user.getWxOpenId());
      redPackParams.setMoney(money);
      redPackParams.setTotalNum(1);
      redPackParams.setWishing("账户中剩余余额请在本App内完成提现");
      redPackParams.setClientIp("106.80.118.163");
      redPackParams.setActName("自动提现");
      redPackParams.setKey(key);
      redPackParams.setRemark("微信自动提现");
      // redPackParams.setSceneId(null);
      // redPackParams.setRiskInfo(null);
      // 发生红包状态
      boolean stateRedPack = false;
      String pwd = "1520950211";
      InputStream cert = ExtractServiceImpl.class.getClassLoader()
            .getResourceAsStream("certificate/apiclient_cert.p12"); // 读取.p12文件
      // 执行发放红包
      try {
         String result = WXPayUtil.redPackToOpenId(redPackParams, pwd, cert);
         if (!StringUtil.isNullOrEmpty(result)) {
            stateRedPack = parseSendResult(result);
         }
         if (!stateRedPack) {
            String redPackRecord = WXPayUtil.getRedPackRecord(billno, mchId, appId, key, pwd, cert);
            if (!StringUtil.isNullOrEmpty(redPackRecord)) {
               updeteRecord = parseDTO(redPackRecord);
            }
         }
      } catch (Exception e) {
         String redPackRecord = WXPayUtil.getRedPackRecord(billno, mchId, appId, key, pwd, cert);
         if (!StringUtil.isNullOrEmpty(redPackRecord)) {
            updeteRecord = parseDTO(redPackRecord);
         }
         LogHelper.errorDetailInfo(e);
      }
      try {
         cert.close();
      } catch (IOException e1) {
         e1.printStackTrace();
      }
      // 更新信息
      if (updeteRecord == null) {
         updeteRecord = new ExtractWeiXinRecord();
      } else {
         stateRedPack = true;
      }
      updeteRecord.setId(recordId);
      updeteRecord.setStatus(ExtractWeiXinRecord.SENDING);
      updeteRecord.setBillno(billno);
      extractWeiXinRecordService.updateByPrimaryKeySelective(updeteRecord);
      // 红包发放失败
      if (!stateRedPack)
         return;
      // 3、加入资金明细
      UserMoneyDetail detail = new UserMoneyDetail();
      detail.setCreateTime(new Date());
      detail.setIdentifyCode(StringUtil.Md5(UserMoneyDetailTypeEnum.extractAutoWX.name() + ":" + recordId));
      detail.setMoney(money);
      detail.setTitle(UserMoneyDetailTypeEnum.extractAutoWX.getDesc());
      detail.setType(UserMoneyDetailTypeEnum.extractAutoWX);
      detail.setUpdateTime(new Date());
      detail.setUserInfo(user);
      try {
         userMoneyDetailService.addUserMoneyDetail(detail);
      } catch (UserMoneyDetailException e) {
         LogHelper.errorDetailInfo(e);
      }
      // 4、发送消息通知
      String desc = "为保障你的账户余额安全,自动提现金额将不会高于5元";
      String beizu = "账户中剩余余额请在本App内完成提现";
      userMoneyMsgNotificationService.extractAuto(extractRecord, "未领取-提现中", desc, beizu);
   }
   private boolean parseSendResult(String result) {
      try {
         Document document = DocumentHelper.parseText(result);
         // 获取根节点元素对象
         Element root = document.getRootElement();
         Element returnCode = root.element("return_code");
         if (!"SUCCESS".equalsIgnoreCase(returnCode.getText())) {
            Element returnMsg = root.element("return_msg");
            System.out.println(returnMsg.getText());
            return false;
         }
         Element resultCode = root.element("result_code");
         if (!"SUCCESS".equalsIgnoreCase(resultCode.getText())) {
            Element errCode = root.element("err_code");
            Element errCodeDes = root.element("err_code_des");
            System.out.println(errCode.getText() + ":" + errCodeDes.getText());
            return false;
         }
         return true;
      } catch (DocumentException e) {
         e.printStackTrace();
         LogHelper.errorDetailInfo(e);
      }
      return false;
   }
   private ExtractWeiXinRecord parseDTO(String result) {
      try {
         Document document = DocumentHelper.parseText(result);
         // 获取根节点元素对象
         Element root = document.getRootElement();
         Element returnCode = root.element("return_code");
         if (!"SUCCESS".equalsIgnoreCase(returnCode.getText())) {
            Element returnMsg = root.element("return_msg");
            System.out.println(returnMsg.getText());
            return null;
         }
         Element resultCode = root.element("result_code");
         if (!"SUCCESS".equalsIgnoreCase(resultCode.getText())) {
            Element errCode = root.element("err_code");
            Element errCodeDes = root.element("err_code_des");
            System.out.println(errCode.getText() + ":" + errCodeDes.getText());
         }
         ExtractWeiXinRecord resultRecord = new ExtractWeiXinRecord();
         resultRecord.setBillno(root.element("result_code").getText());
         resultRecord.setDetailno(root.element("detail_id").getText());
         resultRecord.setStatus(root.element("status").getText());
         resultRecord.setSendType(root.element("send_type").getText());
         resultRecord.setHbType(root.element("result_code").getText());
         String totalNum = root.element("total_num").getText();
         resultRecord.setTotalNum(Integer.parseInt(totalNum));
         String sendTime = root.element("send_time").getText();
         resultRecord.setSendTime(new Date(TimeUtil.convertDateToTemp2(sendTime)));
         Element element = root.element("hblist");
         Iterator<?> iterator = element.elementIterator();
         while (iterator.hasNext()) {
            Element childElement = (Element) iterator.next();
            Element rcvTime = childElement.element("rcv_time");
            resultRecord.setRcvTime(new Date(TimeUtil.convertDateToTemp2(rcvTime.getText())));
            break;
         }
         return resultRecord;
      } catch (DocumentException e) {
         e.printStackTrace();
         LogHelper.errorDetailInfo(e);
      }
      return null;
   }
   @Override
   public List<UserInfo> preAutoUser() throws Exception {
      int page = 0;
      int pageSize = 100;
      int maxSize = 300;
      Date nowDate = new Date();
      // 一、自动提现针对的用户群: 前提条件:用户在距今60天到90天内未活跃过的用户
      String beganDate = DateUtil.reduceDayTostring(90, nowDate);
      String endDate = DateUtil.reduceDayTostring(60, nowDate);
      // 条件3:距离上一次成功领取微信红包已经超过了30天时间,可在第31天再次下发;
      String receivedDate = DateUtil.reduceDayTostring(30, nowDate);
      // 条件4:距离上一次未成功领取微信红包已经超过了15天时间,可在第16天再次下发;
      String refundDate = DateUtil.reduceDayTostring(15, nowDate);
      // 余额最低限制
      BigDecimal minSurplus = BigDecimal.valueOf(Constant.AUTO_EXTRACT_MIN_SURPLUS);
      List<UserInfo> list = new ArrayList<UserInfo>();
      while (true) {
         // 查询满足条件 1、2 的uid
         List<UserInfo> listUser = userInfoService.getAutoExtractUser(page * pageSize, pageSize, minSurplus,
               beganDate, endDate);
         if (listUser == null || listUser.isEmpty())
            break;
         List<Long> listId = new ArrayList<Long>();
         for (UserInfo userInfo : listUser) {
            listId.add(userInfo.getId());
         }
         // 查询记录是否满足
         List<Long> listValid = extractWeiXinRecordService.getValidUsers(listId, receivedDate, refundDate);
         if (listValid == null || listValid.isEmpty()) {
            page++;
            continue;
         }
         for (Long uid : listValid) {
            if (list.size() >= maxSize)
               break;
            for (UserInfo userInfo : listUser) {
               if (list.size() >= maxSize)
                  break;
               if (userInfo.getId().longValue() == uid.longValue()) {
                  list.add(userInfo);
                  break;
               }
            }
         }
         if (list.size() >= maxSize)
            break;
         page++;
      }
      return list;
   }
   @Override
   public List<String> getAutoExtractOpenIds() throws Exception {
      int page = 0;
      int pageSize = 100;
      int maxSize = 301; // appId + 实际openid300个
      Date nowDate = new Date();
      // 一、自动提现针对的用户群: 前提条件:用户在距今60天到90天内未活跃过的用户
      String beganDate = DateUtil.reduceDayTostring(90, nowDate);
      String endDate = DateUtil.reduceDayTostring(60, nowDate);
      // 条件3:距离上一次成功领取微信红包已经超过了30天时间,可在第31天再次下发;
      String receivedDate = DateUtil.reduceDayTostring(30, nowDate);
      // 条件4:距离上一次未成功领取微信红包已经超过了15天时间,可在第16天再次下发;
      String refundDate = DateUtil.reduceDayTostring(15, nowDate);
      // 提现金额
      BigDecimal money = BigDecimal.valueOf(Constant.AUTO_EXTRACT_MONEY);
      // 余额最低限制
      BigDecimal minSurplus = BigDecimal.valueOf(Constant.AUTO_EXTRACT_MIN_SURPLUS);
      List<String> listOpendIDs = new ArrayList<String>();
      // 首行appID
      listOpendIDs.add(Constant.getWXAccount(null, null).getAppId());
      while (true) {
         // 查询满足条件 1、2 的uid
         List<UserInfo> listUser = userInfoService.getAutoExtractUser(page * pageSize, pageSize, minSurplus,
               beganDate, endDate);
         if (listUser == null || listUser.isEmpty())
            break;
         List<Long> listId = new ArrayList<Long>();
         for (UserInfo userInfo : listUser) {
            listId.add(userInfo.getId());
         }
         // 查询记录是否满足
         List<Long> listValid = extractWeiXinRecordService.getValidUsers(listId, receivedDate, refundDate);
         if (listValid == null || listValid.isEmpty()) {
            page++;
            continue;
         }
         for (Long uid : listValid) {
            UserInfo userInfo = subHongBaoByUid(uid, money, minSurplus);
            if (userInfo != null) {
               listOpendIDs.add(userInfo.getWxOpenId());
               if (listOpendIDs.size() >= maxSize)
                  break;
            }
         }
         if (listOpendIDs.size() >= maxSize)
            break;
         page++;
      }
      return listOpendIDs;
   }
   @Transactional(rollbackFor = Exception.class)
   private UserInfo subHongBaoByUid(Long uid, BigDecimal money, BigDecimal minSurplus) {
      UserInfo userInfo = userInfoMapper.selectByPrimaryKeyForUpdate(uid);
      if (userInfo != null && !StringUtil.isNullOrEmpty(userInfo.getWxOpenId())
            && !StringUtil.isNullOrEmpty(userInfo.getWxUnionId())
            && userInfo.getMyHongBao().compareTo(minSurplus) >= 0) {
         // 微信提现记录
         ExtractWeiXinRecord extractRecord = new ExtractWeiXinRecord();
         extractRecord.setUid(uid);
         extractRecord.setOpenId(userInfo.getWxOpenId());
         extractRecord.setUnionId(userInfo.getWxUnionId());
         extractRecord.setMoney(money);
         extractRecord.setStatus(ExtractWeiXinRecord.SENDING);
         extractRecord.setType(ExtractWeiXinRecord.TYPE_MANUAL);
         extractRecord.setCreateTime(new Date());
         extractRecord.setUpdateTime(new Date());
         extractWeiXinRecordService.insertSelective(extractRecord);
         // 记录id
         Long recordId = extractRecord.getId();
         // 资金明细
         UserMoneyDetail detail = new UserMoneyDetail();
         detail.setCreateTime(new Date());
         detail.setIdentifyCode(StringUtil.Md5(UserMoneyDetailTypeEnum.extractAutoWX.name() + ":" + recordId));
         detail.setMoney(new BigDecimal("-" + money.toString()));
         detail.setTitle(UserMoneyDetailTypeEnum.extractAutoWX.getDesc());
         detail.setType(UserMoneyDetailTypeEnum.extractAutoWX);
         detail.setUpdateTime(new Date());
         detail.setUserInfo(userInfo);
         // 资金计算
         userMoneyService.subUserMoney(userInfo.getId(), money, detail);
         // 4、发送消息通知
         String desc = "为保障你的账户余额安全,自动提现金额将不会高于5元";
         String beizu = "账户中剩余余额请在本App内完成提现";
         userMoneyMsgNotificationService.extractAuto(extractRecord, "未领取-提现中", desc, beizu);
         // 满足条件返回信息
         return userInfo;
      }
      return null;
   }
   @Override
   public void updateManualExtractRecord(List<RedPackRecord> list) throws ExtractException {
      if (list == null || list.isEmpty())
         throw new ExtractException(1, "红包记录信息为空");
      for (RedPackRecord redPackRecord : list) {
         updateWeiXinRecord(redPackRecord);
      }
   }
   @Transactional(rollbackFor = Exception.class)
   private void updateWeiXinRecord(RedPackRecord redPackRecord) {
      if (StringUtil.isNullOrEmpty(redPackRecord.getOpenId()))
         return;
      ExtractWeiXinRecord record = extractWeiXinRecordService.getByOpenIdAndType(redPackRecord.getOpenId(),
            ExtractWeiXinRecord.TYPE_MANUAL);
      if (record == null)
         return;
      // 状态过滤
      String statusOld = record.getStatus();
      if (StringUtil.isNullOrEmpty(statusOld) || ExtractWeiXinRecord.REFUND.equals(statusOld)
            || ExtractWeiXinRecord.RECEIVED.equals(statusOld))
         return;
      ExtractWeiXinRecord updeteRecord = new ExtractWeiXinRecord();
      updeteRecord.setId(record.getId());
      updeteRecord.setUpdateTime(new Date());
      String billno = redPackRecord.getBillno();
      if (!StringUtil.isNullOrEmpty(billno)) {
         updeteRecord.setBillno(billno.replace("`", "").replace("'", ""));
      }
      String detailno = redPackRecord.getDetailno();
      if (!StringUtil.isNullOrEmpty(detailno)) {
         updeteRecord.setDetailno(detailno.replace("`", "").replace("'", ""));
      }
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
      String rcvTime = redPackRecord.getRcvTime();
      if (!StringUtil.isNullOrEmpty(rcvTime)) {
         try {
            updeteRecord.setRcvTime(sdf.parse(rcvTime));
         } catch (ParseException e) {
            e.printStackTrace();
         }
      }
      String sendTime = redPackRecord.getSendTime();
      if (!StringUtil.isNullOrEmpty(sendTime)) {
         try {
            updeteRecord.setSendTime(sdf.parse(sendTime));
         } catch (ParseException e) {
            e.printStackTrace();
         }
      }
      String status = redPackRecord.getStatus();
      if (!StringUtil.isNullOrEmpty(status)) {
         switch (status) {
         case "已发放待领取":
            status = ExtractWeiXinRecord.SENT;
            break;
         case "过期未领退款":
            status = ExtractWeiXinRecord.REFUND;
            break;
         case "已领取":
            status = ExtractWeiXinRecord.RECEIVED;
            break;
         default:
            status = null;
            break;
         }
      }
      updeteRecord.setStatus(status);
      extractWeiXinRecordService.updateByPrimaryKeySelective(updeteRecord);
      if (ExtractWeiXinRecord.RECEIVED.equals(status)) {
         // 发送消息通知
         userMoneyMsgNotificationService.extractAuto(record, "已领取-已提现", null, null);
      } else if (ExtractWeiXinRecord.REFUND.equals(status)) {
         // 资金明细
         UserMoneyDetail detail = new UserMoneyDetail();
         detail.setCreateTime(new Date());
         detail.setIdentifyCode(
               StringUtil.Md5(UserMoneyDetailTypeEnum.extractAutoWXRefund.name() + ":" + record.getId()));
         detail.setMoney(record.getMoney());
         detail.setTitle(UserMoneyDetailTypeEnum.extractAutoWXRefund.getDesc());
         detail.setType(UserMoneyDetailTypeEnum.extractAutoWXRefund);
         detail.setUpdateTime(new Date());
         detail.setUserInfo(new UserInfo(record.getUid()));
         // 资金计算
         userMoneyService.addUserMoney(record.getUid(), record.getMoney(), detail);
         // 发送消息通知
         userMoneyMsgNotificationService.extractAuto(record, "已退回-余额中", null, null);
      }
   }
}
package com.yeshi.fanli.service.impl.money.extract;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import com.yeshi.fanli.entity.SystemEnum;
import com.yeshi.fanli.util.*;
import com.yeshi.fanli.util.mq.rabbit.RabbitmqManager;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.yeshi.utils.DateUtil;
import org.yeshi.utils.entity.wx.RedPackParams;
import org.yeshi.utils.entity.wx.RedPackRecord;
import org.yeshi.utils.wx.WXPayUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.google.gson.Gson;
import com.yeshi.fanli.dao.mybatis.AccountMessageMapper;
import com.yeshi.fanli.dao.mybatis.AlipayAccountValidNormalHistoryMapper;
import com.yeshi.fanli.dao.mybatis.ExtractAuditRecordMapper;
import com.yeshi.fanli.dao.mybatis.ExtractMapper;
import com.yeshi.fanli.dao.mybatis.ExtractRecordMapper;
import com.yeshi.fanli.dao.mybatis.HongBaoV2Mapper;
import com.yeshi.fanli.dao.mybatis.PayInfoMapper;
import com.yeshi.fanli.dao.mybatis.UserInfoMapper;
import com.yeshi.fanli.dao.mybatis.money.UserMoneyDetailMapper;
import com.yeshi.fanli.dto.HongBao;
import com.yeshi.fanli.dto.money.ExtractOrderStatisticDTO;
import com.yeshi.fanli.entity.bus.user.AlipayTransferResultInfo;
import com.yeshi.fanli.entity.bus.user.Extract;
import com.yeshi.fanli.entity.bus.user.ExtractAuditRecord;
import com.yeshi.fanli.entity.bus.user.ExtractRecord;
import com.yeshi.fanli.entity.bus.user.ExtractWeiXinRecord;
import com.yeshi.fanli.entity.bus.user.HongBaoV2;
import com.yeshi.fanli.entity.bus.user.PayInfo;
import com.yeshi.fanli.entity.bus.user.UserAccountBindingHistory;
import com.yeshi.fanli.entity.bus.user.UserInfo;
import com.yeshi.fanli.entity.common.AdminUser;
import com.yeshi.fanli.entity.money.UserMoneyDetail;
import com.yeshi.fanli.entity.money.UserMoneyDetail.UserMoneyDetailTypeEnum;
import com.yeshi.fanli.entity.system.ConfigKeyEnum;
import com.yeshi.fanli.exception.ExtractException;
import com.yeshi.fanli.exception.NotExistObjectException;
import com.yeshi.fanli.exception.ObjectStateException;
import com.yeshi.fanli.exception.money.UserMoneyDetailException;
import com.yeshi.fanli.log.LogHelper;
import com.yeshi.fanli.service.inter.config.ConfigService;
import com.yeshi.fanli.service.inter.config.SystemConfigService;
import com.yeshi.fanli.service.inter.money.UserMoneyDebtService;
import com.yeshi.fanli.service.inter.money.UserMoneyDetailService;
import com.yeshi.fanli.service.inter.money.UserMoneyService;
import com.yeshi.fanli.service.inter.money.extract.ExtractRecordService;
import com.yeshi.fanli.service.inter.money.extract.ExtractService;
import com.yeshi.fanli.service.inter.money.extract.ExtractWeiXinRecordService;
import com.yeshi.fanli.service.inter.money.msg.UserMoneyMsgNotificationService;
import com.yeshi.fanli.service.inter.order.CommonOrderCountService;
import com.yeshi.fanli.service.inter.order.HongBaoV2Service;
import com.yeshi.fanli.service.inter.order.OrderUserStatisticService;
import com.yeshi.fanli.service.inter.push.PushService;
import com.yeshi.fanli.service.inter.user.UserAccountBindingHistoryService;
import com.yeshi.fanli.service.inter.user.UserInfoService;
import org.yeshi.utils.MoneyBigDecimalUtil;
import org.yeshi.utils.TimeUtil;
import com.yeshi.fanli.util.factory.UserMoneyDetailFactory;
@Service
public class ExtractServiceImpl implements ExtractService {
    @Resource
    private UserInfoService userInfoService;
    @Resource
    private ConfigService configService;
    @Resource
    private ExtractRecordService extractRecordService;
    @Resource
    private SystemConfigService systemConfigService;
    @Resource
    private ExtractMapper extractMapper;
    @Resource
    private ExtractAuditRecordMapper extractAuditRecordMapper;
    @Resource
    private UserInfoMapper userInfoMapper;
    @Resource
    private PayInfoMapper payInfoMapper;
    @Resource
    private AccountMessageMapper accountMessageMapper;
    @Resource
    private ExtractRecordMapper extractRecordMapper;
    @Resource
    private HongBaoV2Mapper hongBaoV2Mapper;
    @Resource
    private HongBaoV2Service hongBaoV2Service;
    @Resource
    private PushService pushService;
    @Resource
    private UserMoneyDetailMapper userMoneyDetailMapper;
    @Resource
    private UserMoneyMsgNotificationService userMoneyMsgNotificationService;
    @Resource
    private AlipayAccountValidNormalHistoryMapper alipayAccountValidNormalHistoryMapper;
    @Resource
    private UserMoneyDetailService userMoneyDetailService;
    @Resource
    private UserAccountBindingHistoryService userAccountBindingHistoryService;
    @Resource
    private UserMoneyDebtService userMoneyDebtService;
    @Resource
    private UserMoneyService userMoneyService;
    @Resource
    private OrderUserStatisticService orderUserStatisticService;
    @Resource
    private ExtractWeiXinRecordService extractWeiXinRecordService;
    @Resource
    private CommonOrderCountService commonOrderCountService;
    @Resource
    private RabbitmqManager rabbitmqManager;
    @Transactional
    public Integer addExtract(Extract extract) {
        Integer integer = extract(extract);
        return integer;
    }
    @Transactional
    public Integer passExtract(final long id, AdminUser admin) {
        Extract find = extractMapper.selectByPrimaryKeyForUpdate(id);
        if (find == null)
            return Constant.NOT_EXIST_OBJACT;
        if (find.getState() != Extract.STATE_NOT_PROCESS) {
            return Constant.OBJECT_STATE_EXCEPTION;
        }
        // 更改提现状态为处理中
        Extract updateExtract = new Extract();
        updateExtract.setId(id);
        updateExtract.setState(Extract.STATE_PROCESSING);
        extractMapper.updateByPrimaryKeySelective(updateExtract);
        // 改变资金记录状态
        UserMoneyDetail detail = userMoneyDetailService.selectByTypeAndUidAndIdentifyCode(
                UserMoneyDetailTypeEnum.extract, find.getUserInfo().getId(), find.getId());
        if (detail != null) {
            UserMoneyDetail update = new UserMoneyDetail(detail.getId());
            update.setShow(true);
            update.setUpdateTime(new Date());
            userMoneyDetailMapper.updateByPrimaryKeySelective(update);
        }
        transfer(find, admin); // 提现通过,支付宝转账
        return null;
    }
    @Transactional(rollbackFor = Exception.class)
    public synchronized void rejectExtract(long id, String reason, AdminUser admin)
            throws ObjectStateException, NotExistObjectException {
        Extract find = extractMapper.selectByPrimaryKey(id);
        if (find == null) {
            throw new NotExistObjectException("不存在该对象");
        }
        if (find.getState() != Constant.EXTRACT_DEFUALT) {
            throw new ObjectStateException("该状态不等于不为初始状态");
        }
        UserInfo user = find.getUserInfo();
        UserMoneyDetail userMoneyDetail = null;
        try {
            userMoneyDetail = UserMoneyDetailFactory.createExtractReject(find);
        } catch (UserMoneyDetailException e1) {
            e1.printStackTrace();
        }
        // 增加资金
        userMoneyService.addUserMoney(user.getId(), find.getMoney(), userMoneyDetail);
        // 更新原来的状态
        Extract updateExtract = new Extract();
        updateExtract.setId(id);
        updateExtract.setState(Constant.EXTRACT_REJECT);
        updateExtract.setReason(reason);
        extractMapper.updateByPrimaryKeySelective(updateExtract);
        long auditTime = java.lang.System.currentTimeMillis();
        // 更新审核记录
        ExtractAuditRecord auditRecord = new ExtractAuditRecord();
        List<ExtractAuditRecord> records = extractAuditRecordMapper.getbyExtractId(id);
        if (records != null && records.size() > 0) {
            auditRecord = records.get(0);
        }
        // 角色默认:客服
        auditRecord.setAuditRole("客服");
        // 审核人
        auditRecord.setAdminUser(admin);
        // 提现之后金额 不变
        auditRecord.setAfterMoney(auditRecord.getBeforeMoney());
        // 审核时间
        auditRecord.setAuditTime(auditTime);
        // 历史提现金额
        Long uid = user.getId();
        double countSuccessMoneys = extractMapper.countSuccessMoneysByUid(uid);
        auditRecord.setCountMoney(new BigDecimal(countSuccessMoneys));
        // 历史提现次数
        long countSuccess = extractMapper.countSuccessByUid(uid);
        auditRecord.setCountNum(countSuccess);
        // 更新提现记录审核表
        extractAuditRecordMapper.updateByPrimaryKeySelective(auditRecord);
        // 新版资金详情
        // 新版通知
        userMoneyMsgNotificationService.extractFail(find, reason);
    }
    /**
     * 提现申请
     *
     * @param extract
     * @return
     */
    @Transactional
    private Integer extract(Extract extract) {
        UserAccountBindingHistory history = userAccountBindingHistoryService
                .getLatestHistory(extract.getUserInfo().getId(), UserAccountBindingHistory.TYPE_PHONE);
        // 手机号更换绑定的7天内不能提现
        if (history != null && !history.getFirst()
                && (System.currentTimeMillis() - history.getCreateTime().getTime()) < 1000 * 60 * 60 * 24 * 7L)
            return 111;
        UserInfo user = userInfoMapper.selectByPrimaryKeyForUpdate(extract.getUserInfo().getId());
        // 余额不足
        if (user.getMyHongBao().compareTo(extract.getMoney()) < 0) {
            return 3;
        }
        // 有借贷关系
        boolean isHaveToReplay = userMoneyDebtService.isHaveDebtToRepay(extract.getUserInfo().getId());
        if (isHaveToReplay) {
            return 110;
        }
        final String autoExtract = configService.getValue(ConfigKeyEnum.extractWay.getKey(), user.getSystem()); // 是否自动转账
        final String maxCount = configService.getValue(ConfigKeyEnum.extractDayCount.getKey(), user.getSystem());
        final String maxMoney = configService.getValue(ConfigKeyEnum.extractMoneyDay.getKey(), user.getSystem());
        Integer type = setExtractRecord(extract, maxCount, maxMoney);
        if (type != 0) {
            return type;
        }
        extractMapper.insertSelective(extract);
        final ExtractAuditRecord auditRecord = new ExtractAuditRecord();
        auditRecord.setBeforeMoney(user.getMyHongBao());
        auditRecord.setExtract(extract);
        Date minTime = new Date(System.currentTimeMillis() - 1000 * 60 * 60L * 24 * 180);
        extractAuditRecordMapper.insertSelective(auditRecord);
        ThreadUtil.run(new Runnable() {
            @Override
            public void run() {
                // 统计数据
                int less10Count = commonOrderCountService.countOderByUidAndLess10(user.getId());
                ExtractAuditRecord update = new ExtractAuditRecord();
                update.setId(auditRecord.getId());
                int orderCountBigMoneyOrder = orderUserStatisticService.countOrderMoneyMoreByUidAndMinTime(user.getId(),
                        minTime, OrderConstant.BIG_ORDER_MONEY);
                BigDecimal weiQuanOrderFanAmount = orderUserStatisticService.sumWeiQuanOrderFanAmountByUid(user.getId(),
                        minTime);
                int weiQuanOrderCount = orderUserStatisticService.countWeiQuanOrderByUid(user.getId(), minTime);
                update.setExtraInfoStr(new Gson().toJson(new ExtractOrderStatisticDTO(orderCountBigMoneyOrder,
                        weiQuanOrderCount, weiQuanOrderFanAmount, 0, less10Count)));
                extractAuditRecordMapper.updateByPrimaryKeySelective(update);
            }
        });
        // 新版资金详情
        UserMoneyDetail userMoneyDetail = null;
        try {
            userMoneyDetail = UserMoneyDetailFactory.createExtract(extract, null);
        } catch (UserMoneyDetailException e2) {
            try {
                LogHelper.errorDetailInfo(e2);
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
        // 减去账户资金
        userMoneyService.subUserMoney(extract.getUserInfo().getId(), extract.getMoney(), userMoneyDetail);
        // 添加新版通知
        userMoneyMsgNotificationService.extractApplay(extract);
        if ("是".equals(autoExtract)) {
            LogHelper.userInfo("uid=" + user.getId() + ",提交转账申请!");
        } else {// 暂时不自动提现
            // transfer(extract, null);
        }
        return null;
    }
    /**
     * 转账
     *
     * @param extract
     * @param session
     */
    private void transfer(Extract extract, AdminUser adminUser) {
        Integer type = extract.getType();
        if (Constant.ZHIFUBAO == type) {
            extractByZhiFuBao(extract, adminUser);
        } else {
            LogHelper.userInfo("提现类型错误:" + type);
        }
    }
    /**
     * 增加提现记录
     *
     * @param extract
     * @param maxCount 最多提现次数
     * @param maxMoney 最大提现金额
     * @param session
     * @return 如果为0,则增加成功。为1,则超过每日最多提现次数。为2,则超过每日最多提现金额
     */
    @Transactional
    public Integer setExtractRecord(Extract extract, String maxCount, String maxMoney) {
        long uid = extract.getUserInfo().getId();
        BigDecimal money = extract.getMoney();
        List<ExtractRecord> extractRecordList = extractRecordMapper.selectByUidAndToday(uid);
        if (extractRecordList.size() == 0) {
            ExtractRecord er = new ExtractRecord();
            er.setCount(1);
            er.setMoney(money);
            er.setUserInfo(new UserInfo(uid));
            er.setCreateTime(java.lang.System.currentTimeMillis());
            extractRecordMapper.insertSelective(er);
        } else {
            ExtractRecord er = extractRecordList.get(0);
            int count = er.getCount();
            int maxCountInt = Integer.parseInt(maxCount);
            if (count >= maxCountInt) {
                return 1;
            }
            BigDecimal oldMoney = er.getMoney();
            BigDecimal sumMoney = MoneyBigDecimalUtil.add(money, oldMoney);
            BigDecimal maxMoneyDou = new BigDecimal(maxMoney);
            if (maxMoneyDou.compareTo(sumMoney) == -1) {
                return 2;
            }
            ExtractRecord updateER = new ExtractRecord();
            updateER.setId(er.getId());
            updateER.setCount(count + 1);
            updateER.setMoney(sumMoney);
            er.setCreateTime(java.lang.System.currentTimeMillis());
            extractRecordMapper.updateByPrimaryKeySelective(updateER);
        }
        return 0;
    }
    private String getOrderPrefix(SystemEnum system) {
        if (system == SystemEnum.yhqjx) {
            return "TJ";
        } else if (system == SystemEnum.hsb) {
            return "HSB";
        }
        return "";
    }
    /**
     * 提现到支付宝
     *
     * @param extract
     * @param session
     */
    // TODO 转账逻辑需要改变,固定IP
    private void extractByZhiFuBao(Extract extract, AdminUser adminUser) {
        LogHelper.userErrorInfo("提现:开始通过提现-" + extract.getId());
        //获取用户的系统
        UserInfo user = userInfoMapper.selectByPrimaryKey(extract.getUserInfo().getId());
        String appName = user.getSystem().getName();
        //备注
        String remark = appName + "APP渠道提现";
        //理由
        String reason = String.format("用户ID【%s】发起的提现", getOrderPrefix(user.getSystem()) + user.getId());
        AlipayFundTransUniTransferResponse response = null;
        try {
            response = AlipayUtil.transferNoThrowException("widthdraw_" + extract.getId(), extract.getAccount(), extract.getName(), extract.getMoney(), remark, reason);
            LogHelper.userErrorInfo("提现:支付宝通过提现成功-" + extract.getId());
        } catch (AlipayApiException e) {
            LogHelper.errorDetailInfo(e, "支付宝转账异常:" + extract.getId(), "");
            LogHelper.userErrorInfo("提现:支付宝提现异常:" + response + ",提现信息" + GsonUtil.toJson(extract));
        }
        try {
            rabbitmqManager.addExtractResultMsg(extract, response, adminUser);
            LogHelper.userErrorInfo("提现:添加处理队列成功-" + extract.getId());
        } catch (Exception e) {
            LogHelper
                    .userErrorInfo("提现:支付宝提现CMQ异常:" + new Gson().toJson(response) + ",提现信息" + GsonUtil.toJson(extract));
        }
    }
    /**
     * 提现失败
     *
     * @param extract
     * @param msg
     */
    private void extractFail(Extract extract, String subCode, String msg) {
        UserInfo user = extract.getUserInfo();
        // MoneyRecord moneyRecord = new MoneyRecord(user, null, extract
        // .getMoney(), "提现", "提现失败", new Date().getTime(), 3);
        if ("PAYER_BALANCE_NOT_ENOUGH".equals(subCode) || "BALANCE_IS_NOT_ENOUGH".equals(subCode)) {
            Extract updateExtract = new Extract();
            updateExtract.setId(extract.getId());
            updateExtract.setState(Constant.EXTRACT_DEFUALT);
            updateExtract.setReason(msg);
            extractMapper.updateByPrimaryKeySelective(updateExtract);
        } else {
            // 老版本功能
            // List<MoneyRecord> list = moneyRecordDao.list("from MoneyRecord mr
            // where mr.extract.id =" + extract.getId());
            // if (list.size() > 0) {
            // MoneyRecord moneyRecord = list.get(0);
            // moneyRecordMapper.deleteByPrimaryKey(moneyRecord.getId());
            // }
            Extract updateExtract = new Extract();
            updateExtract.setId(extract.getId());
            updateExtract.setState(Constant.EXTRACT_REJECT);
            updateExtract.setReason(msg);
            extractMapper.updateByPrimaryKeySelective(updateExtract);
            UserMoneyDetail userMoneyDetail = null;
            // 新版资金详情
            try {
                userMoneyDetail = UserMoneyDetailFactory.createExtractReject(extract);
            } catch (UserMoneyDetailException e2) {
                try {
                    LogHelper.errorDetailInfo(e2);
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
            // 增加资金
            userMoneyService.addUserMoney(user.getId(), extract.getMoney(), userMoneyDetail);
            try {
                LogHelper.userInfo("支付宝转账失败:[提现IP:" + extract.getIp() + ",所转账号:" + extract.getAccount() + ",真实姓名:"
                        + extract.getName() + ",所转金额:" + extract.getMoney() + ",失败原因" + extract.getReason() + "]");
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 新版提现
            userMoneyMsgNotificationService.extractFail(extract, null);
        }
    }
    /**
     * 提现成功
     *
     * @param extract
     * @param session
     */
    private void extractSuccess(Extract extract, String alipayNo) {
        // 老版本功能
        // List<MoneyRecord> list = moneyRecordDao.list("from MoneyRecord mr
        // where mr.extract.id = " + extract.getId());
        // MoneyRecord moneyRecord = list.get(0);
        // moneyRecord.setType(3);
        // MoneyRecord updateMoneyRecord = new MoneyRecord();
        // updateMoneyRecord.setId(moneyRecord.getId());
        // updateMoneyRecord.setType(3);
        // moneyRecordMapper.updateByPrimaryKeySelective(updateMoneyRecord);
        Extract updateExtract = new Extract();
        updateExtract.setId(extract.getId());
        updateExtract.setState(Constant.EXTRACT_PASS);
        updateExtract.setReceiveTime(new Date());
        updateExtract.setReason("提现成功");
        extractMapper.updateByPrimaryKeySelective(updateExtract);
        try {
            LogHelper.userInfo("支付宝转账成功:[提现IP:" + extract.getIp() + ",所转账号:" + extract.getAccount() + ",真实姓名:"
                    + extract.getName() + ",所转金额:" + extract.getMoney() + "]");
        } catch (Exception e) {
            e.printStackTrace();
        }
        UserMoneyDetail detailNew = null;
        try {
            detailNew = UserMoneyDetailFactory.createExtract(extract, alipayNo);
        } catch (UserMoneyDetailException e) {
            e.printStackTrace();
        }
        // 外显账户明细
        UserMoneyDetail userMoneyDetail = userMoneyDetailMapper.selectByTypeAndUidAndIdentifyCode(
                UserMoneyDetailTypeEnum.extractNew, extract.getUserInfo().getId(), extract.getId());
        if (userMoneyDetail != null) {
            UserMoneyDetail detail = new UserMoneyDetail(userMoneyDetail.getId());
            detail.setShow(true);
            detail.setUpdateTime(new Date());
            if (detailNew != null)
                detail.setDescInfo(detailNew.getDescInfo());
            userMoneyDetailMapper.updateByPrimaryKeySelective(detail);
        }
        // 新版通知
        userMoneyMsgNotificationService.extractSuccess(extract, alipayNo);
    }
    /**
     * 根据提现记录id获取用户uid
     */
    @Override
    public Extract getExtractById(long id) {
        return extractMapper.selectByPrimaryKey(id);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void checkExtract(Long uid) throws ExtractException {
        BigDecimal compensateMoney = extractMapper.computeCompensateByUid(uid);
        if (compensateMoney == null)
            compensateMoney = new BigDecimal(0);
        // 不判定到账红包问题
        Long count = hongBaoV2Mapper.countByUidAndState(uid, HongBao.STATE_YILINGQU);
        if ((count == null || count == 0) && compensateMoney.compareTo(new BigDecimal(0)) == 0) {
            throw new ExtractException(1, "没有已到账的红包");
        }
        // 查询是否有欠账
        boolean isDebt = userMoneyDebtService.isHaveDebtToRepay(uid);
        if (isDebt)
            throw new ExtractException(3, "有欠账未还");
        // 获取所有收入所得
        BigDecimal hongBaoMoney = hongBaoV2Service.computeMoneyByUidAndState(uid, HongBaoV2.STATE_YILINGQU);
        Date now = new Date();
        //获取团队分红
        List<UserMoneyDetailTypeEnum> typeList = new ArrayList<>();
        typeList.add(UserMoneyDetailTypeEnum.teamDividents);
        BigDecimal teamDividents = userMoneyDetailService.statisticUserTypeMoneyWithDate(uid, typeList, new Date(0),
                now);
        //红包提现收入
        typeList = new ArrayList<>();
        typeList.add(UserMoneyDetailTypeEnum.redPackExchange);
        BigDecimal redPackExchange = userMoneyDetailService.statisticUserTypeMoneyWithDate(uid, typeList, new Date(0),
                now);
        //----------所有支出开始------------
        // 获取提现,获取提现验证
        typeList = new ArrayList<>();
        typeList.add(UserMoneyDetailTypeEnum.extract);
        typeList.add(UserMoneyDetailTypeEnum.extractNew);
        typeList.add(UserMoneyDetailTypeEnum.extractReject);
        typeList.add(UserMoneyDetailTypeEnum.extractVerify);
        typeList.add(UserMoneyDetailTypeEnum.extractVerifyNew);
        BigDecimal extractMoney = userMoneyDetailService.statisticUserTypeMoneyWithDate(uid, typeList, new Date(0),
                now);
        extractMoney = extractMoney.abs();
        // 获取维权
        typeList = new ArrayList<>();
        typeList.add(UserMoneyDetailTypeEnum.weiQuan);
        typeList.add(UserMoneyDetailTypeEnum.fanliWeiQuan);
        typeList.add(UserMoneyDetailTypeEnum.inviteWeiQuan);
        typeList.add(UserMoneyDetailTypeEnum.shareWeiQuan);
        typeList.add(UserMoneyDetailTypeEnum.hongbaoDeduct);
        //新版维权(到账时减去了维权资金,但是在资金明细里面加入了维权金额,但并未外显)
        typeList.add(UserMoneyDetailTypeEnum.fanliWeiQuanNew);
        BigDecimal weiqaunMoney = userMoneyDetailService.statisticUserTypeMoneyWithDate(uid, typeList, new Date(0),
                now);
        weiqaunMoney = weiqaunMoney.abs();
        //--------------所有支出结束------------
        BigDecimal balance = userInfoService.selectByPKey(uid).getMyHongBao();
        BigDecimal after = hongBaoMoney.add(teamDividents).add(redPackExchange).subtract(extractMoney.add(weiqaunMoney).add(balance).add(compensateMoney));
        if (after.compareTo(new BigDecimal("0")) != 0)
            throw new ExtractException(2, "结算资金异常:" + after);
    }
    @Override
    public Extract selectByPrimaryKey(Long id) {
        return extractMapper.selectByPrimaryKey(id);
    }
    @Override
    public Extract getMyTaskInfo(Long adminId) {
        return extractMapper.getMyTaskInfo(adminId);
    }
    @Override
    public Extract getNewTaskInfo() {
        return extractMapper.getNewTaskInfo();
    }
    @Override
    public List<Map<String, Object>> getFinishRecord(int pageIndex, int pageSize, String key, String startTime,
                                                     String endTime) {
        return extractMapper.getFinishRecord((pageIndex - 1) * pageSize, pageSize, key, startTime, endTime);
    }
    @Override
    public int updateByPrimaryKeySelective(Extract record) {
        return extractMapper.updateByPrimaryKeySelective(record);
    }
    @Transactional
    @Override
    public void processExtractResult(AlipayTransferResultInfo info) {
        if (info == null)
            return;
        AlipayFundTransUniTransferResponse response = info.getAlipayFundTransUniTransferResponse();
        Extract extract = info.getExtract();
        AdminUser admin = info.getAdminUser();
        if (response == null)
            return;
        if (extract == null)
            return;
        extract = extractMapper.selectByPrimaryKey(info.getExtract().getId());
        LogHelper.test("提现结果:code-" + response.getCode() + " 信息:" + response.getMsg());
        long uid = extract.getUserInfo().getId();
        if (response.isSuccess()) {
            String code = response.getCode();
            if ("10000".equals(code)) {
                extractSuccess(extract, response.getOrderId());
            } else {
                extractFail(extract, response.getSubCode(), response.getSubMsg());
            }
        } else {
            extractFail(extract, response.getSubCode(), response.getSubMsg());
        }
        PayInfo payInfo = new PayInfo();
        payInfo.setBizno(response.getOutBizNo());
        payInfo.setCreatetime(new Date());
        payInfo.setExtract(extract);
        if ("10000".equals(response.getCode())) {
            payInfo.setState(1);
        } else {
            payInfo.setState(2);
        }
        payInfo.setOrderId(response.getOrderId());
        payInfo.setOrdertime(response.getTransDate());
        payInfo.setInfo(response.getSubMsg());
        payInfoMapper.insertSelective(payInfo);
        // 更新审核记录
        ExtractAuditRecord auditRecord = null;
        List<ExtractAuditRecord> records = extractAuditRecordMapper.getbyExtractId(extract.getId());
        if (records != null && records.size() > 0) {
            auditRecord = records.get(0);
        }
        if (auditRecord != null) {
            // 提现付款记录
            List<PayInfo> paylist = payInfoMapper.getListbyExtractId(extract.getId());
            if (paylist != null && paylist.size() > 0) {
                // 提现成功 : 提现之前总金额:提现时金额减去提现金额
                BigDecimal exceedMoney = MoneyBigDecimalUtil.sub(auditRecord.getBeforeMoney(), extract.getMoney());
                // 提现之后金额
                auditRecord.setAfterMoney(exceedMoney);
            } else {
                // 提现失败:付款方余额不足、账户信息错误 提现之后金额 不变
                auditRecord.setAfterMoney(auditRecord.getBeforeMoney());
            }
            // 历史提现金额
            double countSuccessMoneys = extractMapper.countSuccessMoneysByUid(uid);
            auditRecord.setCountMoney(new BigDecimal(countSuccessMoneys));
            // 历史提现次数
            long countSuccess = extractMapper.countSuccessByUid(uid);
            auditRecord.setCountNum(countSuccess);
            // 角色默认:客服
            auditRecord.setAuditRole("客服");
            // 审核人
            auditRecord.setAdminUser(admin);
            // 审核时间
            auditRecord.setAuditTime(java.lang.System.currentTimeMillis());
            // 更新提现记录审核表
            extractAuditRecordMapper.updateByPrimaryKeySelective(auditRecord);
        }
    }
    @Transactional
    @Override
    public void testExtractSuccess(Long id) {
        Extract extract = extractMapper.selectByPrimaryKey(id);
        extractSuccess(extract, null);
        Long uid = extract.getUserInfo().getId();
        // 更新审核记录
        ExtractAuditRecord auditRecord = null;
        List<ExtractAuditRecord> records = extractAuditRecordMapper.getbyExtractId(extract.getId());
        if (records != null && records.size() > 0) {
            auditRecord = records.get(0);
        }
        if (auditRecord != null) {
            // 提现付款记录
            List<PayInfo> paylist = payInfoMapper.getListbyExtractId(extract.getId());
            if (paylist != null && paylist.size() > 0) {
                // 提现成功 : 提现之前总金额:提现时金额减去提现金额
                BigDecimal exceedMoney = MoneyBigDecimalUtil.sub(auditRecord.getBeforeMoney(), extract.getMoney());
                // 提现之后金额
                auditRecord.setAfterMoney(exceedMoney);
            } else {
                // 提现失败:付款方余额不足、账户信息错误 提现之后金额 不变
                auditRecord.setAfterMoney(auditRecord.getBeforeMoney());
            }
            // 历史提现金额
            double countSuccessMoneys = extractMapper.countSuccessMoneysByUid(uid);
            auditRecord.setCountMoney(new BigDecimal(countSuccessMoneys));
            // 历史提现次数
            long countSuccess = extractMapper.countSuccessByUid(uid);
            auditRecord.setCountNum(countSuccess);
            // 角色默认:客服
            auditRecord.setAuditRole("客服");
            // 审核人
            auditRecord.setAdminUser(new AdminUser(3L));
            // 审核时间
            auditRecord.setAuditTime(java.lang.System.currentTimeMillis());
            // 更新提现记录审核表
            extractAuditRecordMapper.updateByPrimaryKeySelective(auditRecord);
        }
    }
    @Override
    public BigDecimal sumTodayApplyMoney(Long uid, String day) {
        return extractMapper.sumToadyApplyByUid(uid, day);
    }
    @Override
    public BigDecimal sumVerifyingMoney(Long uid) {
        List<Integer> stateList = new ArrayList<>();
        stateList.add(Extract.STATE_NOT_PROCESS);
        stateList.add(Extract.STATE_PROCESSING);
        BigDecimal money = extractMapper.sumMoneyByUidAndState(uid, stateList);
        if (money == null)
            return new BigDecimal(0);
        else
            return money;
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void autoExtract(UserInfo user) {
        if (user == null || user.getWxOpenId() == null || user.getWxUnionId() == null
                || user.getState() != UserInfo.STATE_NORMAL)
            return;
        Date date = new Date();
        BigDecimal money = new BigDecimal(Constant.AUTO_EXTRACT_MONEY);
        // 1、插入记录
        ExtractWeiXinRecord extractRecord = new ExtractWeiXinRecord();
        extractRecord.setUid(user.getId());
        extractRecord.setOpenId(user.getWxOpenId());
        extractRecord.setUnionId(user.getWxUnionId());
        extractRecord.setMoney(money);
        extractRecord.setCreateTime(date);
        extractRecord.setUpdateTime(date);
        extractWeiXinRecordService.insertSelective(extractRecord);
        // 交易号
        Long recordId = extractRecord.getId();
        String billno = "BanLiExtract" + recordId;
        // 更新记录
        ExtractWeiXinRecord updeteRecord = null;
        String mchId = "1520950211";
        String appId = "wx5c0d167c6e3ad726";
        String key = "XYJkJ2018FAfaodCCx899mLl138rfGVd";
        // 2、发放微信红包
        RedPackParams redPackParams = new RedPackParams();
        redPackParams.setBillno(billno);
        redPackParams.setMchId(mchId);
        redPackParams.setWxappId(appId);
        redPackParams.setSendName("板栗快省");
        redPackParams.setOpenid(user.getWxOpenId());
        redPackParams.setMoney(money);
        redPackParams.setTotalNum(1);
        redPackParams.setWishing("账户中剩余余额请在本App内完成提现");
        redPackParams.setClientIp("106.80.118.163");
        redPackParams.setActName("自动提现");
        redPackParams.setKey(key);
        redPackParams.setRemark("微信自动提现");
        // redPackParams.setSceneId(null);
        // redPackParams.setRiskInfo(null);
        // 发生红包状态
        boolean stateRedPack = false;
        String pwd = "1520950211";
        InputStream cert = ExtractServiceImpl.class.getClassLoader()
                .getResourceAsStream("certificate/apiclient_cert.p12"); // 读取.p12文件
        // 执行发放红包
        try {
            String result = WXPayUtil.redPackToOpenId(redPackParams, pwd, cert);
            if (!StringUtil.isNullOrEmpty(result)) {
                stateRedPack = parseSendResult(result);
            }
            if (!stateRedPack) {
                String redPackRecord = WXPayUtil.getRedPackRecord(billno, mchId, appId, key, pwd, cert);
                if (!StringUtil.isNullOrEmpty(redPackRecord)) {
                    updeteRecord = parseDTO(redPackRecord);
                }
            }
        } catch (Exception e) {
            String redPackRecord = WXPayUtil.getRedPackRecord(billno, mchId, appId, key, pwd, cert);
            if (!StringUtil.isNullOrEmpty(redPackRecord)) {
                updeteRecord = parseDTO(redPackRecord);
            }
            LogHelper.errorDetailInfo(e);
        }
        try {
            cert.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        // 更新信息
        if (updeteRecord == null) {
            updeteRecord = new ExtractWeiXinRecord();
        } else {
            stateRedPack = true;
        }
        updeteRecord.setId(recordId);
        updeteRecord.setStatus(ExtractWeiXinRecord.SENDING);
        updeteRecord.setBillno(billno);
        extractWeiXinRecordService.updateByPrimaryKeySelective(updeteRecord);
        // 红包发放失败
        if (!stateRedPack)
            return;
        // 3、加入资金明细
        UserMoneyDetail detail = new UserMoneyDetail();
        detail.setCreateTime(new Date());
        detail.setIdentifyCode(StringUtil.Md5(UserMoneyDetailTypeEnum.extractAutoWX.name() + ":" + recordId));
        detail.setMoney(money);
        detail.setTitle(UserMoneyDetailTypeEnum.extractAutoWX.getDesc());
        detail.setType(UserMoneyDetailTypeEnum.extractAutoWX);
        detail.setUpdateTime(new Date());
        detail.setUserInfo(user);
        try {
            userMoneyDetailService.addUserMoneyDetail(detail);
        } catch (UserMoneyDetailException e) {
            LogHelper.errorDetailInfo(e);
        }
    }
    private boolean parseSendResult(String result) {
        try {
            Document document = DocumentHelper.parseText(result);
            // 获取根节点元素对象
            Element root = document.getRootElement();
            Element returnCode = root.element("return_code");
            if (!"SUCCESS".equalsIgnoreCase(returnCode.getText())) {
                Element returnMsg = root.element("return_msg");
                System.out.println(returnMsg.getText());
                return false;
            }
            Element resultCode = root.element("result_code");
            if (!"SUCCESS".equalsIgnoreCase(resultCode.getText())) {
                Element errCode = root.element("err_code");
                Element errCodeDes = root.element("err_code_des");
                System.out.println(errCode.getText() + ":" + errCodeDes.getText());
                return false;
            }
            return true;
        } catch (DocumentException e) {
            e.printStackTrace();
            LogHelper.errorDetailInfo(e);
        }
        return false;
    }
    private ExtractWeiXinRecord parseDTO(String result) {
        try {
            Document document = DocumentHelper.parseText(result);
            // 获取根节点元素对象
            Element root = document.getRootElement();
            Element returnCode = root.element("return_code");
            if (!"SUCCESS".equalsIgnoreCase(returnCode.getText())) {
                Element returnMsg = root.element("return_msg");
                System.out.println(returnMsg.getText());
                return null;
            }
            Element resultCode = root.element("result_code");
            if (!"SUCCESS".equalsIgnoreCase(resultCode.getText())) {
                Element errCode = root.element("err_code");
                Element errCodeDes = root.element("err_code_des");
                System.out.println(errCode.getText() + ":" + errCodeDes.getText());
            }
            ExtractWeiXinRecord resultRecord = new ExtractWeiXinRecord();
            resultRecord.setBillno(root.element("result_code").getText());
            resultRecord.setDetailno(root.element("detail_id").getText());
            resultRecord.setStatus(root.element("status").getText());
            resultRecord.setSendType(root.element("send_type").getText());
            resultRecord.setHbType(root.element("result_code").getText());
            String totalNum = root.element("total_num").getText();
            resultRecord.setTotalNum(Integer.parseInt(totalNum));
            String sendTime = root.element("send_time").getText();
            resultRecord.setSendTime(new Date(TimeUtil.convertDateToTemp2(sendTime)));
            Element element = root.element("hblist");
            Iterator<?> iterator = element.elementIterator();
            while (iterator.hasNext()) {
                Element childElement = (Element) iterator.next();
                Element rcvTime = childElement.element("rcv_time");
                resultRecord.setRcvTime(new Date(TimeUtil.convertDateToTemp2(rcvTime.getText())));
                break;
            }
            return resultRecord;
        } catch (DocumentException e) {
            e.printStackTrace();
            LogHelper.errorDetailInfo(e);
        }
        return null;
    }
    @Override
    public List<UserInfo> preAutoUser() throws Exception {
        int page = 0;
        int pageSize = 100;
        int maxSize = 300;
        Date nowDate = new Date();
        // 一、自动提现针对的用户群: 前提条件:用户在距今60天到90天内未活跃过的用户
        String beganDate = DateUtil.reduceDayTostring(90, nowDate);
        String endDate = DateUtil.reduceDayTostring(60, nowDate);
        // 条件3:距离上一次成功领取微信红包已经超过了30天时间,可在第31天再次下发;
        String receivedDate = DateUtil.reduceDayTostring(30, nowDate);
        // 条件4:距离上一次未成功领取微信红包已经超过了15天时间,可在第16天再次下发;
        String refundDate = DateUtil.reduceDayTostring(15, nowDate);
        // 余额最低限制
        BigDecimal minSurplus = BigDecimal.valueOf(Constant.AUTO_EXTRACT_MIN_SURPLUS);
        List<UserInfo> list = new ArrayList<UserInfo>();
        while (true) {
            // 查询满足条件 1、2 的uid
            List<UserInfo> listUser = userInfoService.getAutoExtractUser(page * pageSize, pageSize, minSurplus,
                    beganDate, endDate);
            if (listUser == null || listUser.isEmpty())
                break;
            List<Long> listId = new ArrayList<Long>();
            for (UserInfo userInfo : listUser) {
                listId.add(userInfo.getId());
            }
            // 查询记录是否满足
            List<Long> listValid = extractWeiXinRecordService.getValidUsers(listId, receivedDate, refundDate);
            if (listValid == null || listValid.isEmpty()) {
                page++;
                continue;
            }
            for (Long uid : listValid) {
                if (list.size() >= maxSize)
                    break;
                for (UserInfo userInfo : listUser) {
                    if (list.size() >= maxSize)
                        break;
                    if (userInfo.getId().longValue() == uid.longValue()) {
                        list.add(userInfo);
                        break;
                    }
                }
            }
            if (list.size() >= maxSize)
                break;
            page++;
        }
        return list;
    }
    @Override
    public List<String> getAutoExtractOpenIds() throws Exception {
        int page = 0;
        int pageSize = 100;
        int maxSize = 301; // appId + 实际openid300个
        Date nowDate = new Date();
        // 一、自动提现针对的用户群: 前提条件:用户在距今60天到90天内未活跃过的用户
        String beganDate = DateUtil.reduceDayTostring(90, nowDate);
        String endDate = DateUtil.reduceDayTostring(60, nowDate);
        // 条件3:距离上一次成功领取微信红包已经超过了30天时间,可在第31天再次下发;
        String receivedDate = DateUtil.reduceDayTostring(30, nowDate);
        // 条件4:距离上一次未成功领取微信红包已经超过了15天时间,可在第16天再次下发;
        String refundDate = DateUtil.reduceDayTostring(15, nowDate);
        // 提现金额
        BigDecimal money = BigDecimal.valueOf(Constant.AUTO_EXTRACT_MONEY);
        // 余额最低限制
        BigDecimal minSurplus = BigDecimal.valueOf(Constant.AUTO_EXTRACT_MIN_SURPLUS);
        List<String> listOpendIDs = new ArrayList<String>();
        // 首行appID
        listOpendIDs.add(Constant.getWXAccount(null, null).getAppId());
        while (true) {
            // 查询满足条件 1、2 的uid
            List<UserInfo> listUser = userInfoService.getAutoExtractUser(page * pageSize, pageSize, minSurplus,
                    beganDate, endDate);
            if (listUser == null || listUser.isEmpty())
                break;
            List<Long> listId = new ArrayList<Long>();
            for (UserInfo userInfo : listUser) {
                listId.add(userInfo.getId());
            }
            // 查询记录是否满足
            List<Long> listValid = extractWeiXinRecordService.getValidUsers(listId, receivedDate, refundDate);
            if (listValid == null || listValid.isEmpty()) {
                page++;
                continue;
            }
            for (Long uid : listValid) {
                UserInfo userInfo = subHongBaoByUid(uid, money, minSurplus);
                if (userInfo != null) {
                    listOpendIDs.add(userInfo.getWxOpenId());
                    if (listOpendIDs.size() >= maxSize)
                        break;
                }
            }
            if (listOpendIDs.size() >= maxSize)
                break;
            page++;
        }
        return listOpendIDs;
    }
    @Override
    public List<UserInfo> preAutoUserTo1212() throws Exception {
        int page = 0;
        int pageSize = 100;
        int maxSize = 300;
        Date nowDate = new Date();
        // 条件3:距离上一次成功领取微信红包已经超过了30天时间,可在第31天再次下发;
        String receivedDate = DateUtil.reduceDayTostring(30, nowDate);
        // 条件4:距离上一次未成功领取微信红包已经超过了15天时间,可在第16天再次下发;
        String refundDate = DateUtil.reduceDayTostring(15, nowDate);
        // 余额最低限制
        List<UserInfo> list = new ArrayList<UserInfo>();
        while (true) {
            // 查询满足条件 1、2 的uid
            List<UserInfo> listUser = userInfoService.getAutoExtractUserTo1212(page * pageSize, pageSize);
            if (listUser == null || listUser.isEmpty())
                break;
            List<Long> listId = new ArrayList<Long>();
            for (UserInfo userInfo : listUser) {
                listId.add(userInfo.getId());
            }
            // 查询记录是否满足
            List<Long> listValid = extractWeiXinRecordService.getValidUsers(listId, receivedDate, refundDate);
            if (listValid == null || listValid.isEmpty()) {
                page++;
                continue;
            }
            for (Long uid : listValid) {
                if (list.size() >= maxSize)
                    break;
                for (UserInfo userInfo : listUser) {
                    if (list.size() >= maxSize)
                        break;
                    if (userInfo.getId().longValue() == uid.longValue()) {
                        list.add(userInfo);
                        break;
                    }
                }
            }
            if (list.size() >= maxSize)
                break;
            page++;
        }
        return list;
    }
    @Override
    public List<String> getAutoExtractOpenIdsTo1212() throws Exception {
        int page = 0;
        int pageSize = 100;
        int maxSize = 301; // appId + 实际openid300个
        Date nowDate = new Date();
        // 条件3:距离上一次成功领取微信红包已经超过了30天时间,可在第31天再次下发;
        String receivedDate = DateUtil.reduceDayTostring(30, nowDate);
        // 条件4:距离上一次未成功领取微信红包已经超过了15天时间,可在第16天再次下发;
        String refundDate = DateUtil.reduceDayTostring(15, nowDate);
        // 提现金额
        BigDecimal money = BigDecimal.valueOf(1);
        List<String> listOpendIDs = new ArrayList<String>();
        // 首行appID
        listOpendIDs.add(Constant.getWXAccount(null, null).getAppId());
        while (true) {
            // 查询满足条件 1、2 的uid
            List<UserInfo> listUser = userInfoService.getAutoExtractUserTo1212(page * pageSize, pageSize);
            if (listUser == null || listUser.isEmpty())
                break;
            List<Long> listId = new ArrayList<Long>();
            for (UserInfo userInfo : listUser) {
                listId.add(userInfo.getId());
            }
            // 查询记录是否满足
            List<Long> listValid = extractWeiXinRecordService.getValidUsers(listId, receivedDate, refundDate);
            if (listValid == null || listValid.isEmpty()) {
                page++;
                continue;
            }
            for (Long uid : listValid) {
                UserInfo userInfo = subHongBaoByUid(uid, money, money);
                if (userInfo != null) {
                    listOpendIDs.add(userInfo.getWxOpenId());
                    if (listOpendIDs.size() >= maxSize)
                        break;
                }
            }
            if (listOpendIDs.size() >= maxSize)
                break;
            page++;
        }
        return listOpendIDs;
    }
    @Transactional(rollbackFor = Exception.class)
    private UserInfo subHongBaoByUid(Long uid, BigDecimal money, BigDecimal minSurplus) {
        UserInfo userInfo = userInfoMapper.selectByPrimaryKeyForUpdate(uid);
        if (userInfo != null && !StringUtil.isNullOrEmpty(userInfo.getWxOpenId())
                && !StringUtil.isNullOrEmpty(userInfo.getWxUnionId())
                && userInfo.getMyHongBao().compareTo(minSurplus) >= 0) {
            // 微信提现记录
            ExtractWeiXinRecord extractRecord = new ExtractWeiXinRecord();
            extractRecord.setUid(uid);
            extractRecord.setOpenId(userInfo.getWxOpenId());
            extractRecord.setUnionId(userInfo.getWxUnionId());
            extractRecord.setMoney(money);
            extractRecord.setStatus(ExtractWeiXinRecord.SENDING);
            extractRecord.setType(ExtractWeiXinRecord.TYPE_MANUAL);
            extractRecord.setCreateTime(new Date());
            extractRecord.setUpdateTime(new Date());
            extractWeiXinRecordService.insertSelective(extractRecord);
            // 记录id
            Long recordId = extractRecord.getId();
            // 资金明细
            UserMoneyDetail detail = new UserMoneyDetail();
            detail.setCreateTime(new Date());
            detail.setIdentifyCode(StringUtil.Md5(UserMoneyDetailTypeEnum.extractAutoWX.name() + ":" + recordId));
            detail.setMoney(new BigDecimal("-" + money.toString()));
            detail.setTitle(UserMoneyDetailTypeEnum.extractAutoWX.getDesc());
            detail.setType(UserMoneyDetailTypeEnum.extractAutoWX);
            detail.setUpdateTime(new Date());
            detail.setUserInfo(userInfo);
            // 资金计算
            userMoneyService.subUserMoney(userInfo.getId(), money, detail);
            // 满足条件返回信息
            return userInfo;
        }
        return null;
    }
    @Override
    public void updateManualExtractRecord(List<RedPackRecord> list) throws ExtractException {
        if (list == null || list.isEmpty())
            throw new ExtractException(1, "红包记录信息为空");
        for (RedPackRecord redPackRecord : list) {
            updateWeiXinRecord(redPackRecord);
        }
    }
    @Transactional(rollbackFor = Exception.class)
    private void updateWeiXinRecord(RedPackRecord redPackRecord) {
        if (StringUtil.isNullOrEmpty(redPackRecord.getOpenId()))
            return;
        ExtractWeiXinRecord record = extractWeiXinRecordService.getByOpenIdAndType(redPackRecord.getOpenId(),
                ExtractWeiXinRecord.TYPE_MANUAL);
        if (record == null)
            return;
        // 状态过滤
        String statusOld = record.getStatus();
        if (StringUtil.isNullOrEmpty(statusOld) || ExtractWeiXinRecord.REFUND.equals(statusOld)
                || ExtractWeiXinRecord.RECEIVED.equals(statusOld))
            return;
        ExtractWeiXinRecord updeteRecord = new ExtractWeiXinRecord();
        updeteRecord.setId(record.getId());
        updeteRecord.setUpdateTime(new Date());
        String billno = redPackRecord.getBillno();
        if (!StringUtil.isNullOrEmpty(billno)) {
            updeteRecord.setBillno(billno.replace("`", "").replace("'", ""));
        }
        String detailno = redPackRecord.getDetailno();
        if (!StringUtil.isNullOrEmpty(detailno)) {
            updeteRecord.setDetailno(detailno.replace("`", "").replace("'", ""));
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String rcvTime = redPackRecord.getRcvTime();
        if (!StringUtil.isNullOrEmpty(rcvTime)) {
            try {
                updeteRecord.setRcvTime(sdf.parse(rcvTime));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        String sendTime = redPackRecord.getSendTime();
        if (!StringUtil.isNullOrEmpty(sendTime)) {
            try {
                updeteRecord.setSendTime(sdf.parse(sendTime));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        String status = redPackRecord.getStatus();
        if (!StringUtil.isNullOrEmpty(status)) {
            switch (status) {
                case "已发放待领取":
                    status = ExtractWeiXinRecord.SENT;
                    break;
                case "过期未领退款":
                    status = ExtractWeiXinRecord.REFUND;
                    break;
                case "已领取":
                    status = ExtractWeiXinRecord.RECEIVED;
                    break;
                default:
                    status = null;
                    break;
            }
        }
        updeteRecord.setStatus(status);
        extractWeiXinRecordService.updateByPrimaryKeySelective(updeteRecord);
        if (ExtractWeiXinRecord.RECEIVED.equals(status)) {
        } else if (ExtractWeiXinRecord.REFUND.equals(status)) {
            // 资金明细
            UserMoneyDetail detail = new UserMoneyDetail();
            detail.setCreateTime(new Date());
            detail.setIdentifyCode(
                    StringUtil.Md5(UserMoneyDetailTypeEnum.extractAutoWXRefund.name() + ":" + record.getId()));
            detail.setMoney(record.getMoney());
            detail.setTitle(UserMoneyDetailTypeEnum.extractAutoWXRefund.getDesc());
            detail.setType(UserMoneyDetailTypeEnum.extractAutoWXRefund);
            detail.setUpdateTime(new Date());
            detail.setUserInfo(new UserInfo(record.getUid()));
            // 资金计算
            userMoneyService.addUserMoney(record.getUid(), record.getMoney(), detail);
        }
    }
    @Override
    public List<Extract> getExtractSucceedRecord(int page, int pageSize, Long uid) {
        return extractMapper.getExtractSucceedRecord((page - 1) * pageSize, pageSize, uid);
    }
    @Override
    public long countExtractSucceedRecord(Long uid) {
        Long count = extractMapper.countExtractSucceedRecord(uid);
        return count == null ? 0 : count;
    }
}