admin
2020-05-06 24a8d17e007545f7426c48352109aa1a9c6587ee
fanli/src/main/java/com/yeshi/fanli/service/impl/money/extract/ExtractServiceImpl.java
@@ -53,6 +53,7 @@
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;
@@ -67,6 +68,7 @@
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;
@@ -77,6 +79,7 @@
import com.yeshi.fanli.util.GsonUtil;
import com.yeshi.fanli.util.MoneyBigDecimalUtil;
import com.yeshi.fanli.util.StringUtil;
import com.yeshi.fanli.util.ThreadUtil;
import com.yeshi.fanli.util.TimeUtil;
import com.yeshi.fanli.util.factory.UserMoneyDetailFactory;
@@ -147,10 +150,12 @@
   @Resource
   private OrderUserStatisticService orderUserStatisticService;
   @Resource
   private ExtractWeiXinRecordService extractWeiXinRecordService;
   @Resource
   private CommonOrderCountService commonOrderCountService;
   @Transactional
   public Integer addExtract(Extract extract) {
@@ -173,12 +178,22 @@
      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
   @Transactional(rollbackFor = Exception.class)
   public synchronized void rejectExtract(long id, String reason, AdminUser admin)
         throws ObjectStateException, NotExistObjectException {
      Extract find = extractMapper.selectByPrimaryKey(id);
@@ -258,9 +273,9 @@
            && (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");
      final String autoExtract = configService.get(ConfigKeyEnum.extractWay.getKey()); // 是否自动转账
      final String maxCount = configService.get(ConfigKeyEnum.extractDayCount.getKey());
      final String maxMoney = configService.get(ConfigKeyEnum.extractMoneyDay.getKey());
      UserInfo user = userInfoMapper.selectByPrimaryKeyForUpdate(extract.getUserInfo().getId());
      // 余额不足
@@ -281,25 +296,37 @@
      extractMapper.insertSelective(extract);
      ExtractAuditRecord auditRecord = new ExtractAuditRecord();
      final 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);
      ThreadUtil.run(new Runnable() {
         @Override
         public void run() {
            // 统计数据
            int less10Count = commonOrderCountService.countOderByUidAndLess10(user.getId());
            ExtractAuditRecord update = new ExtractAuditRecord();
            update.setId(auditRecord.getId());
            int orderCount50More = orderUserStatisticService.countOrderCount100MoreByUidAndMinTime(user.getId(),
                  minTime);
            BigDecimal weiQuanOrderFanAmount = orderUserStatisticService.sumWeiQuanOrderFanAmountByUid(user.getId(),
                  minTime);
            int weiQuanOrderCount = orderUserStatisticService.countWeiQuanOrderByUid(user.getId(), minTime);
            update.setExtraInfoStr(new Gson().toJson(new ExtractOrderStatisticDTO(orderCount50More,
                  weiQuanOrderCount, weiQuanOrderFanAmount, 0, less10Count)));
            extractAuditRecordMapper.updateByPrimaryKeySelective(update);
         }
      });
      // 新版资金详情
      UserMoneyDetail userMoneyDetail = null;
      try {
         userMoneyDetail = UserMoneyDetailFactory.createExtract(extract);
         userMoneyDetail = UserMoneyDetailFactory.createExtract(extract, null);
      } catch (UserMoneyDetailException e2) {
         try {
            LogHelper.errorDetailInfo(e2);
@@ -318,7 +345,6 @@
         LogHelper.userInfo("uid=" + user.getId() + ",提交转账申请!");
      } else {// 暂时不自动提现
         // transfer(extract, null);
         ;
      }
      return null;
   }
@@ -394,17 +420,17 @@
    * @param extract
    * @param session
    */
   //TODO 转账逻辑需要改变,固定IP
   // TODO 转账逻辑需要改变,固定IP
   @Transactional
   private void extractByZhiFuBao(Extract extract, AdminUser adminUser) {
      LogHelper.userErrorInfo("提现:开始通过提现-"+extract.getId());
      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("out_biz_no", "widthdraw_" + extract.getId());// 最长长度64位,支持英文,下划线,数字
      json.put("payee_type", "ALIPAY_LOGONID");
      json.put("payee_account", extract.getAccount());
      json.put("amount", extract.getMoney());
@@ -415,17 +441,18 @@
      AlipayFundTransToaccountTransferResponse response = null;
      try {
         response = alipayClient.execute(request);
         LogHelper.userErrorInfo("提现:支付宝通过提现成功-"+extract.getId());
         LogHelper.userErrorInfo("提现:支付宝通过提现成功-" + extract.getId());
      } catch (AlipayApiException e) {
         e.printStackTrace();
         LogHelper.errorDetailInfo(e, "支付宝转账异常:" + extract.getId(), "");
         LogHelper.userErrorInfo("提现:支付宝提现异常:" + response + ",提现信息" + GsonUtil.toJson(extract));
      }
      try {
         CMQManager.getInstance().addExtractResultMsg(extract, response, adminUser);
         LogHelper.userErrorInfo("提现:添加处理队列成功-"+extract.getId());
         LogHelper.userErrorInfo("提现:添加处理队列成功-" + extract.getId());
      } catch (Exception e) {
         LogHelper.userErrorInfo("提现:支付宝提现CMQ异常:" + new Gson().toJson(response) + ",提现信息" + GsonUtil.toJson(extract));
         LogHelper
               .userErrorInfo("提现:支付宝提现CMQ异常:" + new Gson().toJson(response) + ",提现信息" + GsonUtil.toJson(extract));
      }
   }
@@ -496,7 +523,7 @@
    * @param session
    */
   @Transactional
   private void extractSuccess(Extract extract) {
   private void extractSuccess(Extract extract,String alipayNo) {
      // 老版本功能
      // List<MoneyRecord> list = moneyRecordDao.list("from MoneyRecord mr
      // where mr.extract.id = " + extract.getId());
@@ -519,8 +546,27 @@
      } 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);
      userMoneyMsgNotificationService.extractSuccess(extract, alipayNo);
   }
   /**
@@ -531,7 +577,7 @@
      return extractMapper.selectByPrimaryKey(id);
   }
   @Transactional
   @Transactional(rollbackFor = Exception.class)
   @Override
   public void checkExtract(Long uid) throws ExtractException {
      BigDecimal compensateMoney = extractMapper.computeCompensateByUid(uid);
@@ -553,8 +599,10 @@
      // 获取提现,获取提现验证
      List<UserMoneyDetailTypeEnum> 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();
@@ -623,7 +671,7 @@
      if (response.isSuccess()) {
         String code = response.getCode();
         if ("10000".equals(code)) {
            extractSuccess(extract);
            extractSuccess(extract,response.getOrderId());
         } else {
            extractFail(extract, response.getSubMsg());
         }
@@ -683,7 +731,6 @@
         // 更新提现记录审核表
         extractAuditRecordMapper.updateByPrimaryKeySelective(auditRecord);
      }
   }
@@ -692,7 +739,7 @@
   @Override
   public void testExtractSuccess(Long id) {
      Extract extract = extractMapper.selectByPrimaryKey(id);
      extractSuccess(extract);
      extractSuccess(extract,null);
      Long uid = extract.getUserInfo().getId();
      // 更新审核记录
@@ -737,55 +784,53 @@
   }
   @Override
   public BigDecimal sumTodayApplyMoney(Long uid,String day) {
      return extractMapper.sumToadyApplyByUid(uid,day);
   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)
      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)
      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.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);
@@ -800,22 +845,22 @@
      redPackParams.setActName("自动提现");
      redPackParams.setKey(key);
      redPackParams.setRemark("微信自动提现");
      //redPackParams.setSceneId(null);
      //redPackParams.setRiskInfo(null);
      // redPackParams.setSceneId(null);
      // redPackParams.setRiskInfo(null);
      // 发生红包状态
      boolean stateRedPack = false;
      String pwd = "1520950211";
      InputStream cert = ExtractServiceImpl.class.getClassLoader().getResourceAsStream("certificate/apiclient_cert.p12"); // 读取.p12文件
      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)) {
@@ -834,23 +879,23 @@
      } 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;
      if (!stateRedPack)
         return;
      // 3、加入资金明细
      UserMoneyDetail detail = new UserMoneyDetail();
      detail.setCreateTime(new Date());
@@ -865,97 +910,209 @@
      } 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;
         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;
         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;
@@ -964,52 +1121,107 @@
      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());
      List<UserInfo> list = new ArrayList<UserInfo>();
      while (true) {
         // 查询满足条件 1、2 的uid
         List<Long> listId = userInfoService.getAutoExtractUserIds(page * pageSize, pageSize, minSurplus);
         if (listId == null || listId.isEmpty())
         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 ++;
            page++;
            continue;
         }
         for (Long uid: listValid) {
            UserInfo userInfo = subHongBaoByUid(uid, money, minSurplus);
         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 ++;
         page++;
      }
      return listOpendIDs;
   }
   @Transactional(rollbackFor = Exception.class)
   private UserInfo subHongBaoByUid(Long uid, BigDecimal money, BigDecimal minSurplus) {
      UserInfo userInfo = userInfoMapper.selectByPrimaryKeyForUpdate(uid);
      if (userInfo != null && userInfo.getMyHongBao().compareTo(minSurplus) >= 0) {
      if (userInfo != null && !StringUtil.isNullOrEmpty(userInfo.getWxOpenId())
            && !StringUtil.isNullOrEmpty(userInfo.getWxUnionId())
            && userInfo.getMyHongBao().compareTo(minSurplus) >= 0) {
         // 微信提现记录
         ExtractWeiXinRecord extractRecord = new ExtractWeiXinRecord();
         extractRecord.setUid(uid);
@@ -1023,73 +1235,66 @@
         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.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{
   public void updateManualExtractRecord(List<RedPackRecord> list) throws ExtractException {
      if (list == null || list.isEmpty())
         throw new ExtractException(1, "红包记录信息为空");
      for (RedPackRecord redPackRecord: list) {
      for (RedPackRecord redPackRecord : list) {
         updateWeiXinRecord(redPackRecord);
      }
   }
   @Transactional(rollbackFor = Exception.class)
   private void updateWeiXinRecord(RedPackRecord redPackRecord){
   private void updateWeiXinRecord(RedPackRecord redPackRecord) {
      if (StringUtil.isNullOrEmpty(redPackRecord.getOpenId()))
         return;
      ExtractWeiXinRecord record  = extractWeiXinRecordService.getByOpenIdAndType(redPackRecord.getOpenId(), ExtractWeiXinRecord.TYPE_MANUAL);
      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.RFUND_ING.equals(statusOld))
      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("`", ""));
         updeteRecord.setBillno(billno.replace("`", "").replace("'", ""));
      }
      String detailno = redPackRecord.getDetailno();
      if (!StringUtil.isNullOrEmpty(detailno)) {
         updeteRecord.setDetailno(detailno.replace("`", ""));
         updeteRecord.setDetailno(detailno.replace("`", "").replace("'", ""));
      }
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm");
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
      String rcvTime = redPackRecord.getRcvTime();
      if (!StringUtil.isNullOrEmpty(rcvTime)) {
         try {
@@ -1098,7 +1303,7 @@
            e.printStackTrace();
         }
      }
      String sendTime = redPackRecord.getSendTime();
      if (!StringUtil.isNullOrEmpty(sendTime)) {
         try {
@@ -1107,44 +1312,42 @@
            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;
         }
         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.REFUND.equals(status))
         return;
      // 资金明细
      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);
      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);
      }
   }
}