| | |
| | | package com.yami.trading.api.controller; |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.hutool.http.HttpStatus; |
| | | import cn.hutool.json.JSONUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import com.yami.trading.UD.Coin; |
| | | import com.yami.trading.UD.ResultMsg; |
| | | import com.yami.trading.UD.UdunClient; |
| | | import com.yami.trading.UD.UdunException; |
| | | import com.yami.trading.api.util.ServletUtil; |
| | | import com.yami.trading.bean.item.domain.Item; |
| | | import com.yami.trading.bean.model.User; |
| | | import com.yami.trading.bean.model.Withdraw; |
| | | import com.yami.trading.common.constants.Constants; |
| | |
| | | PasswordEncoder passwordEncoder; |
| | | @Autowired |
| | | private IdentifyingCodeTimeWindowService identifyingCodeTimeWindowService; |
| | | @Autowired |
| | | UdunClient udunClient; |
| | | |
| | | @Override |
| | | public void afterPropertiesSet() throws Exception { |
| | |
| | | public Result apply(HttpServletRequest request, String session_token, String safeword, |
| | | String amount, String from, String currency, |
| | | String channel, String language, String verifcode_type, String verifcode_value) { |
| | | String partyId = SecurityUtils.getUser().getUserId(); |
| | | User currentUser = userService.getById(partyId); |
| | | if (currentUser != null && currentUser.getAccountType() != null && currentUser.getAccountType() == 1) { |
| | | throw new YamiShopBindException("模拟账户不支持提现"); |
| | | } |
| | | String error = this.verif(amount); |
| | | if (!StringUtils.isNullOrEmpty(error)) { |
| | | throw new YamiShopBindException(error); |
| | | } |
| | | double amount_double = Double.valueOf(amount).doubleValue(); |
| | | // 交易所提现是否需要资金密码 |
| | | String exchange_withdraw_need_safeword = this.sysparaService.find("exchange_withdraw_need_safeword").getSvalue(); |
| | | if (StringUtils.isEmptyString(exchange_withdraw_need_safeword)) { |
| | | throw new YamiShopBindException("系统参数错误"); |
| | | } |
| | | // 开关打开,则验证 |
| | | if ("true".equals(exchange_withdraw_need_safeword)) { |
| | | // 资金密码验证 |
| | | if (StringUtils.isEmptyString(safeword)) { |
| | | throw new YamiShopBindException("资金密码不能为空"); |
| | | Result resultObject=new Result(); |
| | | try { |
| | | String partyId = SecurityUtils.getUser().getUserId(); |
| | | String error = this.verif(amount); |
| | | if (!StringUtils.isNullOrEmpty(error)) { |
| | | throw new YamiShopBindException(error); |
| | | } |
| | | if (safeword.length() < 6 || safeword.length() > 12) { |
| | | throw new YamiShopBindException("资金密码必须6-12位"); |
| | | double amount_double = Double.valueOf(amount).doubleValue(); |
| | | // 交易所提现是否需要资金密码 |
| | | String exchange_withdraw_need_safeword = this.sysparaService.find("exchange_withdraw_need_safeword").getSvalue(); |
| | | if (StringUtils.isEmptyString(exchange_withdraw_need_safeword)) { |
| | | throw new YamiShopBindException("系统参数错误"); |
| | | } |
| | | if (!userService.checkLoginSafeword(SecurityUtils.getUser().getUserId(), safeword)) { |
| | | throw new YamiShopBindException("资金密码错误"); |
| | | // 开关打开,则验证 |
| | | if ("true".equals(exchange_withdraw_need_safeword)) { |
| | | // 资金密码验证 |
| | | if (StringUtils.isEmptyString(safeword)) { |
| | | throw new YamiShopBindException("资金密码不能为空"); |
| | | } |
| | | if (safeword.length() < 6 || safeword.length() > 12) { |
| | | throw new YamiShopBindException("资金密码必须6-12位"); |
| | | } |
| | | if (!userService.checkLoginSafeword(SecurityUtils.getUser().getUserId(), safeword)) { |
| | | throw new YamiShopBindException("资金密码错误"); |
| | | } |
| | | if (StringUtils.isNotEmpty(verifcode_type)) { |
| | | // 校验用户的验证码 |
| | | userService.checkCode(partyId, verifcode_type, verifcode_value); |
| | | } |
| | | } |
| | | if (StringUtils.isNotEmpty(verifcode_type)) { |
| | | // 校验用户的验证码 |
| | | userService.checkCode(partyId, verifcode_type, verifcode_value); |
| | | } |
| | | } |
| | | Object object = this.sessionTokenService.cacheGet(session_token); |
| | | this.sessionTokenService.del(session_token); |
| | | Object object = this.sessionTokenService.cacheGet(session_token); |
| | | this.sessionTokenService.del(session_token); |
| | | // if (null == object || !SecurityUtils.getUser().getUserId().equals((String) object)) { |
| | | // throw new YamiShopBindException("请稍后再试"); |
| | | // } |
| | | Withdraw withdraw = new Withdraw(); |
| | | withdraw.setUserId(partyId); |
| | | withdraw.setVolume(new BigDecimal(amount_double)); |
| | | withdraw.setAddress(from); |
| | | withdraw.setCurrency(currency); |
| | | withdraw.setTx(""); |
| | | withdraw.setDeviceIp(ServletUtil.getIp(request)); |
| | | // 保存 |
| | | this.withdrawService.saveApply(withdraw, channel, null, language); |
| | | return Result.succeed(null); |
| | | Withdraw withdraw = new Withdraw(); |
| | | withdraw.setUserId(partyId); |
| | | withdraw.setVolume(new BigDecimal(amount_double)); |
| | | withdraw.setAddress(from); |
| | | withdraw.setCurrency(currency); |
| | | withdraw.setTx(""); |
| | | withdraw.setDeviceIp(ServletUtil.getIp(request)); |
| | | |
| | | |
| | | //获取商户支持币种 |
| | | List<Coin> coinList = udunClient.listSupportCoin(false); |
| | | String channelName ; |
| | | if (channel.toUpperCase().contains("USDC")) { |
| | | channelName = "USDC"; |
| | | } else { |
| | | channelName = channel.replace("_", ""); |
| | | } |
| | | Coin coin = coinList.stream().filter(x -> x.getName().replace("-","").equals(channelName)).findFirst().orElse(null); |
| | | if (coin == null) { |
| | | throw new YamiShopBindException("不支持的提现币种"); |
| | | } |
| | | if (!udunClient.checkAddress(coin.getMainCoinType(), from)) { |
| | | throw new YamiShopBindException("提现地址异常"); |
| | | } |
| | | |
| | | // 保存 |
| | | this.withdrawService.saveApply(withdraw, channel, null, language); |
| | | ResultMsg resultMsg = udunClient.withdraw(from, withdraw.getVolume(), coin.getMainCoinType(), |
| | | coin.getCoinType(), withdraw.getOrderNo(), null); |
| | | if (resultMsg.getCode() != HttpStatus.HTTP_OK) { |
| | | log.error("withdraw:{}", JSONUtil.toJsonStr(resultMsg)); |
| | | throw new UdunException(resultMsg.getCode(), resultMsg.getMessage()); |
| | | } |
| | | resultObject.setCode(0); |
| | | } catch (YamiShopBindException e) { // 1. 显式捕获业务异常,优先处理 |
| | | resultObject.setCode(1); |
| | | resultObject.setMsg("失败"); |
| | | log.error("业务异常: {}", e.getMessage()); |
| | | throw e; |
| | | } catch (UdunException e) { |
| | | resultObject.setCode(1); |
| | | resultObject.setMsg("失败"); |
| | | log.error("Withdraw ud error:{}", e.getMessage()); |
| | | throw e; |
| | | } catch (Throwable t) { |
| | | resultObject.setCode(1); |
| | | resultObject.setMsg("失败"); |
| | | log.error("error: {}", t.getMessage()); |
| | | throw new RuntimeException(t); |
| | | } |
| | | return resultObject; |
| | | } |
| | | |
| | | @PostMapping("withdrawCallback.action") |
| | | public ResultMsg withdrawCallback(HttpServletRequest request){ |
| | | String timestamp = request.getParameter("timestamp"); |
| | | String nonce = request.getParameter("nonce"); |
| | | String sign = request.getParameter("sign"); |
| | | String body = request.getParameter("body"); |
| | | |
| | | ResultMsg resultMsg = new ResultMsg(); |
| | | try{ |
| | | log.info("===withdrawCallback===:{}", body); |
| | | boolean flag = udunClient.checkSign(timestamp, nonce, body, sign); |
| | | log.info("===withdrawCallback===sign:{}", flag); |
| | | |
| | | if (!flag){ |
| | | resultMsg.setCode(406); |
| | | resultMsg.setMessage("提现回调验签失败"); |
| | | return resultMsg; |
| | | } |
| | | ObjectMapper objectMapper = new ObjectMapper(); |
| | | Map<String, Object> map = objectMapper.readValue(body, HashMap.class); |
| | | String address = map.get("address").toString(); |
| | | String order_no = map.get("businessId").toString(); |
| | | |
| | | Withdraw withdraw = withdrawService.getOne(new LambdaQueryWrapper<>(Withdraw.class) |
| | | .eq(Withdraw::getOrderNo, order_no).last(" limit 1 ")); |
| | | if(ObjectUtil.isEmpty(withdraw) && withdraw.getStatus() != 0 && !withdraw.getAddress().equals(address)){ |
| | | log.info("withdraw failed:{}", withdraw); |
| | | resultMsg.setCode(200); |
| | | return resultMsg; |
| | | } |
| | | Integer status = Integer.valueOf(map.get("status").toString()); |
| | | if (status == 3) { //交易成功 |
| | | withdrawService.examineOk(withdraw.getUuid(), null); |
| | | } else if(status == 2) { //驳回 |
| | | withdrawService.reject(withdraw.getUuid(), "订单失败:" + status, "withdrawCallback"); |
| | | } |
| | | resultMsg.setCode(200); |
| | | }catch (Exception e){ |
| | | resultMsg.setCode(500); |
| | | resultMsg.setMessage("回调处理失败"); |
| | | } |
| | | return resultMsg; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | @GetMapping("fee") |
| | | @ApiOperation("提现手续费") |
| | | public Result fee(String channel, String amount) { |
| | | public Result fee(String channel, String amount, String type) { |
| | | String error = this.verif(amount); |
| | | if (!StringUtils.isNullOrEmpty(error)) { |
| | | throw new YamiShopBindException(error); |
| | |
| | | // 手续费(USDT) |
| | | // 提现手续费类型,fixed是单笔固定金额,rate是百分比,part是分段 |
| | | String withdraw_fee_type = this.sysparaService.find("withdraw_fee_type").getSvalue(); |
| | | // fixed单笔固定金额 和 rate百分比 的手续费数值 |
| | | double withdraw_fee = Double.valueOf(this.sysparaService.find("withdraw_fee").getSvalue()); |
| | | 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").getSvalue(); |
| | | 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; |
| | | map.put("withdraw_fee_type", withdraw_fee_type); |
| | | if (type!=null && type.equalsIgnoreCase(Item.cryptos)) { |
| | | fee = 0; |
| | | } else { |
| | | // fixed单笔固定金额 和 rate百分比 的手续费数值 |
| | | double withdraw_fee = Double.valueOf(this.sysparaService.find("withdraw_fee").getSvalue()); |
| | | 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").getSvalue(); |
| | | 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++; |
| | | } |
| | | i++; |
| | | } |
| | | } |
| | | map.put("withdraw_fee_type", withdraw_fee_type); |
| | | } |
| | | |
| | | double volume_last = Arith.sub(amount_double, fee); |