package com.hehenian.biz.service.trade.impl; import com.hehenian.biz.common.account.dataobject.AccountUserDo; import com.hehenian.biz.common.base.result.IResult; import com.hehenian.biz.common.base.result.ResultSupport; import com.hehenian.biz.common.exception.BusinessException; import com.hehenian.biz.common.trade.IWithdrawService; import com.hehenian.biz.common.trade.dataobject.MerCashDo; import com.hehenian.biz.common.trade.dataobject.WithdrawDo; import com.hehenian.biz.common.util.CalculateUtils; import com.hehenian.biz.component.account.IBankCardComponent; import com.hehenian.biz.component.account.IPersonComponent; import com.hehenian.biz.component.account.IUserComponent; import com.hehenian.biz.component.trade.IFundrecordComponent; import com.hehenian.biz.component.trade.IMerCostComponent; import com.hehenian.biz.component.trade.IReconciliationComponent; import com.hehenian.biz.component.trade.IWithdrawComponent; import com.hehenian.biz.facade.account.AccountType; import com.hehenian.biz.facade.account.IAccountManagerService; import com.hehenian.biz.facade.account.parameter.InParameter; import com.hehenian.biz.facade.account.parameter.OutParameter; import com.ibm.icu.text.DecimalFormat; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.DateUtils; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Calendar; import java.util.Date; @Service("withdrawService") public class WithdrawServiceImpl implements IWithdrawService { private final Logger logger = Logger.getLogger(this.getClass()); @Autowired private IAccountManagerService accountManagerService; @Autowired private IWithdrawComponent withdrawComponent; @Autowired private IUserComponent userComponent; @Autowired private IPersonComponent personComponent; @Autowired private IBankCardComponent bankCardComponent; @Autowired private IMerCostComponent merCostComponent; @Autowired private IFundrecordComponent fundrecordComponent; @Autowired private IReconciliationComponent reconciliationComponent; @Override public IResult<?> addWithdraw(WithdrawDo withdrawDo) { IResult<String> result = new ResultSupport<String>(); try { // 校验提现申请信息 result = checkWithdrawApply(withdrawDo); if (!result.isSuccess()) { return result; } // 新增提现申请 withdrawComponent.addWithdraw(withdrawDo); // 发送提现申请请求到汇付 return cash(withdrawDo); } catch (BusinessException e) { result.setSuccess(false); result.setErrorMessage(e.getMessage()); logger.error(e.getMessage(), e); } catch (Exception e) { result.setSuccess(false); result.setErrorMessage("操作失败,请稍后再试!"); logger.error(e.getMessage(), e); } return result; } /** * 提现申请 * * @param withdrawDo * @return */ private IResult<String> cash(WithdrawDo withdrawDo) { AccountUserDo accountUserDo = userComponent.getById(withdrawDo.getUserId()); InParameter inParameter = new InParameter(); inParameter.setOrdId(withdrawDo.getId() + ""); inParameter.setRetUrl("cash.do"); inParameter.setBgRetUrl("cashBg.do"); inParameter.getParams().put("usrCustId", accountUserDo.getUsrCustId() + "");// 汇付注册客户号 inParameter.getParams().put("transAmt", new DecimalFormat("#0.00").format(withdrawDo.getSum())); inParameter.getParams().put("openAcctId", (withdrawDo.getAcount() != null ? withdrawDo.getAcount() : "")); inParameter.getParams().put("servFee", getWithdrawServFee(withdrawDo.getUserId(), withdrawDo.getSum()));// 提现服务费 OutParameter outParameter = accountManagerService.cash(inParameter, AccountType.CHINAPNR); IResult<String> result = new ResultSupport<String>(); if (outParameter.isSuccess()) { result.setSuccess(true); result.setModel((String) outParameter.getParams().get("htmlText")); } else { result.setSuccess(false); result.setErrorMessage(outParameter.getRespDesc()); } return result; } /** * 获取提现服务费,每月三笔免费提现,其余按提现1%收取,最高2元每笔 * * @param userId * @param transAmt * @return * @author: liuzgmf * @date: 2014年10月17日下午2:17:28 */ private Double getWithdrawServFee(Long userId, Double transAmt) { Date beginDate = DateUtils.truncate(DateUtils.setDays(new Date(), 1), Calendar.DATE); Date endDate = DateUtils.addMonths(beginDate, 1); int count = withdrawComponent.countWithdrawQty(userId, beginDate, endDate); if (count > 3) { Double servFee = CalculateUtils.mul(transAmt, 0.01); return (CalculateUtils.lt(servFee, 2.00) ? servFee : 2.00); } else { return 0.00; } } /** * 校验提现申请信息 * * @param withdrawDo * @return */ private IResult<String> checkWithdrawApply(WithdrawDo withdrawDo) { IResult<String> result = new ResultSupport<String>(); AccountUserDo userDo = userComponent.getById(withdrawDo.getUserId()); if (userDo == null) { result.setSuccess(false); result.setErrorMessage("无此用户!"); return result; } if (userDo.getEnable().intValue() == 2) { result.setSuccess(false); result.setErrorMessage("禁用用户!"); return result; } if (userDo.getEnable().intValue() == 3) { result.setSuccess(false); result.setErrorMessage("黑名单用户!"); return result; } double withdrawAmt = CalculateUtils.sub(userDo.getUsableSum(), userDo.getLockAmount()); if (CalculateUtils.lt(withdrawAmt, withdrawDo.getSum())) { result.setSuccess(false); result.setErrorMessage("账户余额不足!"); return result; } result.setSuccess(true); return result; } @Override public Integer deleteById(Long id) { return withdrawComponent.deleteById(id); } @Override public WithdrawDo getById(Long id) { return withdrawComponent.getById(id); } @Override public IResult<?> addWithdrawCallback(WithdrawDo withdrawDo) { IResult<Integer> result = new ResultSupport<Integer>(true); try { WithdrawDo localWithdrawDo = withdrawComponent.getById(withdrawDo.getId()); if (!CalculateUtils.eq(localWithdrawDo.getSum(), withdrawDo.getSum())) { throw new BusinessException("提现申请[" + withdrawDo.getId() + "]金额[" + localWithdrawDo.getSum() + "]与汇付返回提现金额[" + withdrawDo.getSum() + "]不一致!"); } AccountUserDo userDo = userComponent.getUserByCustId(withdrawDo.getUsrCustId()); if (userDo.getId().longValue() != localWithdrawDo.getUserId().longValue()) { throw new BusinessException("提现[" + withdrawDo.getId() + "]用户不一致!"); } if (StringUtils.isNotBlank(localWithdrawDo.getTrxId())) { throw new BusinessException("提现记录[" + withdrawDo.getId() + "]已处理!"); } // 发送冻结请求到汇付 InParameter inParameter = new InParameter(); inParameter.setOrdId(fundrecordComponent.getAutoIncrementId() + ""); inParameter.getParams().put("usrCustId", withdrawDo.getUsrCustId()); inParameter.getParams().put("transAmt", new DecimalFormat("#0.00").format(withdrawDo.getSum())); OutParameter outParameter = accountManagerService.usrFreezeBg(inParameter, AccountType.CHINAPNR); if (!outParameter.isSuccess()) { withdrawComponent.updateStatus(withdrawDo.getId(), 5, 0); throw new BusinessException("冻结用户提现[" + withdrawDo.getId() + "]金额失败!"); } withdrawDo.setTrxId(outParameter.getTrxId()); // 执行平台提现申请操作,如果操作失败,解冻提现金额 try { withdrawComponent.updateWithdrawCallback(withdrawDo); } catch (RuntimeException e) { logger.error(e.getMessage(), e); usrUnFreeze(withdrawDo.getId(), withdrawDo.getTrxId()); } } catch (BusinessException e) { result.setSuccess(false); result.setErrorMessage(e.getMessage()); logger.warn(e.getMessage()); } catch (Exception e) { result.setSuccess(false); result.setErrorMessage("操作失败,请稍后再试!"); logger.error(e.getMessage(), e); } return result; } /** * 解冻用户提现金额 * * @param withdrawDo * @author: liuzgmf * @date: 2014-11-4下午4:06:33 */ private void usrUnFreeze(long ordId, String trxId) { InParameter inParameter = new InParameter(); inParameter.setOrdId(ordId + ""); inParameter.setTrxId(trxId); OutParameter outParameter = accountManagerService.usrUnFreeze(inParameter, AccountType.CHINAPNR); if (!outParameter.isSuccess()) { throw new BusinessException("解冻用户提现[" + ordId + "]金额失败!"); } } @Override public IResult<?> updateWithdrawAudit(WithdrawDo withdrawDo) { IResult<?> result = new ResultSupport<String>(true); try { result = checkAuditingWithdraw(withdrawDo.getId()); if (!result.isSuccess()) { return result; } if (withdrawDo.getStatus().intValue() == 5) {// 如果拒绝提现,则需要解冻用户的提现金额 InParameter inParameter = new InParameter(); WithdrawDo localWithdrawDo = withdrawComponent.getById(withdrawDo.getId()); inParameter.setTrxId(localWithdrawDo.getTrxId()); OutParameter outParameter = accountManagerService.usrUnFreeze(inParameter, AccountType.CHINAPNR); if (!outParameter.isSuccess()) { throw new BusinessException("审核失败,提现金额解冻失败!"); } withdrawComponent.updateWithdrawFault(withdrawDo); } else { withdrawComponent.updateWithdrawAudit(withdrawDo); } result.setSuccess(true); } catch (BusinessException e) { result.setSuccess(false); result.setErrorMessage(e.getMessage()); logger.warn(e.getMessage()); } catch (Exception e) { result.setSuccess(false); result.setErrorMessage("操作失败,请稍后再试!"); logger.error(e.getMessage(), e); } return result; } private IResult<?> checkAuditingWithdraw(Long withdrawId) { IResult<String> result = new ResultSupport<String>(); WithdrawDo localWithdrawDo = withdrawComponent.getById(withdrawId); if (localWithdrawDo.getStatus().intValue() == 2) { result.setSuccess(false); result.setErrorMessage("该笔提现款已完成!"); return result; } if (localWithdrawDo.getStatus().intValue() == 3) { result.setSuccess(false); result.setErrorMessage("该笔提现款已取消!"); return result; } if (localWithdrawDo.getStatus().intValue() == 4) { result.setSuccess(false); result.setErrorMessage("该笔提现款正在转账中!"); return result; } if (localWithdrawDo.getStatus().intValue() == 5) { result.setSuccess(false); result.setErrorMessage("该笔提现款已受理!"); return result; } result.setSuccess(true); return result; } @Override public IResult<?> updateWithdrawTransfer(WithdrawDo withdrawDo) { IResult<?> result = new ResultSupport<String>(); try { // 校验提现申请记录是否符合提现要求 result = checkWithdrawStatus(withdrawDo); if (!result.isSuccess()) { return result; } // 解冻 WithdrawDo localWithdrawDo = withdrawComponent.getById(withdrawDo.getId()); InParameter inParameter = new InParameter(); inParameter.setOrdId(localWithdrawDo.getId() + ""); inParameter.setTrxId(localWithdrawDo.getTrxId()); OutParameter outParameter = accountManagerService.usrUnFreeze(inParameter, AccountType.CHINAPNR); if (!outParameter.isSuccess()) { result.setSuccess(false); result.setErrorMessage(outParameter.getRespDesc()); return result; } // 提现复核 InParameter costInParameter = new InParameter(); costInParameter.setOrdId(localWithdrawDo.getId() + ""); AccountUserDo userDo = userComponent.getById(localWithdrawDo.getUserId()); costInParameter.getParams().put("usrCustId", userDo.getUsrCustId() + ""); costInParameter.getParams().put("transAmt", new DecimalFormat("#0.00").format(localWithdrawDo.getSum())); costInParameter.getParams().put("auditFlag", getAuditFlag(withdrawDo.getStatus())); outParameter = accountManagerService.cashAudit(costInParameter, AccountType.CHINAPNR); if (!outParameter.isSuccess() && !"重复交易".equals(outParameter.getRespDesc())) { result.setSuccess(false); result.setErrorMessage(outParameter.getRespDesc()); return result; } // 校验提现金额 String transAmt = (String) outParameter.getParams().get("TransAmt"); if (StringUtils.isBlank(transAmt) || CalculateUtils.le(Double.valueOf(transAmt), 0.00)) { result.setSuccess(false); result.setErrorMessage("转账金额错误!"); return result; } // 修改提现记录及增加交易记录 withdrawDo.setSum(Double.valueOf(transAmt)); boolean success = withdrawComponent.updateWithdrawTransfer(withdrawDo); if (success) { result.setSuccess(true); return result; } else { result.setSuccess(false); result.setErrorMessage("操作失败,请稍后再试!"); } } catch (BusinessException e) { result.setSuccess(false); result.setErrorMessage(e.getMessage()); logger.warn(e.getMessage()); } catch (Exception e) { result.setSuccess(false); result.setErrorMessage("操作失败,请稍后再试!"); logger.error(e.getMessage(), e); } return result; } /** * 获取审核状态 * * @return */ private String getAuditFlag(Integer status) { if (status.intValue() == 2) { return "S"; } else if (status.intValue() == 5) { return "R"; } return null; } /** * 交易提现申请记录的状态 * * @param withdrawDo * @param result * @return */ private IResult<?> checkWithdrawStatus(WithdrawDo withdrawDo) { IResult<String> result = new ResultSupport<String>(); WithdrawDo localWithdrawDo = withdrawComponent.getById(withdrawDo.getId()); if (localWithdrawDo == null) { result.setSuccess(false); result.setErrorMessage("提现申请记录不存在!"); return result; } localWithdrawDo.setStatus(localWithdrawDo.getStatus() == null ? 5 : localWithdrawDo.getStatus()); if (localWithdrawDo.getStatus().intValue() == 1) { result.setSuccess(false); result.setErrorMessage("该笔提现款正在审核中!"); return result; } if (localWithdrawDo.getStatus().intValue() == 2) { result.setSuccess(false); result.setErrorMessage("该笔提现款已完成!"); return result; } if (localWithdrawDo.getStatus().intValue() == 3) { result.setSuccess(false); result.setErrorMessage("该笔提现款已取消!"); return result; } if (localWithdrawDo.getStatus().intValue() == 5) { result.setSuccess(false); result.setErrorMessage("该笔提现款已受理!"); return result; } result.setSuccess(true); return result; } @Override public IResult<?> addMerWithdraw(MerCashDo merCashDo) { IResult<?> result = new ResultSupport<String>(); try { // 新增平台提现记录 Long merCostId = merCostComponent.addMerCash(merCashDo); // 平台提现 InParameter inParameter = new InParameter(); inParameter.setOrdId(merCostId + ""); inParameter.getParams().put("usrCustId", merCashDo.getUsrCustId()); inParameter.getParams().put("transAmt", merCashDo.getSum()); inParameter.getParams().put("remark", ""); OutParameter outParameter = accountManagerService.merCash(inParameter, AccountType.CHINAPNR); if (!outParameter.isSuccess()) { result.setSuccess(false); result.setErrorMessage(outParameter.getRespDesc()); return result; } // 修改平台提现记录 String feeAmt = (String) outParameter.getParams().get("FeeAmt"); merCashDo.setPoundage(Double.parseDouble(feeAmt));// 提现手续费 merCashDo.setCardNo((String) outParameter.getParams().get("OpenAcctId"));// 银行卡号 merCashDo.setStatus(1);// 1代表成功 merCostComponent.updateMerCash(merCashDo); result.setSuccess(true); } catch (BusinessException e) { result.setSuccess(false); result.setErrorMessage(e.getMessage()); logger.warn(e.getMessage()); } catch (Exception e) { result.setSuccess(false); result.setErrorMessage("操作失败,请稍后再试!"); logger.error(e.getMessage(), e); } return result; } @Override public boolean updateStatus(Long withdrawId, Integer status, Integer origStatus) { return withdrawComponent.updateStatus(withdrawId, status, origStatus); } }