package project.web.api; import java.io.IOException; import java.text.DecimalFormat; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import kernel.exception.BusinessException; import kernel.sessiontoken.SessionTokenService; import kernel.util.Arith; import kernel.util.DateUtils; import kernel.util.StringUtils; import kernel.util.ThreadUtils; import kernel.web.BaseAction; import kernel.web.ResultObject; import project.Constants; import project.data.DataService; import project.log.Log; import project.log.LogService; import project.party.PartyService; import project.party.model.Party; import project.redis.RedisHandler; import project.syspara.SysparaService; import project.wallet.WalletGatherService; import project.wallet.WalletLogService; import project.wallet.WalletService; import project.wallet.internal.WalletGatherServiceImpl; import project.withdraw.Withdraw; import project.withdraw.WithdrawService; import util.LockFilter; /** * 提现 */ @RestController @CrossOrigin public class WithdrawController extends BaseAction { @Autowired private PartyService partyService; @Autowired private SysparaService sysparaService; @Autowired private WithdrawService withdrawService; @Autowired protected WalletLogService walletLogService; @Autowired private LogService logService; @Autowired private RedisHandler redisHandler; @Autowired private JdbcTemplate jdbcTemplate; @Autowired private WalletService walletService; private final String action = "/api/withdraw!"; @Autowired private SessionTokenService sessionTokenService; private static final Logger logger = LoggerFactory.getLogger(WithdrawController.class); /** * 首次进入页面,传递session_token */ @RequestMapping(action + "withdraw_open.action") public Object withdraw_open() throws IOException { ResultObject resultObject = new ResultObject(); resultObject = this.readSecurityContextFromSession(resultObject); if (!"0".equals(resultObject.getCode())) { return resultObject; } try { String partyId = getLoginPartyId(); String session_token = this.sessionTokenService.savePut(partyId); Map data = new HashMap(); data.put("session_token", session_token); resultObject.setData(data); } catch (BusinessException e) { resultObject.setCode("1"); resultObject.setMsg(e.getMessage()); } catch (Throwable t) { resultObject.setCode("1"); resultObject.setMsg("程序错误"); logger.error("error:", t); } return resultObject; } /** * 提现申请 * * safeword 资金密码 * amount 提现金额 * from 客户转出地址 * currency 货币 CNY USD * channel 渠道 USDT,BTC,ETH */ @RequestMapping(action + "apply.action") public Object apply(HttpServletRequest request) throws IOException { String session_token = request.getParameter("session_token"); String safeword = request.getParameter("safeword"); String amount = request.getParameter("amount"); String from = request.getParameter("from"); String currency = request.getParameter("currency"); String channel = request.getParameter("channel"); String googleCode = request.getParameter("googleCode"); ResultObject resultObject = new ResultObject(); resultObject = this.readSecurityContextFromSession(resultObject); if (!"0".equals(resultObject.getCode())) { return resultObject; } String partyId = this.getLoginPartyId(); boolean lock = false; try { String error = this.verif(amount); if (!StringUtils.isNullOrEmpty(error)) { throw new BusinessException(error); } double amount_double = Double.valueOf(amount).doubleValue(); // 交易所提现是否需要资金密码 String exchange_withdraw_need_safeword = this.sysparaService.find("exchange_withdraw_need_safeword").getValue(); if(StringUtils.isEmptyString(exchange_withdraw_need_safeword)) { throw new BusinessException("系统参数错误"); } if ("true".equals(exchange_withdraw_need_safeword)) { if (StringUtils.isEmptyString(safeword)) { throw new BusinessException("资金密码不能为空"); } if (safeword.length() < 6 || safeword.length() > 12) { throw new BusinessException("资金密码必须6-12位"); } if (!this.partyService.checkSafeword(safeword, partyId)) { throw new BusinessException("资金密码错误"); } } if (!LockFilter.add(partyId)) { throw new BusinessException(error); } lock = true; Object object = this.sessionTokenService.cacheGet(session_token); this.sessionTokenService.del(session_token); if (null == object || !this.getLoginPartyId().equals((String) object)) { throw new BusinessException("请稍后再试"); } Withdraw withdraw = new Withdraw(); withdraw.setPartyId(partyId); withdraw.setVolume(amount_double); withdraw.setAddress(from); withdraw.setCurrency(currency); withdraw.setDeviceIp(this.getIp()); // 保存 WalletGatherService walletGatherService = new WalletGatherServiceImpl(jdbcTemplate,redisHandler,walletService); this.withdrawService.saveApply(withdraw, channel, null, googleCode,walletGatherService); Log log = new Log(); Party party = this.partyService.cachePartyBy(partyId, false); log.setCategory(Constants.LOG_CATEGORY_SECURITY); log.setLog("用户提现申请,订单号["+withdraw.getOrder_no()+"],ip[" + this.getIp(getRequest()) + "]"); log.setPartyId(partyId); log.setUsername(party.getUsername()); logService.saveAsyn(log); // 挂住线程保证事务提交 ThreadUtils.sleep(300); } catch (BusinessException e) { if (105 == e.getSign()) { resultObject.setCode("105"); } else if (401 == e.getSign()) { resultObject.setCode("401"); } else if (506 == e.getSign()) { resultObject.setCode("506"); } else { resultObject.setCode("1"); } resultObject.setMsg(e.getMessage()); } catch (Throwable t) { resultObject.setCode("1"); resultObject.setMsg("程序错误"); System.out.println("提现问题"); t.printStackTrace(); logger.error("error:", t); } finally { if (lock) { LockFilter.remove(partyId); } } return resultObject; } /** * 提现订单详情 * * order_no 订单号 */ @RequestMapping(action + "get.action") public Object get(HttpServletRequest request) throws IOException { String order_no = request.getParameter("order_no"); ResultObject resultObject = new ResultObject(); try { Withdraw withdraw = this.withdrawService.findByOrderNo(order_no); Map map = new HashMap(); map.put("order_no", withdraw.getOrder_no()); map.put("volume", withdraw.getVolume()); map.put("amount", withdraw.getAmount()); map.put("create_time", DateUtils.format(withdraw.getCreateTime(), DateUtils.DF_yyyyMMddHHmmss)); map.put("review_time", DateUtils.format(withdraw.getReviewTime(), DateUtils.DF_yyyyMMddHHmmss)); map.put("to", withdraw.getAddress()); map.put("fee", withdraw.getAmount_fee()); map.put("coin_blockchain", withdraw.getMethod()); map.put("coin", withdraw.getMethod().indexOf("BTC") != -1 || withdraw.getMethod().indexOf("ETH") != -1 ? withdraw.getMethod() : "USDT"); map.put("state", withdraw.getSucceeded()); map.put("failure_msg", withdraw.getFailure_msg()); resultObject.setData(map); } catch (BusinessException e) { resultObject.setCode("1"); resultObject.setMsg(e.getMessage()); } catch (Throwable t) { resultObject.setCode("1"); resultObject.setMsg("程序错误"); logger.error("error:", t); } return resultObject; } /** * 提现记录 */ @RequestMapping(action + "list.action") public Object list(HttpServletRequest request) throws IOException { String page_no = request.getParameter("page_no"); ResultObject resultObject = new ResultObject(); resultObject = this.readSecurityContextFromSession(resultObject); if (!"0".equals(resultObject.getCode())) { return resultObject; } try { if (StringUtils.isNullOrEmpty(page_no)) { page_no = "1"; } if (!StringUtils.isInteger(page_no)) { throw new BusinessException("页码不是整数"); } if (Integer.valueOf(page_no).intValue() <= 0) { throw new BusinessException("页码不能小于等于0"); } int page_no_int = Integer.valueOf(page_no).intValue(); List> data = this.walletLogService.pagedQueryWithdraw(page_no_int, 10, this.getLoginPartyId(), "1").getElements(); for (Map log : data) { if (null == log.get("coin") || !StringUtils.isNotEmpty(log.get("coin").toString())) log.put("coin", Constants.WALLET); else { log.put("coin", log.get("coin").toString().toUpperCase()); } } resultObject.setData(data); } catch (BusinessException e) { resultObject.setCode("1"); resultObject.setMsg(e.getMessage()); } catch (Throwable t) { resultObject.setCode("1"); resultObject.setMsg("程序错误"); logger.error("error:", t); } return resultObject; } /** * 提现手续费 * * channel 渠道 USDT,OTC * amount 提币数量 */ @RequestMapping(action + "fee.action") public Object fee(HttpServletRequest request) throws IOException { String channel = request.getParameter("channel"); String amount = request.getParameter("amount"); ResultObject resultObject = new ResultObject(); try { String error = this.verif(amount); if (!StringUtils.isNullOrEmpty(error)) { throw new BusinessException(error); } double amount_double = Double.valueOf(amount).doubleValue(); Map map = new HashMap(); DecimalFormat df = new DecimalFormat("#.########"); double fee = 0; channel = StringUtils.isEmptyString(channel) ? "USDT" : channel; if (channel.indexOf("BTC") != -1 || channel.indexOf("ETH") != -1) { map.put("withdraw_fee_type", "rate"); fee = this.withdrawService.getOtherChannelWithdrawFee(amount_double); } else { // 手续费(USDT) // 提现手续费类型,fixed是单笔固定金额,rate是百分比,part是分段 String withdraw_fee_type = this.sysparaService.find("withdraw_fee_type").getValue(); // fixed单笔固定金额 和 rate百分比 的手续费数值 double withdraw_fee = Double.valueOf(this.sysparaService.find("withdraw_fee").getValue()); if ("fixed".equals(withdraw_fee_type)) { fee = withdraw_fee; } if ("rate".equals(withdraw_fee_type)) { withdraw_fee = Arith.div(withdraw_fee, 100); fee = Arith.mul(amount_double, withdraw_fee); } if ("part".equals(withdraw_fee_type)) { // 提现手续费part分段的值 String withdraw_fee_part = this.sysparaService.find("withdraw_fee_part").getValue(); String[] withdraw_fee_parts = withdraw_fee_part.split(","); for (int i = 0; i < withdraw_fee_parts.length; i++) { double part_amount = Double.valueOf(withdraw_fee_parts[i]); double part_fee = Double.valueOf(withdraw_fee_parts[i + 1]); if (amount_double <= part_amount) { fee = part_fee; break; } i++; } } map.put("withdraw_fee_type", withdraw_fee_type); } double volume_last = Arith.sub(amount_double, fee); if (volume_last < 0) { volume_last = 0; } map.put("fee", fee); map.put("volume_last", df.format(volume_last)); resultObject.setData(map); } catch (BusinessException e) { resultObject.setCode("1"); resultObject.setMsg(e.getMessage()); } catch (Throwable t) { resultObject.setCode("1"); resultObject.setMsg("程序错误"); logger.error("error:", t); } return resultObject; } /** * 提现限额 * * channel 渠道 USDT,OTC */ @RequestMapping(action + "limit.action") public Object limit(HttpServletRequest request) throws IOException { String channel = request.getParameter("channel"); ResultObject resultObject = new ResultObject(); try { Map map = new HashMap(); channel = StringUtils.isEmptyString(channel) ? "USDT" : channel; if (channel.indexOf("BTC") != -1) { map.put("limit", this.sysparaService.find("withdraw_limit_btc").getValue()); } else if (channel.indexOf("ETH") != -1) { map.put("limit", this.sysparaService.find("withdraw_limit_eth").getValue()); } else { map.put("limit", this.sysparaService.find("withdraw_limit").getValue()); } resultObject.setData(map); } catch (BusinessException e) { resultObject.setCode("1"); resultObject.setMsg(e.getMessage()); } catch (Throwable t) { resultObject.setCode("1"); resultObject.setMsg("程序错误"); logger.error("error:", t); } return resultObject; } private String verif(String amount) { if (StringUtils.isNullOrEmpty(amount)) { return "提币数量必填"; } if (!StringUtils.isDouble(amount)) { return "提币数量输入错误,请输入浮点数"; } if (Double.valueOf(amount).doubleValue() <= 0) { return "提币数量不能小于等于0"; } return null; } }