package com.yeshi.fanli.service.impl.user; import java.io.Serializable; import java.math.BigDecimal; import java.util.Date; import java.util.List; import java.util.Map; import java.util.UUID; import javax.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; 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.AccountDetailsMapper; 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.MoneyRecordMapper; import com.yeshi.fanli.dao.mybatis.PayInfoMapper; import com.yeshi.fanli.dao.mybatis.SystemMapper; import com.yeshi.fanli.dao.mybatis.UserInfoMapper; import com.yeshi.fanli.dao.mybatis.hongbao.HongBaoMapper; import com.yeshi.fanli.dao.mybatis.money.UserMoneyDetailMapper; import com.yeshi.fanli.dao.user.AccountDetailsDao; import com.yeshi.fanli.dao.user.AccountMessageDao; import com.yeshi.fanli.dao.user.ExtractDao; import com.yeshi.fanli.dao.user.ExtractRecordDao; import com.yeshi.fanli.dao.user.MoneyRecordDao; import com.yeshi.fanli.entity.bus.user.AccountDetails; 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.HongBao; import com.yeshi.fanli.entity.bus.user.MoneyRecord; import com.yeshi.fanli.entity.bus.user.PayInfo; 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.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.msg.UserMoneyMsgNotificationService; import com.yeshi.fanli.service.inter.push.PushService; import com.yeshi.fanli.service.inter.user.AccountDetailsService; import com.yeshi.fanli.service.inter.user.AccountMessageService; import com.yeshi.fanli.service.inter.user.ExtractRecordService; import com.yeshi.fanli.service.inter.user.ExtractService; import com.yeshi.fanli.service.inter.user.MoneyRecordService; import com.yeshi.fanli.service.inter.user.UserInfoService; import com.yeshi.fanli.service.inter.user.UserNotificationService; 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.TimeUtil; import com.yeshi.fanli.util.factory.AccountDetailsFactory; import com.yeshi.fanli.util.factory.UserMoneyDetailFactory; import net.sf.json.JSONObject; @Service public class ExtractServiceImpl implements ExtractService { @Resource private ExtractDao extractDao; @Resource private UserInfoService userInfoService; @Resource private MoneyRecordService moneyRecordService; @Resource private ConfigService configService; @Resource private ExtractRecordService extractRecordService; @Resource private SystemConfigService systemConfigService; @Resource private AccountDetailsService accountDetailsService; @Resource private AccountMessageService accountMessageService; @Resource private ExtractMapper extractMapper; @Resource private ExtractAuditRecordMapper extractAuditRecordMapper; @Resource private UserInfoMapper userInfoMapper; @Resource private ExtractRecordDao extractRecordDao; @Resource private MoneyRecordDao moneyRecordDao; @Resource private AccountDetailsDao accountDetailsDao; @Resource private AccountMessageDao accountMessageDao; @Resource private PayInfoMapper payInfoMapper; @Resource private AccountDetailsMapper accountDetailsMapper; @Resource private MoneyRecordMapper moneyRecordMapper; @Resource private AccountMessageMapper accountMessageMapper; @Resource private ExtractRecordMapper extractRecordMapper; @Resource private SystemMapper systemMapper; @Resource private HongBaoMapper hongBaoMapper; @Resource private HongBaoV2Mapper hongBaoV2Mapper; @Resource private PushService pushService; @Resource private UserNotificationService userNotificationService; @Resource private UserMoneyDetailMapper userMoneyDetailMapper; @Resource private UserMoneyMsgNotificationService userMoneyMsgNotificationService; @Resource private AlipayAccountValidNormalHistoryMapper alipayAccountValidNormalHistoryMapper; public List getExtractInfoByUid(long uid) { return extractDao.list("from Extract e where e.userInfo.id=? and e.state != 2", new Serializable[] { uid }); } @Transactional public Integer addExtract(Extract extract) { Integer integer = extract(extract); return integer; } public List getExtractList(int index) { int start = index * Constant.PAGE_SIZE; return extractDao.list("from Extract e order by e.id desc", start, Constant.PAGE_SIZE, new Serializable[] {}); } public int getCount() { Long lcount = extractDao.getCount("select count(e.id) from Extract e"); return lcount.intValue(); } @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); transfer(find, admin); // 提现通过,支付宝转账 return null; } @Transactional public synchronized void rejectExtract(long id, String reason, long extractTime, 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(); userInfoMapper.addHongBaoByUid(user.getId(), find.getMoney()); // 删除提现记录 moneyRecordMapper.deleteMoneyRecordByExtractId(id); // 更新原来的状态 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 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); AccountDetails ad = AccountDetailsFactory.create("+" + find.getMoney(), AccountDetailsFactory.HUIKUAN, null, find, find.getUserInfo()); accountDetailsMapper.insertSelective(ad); // 新版资金详情 try { UserMoneyDetail userMoneyDetail = UserMoneyDetailFactory.createExtractReject(find); userMoneyDetail.setId(ad.getId()); userMoneyDetailMapper.insert(userMoneyDetail); } catch (UserMoneyDetailException e2) { try { LogHelper.errorDetailInfo(e2); } catch (Exception e3) { e3.printStackTrace(); } } try { userNotificationService.extractWrong(user.getId(), find, TimeUtil.getGernalTime(find.getExtractTime(), "yyyy-MM-dd HH:mm")); } catch (Exception e) { e.printStackTrace(); } // 新版通知 userMoneyMsgNotificationService.extractFail(find, reason); } /** * 提现申请 * * @param extract * @return */ @Transactional private Integer extract(Extract extract) { 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; } 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); extractAuditRecordMapper.insertSelective(auditRecord); // 减去账户资金 userInfoMapper.subHongBaoByUid(extract.getUserInfo().getId(), extract.getMoney()); MoneyRecord moneyRecord = new MoneyRecord(user, null, extract.getMoney(), "提现", "", extract.getExtractTime(), 2); moneyRecord.setExtract(extract); moneyRecordMapper.insertSelective(moneyRecord); AccountDetails ad = AccountDetailsFactory.create("-" + extract.getMoney(), AccountDetailsFactory.TIXIAN, null, extract, user); accountDetailsMapper.insertSelective(ad); // 新版资金详情 try { UserMoneyDetail userMoneyDetail = UserMoneyDetailFactory.createExtract(extract); userMoneyDetail.setId(ad.getId()); userMoneyDetailMapper.insert(userMoneyDetail); } catch (UserMoneyDetailException e2) { try { LogHelper.errorDetailInfo(e2); } catch (Exception e1) { e1.printStackTrace(); } } userNotificationService.extractApply(extract.getUserInfo().getId()); // 添加新版通知 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 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 */ @Transactional private void extractByZhiFuBao(Extract extract, AdminUser adminUser) { 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 uuid = UUID.randomUUID().toString().replace("-", ""); String appName = systemConfigService.get("appName", extract.getSystem()); JSONObject json = new JSONObject(); json.put("out_biz_no", uuid); json.put("payee_type", "ALIPAY_LOGONID"); json.put("payee_account", extract.getAccount()); json.put("amount", extract.getMoney()); json.put("payer_show_name", appName + "提现"); json.put("payee_real_name", extract.getName()); json.put("remark", "来自" + appName + "的提现"); request.setBizContent(json.toString()); AlipayFundTransToaccountTransferResponse response = null; try { response = alipayClient.execute(request); } catch (AlipayApiException e) { e.printStackTrace(); LogHelper.userErrorInfo("支付宝提现异常:" + response + ",提现信息" + GsonUtil.toJson(extract)); } try { CMQManager.getInstance().addExtractResultMsg(extract, response, adminUser); } 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 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); userInfoMapper.addHongBaoByUid(user.getId(), extract.getMoney()); AccountDetails ad = AccountDetailsFactory.create("+" + extract.getMoney(), AccountDetailsFactory.HUIKUAN, null, extract, extract.getUserInfo()); accountDetailsMapper.insertSelective(ad); // 新版资金详情 try { UserMoneyDetail userMoneyDetail = UserMoneyDetailFactory.createExtractReject(extract); userMoneyDetail.setId(ad.getId()); userMoneyDetailMapper.insert(userMoneyDetail); } catch (UserMoneyDetailException e2) { try { LogHelper.errorDetailInfo(e2); } catch (Exception e1) { e1.printStackTrace(); } } try { userNotificationService.extractTransferFail(user.getId(), TimeUtil.getGernalTime(extract.getExtractTime(), "yyyy-MM-dd HH:mm")); 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 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 { userNotificationService.extractSuccess(extract.getUserInfo().getId(), extract, TimeUtil.getGernalTime(extract.getExtractTime(), "yyyy-MM-dd HH:mm")); 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 extractDao.find(Extract.class, id); } @Override public void checkExtract(String uid) throws ExtractException { Long count = hongBaoV2Mapper.countByUidAndState(Long.parseLong(uid), HongBao.STATE_YILINGQU); if (count == null || count == 0) throw new ExtractException(1, "没有已到账的红包"); List list = extractMapper.checkExtract(uid); if (list != null && list.size() > 0 && list.get(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> 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 records = extractAuditRecordMapper.getbyExtractId(extract.getId()); if (records != null && records.size() > 0) { auditRecord = records.get(0); } if (auditRecord != null) { // 提现付款记录 List 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); Long uid = extract.getUserInfo().getId(); // 更新审核记录 ExtractAuditRecord auditRecord = null; List records = extractAuditRecordMapper.getbyExtractId(extract.getId()); if (records != null && records.size() > 0) { auditRecord = records.get(0); } if (auditRecord != null) { // 提现付款记录 List 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 double countTodayMoney(Long uid) { return extractMapper.countTodayMoney(uid); } }